1 /* $NetBSD: readconf.c,v 1.34 2021/04/19 14:40:15 christos Exp $ */ 2 /* $OpenBSD: readconf.c,v 1.353 2021/04/03 06:18:40 djm Exp $ */ 3 4 /* 5 * Author: Tatu Ylonen <ylo@cs.hut.fi> 6 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 7 * All rights reserved 8 * Functions for reading the configuration files. 9 * 10 * As far as I am concerned, the code I have written for this software 11 * can be used freely for any purpose. Any derived versions of this 12 * software must be clearly marked as such, and if the derived work is 13 * incompatible with the protocol description in the RFC file, it must be 14 * called by a name other than "ssh" or "Secure Shell". 15 */ 16 17 #include "includes.h" 18 __RCSID("$NetBSD: readconf.c,v 1.34 2021/04/19 14:40:15 christos Exp $"); 19 #include <sys/types.h> 20 #include <sys/stat.h> 21 #include <sys/socket.h> 22 #include <sys/wait.h> 23 #include <sys/un.h> 24 25 #include <netinet/in.h> 26 #include <netinet/ip.h> 27 28 #include <ctype.h> 29 #include <errno.h> 30 #include <fcntl.h> 31 #include <glob.h> 32 #include <netdb.h> 33 #include <paths.h> 34 #include <pwd.h> 35 #include <signal.h> 36 #include <stdio.h> 37 #include <string.h> 38 #include <stdarg.h> 39 #include <unistd.h> 40 #include <limits.h> 41 #include <util.h> 42 #include <vis.h> 43 44 #include "xmalloc.h" 45 #include "ssh.h" 46 #include "ssherr.h" 47 #include "compat.h" 48 #include "cipher.h" 49 #include "pathnames.h" 50 #include "log.h" 51 #include "sshkey.h" 52 #include "misc.h" 53 #include "readconf.h" 54 #include "match.h" 55 #include "kex.h" 56 #include "mac.h" 57 #include "fmt_scaled.h" 58 #include "uidswap.h" 59 #include "myproposal.h" 60 #include "digest.h" 61 62 /* Format of the configuration file: 63 64 # Configuration data is parsed as follows: 65 # 1. command line options 66 # 2. user-specific file 67 # 3. system-wide file 68 # Any configuration value is only changed the first time it is set. 69 # Thus, host-specific definitions should be at the beginning of the 70 # configuration file, and defaults at the end. 71 72 # Host-specific declarations. These may override anything above. A single 73 # host may match multiple declarations; these are processed in the order 74 # that they are given in. 75 76 Host *.ngs.fi ngs.fi 77 User foo 78 79 Host fake.com 80 Hostname another.host.name.real.org 81 User blaah 82 Port 34289 83 ForwardX11 no 84 ForwardAgent no 85 86 Host books.com 87 RemoteForward 9999 shadows.cs.hut.fi:9999 88 Ciphers 3des-cbc 89 90 Host fascist.blob.com 91 Port 23123 92 User tylonen 93 PasswordAuthentication no 94 95 Host puukko.hut.fi 96 User t35124p 97 ProxyCommand ssh-proxy %h %p 98 99 Host *.fr 100 PublicKeyAuthentication no 101 102 Host *.su 103 Ciphers aes128-ctr 104 PasswordAuthentication no 105 106 Host vpn.fake.com 107 Tunnel yes 108 TunnelDevice 3 109 110 # Defaults for various options 111 Host * 112 ForwardAgent no 113 ForwardX11 no 114 PasswordAuthentication yes 115 StrictHostKeyChecking yes 116 TcpKeepAlive no 117 IdentityFile ~/.ssh/identity 118 Port 22 119 EscapeChar ~ 120 121 */ 122 123 static int read_config_file_depth(const char *filename, struct passwd *pw, 124 const char *host, const char *original_host, Options *options, 125 int flags, int *activep, int *want_final_pass, int depth); 126 static int process_config_line_depth(Options *options, struct passwd *pw, 127 const char *host, const char *original_host, char *line, 128 const char *filename, int linenum, int *activep, int flags, 129 int *want_final_pass, int depth); 130 131 /* Keyword tokens. */ 132 133 typedef enum { 134 oBadOption, 135 oHost, oMatch, oInclude, 136 oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout, 137 oGatewayPorts, oExitOnForwardFailure, 138 oPasswordAuthentication, 139 oChallengeResponseAuthentication, oXAuthLocation, 140 #if defined(KRB4) || defined(KRB5) 141 oKerberosAuthentication, 142 #endif 143 #if defined(AFS) || defined(KRB5) 144 oKerberosTgtPassing, 145 #endif 146 #ifdef AFS 147 oAFSTokenPassing, 148 #endif 149 oIdentityFile, oHostname, oPort, oRemoteForward, oLocalForward, 150 oPermitRemoteOpen, 151 oCertificateFile, oAddKeysToAgent, oIdentityAgent, 152 oUser, oEscapeChar, oProxyCommand, 153 oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, 154 oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, 155 oTCPKeepAlive, oNumberOfPasswordPrompts, 156 oLogFacility, oLogLevel, oLogVerbose, oCiphers, oMacs, 157 oPubkeyAuthentication, 158 oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, 159 oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, 160 oHostKeyAlgorithms, oBindAddress, oBindInterface, oPKCS11Provider, 161 oClearAllForwardings, oNoHostAuthenticationForLocalhost, 162 oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, 163 oAddressFamily, oGssAuthentication, oGssDelegateCreds, 164 oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, 165 oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist, 166 oHashKnownHosts, 167 oTunnel, oTunnelDevice, 168 oLocalCommand, oPermitLocalCommand, oRemoteCommand, 169 oVisualHostKey, 170 oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass, 171 oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, 172 oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, 173 oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys, 174 oFingerprintHash, oUpdateHostkeys, oHostbasedAcceptedAlgorithms, 175 oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump, 176 oSecurityKeyProvider, oKnownHostsCommand, 177 oNoneEnabled, oTcpRcvBufPoll, oTcpRcvBuf, oNoneSwitch, oHPNDisabled, 178 oHPNBufferSize, 179 oSendVersionFirst, 180 oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported 181 } OpCodes; 182 183 /* Textual representations of the tokens. */ 184 185 static struct { 186 const char *name; 187 OpCodes opcode; 188 } keywords[] = { 189 /* Deprecated options */ 190 { "protocol", oIgnore }, /* NB. silently ignored */ 191 { "cipher", oDeprecated }, 192 { "fallbacktorsh", oDeprecated }, 193 { "globalknownhostsfile2", oDeprecated }, 194 { "rhostsauthentication", oDeprecated }, 195 { "userknownhostsfile2", oDeprecated }, 196 { "useroaming", oDeprecated }, 197 { "usersh", oDeprecated }, 198 { "useprivilegedport", oDeprecated }, 199 200 /* Unsupported options */ 201 #ifdef AFS 202 { "afstokenpassing", oAFSTokenPassing }, 203 #else 204 { "afstokenpassing", oUnsupported }, 205 #endif 206 #if defined(KRB4) || defined(KRB5) 207 { "kerberosauthentication", oKerberosAuthentication }, 208 #else 209 { "kerberosauthentication", oUnsupported }, 210 #endif 211 #if defined(AFS) || defined(KRB5) 212 { "kerberostgtpassing", oKerberosTgtPassing }, 213 { "kerberos5tgtpassing", oKerberosTgtPassing }, /* alias */ 214 { "kerberos4tgtpassing", oKerberosTgtPassing }, /* alias */ 215 #else 216 { "kerberostgtpassing", oUnsupported }, 217 { "kerberos5tgtpassing", oUnsupported }, 218 { "kerberos4tgtpassing", oUnsupported }, 219 #endif 220 { "rsaauthentication", oUnsupported }, 221 { "rhostsrsaauthentication", oUnsupported }, 222 { "compressionlevel", oUnsupported }, 223 224 /* Sometimes-unsupported options */ 225 #if defined(GSSAPI) 226 { "gssapiauthentication", oGssAuthentication }, 227 { "gssapidelegatecredentials", oGssDelegateCreds }, 228 # else 229 { "gssapiauthentication", oUnsupported }, 230 { "gssapidelegatecredentials", oUnsupported }, 231 #endif 232 #ifdef ENABLE_PKCS11 233 { "pkcs11provider", oPKCS11Provider }, 234 { "smartcarddevice", oPKCS11Provider }, 235 # else 236 { "smartcarddevice", oUnsupported }, 237 { "pkcs11provider", oUnsupported }, 238 #endif 239 240 { "forwardagent", oForwardAgent }, 241 { "forwardx11", oForwardX11 }, 242 { "forwardx11trusted", oForwardX11Trusted }, 243 { "forwardx11timeout", oForwardX11Timeout }, 244 { "exitonforwardfailure", oExitOnForwardFailure }, 245 { "xauthlocation", oXAuthLocation }, 246 { "gatewayports", oGatewayPorts }, 247 { "passwordauthentication", oPasswordAuthentication }, 248 { "kbdinteractiveauthentication", oKbdInteractiveAuthentication }, 249 { "kbdinteractivedevices", oKbdInteractiveDevices }, 250 { "pubkeyauthentication", oPubkeyAuthentication }, 251 { "dsaauthentication", oPubkeyAuthentication }, /* alias */ 252 { "hostbasedauthentication", oHostbasedAuthentication }, 253 { "challengeresponseauthentication", oChallengeResponseAuthentication }, 254 { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */ 255 { "tisauthentication", oChallengeResponseAuthentication }, /* alias */ 256 #if defined(GSSAPI) 257 { "gssapiauthentication", oGssAuthentication }, 258 { "gssapidelegatecredentials", oGssDelegateCreds }, 259 #else 260 { "gssapiauthentication", oUnsupported }, 261 { "gssapidelegatecredentials", oUnsupported }, 262 #endif 263 { "identityfile", oIdentityFile }, 264 { "identityfile2", oIdentityFile }, /* obsolete */ 265 { "identitiesonly", oIdentitiesOnly }, 266 { "certificatefile", oCertificateFile }, 267 { "addkeystoagent", oAddKeysToAgent }, 268 { "identityagent", oIdentityAgent }, 269 { "hostname", oHostname }, 270 { "hostkeyalias", oHostKeyAlias }, 271 { "proxycommand", oProxyCommand }, 272 { "port", oPort }, 273 { "ciphers", oCiphers }, 274 { "macs", oMacs }, 275 { "remoteforward", oRemoteForward }, 276 { "localforward", oLocalForward }, 277 { "permitremoteopen", oPermitRemoteOpen }, 278 { "user", oUser }, 279 { "host", oHost }, 280 { "match", oMatch }, 281 { "escapechar", oEscapeChar }, 282 { "globalknownhostsfile", oGlobalKnownHostsFile }, 283 { "userknownhostsfile", oUserKnownHostsFile }, 284 { "connectionattempts", oConnectionAttempts }, 285 { "batchmode", oBatchMode }, 286 { "checkhostip", oCheckHostIP }, 287 { "stricthostkeychecking", oStrictHostKeyChecking }, 288 { "compression", oCompression }, 289 { "tcpkeepalive", oTCPKeepAlive }, 290 { "keepalive", oTCPKeepAlive }, /* obsolete */ 291 { "numberofpasswordprompts", oNumberOfPasswordPrompts }, 292 { "syslogfacility", oLogFacility }, 293 { "loglevel", oLogLevel }, 294 { "logverbose", oLogVerbose }, 295 { "dynamicforward", oDynamicForward }, 296 { "preferredauthentications", oPreferredAuthentications }, 297 { "hostkeyalgorithms", oHostKeyAlgorithms }, 298 { "casignaturealgorithms", oCASignatureAlgorithms }, 299 { "bindaddress", oBindAddress }, 300 { "bindinterface", oBindInterface }, 301 { "clearallforwardings", oClearAllForwardings }, 302 { "enablesshkeysign", oEnableSSHKeysign }, 303 { "verifyhostkeydns", oVerifyHostKeyDNS }, 304 { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost }, 305 { "rekeylimit", oRekeyLimit }, 306 { "connecttimeout", oConnectTimeout }, 307 { "addressfamily", oAddressFamily }, 308 { "serveraliveinterval", oServerAliveInterval }, 309 { "serveralivecountmax", oServerAliveCountMax }, 310 { "sendenv", oSendEnv }, 311 { "setenv", oSetEnv }, 312 { "controlpath", oControlPath }, 313 { "controlmaster", oControlMaster }, 314 { "controlpersist", oControlPersist }, 315 { "hashknownhosts", oHashKnownHosts }, 316 { "include", oInclude }, 317 { "tunnel", oTunnel }, 318 { "tunneldevice", oTunnelDevice }, 319 { "localcommand", oLocalCommand }, 320 { "permitlocalcommand", oPermitLocalCommand }, 321 { "remotecommand", oRemoteCommand }, 322 { "visualhostkey", oVisualHostKey }, 323 { "kexalgorithms", oKexAlgorithms }, 324 { "ipqos", oIPQoS }, 325 { "requesttty", oRequestTTY }, 326 { "proxyusefdpass", oProxyUseFdpass }, 327 { "canonicaldomains", oCanonicalDomains }, 328 { "canonicalizefallbacklocal", oCanonicalizeFallbackLocal }, 329 { "canonicalizehostname", oCanonicalizeHostname }, 330 { "canonicalizemaxdots", oCanonicalizeMaxDots }, 331 { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs }, 332 { "streamlocalbindmask", oStreamLocalBindMask }, 333 { "streamlocalbindunlink", oStreamLocalBindUnlink }, 334 { "revokedhostkeys", oRevokedHostKeys }, 335 { "fingerprinthash", oFingerprintHash }, 336 { "updatehostkeys", oUpdateHostkeys }, 337 { "hostbasedalgorithms", oHostbasedAcceptedAlgorithms }, 338 { "hostbasedkeytypes", oHostbasedAcceptedAlgorithms }, /* obsolete */ 339 { "pubkeyacceptedalgorithms", oPubkeyAcceptedAlgorithms }, 340 { "pubkeyacceptedkeytypes", oPubkeyAcceptedAlgorithms }, /* obsolete */ 341 { "proxyjump", oProxyJump }, 342 { "noneenabled", oNoneEnabled }, 343 { "tcprcvbufpoll", oTcpRcvBufPoll }, 344 { "tcprcvbuf", oTcpRcvBuf }, 345 { "noneswitch", oNoneSwitch }, 346 { "hpndisabled", oHPNDisabled }, 347 { "hpnbuffersize", oHPNBufferSize }, 348 { "sendversionfirst", oSendVersionFirst }, 349 { "ignoreunknown", oIgnoreUnknown }, 350 { "proxyjump", oProxyJump }, 351 { "securitykeyprovider", oSecurityKeyProvider }, 352 { "knownhostscommand", oKnownHostsCommand }, 353 354 { NULL, oBadOption } 355 }; 356 357 static const char *lookup_opcode_name(OpCodes code); 358 359 const char * 360 kex_default_pk_alg(void) 361 { 362 static char *pkalgs; 363 364 if (pkalgs == NULL) { 365 char *all_key; 366 367 all_key = sshkey_alg_list(0, 0, 1, ','); 368 pkalgs = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key); 369 free(all_key); 370 } 371 return pkalgs; 372 } 373 374 char * 375 ssh_connection_hash(const char *thishost, const char *host, const char *portstr, 376 const char *user) 377 { 378 struct ssh_digest_ctx *md; 379 u_char conn_hash[SSH_DIGEST_MAX_LENGTH]; 380 381 if ((md = ssh_digest_start(SSH_DIGEST_SHA1)) == NULL || 382 ssh_digest_update(md, thishost, strlen(thishost)) < 0 || 383 ssh_digest_update(md, host, strlen(host)) < 0 || 384 ssh_digest_update(md, portstr, strlen(portstr)) < 0 || 385 ssh_digest_update(md, user, strlen(user)) < 0 || 386 ssh_digest_final(md, conn_hash, sizeof(conn_hash)) < 0) 387 fatal_f("mux digest failed"); 388 ssh_digest_free(md); 389 return tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1)); 390 } 391 392 /* 393 * Adds a local TCP/IP port forward to options. Never returns if there is an 394 * error. 395 */ 396 397 void 398 add_local_forward(Options *options, const struct Forward *newfwd) 399 { 400 struct Forward *fwd; 401 int i; 402 403 /* Don't add duplicates */ 404 for (i = 0; i < options->num_local_forwards; i++) { 405 if (forward_equals(newfwd, options->local_forwards + i)) 406 return; 407 } 408 options->local_forwards = xreallocarray(options->local_forwards, 409 options->num_local_forwards + 1, 410 sizeof(*options->local_forwards)); 411 fwd = &options->local_forwards[options->num_local_forwards++]; 412 413 fwd->listen_host = newfwd->listen_host; 414 fwd->listen_port = newfwd->listen_port; 415 fwd->listen_path = newfwd->listen_path; 416 fwd->connect_host = newfwd->connect_host; 417 fwd->connect_port = newfwd->connect_port; 418 fwd->connect_path = newfwd->connect_path; 419 } 420 421 /* 422 * Adds a remote TCP/IP port forward to options. Never returns if there is 423 * an error. 424 */ 425 426 void 427 add_remote_forward(Options *options, const struct Forward *newfwd) 428 { 429 struct Forward *fwd; 430 int i; 431 432 /* Don't add duplicates */ 433 for (i = 0; i < options->num_remote_forwards; i++) { 434 if (forward_equals(newfwd, options->remote_forwards + i)) 435 return; 436 } 437 options->remote_forwards = xreallocarray(options->remote_forwards, 438 options->num_remote_forwards + 1, 439 sizeof(*options->remote_forwards)); 440 fwd = &options->remote_forwards[options->num_remote_forwards++]; 441 442 fwd->listen_host = newfwd->listen_host; 443 fwd->listen_port = newfwd->listen_port; 444 fwd->listen_path = newfwd->listen_path; 445 fwd->connect_host = newfwd->connect_host; 446 fwd->connect_port = newfwd->connect_port; 447 fwd->connect_path = newfwd->connect_path; 448 fwd->handle = newfwd->handle; 449 fwd->allocated_port = 0; 450 } 451 452 static void 453 clear_forwardings(Options *options) 454 { 455 int i; 456 457 for (i = 0; i < options->num_local_forwards; i++) { 458 free(options->local_forwards[i].listen_host); 459 free(options->local_forwards[i].listen_path); 460 free(options->local_forwards[i].connect_host); 461 free(options->local_forwards[i].connect_path); 462 } 463 if (options->num_local_forwards > 0) { 464 free(options->local_forwards); 465 options->local_forwards = NULL; 466 } 467 options->num_local_forwards = 0; 468 for (i = 0; i < options->num_remote_forwards; i++) { 469 free(options->remote_forwards[i].listen_host); 470 free(options->remote_forwards[i].listen_path); 471 free(options->remote_forwards[i].connect_host); 472 free(options->remote_forwards[i].connect_path); 473 } 474 if (options->num_remote_forwards > 0) { 475 free(options->remote_forwards); 476 options->remote_forwards = NULL; 477 } 478 options->num_remote_forwards = 0; 479 options->tun_open = SSH_TUNMODE_NO; 480 } 481 482 void 483 add_certificate_file(Options *options, const char *path, int userprovided) 484 { 485 int i; 486 487 if (options->num_certificate_files >= SSH_MAX_CERTIFICATE_FILES) 488 fatal("Too many certificate files specified (max %d)", 489 SSH_MAX_CERTIFICATE_FILES); 490 491 /* Avoid registering duplicates */ 492 for (i = 0; i < options->num_certificate_files; i++) { 493 if (options->certificate_file_userprovided[i] == userprovided && 494 strcmp(options->certificate_files[i], path) == 0) { 495 debug2_f("ignoring duplicate key %s", path); 496 return; 497 } 498 } 499 500 options->certificate_file_userprovided[options->num_certificate_files] = 501 userprovided; 502 options->certificate_files[options->num_certificate_files++] = 503 xstrdup(path); 504 } 505 506 void 507 add_identity_file(Options *options, const char *dir, const char *filename, 508 int userprovided) 509 { 510 char *path; 511 int i; 512 513 if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES) 514 fatal("Too many identity files specified (max %d)", 515 SSH_MAX_IDENTITY_FILES); 516 517 if (dir == NULL) /* no dir, filename is absolute */ 518 path = xstrdup(filename); 519 else if (xasprintf(&path, "%s%s", dir, filename) >= PATH_MAX) 520 fatal("Identity file path %s too long", path); 521 522 /* Avoid registering duplicates */ 523 for (i = 0; i < options->num_identity_files; i++) { 524 if (options->identity_file_userprovided[i] == userprovided && 525 strcmp(options->identity_files[i], path) == 0) { 526 debug2_f("ignoring duplicate key %s", path); 527 free(path); 528 return; 529 } 530 } 531 532 options->identity_file_userprovided[options->num_identity_files] = 533 userprovided; 534 options->identity_files[options->num_identity_files++] = path; 535 } 536 537 int 538 default_ssh_port(void) 539 { 540 static int port; 541 struct servent *sp; 542 543 if (port == 0) { 544 sp = getservbyname(SSH_SERVICE_NAME, "tcp"); 545 port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT; 546 } 547 return port; 548 } 549 550 /* 551 * Execute a command in a shell. 552 * Return its exit status or -1 on abnormal exit. 553 */ 554 static int 555 execute_in_shell(const char *cmd) 556 { 557 const char *shell; 558 pid_t pid; 559 int status; 560 561 if ((shell = getenv("SHELL")) == NULL) 562 shell = _PATH_BSHELL; 563 564 if (access(shell, X_OK) == -1) { 565 fatal("Shell \"%s\" is not executable: %s", 566 shell, strerror(errno)); 567 } 568 569 debug("Executing command: '%.500s'", cmd); 570 571 /* Fork and execute the command. */ 572 if ((pid = fork()) == 0) { 573 char *argv[4]; 574 575 if (stdfd_devnull(1, 1, 0) == -1) 576 fatal_f("stdfd_devnull failed"); 577 closefrom(STDERR_FILENO + 1); 578 579 argv[0] = __UNCONST(shell); 580 argv[1] = __UNCONST("-c"); 581 argv[2] = xstrdup(cmd); 582 argv[3] = NULL; 583 584 execv(argv[0], argv); 585 error("Unable to execute '%.100s': %s", cmd, strerror(errno)); 586 /* Die with signal to make this error apparent to parent. */ 587 ssh_signal(SIGTERM, SIG_DFL); 588 kill(getpid(), SIGTERM); 589 _exit(1); 590 } 591 /* Parent. */ 592 if (pid == -1) 593 fatal_f("fork: %.100s", strerror(errno)); 594 595 while (waitpid(pid, &status, 0) == -1) { 596 if (errno != EINTR && errno != EAGAIN) 597 fatal_f("waitpid: %s", strerror(errno)); 598 } 599 if (!WIFEXITED(status)) { 600 error("command '%.100s' exited abnormally", cmd); 601 return -1; 602 } 603 debug3("command returned status %d", WEXITSTATUS(status)); 604 return WEXITSTATUS(status); 605 } 606 607 /* 608 * Parse and execute a Match directive. 609 */ 610 static int 611 match_cfg_line(Options *options, char **condition, struct passwd *pw, 612 const char *host_arg, const char *original_host, int final_pass, 613 int *want_final_pass, const char *filename, int linenum) 614 { 615 char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria; 616 const char *ruser; 617 int r, port, this_result, result = 1, attributes = 0, negate; 618 char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; 619 char uidstr[32]; 620 621 /* 622 * Configuration is likely to be incomplete at this point so we 623 * must be prepared to use default values. 624 */ 625 port = options->port <= 0 ? default_ssh_port() : options->port; 626 ruser = options->user == NULL ? pw->pw_name : options->user; 627 if (final_pass) { 628 host = xstrdup(options->hostname); 629 } else if (options->hostname != NULL) { 630 /* NB. Please keep in sync with ssh.c:main() */ 631 host = percent_expand(options->hostname, 632 "h", host_arg, (char *)NULL); 633 } else { 634 host = xstrdup(host_arg); 635 } 636 637 debug2("checking match for '%s' host %s originally %s", 638 cp, host, original_host); 639 while ((oattrib = attrib = strdelim(&cp)) && *attrib != '\0') { 640 criteria = NULL; 641 this_result = 1; 642 if ((negate = attrib[0] == '!')) 643 attrib++; 644 /* criteria "all" and "canonical" have no argument */ 645 if (strcasecmp(attrib, "all") == 0) { 646 if (attributes > 1 || 647 ((arg = strdelim(&cp)) != NULL && *arg != '\0')) { 648 error("%.200s line %d: '%s' cannot be combined " 649 "with other Match attributes", 650 filename, linenum, oattrib); 651 result = -1; 652 goto out; 653 } 654 if (result) 655 result = negate ? 0 : 1; 656 goto out; 657 } 658 attributes++; 659 if (strcasecmp(attrib, "canonical") == 0 || 660 strcasecmp(attrib, "final") == 0) { 661 /* 662 * If the config requests "Match final" then remember 663 * this so we can perform a second pass later. 664 */ 665 if (strcasecmp(attrib, "final") == 0 && 666 want_final_pass != NULL) 667 *want_final_pass = 1; 668 r = !!final_pass; /* force bitmask member to boolean */ 669 if (r == (negate ? 1 : 0)) 670 this_result = result = 0; 671 debug3("%.200s line %d: %smatched '%s'", 672 filename, linenum, 673 this_result ? "" : "not ", oattrib); 674 continue; 675 } 676 /* All other criteria require an argument */ 677 if ((arg = strdelim(&cp)) == NULL || *arg == '\0') { 678 error("Missing Match criteria for %s", attrib); 679 result = -1; 680 goto out; 681 } 682 if (strcasecmp(attrib, "host") == 0) { 683 criteria = xstrdup(host); 684 r = match_hostname(host, arg) == 1; 685 if (r == (negate ? 1 : 0)) 686 this_result = result = 0; 687 } else if (strcasecmp(attrib, "originalhost") == 0) { 688 criteria = xstrdup(original_host); 689 r = match_hostname(original_host, arg) == 1; 690 if (r == (negate ? 1 : 0)) 691 this_result = result = 0; 692 } else if (strcasecmp(attrib, "user") == 0) { 693 criteria = xstrdup(ruser); 694 r = match_pattern_list(ruser, arg, 0) == 1; 695 if (r == (negate ? 1 : 0)) 696 this_result = result = 0; 697 } else if (strcasecmp(attrib, "localuser") == 0) { 698 criteria = xstrdup(pw->pw_name); 699 r = match_pattern_list(pw->pw_name, arg, 0) == 1; 700 if (r == (negate ? 1 : 0)) 701 this_result = result = 0; 702 } else if (strcasecmp(attrib, "exec") == 0) { 703 char *conn_hash_hex, *keyalias; 704 705 if (gethostname(thishost, sizeof(thishost)) == -1) 706 fatal("gethostname: %s", strerror(errno)); 707 strlcpy(shorthost, thishost, sizeof(shorthost)); 708 shorthost[strcspn(thishost, ".")] = '\0'; 709 snprintf(portstr, sizeof(portstr), "%d", port); 710 snprintf(uidstr, sizeof(uidstr), "%llu", 711 (unsigned long long)pw->pw_uid); 712 conn_hash_hex = ssh_connection_hash(thishost, host, 713 portstr, ruser); 714 keyalias = options->host_key_alias ? 715 options->host_key_alias : host; 716 717 cmd = percent_expand(arg, 718 "C", conn_hash_hex, 719 "L", shorthost, 720 "d", pw->pw_dir, 721 "h", host, 722 "k", keyalias, 723 "l", thishost, 724 "n", original_host, 725 "p", portstr, 726 "r", ruser, 727 "u", pw->pw_name, 728 "i", uidstr, 729 (char *)NULL); 730 free(conn_hash_hex); 731 if (result != 1) { 732 /* skip execution if prior predicate failed */ 733 debug3("%.200s line %d: skipped exec " 734 "\"%.100s\"", filename, linenum, cmd); 735 free(cmd); 736 continue; 737 } 738 r = execute_in_shell(cmd); 739 if (r == -1) { 740 fatal("%.200s line %d: match exec " 741 "'%.100s' error", filename, 742 linenum, cmd); 743 } 744 criteria = xstrdup(cmd); 745 free(cmd); 746 /* Force exit status to boolean */ 747 r = r == 0; 748 if (r == (negate ? 1 : 0)) 749 this_result = result = 0; 750 } else { 751 error("Unsupported Match attribute %s", attrib); 752 result = -1; 753 goto out; 754 } 755 debug3("%.200s line %d: %smatched '%s \"%.100s\"' ", 756 filename, linenum, this_result ? "": "not ", 757 oattrib, criteria); 758 free(criteria); 759 } 760 if (attributes == 0) { 761 error("One or more attributes required for Match"); 762 result = -1; 763 goto out; 764 } 765 out: 766 if (result != -1) 767 debug2("match %sfound", result ? "" : "not "); 768 *condition = cp; 769 free(host); 770 return result; 771 } 772 773 /* Remove environment variable by pattern */ 774 static void 775 rm_env(Options *options, const char *arg, const char *filename, int linenum) 776 { 777 int i, j, onum_send_env = options->num_send_env; 778 char *cp; 779 780 /* Remove an environment variable */ 781 for (i = 0; i < options->num_send_env; ) { 782 cp = xstrdup(options->send_env[i]); 783 if (!match_pattern(cp, arg + 1)) { 784 free(cp); 785 i++; 786 continue; 787 } 788 debug3("%s line %d: removing environment %s", 789 filename, linenum, cp); 790 free(cp); 791 free(options->send_env[i]); 792 options->send_env[i] = NULL; 793 for (j = i; j < options->num_send_env - 1; j++) { 794 options->send_env[j] = options->send_env[j + 1]; 795 options->send_env[j + 1] = NULL; 796 } 797 options->num_send_env--; 798 /* NB. don't increment i */ 799 } 800 if (onum_send_env != options->num_send_env) { 801 options->send_env = xrecallocarray(options->send_env, 802 onum_send_env, options->num_send_env, 803 sizeof(*options->send_env)); 804 } 805 } 806 807 /* 808 * Returns the number of the token pointed to by cp or oBadOption. 809 */ 810 static OpCodes 811 parse_token(const char *cp, const char *filename, int linenum, 812 const char *ignored_unknown) 813 { 814 int i; 815 816 for (i = 0; keywords[i].name; i++) 817 if (strcmp(cp, keywords[i].name) == 0) 818 return keywords[i].opcode; 819 if (ignored_unknown != NULL && 820 match_pattern_list(cp, ignored_unknown, 1) == 1) 821 return oIgnoredUnknownOption; 822 error("%s: line %d: Bad configuration option: %s", 823 filename, linenum, cp); 824 return oBadOption; 825 } 826 827 /* Multistate option parsing */ 828 struct multistate { 829 const char *key; 830 int value; 831 }; 832 static const struct multistate multistate_flag[] = { 833 { "true", 1 }, 834 { "false", 0 }, 835 { "yes", 1 }, 836 { "no", 0 }, 837 { NULL, -1 } 838 }; 839 static const struct multistate multistate_yesnoask[] = { 840 { "true", 1 }, 841 { "false", 0 }, 842 { "yes", 1 }, 843 { "no", 0 }, 844 { "ask", 2 }, 845 { NULL, -1 } 846 }; 847 static const struct multistate multistate_strict_hostkey[] = { 848 { "true", SSH_STRICT_HOSTKEY_YES }, 849 { "false", SSH_STRICT_HOSTKEY_OFF }, 850 { "yes", SSH_STRICT_HOSTKEY_YES }, 851 { "no", SSH_STRICT_HOSTKEY_OFF }, 852 { "ask", SSH_STRICT_HOSTKEY_ASK }, 853 { "off", SSH_STRICT_HOSTKEY_OFF }, 854 { "accept-new", SSH_STRICT_HOSTKEY_NEW }, 855 { NULL, -1 } 856 }; 857 static const struct multistate multistate_yesnoaskconfirm[] = { 858 { "true", 1 }, 859 { "false", 0 }, 860 { "yes", 1 }, 861 { "no", 0 }, 862 { "ask", 2 }, 863 { "confirm", 3 }, 864 { NULL, -1 } 865 }; 866 static const struct multistate multistate_addressfamily[] = { 867 { "inet", AF_INET }, 868 { "inet6", AF_INET6 }, 869 { "any", AF_UNSPEC }, 870 { NULL, -1 } 871 }; 872 static const struct multistate multistate_controlmaster[] = { 873 { "true", SSHCTL_MASTER_YES }, 874 { "yes", SSHCTL_MASTER_YES }, 875 { "false", SSHCTL_MASTER_NO }, 876 { "no", SSHCTL_MASTER_NO }, 877 { "auto", SSHCTL_MASTER_AUTO }, 878 { "ask", SSHCTL_MASTER_ASK }, 879 { "autoask", SSHCTL_MASTER_AUTO_ASK }, 880 { NULL, -1 } 881 }; 882 static const struct multistate multistate_tunnel[] = { 883 { "ethernet", SSH_TUNMODE_ETHERNET }, 884 { "point-to-point", SSH_TUNMODE_POINTOPOINT }, 885 { "true", SSH_TUNMODE_DEFAULT }, 886 { "yes", SSH_TUNMODE_DEFAULT }, 887 { "false", SSH_TUNMODE_NO }, 888 { "no", SSH_TUNMODE_NO }, 889 { NULL, -1 } 890 }; 891 static const struct multistate multistate_requesttty[] = { 892 { "true", REQUEST_TTY_YES }, 893 { "yes", REQUEST_TTY_YES }, 894 { "false", REQUEST_TTY_NO }, 895 { "no", REQUEST_TTY_NO }, 896 { "force", REQUEST_TTY_FORCE }, 897 { "auto", REQUEST_TTY_AUTO }, 898 { NULL, -1 } 899 }; 900 static const struct multistate multistate_canonicalizehostname[] = { 901 { "true", SSH_CANONICALISE_YES }, 902 { "false", SSH_CANONICALISE_NO }, 903 { "yes", SSH_CANONICALISE_YES }, 904 { "no", SSH_CANONICALISE_NO }, 905 { "always", SSH_CANONICALISE_ALWAYS }, 906 { NULL, -1 } 907 }; 908 static const struct multistate multistate_compression[] = { 909 #ifdef WITH_ZLIB 910 { "yes", COMP_ZLIB }, 911 #endif 912 { "no", COMP_NONE }, 913 { NULL, -1 } 914 }; 915 916 static int 917 parse_multistate_value(const char *arg, const char *filename, int linenum, 918 const struct multistate *multistate_ptr) 919 { 920 int i; 921 922 if (!arg || *arg == '\0') { 923 error("%s line %d: missing argument.", filename, linenum); 924 return -1; 925 } 926 for (i = 0; multistate_ptr[i].key != NULL; i++) { 927 if (strcasecmp(arg, multistate_ptr[i].key) == 0) 928 return multistate_ptr[i].value; 929 } 930 return -1; 931 } 932 933 /* 934 * Processes a single option line as used in the configuration files. This 935 * only sets those values that have not already been set. 936 */ 937 int 938 process_config_line(Options *options, struct passwd *pw, const char *host, 939 const char *original_host, char *line, const char *filename, 940 int linenum, int *activep, int flags) 941 { 942 return process_config_line_depth(options, pw, host, original_host, 943 line, filename, linenum, activep, flags, NULL, 0); 944 } 945 946 #define WHITESPACE " \t\r\n" 947 static int 948 process_config_line_depth(Options *options, struct passwd *pw, const char *host, 949 const char *original_host, char *line, const char *filename, 950 int linenum, int *activep, int flags, int *want_final_pass, int depth) 951 { 952 char *s, **charptr, *endofnumber, *keyword, *arg, *arg2, *p, ch; 953 char **cpptr, ***cppptr, fwdarg[256]; 954 u_int i, *uintptr, uvalue, max_entries = 0; 955 int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0; 956 int remotefwd, dynamicfwd; 957 LogLevel *log_level_ptr; 958 SyslogFacility *log_facility_ptr; 959 long long val64; 960 size_t len; 961 struct Forward fwd; 962 const struct multistate *multistate_ptr; 963 struct allowed_cname *cname; 964 glob_t gl; 965 const char *errstr; 966 967 if (activep == NULL) { /* We are processing a command line directive */ 968 cmdline = 1; 969 activep = &cmdline; 970 } 971 972 /* Strip trailing whitespace. Allow \f (form feed) at EOL only */ 973 if ((len = strlen(line)) == 0) 974 return 0; 975 for (len--; len > 0; len--) { 976 if (strchr(WHITESPACE "\f", line[len]) == NULL) 977 break; 978 line[len] = '\0'; 979 } 980 981 s = line; 982 /* Get the keyword. (Each line is supposed to begin with a keyword). */ 983 if ((keyword = strdelim(&s)) == NULL) 984 return 0; 985 /* Ignore leading whitespace. */ 986 if (*keyword == '\0') 987 keyword = strdelim(&s); 988 if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#') 989 return 0; 990 /* Match lowercase keyword */ 991 lowercase(keyword); 992 993 opcode = parse_token(keyword, filename, linenum, 994 options->ignored_unknown); 995 996 switch (opcode) { 997 case oBadOption: 998 /* don't panic, but count bad options */ 999 return -1; 1000 case oIgnore: 1001 return 0; 1002 case oIgnoredUnknownOption: 1003 debug("%s line %d: Ignored unknown option \"%s\"", 1004 filename, linenum, keyword); 1005 return 0; 1006 case oConnectTimeout: 1007 intptr = &options->connection_timeout; 1008 parse_time: 1009 arg = strdelim(&s); 1010 if (!arg || *arg == '\0') { 1011 error("%s line %d: missing time value.", 1012 filename, linenum); 1013 return -1; 1014 } 1015 if (strcmp(arg, "none") == 0) 1016 value = -1; 1017 else if ((value = convtime(arg)) == -1) { 1018 error("%s line %d: invalid time value.", 1019 filename, linenum); 1020 return -1; 1021 } 1022 if (*activep && *intptr == -1) 1023 *intptr = value; 1024 break; 1025 1026 case oForwardAgent: 1027 intptr = &options->forward_agent; 1028 1029 arg = strdelim(&s); 1030 if (!arg || *arg == '\0') { 1031 error("%s line %d: missing argument.", 1032 filename, linenum); 1033 return -1; 1034 } 1035 1036 value = -1; 1037 multistate_ptr = multistate_flag; 1038 for (i = 0; multistate_ptr[i].key != NULL; i++) { 1039 if (strcasecmp(arg, multistate_ptr[i].key) == 0) { 1040 value = multistate_ptr[i].value; 1041 break; 1042 } 1043 } 1044 if (value != -1) { 1045 if (*activep && *intptr == -1) 1046 *intptr = value; 1047 break; 1048 } 1049 /* ForwardAgent wasn't 'yes' or 'no', assume a path */ 1050 if (*activep && *intptr == -1) 1051 *intptr = 1; 1052 1053 charptr = &options->forward_agent_sock_path; 1054 goto parse_agent_path; 1055 1056 case oForwardX11: 1057 intptr = &options->forward_x11; 1058 parse_flag: 1059 multistate_ptr = multistate_flag; 1060 parse_multistate: 1061 arg = strdelim(&s); 1062 if ((value = parse_multistate_value(arg, filename, linenum, 1063 multistate_ptr)) == -1) { 1064 error("%s line %d: unsupported option \"%s\".", 1065 filename, linenum, arg); 1066 return -1; 1067 } 1068 if (*activep && *intptr == -1) 1069 *intptr = value; 1070 break; 1071 1072 case oForwardX11Trusted: 1073 intptr = &options->forward_x11_trusted; 1074 goto parse_flag; 1075 1076 case oForwardX11Timeout: 1077 intptr = &options->forward_x11_timeout; 1078 goto parse_time; 1079 1080 case oGatewayPorts: 1081 intptr = &options->fwd_opts.gateway_ports; 1082 goto parse_flag; 1083 1084 case oExitOnForwardFailure: 1085 intptr = &options->exit_on_forward_failure; 1086 goto parse_flag; 1087 1088 case oPasswordAuthentication: 1089 intptr = &options->password_authentication; 1090 goto parse_flag; 1091 1092 case oKbdInteractiveAuthentication: 1093 intptr = &options->kbd_interactive_authentication; 1094 goto parse_flag; 1095 1096 case oKbdInteractiveDevices: 1097 charptr = &options->kbd_interactive_devices; 1098 goto parse_string; 1099 1100 case oPubkeyAuthentication: 1101 intptr = &options->pubkey_authentication; 1102 goto parse_flag; 1103 1104 case oHostbasedAuthentication: 1105 intptr = &options->hostbased_authentication; 1106 goto parse_flag; 1107 1108 case oChallengeResponseAuthentication: 1109 intptr = &options->challenge_response_authentication; 1110 goto parse_flag; 1111 1112 #if defined(KRB4) || defined(KRB5) 1113 case oKerberosAuthentication: 1114 intptr = &options->kerberos_authentication; 1115 goto parse_flag; 1116 #endif 1117 #if defined(AFS) || defined(KRB5) 1118 case oKerberosTgtPassing: 1119 intptr = &options->kerberos_tgt_passing; 1120 goto parse_flag; 1121 #endif 1122 1123 case oGssAuthentication: 1124 intptr = &options->gss_authentication; 1125 goto parse_flag; 1126 1127 #ifdef AFS 1128 case oAFSTokenPassing: 1129 intptr = &options->afs_token_passing; 1130 goto parse_flag; 1131 #endif 1132 1133 case oGssDelegateCreds: 1134 intptr = &options->gss_deleg_creds; 1135 goto parse_flag; 1136 1137 case oBatchMode: 1138 intptr = &options->batch_mode; 1139 goto parse_flag; 1140 1141 case oCheckHostIP: 1142 intptr = &options->check_host_ip; 1143 goto parse_flag; 1144 1145 case oNoneEnabled: 1146 intptr = &options->none_enabled; 1147 goto parse_flag; 1148 1149 /* we check to see if the command comes from the */ 1150 /* command line or not. If it does then enable it */ 1151 /* otherwise fail. NONE should never be a default configuration */ 1152 case oNoneSwitch: 1153 if(strcmp(filename,"command-line")==0) 1154 { 1155 intptr = &options->none_switch; 1156 goto parse_flag; 1157 } else { 1158 error("NoneSwitch is found in %.200s.\nYou may only use this configuration option from the command line", filename); 1159 error("Continuing..."); 1160 debug("NoneSwitch directive found in %.200s.", filename); 1161 return 0; 1162 } 1163 1164 case oHPNDisabled: 1165 intptr = &options->hpn_disabled; 1166 goto parse_flag; 1167 1168 case oHPNBufferSize: 1169 intptr = &options->hpn_buffer_size; 1170 goto parse_int; 1171 1172 case oTcpRcvBufPoll: 1173 intptr = &options->tcp_rcv_buf_poll; 1174 goto parse_flag; 1175 1176 case oVerifyHostKeyDNS: 1177 intptr = &options->verify_host_key_dns; 1178 multistate_ptr = multistate_yesnoask; 1179 goto parse_multistate; 1180 1181 case oStrictHostKeyChecking: 1182 intptr = &options->strict_host_key_checking; 1183 multistate_ptr = multistate_strict_hostkey; 1184 goto parse_multistate; 1185 1186 case oCompression: 1187 intptr = &options->compression; 1188 multistate_ptr = multistate_compression; 1189 goto parse_multistate; 1190 1191 case oTCPKeepAlive: 1192 intptr = &options->tcp_keep_alive; 1193 goto parse_flag; 1194 1195 case oNoHostAuthenticationForLocalhost: 1196 intptr = &options->no_host_authentication_for_localhost; 1197 goto parse_flag; 1198 1199 case oNumberOfPasswordPrompts: 1200 intptr = &options->number_of_password_prompts; 1201 goto parse_int; 1202 1203 case oRekeyLimit: 1204 arg = strdelim(&s); 1205 if (!arg || *arg == '\0') { 1206 error("%.200s line %d: Missing argument.", filename, 1207 linenum); 1208 return -1; 1209 } 1210 if (strcmp(arg, "default") == 0) { 1211 val64 = 0; 1212 } else { 1213 if (scan_scaled(arg, &val64) == -1) { 1214 error("%.200s line %d: Bad number '%s': %s", 1215 filename, linenum, arg, strerror(errno)); 1216 return -1; 1217 } 1218 if (val64 != 0 && val64 < 16) { 1219 error("%.200s line %d: RekeyLimit too small", 1220 filename, linenum); 1221 return -1; 1222 } 1223 } 1224 if (*activep && options->rekey_limit == -1) 1225 options->rekey_limit = val64; 1226 if (s != NULL) { /* optional rekey interval present */ 1227 if (strcmp(s, "none") == 0) { 1228 (void)strdelim(&s); /* discard */ 1229 break; 1230 } 1231 intptr = &options->rekey_interval; 1232 goto parse_time; 1233 } 1234 break; 1235 1236 case oIdentityFile: 1237 arg = strdelim(&s); 1238 if (!arg || *arg == '\0') { 1239 error("%.200s line %d: Missing argument.", 1240 filename, linenum); 1241 return -1; 1242 } 1243 if (*activep) { 1244 intptr = &options->num_identity_files; 1245 if (*intptr >= SSH_MAX_IDENTITY_FILES) { 1246 error("%.200s line %d: Too many identity files " 1247 "specified (max %d).", filename, linenum, 1248 SSH_MAX_IDENTITY_FILES); 1249 return -1; 1250 } 1251 add_identity_file(options, NULL, 1252 arg, flags & SSHCONF_USERCONF); 1253 } 1254 break; 1255 1256 case oCertificateFile: 1257 arg = strdelim(&s); 1258 if (!arg || *arg == '\0') { 1259 error("%.200s line %d: Missing argument.", 1260 filename, linenum); 1261 return -1; 1262 } 1263 if (*activep) { 1264 intptr = &options->num_certificate_files; 1265 if (*intptr >= SSH_MAX_CERTIFICATE_FILES) { 1266 error("%.200s line %d: Too many certificate " 1267 "files specified (max %d).", 1268 filename, linenum, 1269 SSH_MAX_CERTIFICATE_FILES); 1270 return -1; 1271 } 1272 add_certificate_file(options, arg, 1273 flags & SSHCONF_USERCONF); 1274 } 1275 break; 1276 1277 case oXAuthLocation: 1278 charptr=&options->xauth_location; 1279 goto parse_string; 1280 1281 case oUser: 1282 charptr = &options->user; 1283 parse_string: 1284 arg = strdelim(&s); 1285 if (!arg || *arg == '\0') { 1286 error("%.200s line %d: Missing argument.", 1287 filename, linenum); 1288 return -1; 1289 } 1290 if (*activep && *charptr == NULL) 1291 *charptr = xstrdup(arg); 1292 break; 1293 1294 case oGlobalKnownHostsFile: 1295 cpptr = (char **)&options->system_hostfiles; 1296 uintptr = &options->num_system_hostfiles; 1297 max_entries = SSH_MAX_HOSTS_FILES; 1298 parse_char_array: 1299 if (*activep && *uintptr == 0) { 1300 while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1301 if ((*uintptr) >= max_entries) { 1302 error("%s line %d: too many known " 1303 "hosts files.", filename, linenum); 1304 return -1; 1305 } 1306 cpptr[(*uintptr)++] = xstrdup(arg); 1307 } 1308 } 1309 return 0; 1310 1311 case oUserKnownHostsFile: 1312 cpptr = (char **)&options->user_hostfiles; 1313 uintptr = &options->num_user_hostfiles; 1314 max_entries = SSH_MAX_HOSTS_FILES; 1315 goto parse_char_array; 1316 1317 case oHostname: 1318 charptr = &options->hostname; 1319 goto parse_string; 1320 1321 case oHostKeyAlias: 1322 charptr = &options->host_key_alias; 1323 goto parse_string; 1324 1325 case oPreferredAuthentications: 1326 charptr = &options->preferred_authentications; 1327 goto parse_string; 1328 1329 case oBindAddress: 1330 charptr = &options->bind_address; 1331 goto parse_string; 1332 1333 case oBindInterface: 1334 charptr = &options->bind_interface; 1335 goto parse_string; 1336 1337 case oPKCS11Provider: 1338 charptr = &options->pkcs11_provider; 1339 goto parse_string; 1340 1341 case oSecurityKeyProvider: 1342 charptr = &options->sk_provider; 1343 goto parse_string; 1344 1345 case oKnownHostsCommand: 1346 charptr = &options->known_hosts_command; 1347 goto parse_command; 1348 1349 case oProxyCommand: 1350 charptr = &options->proxy_command; 1351 /* Ignore ProxyCommand if ProxyJump already specified */ 1352 if (options->jump_host != NULL) 1353 charptr = &options->jump_host; /* Skip below */ 1354 parse_command: 1355 if (s == NULL) { 1356 error("%.200s line %d: Missing argument.", 1357 filename, linenum); 1358 return -1; 1359 } 1360 len = strspn(s, WHITESPACE "="); 1361 if (*activep && *charptr == NULL) 1362 *charptr = xstrdup(s + len); 1363 return 0; 1364 1365 case oProxyJump: 1366 if (s == NULL) { 1367 error("%.200s line %d: Missing argument.", 1368 filename, linenum); 1369 return -1; 1370 } 1371 len = strspn(s, WHITESPACE "="); 1372 if (parse_jump(s + len, options, *activep) == -1) { 1373 error("%.200s line %d: Invalid ProxyJump \"%s\"", 1374 filename, linenum, s + len); 1375 return -1; 1376 } 1377 return 0; 1378 1379 case oPort: 1380 arg = strdelim(&s); 1381 if (!arg || *arg == '\0') { 1382 error("%.200s line %d: Missing argument.", 1383 filename, linenum); 1384 return -1; 1385 } 1386 value = a2port(arg); 1387 if (value <= 0) { 1388 error("%.200s line %d: Bad port '%s'.", 1389 filename, linenum, arg); 1390 return -1; 1391 } 1392 if (*activep && options->port == -1) 1393 options->port = value; 1394 break; 1395 1396 case oConnectionAttempts: 1397 intptr = &options->connection_attempts; 1398 parse_int: 1399 arg = strdelim(&s); 1400 if ((errstr = atoi_err(arg, &value)) != NULL) { 1401 error("%s line %d: integer value %s.", 1402 filename, linenum, errstr); 1403 return -1; 1404 } 1405 if (*activep && *intptr == -1) 1406 *intptr = value; 1407 break; 1408 1409 case oTcpRcvBuf: 1410 intptr = &options->tcp_rcv_buf; 1411 goto parse_int; 1412 1413 case oCiphers: 1414 arg = strdelim(&s); 1415 if (!arg || *arg == '\0') { 1416 error("%.200s line %d: Missing argument.", 1417 filename, linenum); 1418 return -1; 1419 } 1420 if (*arg != '-' && 1421 !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)){ 1422 error("%.200s line %d: Bad SSH2 cipher spec '%s'.", 1423 filename, linenum, arg ? arg : "<NONE>"); 1424 return -1; 1425 } 1426 if (*activep && options->ciphers == NULL) 1427 options->ciphers = xstrdup(arg); 1428 break; 1429 1430 case oMacs: 1431 arg = strdelim(&s); 1432 if (!arg || *arg == '\0') { 1433 error("%.200s line %d: Missing argument.", 1434 filename, linenum); 1435 return -1; 1436 } 1437 if (*arg != '-' && 1438 !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) { 1439 error("%.200s line %d: Bad SSH2 MAC spec '%s'.", 1440 filename, linenum, arg ? arg : "<NONE>"); 1441 return -1; 1442 } 1443 if (*activep && options->macs == NULL) 1444 options->macs = xstrdup(arg); 1445 break; 1446 1447 case oKexAlgorithms: 1448 arg = strdelim(&s); 1449 if (!arg || *arg == '\0') { 1450 error("%.200s line %d: Missing argument.", 1451 filename, linenum); 1452 return -1; 1453 } 1454 if (*arg != '-' && 1455 !kex_names_valid(*arg == '+' || *arg == '^' ? 1456 arg + 1 : arg)) { 1457 error("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.", 1458 filename, linenum, arg ? arg : "<NONE>"); 1459 return -1; 1460 } 1461 if (*activep && options->kex_algorithms == NULL) 1462 options->kex_algorithms = xstrdup(arg); 1463 break; 1464 1465 case oHostKeyAlgorithms: 1466 charptr = &options->hostkeyalgorithms; 1467 parse_pubkey_algos: 1468 arg = strdelim(&s); 1469 if (!arg || *arg == '\0') { 1470 error("%.200s line %d: Missing argument.", 1471 filename, linenum); 1472 return -1; 1473 } 1474 if (*arg != '-' && 1475 !sshkey_names_valid2(*arg == '+' || *arg == '^' ? 1476 arg + 1 : arg, 1)) { 1477 error("%s line %d: Bad key types '%s'.", 1478 filename, linenum, arg ? arg : "<NONE>"); 1479 return -1; 1480 } 1481 if (*activep && *charptr == NULL) 1482 *charptr = xstrdup(arg); 1483 break; 1484 1485 case oCASignatureAlgorithms: 1486 charptr = &options->ca_sign_algorithms; 1487 goto parse_pubkey_algos; 1488 1489 case oLogLevel: 1490 log_level_ptr = &options->log_level; 1491 arg = strdelim(&s); 1492 value = log_level_number(arg); 1493 if (value == SYSLOG_LEVEL_NOT_SET) { 1494 error("%.200s line %d: unsupported log level '%s'", 1495 filename, linenum, arg ? arg : "<NONE>"); 1496 return -1; 1497 } 1498 if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET) 1499 *log_level_ptr = (LogLevel) value; 1500 break; 1501 1502 case oLogFacility: 1503 log_facility_ptr = &options->log_facility; 1504 arg = strdelim(&s); 1505 value = log_facility_number(arg); 1506 if (value == SYSLOG_FACILITY_NOT_SET) { 1507 error("%.200s line %d: unsupported log facility '%s'", 1508 filename, linenum, arg ? arg : "<NONE>"); 1509 return -1; 1510 } 1511 if (*log_facility_ptr == -1) 1512 *log_facility_ptr = (SyslogFacility) value; 1513 break; 1514 1515 case oLogVerbose: 1516 cppptr = &options->log_verbose; 1517 uintptr = &options->num_log_verbose; 1518 if (*activep && *uintptr == 0) { 1519 while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1520 *cppptr = xrecallocarray(*cppptr, *uintptr, 1521 *uintptr + 1, sizeof(**cppptr)); 1522 (*cppptr)[(*uintptr)++] = xstrdup(arg); 1523 } 1524 } 1525 return 0; 1526 1527 case oLocalForward: 1528 case oRemoteForward: 1529 case oDynamicForward: 1530 arg = strdelim(&s); 1531 if (!arg || *arg == '\0') { 1532 error("%.200s line %d: Missing argument.", 1533 filename, linenum); 1534 return -1; 1535 } 1536 1537 remotefwd = (opcode == oRemoteForward); 1538 dynamicfwd = (opcode == oDynamicForward); 1539 1540 if (!dynamicfwd) { 1541 arg2 = strdelim(&s); 1542 if (arg2 == NULL || *arg2 == '\0') { 1543 if (remotefwd) 1544 dynamicfwd = 1; 1545 else { 1546 error("%.200s line %d: Missing target " 1547 "argument.", filename, linenum); 1548 return -1; 1549 } 1550 } else { 1551 /* construct a string for parse_forward */ 1552 snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, 1553 arg2); 1554 } 1555 } 1556 if (dynamicfwd) 1557 strlcpy(fwdarg, arg, sizeof(fwdarg)); 1558 1559 if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0) { 1560 error("%.200s line %d: Bad forwarding specification.", 1561 filename, linenum); 1562 return -1; 1563 } 1564 1565 if (*activep) { 1566 if (remotefwd) { 1567 add_remote_forward(options, &fwd); 1568 } else { 1569 add_local_forward(options, &fwd); 1570 } 1571 } 1572 break; 1573 1574 case oPermitRemoteOpen: 1575 uintptr = &options->num_permitted_remote_opens; 1576 cppptr = &options->permitted_remote_opens; 1577 arg = strdelim(&s); 1578 if (!arg || *arg == '\0') 1579 fatal("%s line %d: missing %s specification", 1580 filename, linenum, lookup_opcode_name(opcode)); 1581 uvalue = *uintptr; /* modified later */ 1582 if (strcmp(arg, "any") == 0 || strcmp(arg, "none") == 0) { 1583 if (*activep && uvalue == 0) { 1584 *uintptr = 1; 1585 *cppptr = xcalloc(1, sizeof(**cppptr)); 1586 (*cppptr)[0] = xstrdup(arg); 1587 } 1588 break; 1589 } 1590 for (; arg != NULL && *arg != '\0'; arg = strdelim(&s)) { 1591 arg2 = xstrdup(arg); 1592 ch = '\0'; 1593 p = hpdelim2(&arg, &ch); 1594 if (p == NULL || ch == '/') { 1595 fatal("%s line %d: missing host in %s", 1596 filename, linenum, 1597 lookup_opcode_name(opcode)); 1598 } 1599 p = cleanhostname(p); 1600 /* 1601 * don't want to use permitopen_port to avoid 1602 * dependency on channels.[ch] here. 1603 */ 1604 if (arg == NULL || 1605 (strcmp(arg, "*") != 0 && a2port(arg) <= 0)) { 1606 fatal("%s line %d: bad port number in %s", 1607 filename, linenum, 1608 lookup_opcode_name(opcode)); 1609 } 1610 if (*activep && uvalue == 0) { 1611 opt_array_append(filename, linenum, 1612 lookup_opcode_name(opcode), 1613 cppptr, uintptr, arg2); 1614 } 1615 free(arg2); 1616 } 1617 break; 1618 1619 case oClearAllForwardings: 1620 intptr = &options->clear_forwardings; 1621 goto parse_flag; 1622 1623 case oHost: 1624 if (cmdline) { 1625 error("Host directive not supported as a command-line " 1626 "option"); 1627 return -1; 1628 } 1629 *activep = 0; 1630 arg2 = NULL; 1631 while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1632 if ((flags & SSHCONF_NEVERMATCH) != 0) 1633 break; 1634 negated = *arg == '!'; 1635 if (negated) 1636 arg++; 1637 if (match_pattern(host, arg)) { 1638 if (negated) { 1639 debug("%.200s line %d: Skipping Host " 1640 "block because of negated match " 1641 "for %.100s", filename, linenum, 1642 arg); 1643 *activep = 0; 1644 break; 1645 } 1646 if (!*activep) 1647 arg2 = arg; /* logged below */ 1648 *activep = 1; 1649 } 1650 } 1651 if (*activep) 1652 debug("%.200s line %d: Applying options for %.100s", 1653 filename, linenum, arg2); 1654 /* Avoid garbage check below, as strdelim is done. */ 1655 return 0; 1656 1657 case oMatch: 1658 if (cmdline) { 1659 error("Host directive not supported as a command-line " 1660 "option"); 1661 return -1; 1662 } 1663 value = match_cfg_line(options, &s, pw, host, original_host, 1664 flags & SSHCONF_FINAL, want_final_pass, 1665 filename, linenum); 1666 if (value < 0) { 1667 error("%.200s line %d: Bad Match condition", filename, 1668 linenum); 1669 return -1; 1670 } 1671 *activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value; 1672 break; 1673 1674 case oEscapeChar: 1675 intptr = &options->escape_char; 1676 arg = strdelim(&s); 1677 if (!arg || *arg == '\0') { 1678 error("%.200s line %d: Missing argument.", 1679 filename, linenum); 1680 return -1; 1681 } 1682 if (strcmp(arg, "none") == 0) 1683 value = SSH_ESCAPECHAR_NONE; 1684 else if (arg[1] == '\0') 1685 value = (u_char) arg[0]; 1686 else if (arg[0] == '^' && arg[2] == 0 && 1687 (u_char) arg[1] >= 64 && (u_char) arg[1] < 128) 1688 value = (u_char) arg[1] & 31; 1689 else { 1690 error("%.200s line %d: Bad escape character.", 1691 filename, linenum); 1692 return -1; 1693 } 1694 if (*activep && *intptr == -1) 1695 *intptr = value; 1696 break; 1697 1698 case oAddressFamily: 1699 intptr = &options->address_family; 1700 multistate_ptr = multistate_addressfamily; 1701 goto parse_multistate; 1702 1703 case oEnableSSHKeysign: 1704 intptr = &options->enable_ssh_keysign; 1705 goto parse_flag; 1706 1707 case oIdentitiesOnly: 1708 intptr = &options->identities_only; 1709 goto parse_flag; 1710 1711 case oServerAliveInterval: 1712 intptr = &options->server_alive_interval; 1713 goto parse_time; 1714 1715 case oServerAliveCountMax: 1716 intptr = &options->server_alive_count_max; 1717 goto parse_int; 1718 1719 case oSendEnv: 1720 while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1721 if (strchr(arg, '=') != NULL) { 1722 error("%s line %d: Invalid environment name.", 1723 filename, linenum); 1724 return -1; 1725 } 1726 if (!*activep) 1727 continue; 1728 if (*arg == '-') { 1729 /* Removing an env var */ 1730 rm_env(options, arg, filename, linenum); 1731 continue; 1732 } else { 1733 /* Adding an env var */ 1734 if (options->num_send_env >= INT_MAX) { 1735 error("%s line %d: too many send env.", 1736 filename, linenum); 1737 return -1; 1738 } 1739 options->send_env = xrecallocarray( 1740 options->send_env, options->num_send_env, 1741 options->num_send_env + 1, 1742 sizeof(*options->send_env)); 1743 options->send_env[options->num_send_env++] = 1744 xstrdup(arg); 1745 } 1746 } 1747 break; 1748 1749 case oSetEnv: 1750 value = options->num_setenv; 1751 while ((arg = strdelimw(&s)) != NULL && *arg != '\0') { 1752 if (strchr(arg, '=') == NULL) { 1753 error("%s line %d: Invalid SetEnv.", 1754 filename, linenum); 1755 return -1; 1756 } 1757 if (!*activep || value != 0) 1758 continue; 1759 /* Adding a setenv var */ 1760 if (options->num_setenv >= INT_MAX) { 1761 error("%s line %d: too many SetEnv.", 1762 filename, linenum); 1763 return -1; 1764 } 1765 options->setenv = xrecallocarray( 1766 options->setenv, options->num_setenv, 1767 options->num_setenv + 1, sizeof(*options->setenv)); 1768 options->setenv[options->num_setenv++] = xstrdup(arg); 1769 } 1770 break; 1771 1772 case oControlPath: 1773 charptr = &options->control_path; 1774 goto parse_string; 1775 1776 case oControlMaster: 1777 intptr = &options->control_master; 1778 multistate_ptr = multistate_controlmaster; 1779 goto parse_multistate; 1780 1781 case oControlPersist: 1782 /* no/false/yes/true, or a time spec */ 1783 intptr = &options->control_persist; 1784 arg = strdelim(&s); 1785 if (!arg || *arg == '\0') { 1786 error("%.200s line %d: Missing ControlPersist" 1787 " argument.", filename, linenum); 1788 return -1; 1789 } 1790 value = 0; 1791 value2 = 0; /* timeout */ 1792 if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 1793 value = 0; 1794 else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 1795 value = 1; 1796 else if ((value2 = convtime(arg)) >= 0) 1797 value = 1; 1798 else { 1799 error("%.200s line %d: Bad ControlPersist argument.", 1800 filename, linenum); 1801 return -1; 1802 } 1803 if (*activep && *intptr == -1) { 1804 *intptr = value; 1805 options->control_persist_timeout = value2; 1806 } 1807 break; 1808 1809 case oHashKnownHosts: 1810 intptr = &options->hash_known_hosts; 1811 goto parse_flag; 1812 1813 case oTunnel: 1814 intptr = &options->tun_open; 1815 multistate_ptr = multistate_tunnel; 1816 goto parse_multistate; 1817 1818 case oTunnelDevice: 1819 arg = strdelim(&s); 1820 if (!arg || *arg == '\0') { 1821 error("%.200s line %d: Missing argument.", 1822 filename, linenum); 1823 return -1; 1824 } 1825 value = a2tun(arg, &value2); 1826 if (value == SSH_TUNID_ERR) { 1827 error("%.200s line %d: Bad tun device.", 1828 filename, linenum); 1829 return -1; 1830 } 1831 if (*activep) { 1832 options->tun_local = value; 1833 options->tun_remote = value2; 1834 } 1835 break; 1836 1837 case oLocalCommand: 1838 charptr = &options->local_command; 1839 goto parse_command; 1840 1841 case oPermitLocalCommand: 1842 intptr = &options->permit_local_command; 1843 goto parse_flag; 1844 1845 case oRemoteCommand: 1846 charptr = &options->remote_command; 1847 goto parse_command; 1848 1849 case oVisualHostKey: 1850 intptr = &options->visual_host_key; 1851 goto parse_flag; 1852 1853 case oInclude: 1854 if (cmdline) { 1855 error("Include directive not supported as a " 1856 "command-line option"); 1857 return -1; 1858 } 1859 value = 0; 1860 while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1861 /* 1862 * Ensure all paths are anchored. User configuration 1863 * files may begin with '~/' but system configurations 1864 * must not. If the path is relative, then treat it 1865 * as living in ~/.ssh for user configurations or 1866 * /etc/ssh for system ones. 1867 */ 1868 if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0) { 1869 error("%.200s line %d: bad include path %s.", 1870 filename, linenum, arg); 1871 return -1; 1872 } 1873 if (!path_absolute(arg) && *arg != '~') { 1874 xasprintf(&arg2, "%s/%s", 1875 (flags & SSHCONF_USERCONF) ? 1876 "~/" _PATH_SSH_USER_DIR : SSHDIR, arg); 1877 } else 1878 arg2 = xstrdup(arg); 1879 memset(&gl, 0, sizeof(gl)); 1880 r = glob(arg2, GLOB_TILDE | GLOB_LIMIT, NULL, &gl); 1881 if (r == GLOB_NOMATCH) { 1882 debug("%.200s line %d: include %s matched no " 1883 "files",filename, linenum, arg2); 1884 free(arg2); 1885 continue; 1886 } else if (r != 0) { 1887 error("%.200s line %d: glob failed for %s.", 1888 filename, linenum, arg2); 1889 return -1; 1890 } 1891 free(arg2); 1892 oactive = *activep; 1893 for (i = 0; i < gl.gl_pathc; i++) { 1894 debug3("%.200s line %d: Including file %s " 1895 "depth %d%s", filename, linenum, 1896 gl.gl_pathv[i], depth, 1897 oactive ? "" : " (parse only)"); 1898 r = read_config_file_depth(gl.gl_pathv[i], 1899 pw, host, original_host, options, 1900 flags | SSHCONF_CHECKPERM | 1901 (oactive ? 0 : SSHCONF_NEVERMATCH), 1902 activep, want_final_pass, depth + 1); 1903 if (r != 1 && errno != ENOENT) { 1904 error("Can't open user config file " 1905 "%.100s: %.100s", gl.gl_pathv[i], 1906 strerror(errno)); 1907 globfree(&gl); 1908 return -1; 1909 } 1910 /* 1911 * don't let Match in includes clobber the 1912 * containing file's Match state. 1913 */ 1914 *activep = oactive; 1915 if (r != 1) 1916 value = -1; 1917 } 1918 globfree(&gl); 1919 } 1920 if (value != 0) 1921 return value; 1922 break; 1923 1924 case oIPQoS: 1925 arg = strdelim(&s); 1926 if ((value = parse_ipqos(arg)) == -1) { 1927 error("%s line %d: Bad IPQoS value: %s", 1928 filename, linenum, arg); 1929 return -1; 1930 } 1931 arg = strdelim(&s); 1932 if (arg == NULL) 1933 value2 = value; 1934 else if ((value2 = parse_ipqos(arg)) == -1) { 1935 error("%s line %d: Bad IPQoS value: %s", 1936 filename, linenum, arg); 1937 return -1; 1938 } 1939 if (*activep) { 1940 options->ip_qos_interactive = value; 1941 options->ip_qos_bulk = value2; 1942 } 1943 break; 1944 1945 case oRequestTTY: 1946 intptr = &options->request_tty; 1947 multistate_ptr = multistate_requesttty; 1948 goto parse_multistate; 1949 1950 case oSendVersionFirst: 1951 intptr = &options->send_version_first; 1952 goto parse_flag; 1953 1954 case oIgnoreUnknown: 1955 charptr = &options->ignored_unknown; 1956 goto parse_string; 1957 1958 case oProxyUseFdpass: 1959 intptr = &options->proxy_use_fdpass; 1960 goto parse_flag; 1961 1962 case oCanonicalDomains: 1963 value = options->num_canonical_domains != 0; 1964 while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1965 if (!valid_domain(arg, 1, &errstr)) { 1966 error("%s line %d: %s", filename, linenum, 1967 errstr); 1968 return -1; 1969 } 1970 if (!*activep || value) 1971 continue; 1972 if (options->num_canonical_domains >= 1973 MAX_CANON_DOMAINS) { 1974 error("%s line %d: too many hostname suffixes.", 1975 filename, linenum); 1976 return -1; 1977 } 1978 options->canonical_domains[ 1979 options->num_canonical_domains++] = xstrdup(arg); 1980 } 1981 break; 1982 1983 case oCanonicalizePermittedCNAMEs: 1984 value = options->num_permitted_cnames != 0; 1985 while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1986 /* Either '*' for everything or 'list:list' */ 1987 if (strcmp(arg, "*") == 0) 1988 arg2 = arg; 1989 else { 1990 lowercase(arg); 1991 if ((arg2 = strchr(arg, ':')) == NULL || 1992 arg2[1] == '\0') { 1993 error("%s line %d: " 1994 "Invalid permitted CNAME \"%s\"", 1995 filename, linenum, arg); 1996 return -1; 1997 } 1998 *arg2 = '\0'; 1999 arg2++; 2000 } 2001 if (!*activep || value) 2002 continue; 2003 if (options->num_permitted_cnames >= 2004 MAX_CANON_DOMAINS) { 2005 error("%s line %d: too many permitted CNAMEs.", 2006 filename, linenum); 2007 return -1; 2008 } 2009 cname = options->permitted_cnames + 2010 options->num_permitted_cnames++; 2011 cname->source_list = xstrdup(arg); 2012 cname->target_list = xstrdup(arg2); 2013 } 2014 break; 2015 2016 case oCanonicalizeHostname: 2017 intptr = &options->canonicalize_hostname; 2018 multistate_ptr = multistate_canonicalizehostname; 2019 goto parse_multistate; 2020 2021 case oCanonicalizeMaxDots: 2022 intptr = &options->canonicalize_max_dots; 2023 goto parse_int; 2024 2025 case oCanonicalizeFallbackLocal: 2026 intptr = &options->canonicalize_fallback_local; 2027 goto parse_flag; 2028 2029 case oStreamLocalBindMask: 2030 arg = strdelim(&s); 2031 if (!arg || *arg == '\0') { 2032 error("%.200s line %d: Missing StreamLocalBindMask " 2033 "argument.", filename, linenum); 2034 return -1; 2035 } 2036 /* Parse mode in octal format */ 2037 value = strtol(arg, &endofnumber, 8); 2038 if (arg == endofnumber || value < 0 || value > 0777) { 2039 error("%.200s line %d: Bad mask.", filename, linenum); 2040 return -1; 2041 } 2042 options->fwd_opts.streamlocal_bind_mask = (mode_t)value; 2043 break; 2044 2045 case oStreamLocalBindUnlink: 2046 intptr = &options->fwd_opts.streamlocal_bind_unlink; 2047 goto parse_flag; 2048 2049 case oRevokedHostKeys: 2050 charptr = &options->revoked_host_keys; 2051 goto parse_string; 2052 2053 case oFingerprintHash: 2054 intptr = &options->fingerprint_hash; 2055 arg = strdelim(&s); 2056 if (!arg || *arg == '\0') { 2057 error("%.200s line %d: Missing argument.", 2058 filename, linenum); 2059 return -1; 2060 } 2061 if ((value = ssh_digest_alg_by_name(arg)) == -1) { 2062 error("%.200s line %d: Invalid hash algorithm \"%s\".", 2063 filename, linenum, arg); 2064 return -1; 2065 } 2066 if (*activep && *intptr == -1) 2067 *intptr = value; 2068 break; 2069 2070 case oUpdateHostkeys: 2071 intptr = &options->update_hostkeys; 2072 multistate_ptr = multistate_yesnoask; 2073 goto parse_multistate; 2074 2075 case oHostbasedAcceptedAlgorithms: 2076 charptr = &options->hostbased_accepted_algos; 2077 goto parse_pubkey_algos; 2078 2079 case oPubkeyAcceptedAlgorithms: 2080 charptr = &options->pubkey_accepted_algos; 2081 goto parse_pubkey_algos; 2082 2083 case oAddKeysToAgent: 2084 arg = strdelim(&s); 2085 arg2 = strdelim(&s); 2086 value = parse_multistate_value(arg, filename, linenum, 2087 multistate_yesnoaskconfirm); 2088 value2 = 0; /* unlimited lifespan by default */ 2089 if (value == 3 && arg2 != NULL) { 2090 /* allow "AddKeysToAgent confirm 5m" */ 2091 if ((value2 = convtime(arg2)) == -1 || 2092 value2 > INT_MAX) { 2093 error("%s line %d: invalid time value.", 2094 filename, linenum); 2095 return -1; 2096 } 2097 } else if (value == -1 && arg2 == NULL) { 2098 if ((value2 = convtime(arg)) == -1 || 2099 value2 > INT_MAX) { 2100 error("%s line %d: unsupported option", 2101 filename, linenum); 2102 return -1; 2103 } 2104 value = 1; /* yes */ 2105 } else if (value == -1 || arg2 != NULL) { 2106 error("%s line %d: unsupported option", 2107 filename, linenum); 2108 return -1; 2109 } 2110 if (*activep && options->add_keys_to_agent == -1) { 2111 options->add_keys_to_agent = value; 2112 options->add_keys_to_agent_lifespan = value2; 2113 } 2114 break; 2115 2116 case oIdentityAgent: 2117 charptr = &options->identity_agent; 2118 arg = strdelim(&s); 2119 if (!arg || *arg == '\0') { 2120 error("%.200s line %d: Missing argument.", 2121 filename, linenum); 2122 return -1; 2123 } 2124 parse_agent_path: 2125 /* Extra validation if the string represents an env var. */ 2126 if ((arg2 = dollar_expand(&r, arg)) == NULL || r) { 2127 error("%.200s line %d: Invalid environment expansion " 2128 "%s.", filename, linenum, arg); 2129 return -1; 2130 } 2131 free(arg2); 2132 /* check for legacy environment format */ 2133 if (arg[0] == '$' && arg[1] != '{' && 2134 !valid_env_name(arg + 1)) { 2135 error("%.200s line %d: Invalid environment name %s.", 2136 filename, linenum, arg); 2137 return -1; 2138 } 2139 if (*activep && *charptr == NULL) 2140 *charptr = xstrdup(arg); 2141 break; 2142 2143 case oDeprecated: 2144 debug("%s line %d: Deprecated option \"%s\"", 2145 filename, linenum, keyword); 2146 return 0; 2147 2148 case oUnsupported: 2149 error("%s line %d: Unsupported option \"%s\"", 2150 filename, linenum, keyword); 2151 return 0; 2152 2153 default: 2154 error("%s line %d: Unimplemented opcode %d", 2155 filename, linenum, opcode); 2156 } 2157 2158 /* Check that there is no garbage at end of line. */ 2159 if ((arg = strdelim(&s)) != NULL && *arg != '\0') { 2160 error("%.200s line %d: garbage at end of line; \"%.200s\".", 2161 filename, linenum, arg); 2162 return -1; 2163 } 2164 return 0; 2165 } 2166 2167 /* 2168 * Reads the config file and modifies the options accordingly. Options 2169 * should already be initialized before this call. This never returns if 2170 * there is an error. If the file does not exist, this returns 0. 2171 */ 2172 int 2173 read_config_file(const char *filename, struct passwd *pw, const char *host, 2174 const char *original_host, Options *options, int flags, 2175 int *want_final_pass) 2176 { 2177 int active = 1; 2178 2179 return read_config_file_depth(filename, pw, host, original_host, 2180 options, flags, &active, want_final_pass, 0); 2181 } 2182 2183 #define READCONF_MAX_DEPTH 16 2184 static int 2185 read_config_file_depth(const char *filename, struct passwd *pw, 2186 const char *host, const char *original_host, Options *options, 2187 int flags, int *activep, int *want_final_pass, int depth) 2188 { 2189 FILE *f; 2190 char *cp, *line = NULL; 2191 size_t linesize = 0; 2192 int linenum; 2193 int bad_options = 0; 2194 2195 if (depth < 0 || depth > READCONF_MAX_DEPTH) 2196 fatal("Too many recursive configuration includes"); 2197 2198 if ((f = fopen(filename, "r")) == NULL) 2199 return 0; 2200 2201 if (flags & SSHCONF_CHECKPERM) { 2202 struct stat sb; 2203 2204 if (fstat(fileno(f), &sb) == -1) 2205 fatal("fstat %s: %s", filename, strerror(errno)); 2206 if (((sb.st_uid != 0 && sb.st_uid != getuid()) || 2207 (sb.st_mode & 022) != 0)) 2208 fatal("Bad owner or permissions on %s", filename); 2209 } 2210 2211 debug("Reading configuration data %.200s", filename); 2212 2213 /* 2214 * Mark that we are now processing the options. This flag is turned 2215 * on/off by Host specifications. 2216 */ 2217 linenum = 0; 2218 while (getline(&line, &linesize, f) != -1) { 2219 /* Update line number counter. */ 2220 linenum++; 2221 /* 2222 * Trim out comments and strip whitespace. 2223 * NB - preserve newlines, they are needed to reproduce 2224 * line numbers later for error messages. 2225 */ 2226 if ((cp = strchr(line, '#')) != NULL) 2227 *cp = '\0'; 2228 if (process_config_line_depth(options, pw, host, original_host, 2229 line, filename, linenum, activep, flags, want_final_pass, 2230 depth) != 0) 2231 bad_options++; 2232 } 2233 free(line); 2234 fclose(f); 2235 if (bad_options > 0) 2236 fatal("%s: terminating, %d bad configuration options", 2237 filename, bad_options); 2238 return 1; 2239 } 2240 2241 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ 2242 int 2243 option_clear_or_none(const char *o) 2244 { 2245 return o == NULL || strcasecmp(o, "none") == 0; 2246 } 2247 2248 /* 2249 * Initializes options to special values that indicate that they have not yet 2250 * been set. Read_config_file will only set options with this value. Options 2251 * are processed in the following order: command line, user config file, 2252 * system config file. Last, fill_default_options is called. 2253 */ 2254 2255 void 2256 initialize_options(Options * options) 2257 { 2258 memset(options, 'X', sizeof(*options)); 2259 options->forward_agent = -1; 2260 options->forward_agent_sock_path = NULL; 2261 options->forward_x11 = -1; 2262 options->forward_x11_trusted = -1; 2263 options->forward_x11_timeout = -1; 2264 options->stdio_forward_host = NULL; 2265 options->stdio_forward_port = 0; 2266 options->clear_forwardings = -1; 2267 options->exit_on_forward_failure = -1; 2268 options->xauth_location = NULL; 2269 options->fwd_opts.gateway_ports = -1; 2270 options->fwd_opts.streamlocal_bind_mask = (mode_t)-1; 2271 options->fwd_opts.streamlocal_bind_unlink = -1; 2272 options->pubkey_authentication = -1; 2273 options->challenge_response_authentication = -1; 2274 #if defined(KRB4) || defined(KRB5) 2275 options->kerberos_authentication = -1; 2276 #endif 2277 #if defined(AFS) || defined(KRB5) 2278 options->kerberos_tgt_passing = -1; 2279 #endif 2280 #ifdef AFS 2281 options->afs_token_passing = -1; 2282 #endif 2283 options->gss_authentication = -1; 2284 options->gss_deleg_creds = -1; 2285 options->password_authentication = -1; 2286 options->kbd_interactive_authentication = -1; 2287 options->kbd_interactive_devices = NULL; 2288 options->hostbased_authentication = -1; 2289 options->batch_mode = -1; 2290 options->check_host_ip = -1; 2291 options->strict_host_key_checking = -1; 2292 options->compression = -1; 2293 options->tcp_keep_alive = -1; 2294 options->port = -1; 2295 options->address_family = -1; 2296 options->connection_attempts = -1; 2297 options->connection_timeout = -1; 2298 options->number_of_password_prompts = -1; 2299 options->ciphers = NULL; 2300 options->macs = NULL; 2301 options->kex_algorithms = NULL; 2302 options->hostkeyalgorithms = NULL; 2303 options->ca_sign_algorithms = NULL; 2304 options->num_identity_files = 0; 2305 memset(options->identity_keys, 0, sizeof(options->identity_keys)); 2306 options->num_certificate_files = 0; 2307 memset(options->certificates, 0, sizeof(options->certificates)); 2308 options->hostname = NULL; 2309 options->host_key_alias = NULL; 2310 options->proxy_command = NULL; 2311 options->jump_user = NULL; 2312 options->jump_host = NULL; 2313 options->jump_port = -1; 2314 options->jump_extra = NULL; 2315 options->user = NULL; 2316 options->escape_char = -1; 2317 options->num_system_hostfiles = 0; 2318 options->num_user_hostfiles = 0; 2319 options->local_forwards = NULL; 2320 options->num_local_forwards = 0; 2321 options->remote_forwards = NULL; 2322 options->num_remote_forwards = 0; 2323 options->permitted_remote_opens = NULL; 2324 options->num_permitted_remote_opens = 0; 2325 options->log_facility = SYSLOG_FACILITY_NOT_SET; 2326 options->log_level = SYSLOG_LEVEL_NOT_SET; 2327 options->num_log_verbose = 0; 2328 options->log_verbose = NULL; 2329 options->preferred_authentications = NULL; 2330 options->bind_address = NULL; 2331 options->bind_interface = NULL; 2332 options->pkcs11_provider = NULL; 2333 options->sk_provider = NULL; 2334 options->enable_ssh_keysign = - 1; 2335 options->no_host_authentication_for_localhost = - 1; 2336 options->identities_only = - 1; 2337 options->rekey_limit = - 1; 2338 options->rekey_interval = -1; 2339 options->verify_host_key_dns = -1; 2340 options->server_alive_interval = -1; 2341 options->server_alive_count_max = -1; 2342 options->send_env = NULL; 2343 options->num_send_env = 0; 2344 options->setenv = NULL; 2345 options->num_setenv = 0; 2346 options->control_path = NULL; 2347 options->control_master = -1; 2348 options->control_persist = -1; 2349 options->control_persist_timeout = 0; 2350 options->hash_known_hosts = -1; 2351 options->tun_open = -1; 2352 options->tun_local = -1; 2353 options->tun_remote = -1; 2354 options->local_command = NULL; 2355 options->permit_local_command = -1; 2356 options->remote_command = NULL; 2357 options->add_keys_to_agent = -1; 2358 options->add_keys_to_agent_lifespan = -1; 2359 options->identity_agent = NULL; 2360 options->visual_host_key = -1; 2361 options->ip_qos_interactive = -1; 2362 options->ip_qos_bulk = -1; 2363 options->request_tty = -1; 2364 options->proxy_use_fdpass = -1; 2365 options->ignored_unknown = NULL; 2366 options->num_canonical_domains = 0; 2367 options->num_permitted_cnames = 0; 2368 options->canonicalize_max_dots = -1; 2369 options->canonicalize_fallback_local = -1; 2370 options->canonicalize_hostname = -1; 2371 options->revoked_host_keys = NULL; 2372 options->fingerprint_hash = -1; 2373 options->update_hostkeys = -1; 2374 options->hostbased_accepted_algos = NULL; 2375 options->pubkey_accepted_algos = NULL; 2376 options->known_hosts_command = NULL; 2377 options->none_switch = -1; 2378 options->none_enabled = -1; 2379 options->hpn_disabled = -1; 2380 options->hpn_buffer_size = -1; 2381 options->tcp_rcv_buf_poll = -1; 2382 options->tcp_rcv_buf = -1; 2383 options->send_version_first = -1; 2384 } 2385 2386 /* 2387 * A petite version of fill_default_options() that just fills the options 2388 * needed for hostname canonicalization to proceed. 2389 */ 2390 void 2391 fill_default_options_for_canonicalization(Options *options) 2392 { 2393 if (options->canonicalize_max_dots == -1) 2394 options->canonicalize_max_dots = 1; 2395 if (options->canonicalize_fallback_local == -1) 2396 options->canonicalize_fallback_local = 1; 2397 if (options->canonicalize_hostname == -1) 2398 options->canonicalize_hostname = SSH_CANONICALISE_NO; 2399 } 2400 2401 /* 2402 * Called after processing other sources of option data, this fills those 2403 * options for which no value has been specified with their default values. 2404 */ 2405 int 2406 fill_default_options(Options * options) 2407 { 2408 char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig; 2409 char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig; 2410 int ret = 0, r; 2411 2412 if (options->forward_agent == -1) 2413 options->forward_agent = 0; 2414 if (options->forward_x11 == -1) 2415 options->forward_x11 = 0; 2416 if (options->forward_x11_trusted == -1) 2417 options->forward_x11_trusted = 0; 2418 if (options->forward_x11_timeout == -1) 2419 options->forward_x11_timeout = 1200; 2420 /* 2421 * stdio forwarding (-W) changes the default for these but we defer 2422 * setting the values so they can be overridden. 2423 */ 2424 if (options->exit_on_forward_failure == -1) 2425 options->exit_on_forward_failure = 2426 options->stdio_forward_host != NULL ? 1 : 0; 2427 if (options->clear_forwardings == -1) 2428 options->clear_forwardings = 2429 options->stdio_forward_host != NULL ? 1 : 0; 2430 if (options->clear_forwardings == 1) 2431 clear_forwardings(options); 2432 2433 if (options->xauth_location == NULL) 2434 options->xauth_location = xstrdup(_PATH_XAUTH); 2435 if (options->fwd_opts.gateway_ports == -1) 2436 options->fwd_opts.gateway_ports = 0; 2437 if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1) 2438 options->fwd_opts.streamlocal_bind_mask = 0177; 2439 if (options->fwd_opts.streamlocal_bind_unlink == -1) 2440 options->fwd_opts.streamlocal_bind_unlink = 0; 2441 if (options->pubkey_authentication == -1) 2442 options->pubkey_authentication = 1; 2443 if (options->challenge_response_authentication == -1) 2444 options->challenge_response_authentication = 1; 2445 #if defined(KRB4) || defined(KRB5) 2446 if (options->kerberos_authentication == -1) 2447 options->kerberos_authentication = 1; 2448 #endif 2449 #if defined(AFS) || defined(KRB5) 2450 if (options->kerberos_tgt_passing == -1) 2451 options->kerberos_tgt_passing = 1; 2452 #endif 2453 #ifdef AFS 2454 if (options->afs_token_passing == -1) 2455 options->afs_token_passing = 1; 2456 #endif 2457 if (options->gss_authentication == -1) 2458 options->gss_authentication = 0; 2459 if (options->gss_deleg_creds == -1) 2460 options->gss_deleg_creds = 0; 2461 if (options->password_authentication == -1) 2462 options->password_authentication = 1; 2463 if (options->kbd_interactive_authentication == -1) 2464 options->kbd_interactive_authentication = 1; 2465 if (options->hostbased_authentication == -1) 2466 options->hostbased_authentication = 0; 2467 if (options->batch_mode == -1) 2468 options->batch_mode = 0; 2469 if (options->check_host_ip == -1) 2470 options->check_host_ip = 0; 2471 if (options->strict_host_key_checking == -1) 2472 options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK; 2473 if (options->compression == -1) 2474 options->compression = 0; 2475 if (options->tcp_keep_alive == -1) 2476 options->tcp_keep_alive = 1; 2477 if (options->port == -1) 2478 options->port = 0; /* Filled in ssh_connect. */ 2479 if (options->address_family == -1) 2480 options->address_family = AF_UNSPEC; 2481 if (options->connection_attempts == -1) 2482 options->connection_attempts = 1; 2483 if (options->number_of_password_prompts == -1) 2484 options->number_of_password_prompts = 3; 2485 /* options->hostkeyalgorithms, default set in myproposals.h */ 2486 if (options->add_keys_to_agent == -1) { 2487 options->add_keys_to_agent = 0; 2488 options->add_keys_to_agent_lifespan = 0; 2489 } 2490 if (options->num_identity_files == 0) { 2491 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0); 2492 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0); 2493 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0); 2494 add_identity_file(options, "~/", 2495 _PATH_SSH_CLIENT_ID_ECDSA_SK, 0); 2496 add_identity_file(options, "~/", 2497 _PATH_SSH_CLIENT_ID_ED25519, 0); 2498 add_identity_file(options, "~/", 2499 _PATH_SSH_CLIENT_ID_ED25519_SK, 0); 2500 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0); 2501 } 2502 if (options->escape_char == -1) 2503 options->escape_char = '~'; 2504 if (options->num_system_hostfiles == 0) { 2505 options->system_hostfiles[options->num_system_hostfiles++] = 2506 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE); 2507 options->system_hostfiles[options->num_system_hostfiles++] = 2508 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2); 2509 } 2510 if (options->update_hostkeys == -1) { 2511 if (options->verify_host_key_dns <= 0 && 2512 (options->num_user_hostfiles == 0 || 2513 (options->num_user_hostfiles == 1 && strcmp(options-> 2514 user_hostfiles[0], _PATH_SSH_USER_HOSTFILE) == 0))) 2515 options->update_hostkeys = SSH_UPDATE_HOSTKEYS_YES; 2516 else 2517 options->update_hostkeys = SSH_UPDATE_HOSTKEYS_NO; 2518 } 2519 if (options->num_user_hostfiles == 0) { 2520 options->user_hostfiles[options->num_user_hostfiles++] = 2521 xstrdup(_PATH_SSH_USER_HOSTFILE); 2522 options->user_hostfiles[options->num_user_hostfiles++] = 2523 xstrdup(_PATH_SSH_USER_HOSTFILE2); 2524 } 2525 if (options->log_level == SYSLOG_LEVEL_NOT_SET) 2526 options->log_level = SYSLOG_LEVEL_INFO; 2527 if (options->log_facility == SYSLOG_FACILITY_NOT_SET) 2528 options->log_facility = SYSLOG_FACILITY_USER; 2529 if (options->no_host_authentication_for_localhost == - 1) 2530 options->no_host_authentication_for_localhost = 0; 2531 if (options->identities_only == -1) 2532 options->identities_only = 0; 2533 if (options->enable_ssh_keysign == -1) 2534 options->enable_ssh_keysign = 0; 2535 if (options->rekey_limit == -1) 2536 options->rekey_limit = 0; 2537 if (options->rekey_interval == -1) 2538 options->rekey_interval = 0; 2539 if (options->verify_host_key_dns == -1) 2540 options->verify_host_key_dns = 0; 2541 if (options->server_alive_interval == -1) 2542 options->server_alive_interval = 0; 2543 if (options->server_alive_count_max == -1) 2544 options->server_alive_count_max = 3; 2545 if (options->none_switch == -1) 2546 options->none_switch = 0; 2547 if (options->hpn_disabled == -1) 2548 options->hpn_disabled = 0; 2549 if (options->hpn_buffer_size > -1) 2550 { 2551 /* if a user tries to set the size to 0 set it to 1KB */ 2552 if (options->hpn_buffer_size == 0) 2553 options->hpn_buffer_size = 1024; 2554 /*limit the buffer to 64MB*/ 2555 if (options->hpn_buffer_size > 65536) 2556 { 2557 options->hpn_buffer_size = 65536*1024; 2558 debug("User requested buffer larger than 64MB. Request reverted to 64MB"); 2559 } 2560 debug("hpn_buffer_size set to %d", options->hpn_buffer_size); 2561 } 2562 if (options->tcp_rcv_buf == 0) 2563 options->tcp_rcv_buf = 1; 2564 if (options->tcp_rcv_buf > -1) 2565 options->tcp_rcv_buf *=1024; 2566 if (options->tcp_rcv_buf_poll == -1) 2567 options->tcp_rcv_buf_poll = 1; 2568 if (options->control_master == -1) 2569 options->control_master = 0; 2570 if (options->control_persist == -1) { 2571 options->control_persist = 0; 2572 options->control_persist_timeout = 0; 2573 } 2574 if (options->hash_known_hosts == -1) 2575 options->hash_known_hosts = 0; 2576 if (options->tun_open == -1) 2577 options->tun_open = SSH_TUNMODE_NO; 2578 if (options->tun_local == -1) 2579 options->tun_local = SSH_TUNID_ANY; 2580 if (options->tun_remote == -1) 2581 options->tun_remote = SSH_TUNID_ANY; 2582 if (options->permit_local_command == -1) 2583 options->permit_local_command = 0; 2584 if (options->visual_host_key == -1) 2585 options->visual_host_key = 0; 2586 if (options->ip_qos_interactive == -1) 2587 options->ip_qos_interactive = IPTOS_DSCP_AF21; 2588 if (options->ip_qos_bulk == -1) 2589 options->ip_qos_bulk = IPTOS_DSCP_CS1; 2590 if (options->request_tty == -1) 2591 options->request_tty = REQUEST_TTY_AUTO; 2592 if (options->proxy_use_fdpass == -1) 2593 options->proxy_use_fdpass = 0; 2594 if (options->canonicalize_max_dots == -1) 2595 options->canonicalize_max_dots = 1; 2596 if (options->canonicalize_fallback_local == -1) 2597 options->canonicalize_fallback_local = 1; 2598 if (options->canonicalize_hostname == -1) 2599 options->canonicalize_hostname = SSH_CANONICALISE_NO; 2600 if (options->fingerprint_hash == -1) 2601 options->fingerprint_hash = SSH_FP_HASH_DEFAULT; 2602 if (options->sk_provider == NULL) 2603 options->sk_provider = xstrdup("internal"); 2604 2605 /* Expand KEX name lists */ 2606 all_cipher = cipher_alg_list(',', 0); 2607 all_mac = mac_alg_list(','); 2608 all_kex = kex_alg_list(','); 2609 all_key = sshkey_alg_list(0, 0, 1, ','); 2610 all_sig = sshkey_alg_list(0, 1, 1, ','); 2611 /* remove unsupported algos from default lists */ 2612 def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher); 2613 def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac); 2614 def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex); 2615 def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key); 2616 def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig); 2617 #define ASSEMBLE(what, defaults, all) \ 2618 do { \ 2619 if ((r = kex_assemble_names(&options->what, \ 2620 defaults, all)) != 0) { \ 2621 error_fr(r, "%s", #what); \ 2622 goto fail; \ 2623 } \ 2624 } while (0) 2625 ASSEMBLE(ciphers, def_cipher, all_cipher); 2626 ASSEMBLE(macs, def_mac, all_mac); 2627 ASSEMBLE(kex_algorithms, def_kex, all_kex); 2628 ASSEMBLE(hostbased_accepted_algos, def_key, all_key); 2629 ASSEMBLE(pubkey_accepted_algos, def_key, all_key); 2630 ASSEMBLE(ca_sign_algorithms, def_sig, all_sig); 2631 #undef ASSEMBLE 2632 2633 if (options->send_version_first == -1) 2634 options->send_version_first = 1; 2635 #define CLEAR_ON_NONE(v) \ 2636 do { \ 2637 if (option_clear_or_none(v)) { \ 2638 free(v); \ 2639 v = NULL; \ 2640 } \ 2641 } while(0) 2642 CLEAR_ON_NONE(options->local_command); 2643 CLEAR_ON_NONE(options->remote_command); 2644 CLEAR_ON_NONE(options->proxy_command); 2645 CLEAR_ON_NONE(options->control_path); 2646 CLEAR_ON_NONE(options->revoked_host_keys); 2647 CLEAR_ON_NONE(options->pkcs11_provider); 2648 CLEAR_ON_NONE(options->sk_provider); 2649 CLEAR_ON_NONE(options->known_hosts_command); 2650 if (options->jump_host != NULL && 2651 strcmp(options->jump_host, "none") == 0 && 2652 options->jump_port == 0 && options->jump_user == NULL) { 2653 free(options->jump_host); 2654 options->jump_host = NULL; 2655 } 2656 /* options->identity_agent distinguishes NULL from 'none' */ 2657 /* options->user will be set in the main program if appropriate */ 2658 /* options->hostname will be set in the main program if appropriate */ 2659 /* options->host_key_alias should not be set by default */ 2660 /* options->preferred_authentications will be set in ssh */ 2661 2662 /* success */ 2663 ret = 0; 2664 fail: 2665 free(all_cipher); 2666 free(all_mac); 2667 free(all_kex); 2668 free(all_key); 2669 free(all_sig); 2670 free(def_cipher); 2671 free(def_mac); 2672 free(def_kex); 2673 free(def_key); 2674 free(def_sig); 2675 return ret; 2676 } 2677 2678 void 2679 free_options(Options *o) 2680 { 2681 int i; 2682 2683 if (o == NULL) 2684 return; 2685 2686 #define FREE_ARRAY(type, n, a) \ 2687 do { \ 2688 type _i; \ 2689 for (_i = 0; _i < (n); _i++) \ 2690 free((a)[_i]); \ 2691 } while (0) 2692 2693 free(o->forward_agent_sock_path); 2694 free(o->xauth_location); 2695 FREE_ARRAY(u_int, o->num_log_verbose, o->log_verbose); 2696 free(o->log_verbose); 2697 free(o->ciphers); 2698 free(o->macs); 2699 free(o->hostkeyalgorithms); 2700 free(o->kex_algorithms); 2701 free(o->ca_sign_algorithms); 2702 free(o->hostname); 2703 free(o->host_key_alias); 2704 free(o->proxy_command); 2705 free(o->user); 2706 FREE_ARRAY(u_int, o->num_system_hostfiles, o->system_hostfiles); 2707 FREE_ARRAY(u_int, o->num_user_hostfiles, o->user_hostfiles); 2708 free(o->preferred_authentications); 2709 free(o->bind_address); 2710 free(o->bind_interface); 2711 free(o->pkcs11_provider); 2712 free(o->sk_provider); 2713 for (i = 0; i < o->num_identity_files; i++) { 2714 free(o->identity_files[i]); 2715 sshkey_free(o->identity_keys[i]); 2716 } 2717 for (i = 0; i < o->num_certificate_files; i++) { 2718 free(o->certificate_files[i]); 2719 sshkey_free(o->certificates[i]); 2720 } 2721 free(o->identity_agent); 2722 for (i = 0; i < o->num_local_forwards; i++) { 2723 free(o->local_forwards[i].listen_host); 2724 free(o->local_forwards[i].listen_path); 2725 free(o->local_forwards[i].connect_host); 2726 free(o->local_forwards[i].connect_path); 2727 } 2728 free(o->local_forwards); 2729 for (i = 0; i < o->num_remote_forwards; i++) { 2730 free(o->remote_forwards[i].listen_host); 2731 free(o->remote_forwards[i].listen_path); 2732 free(o->remote_forwards[i].connect_host); 2733 free(o->remote_forwards[i].connect_path); 2734 } 2735 free(o->remote_forwards); 2736 free(o->stdio_forward_host); 2737 FREE_ARRAY(int, o->num_send_env, o->send_env); 2738 free(o->send_env); 2739 FREE_ARRAY(int, o->num_setenv, o->setenv); 2740 free(o->setenv); 2741 free(o->control_path); 2742 free(o->local_command); 2743 free(o->remote_command); 2744 FREE_ARRAY(int, o->num_canonical_domains, o->canonical_domains); 2745 for (i = 0; i < o->num_permitted_cnames; i++) { 2746 free(o->permitted_cnames[i].source_list); 2747 free(o->permitted_cnames[i].target_list); 2748 } 2749 free(o->revoked_host_keys); 2750 free(o->hostbased_accepted_algos); 2751 free(o->pubkey_accepted_algos); 2752 free(o->jump_user); 2753 free(o->jump_host); 2754 free(o->jump_extra); 2755 free(o->ignored_unknown); 2756 explicit_bzero(o, sizeof(*o)); 2757 #undef FREE_ARRAY 2758 } 2759 2760 struct fwdarg { 2761 char *arg; 2762 int ispath; 2763 }; 2764 2765 /* 2766 * parse_fwd_field 2767 * parses the next field in a port forwarding specification. 2768 * sets fwd to the parsed field and advances p past the colon 2769 * or sets it to NULL at end of string. 2770 * returns 0 on success, else non-zero. 2771 */ 2772 static int 2773 parse_fwd_field(char **p, struct fwdarg *fwd) 2774 { 2775 char *ep, *cp = *p; 2776 int ispath = 0; 2777 2778 if (*cp == '\0') { 2779 *p = NULL; 2780 return -1; /* end of string */ 2781 } 2782 2783 /* 2784 * A field escaped with square brackets is used literally. 2785 * XXX - allow ']' to be escaped via backslash? 2786 */ 2787 if (*cp == '[') { 2788 /* find matching ']' */ 2789 for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) { 2790 if (*ep == '/') 2791 ispath = 1; 2792 } 2793 /* no matching ']' or not at end of field. */ 2794 if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0')) 2795 return -1; 2796 /* NUL terminate the field and advance p past the colon */ 2797 *ep++ = '\0'; 2798 if (*ep != '\0') 2799 *ep++ = '\0'; 2800 fwd->arg = cp + 1; 2801 fwd->ispath = ispath; 2802 *p = ep; 2803 return 0; 2804 } 2805 2806 for (cp = *p; *cp != '\0'; cp++) { 2807 switch (*cp) { 2808 case '\\': 2809 memmove(cp, cp + 1, strlen(cp + 1) + 1); 2810 if (*cp == '\0') 2811 return -1; 2812 break; 2813 case '/': 2814 ispath = 1; 2815 break; 2816 case ':': 2817 *cp++ = '\0'; 2818 goto done; 2819 } 2820 } 2821 done: 2822 fwd->arg = *p; 2823 fwd->ispath = ispath; 2824 *p = cp; 2825 return 0; 2826 } 2827 2828 /* 2829 * parse_forward 2830 * parses a string containing a port forwarding specification of the form: 2831 * dynamicfwd == 0 2832 * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath 2833 * listenpath:connectpath 2834 * dynamicfwd == 1 2835 * [listenhost:]listenport 2836 * returns number of arguments parsed or zero on error 2837 */ 2838 int 2839 parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) 2840 { 2841 struct fwdarg fwdargs[4]; 2842 char *p, *cp; 2843 int i, err; 2844 2845 memset(fwd, 0, sizeof(*fwd)); 2846 memset(fwdargs, 0, sizeof(fwdargs)); 2847 2848 /* 2849 * We expand environment variables before checking if we think they're 2850 * paths so that if ${VAR} expands to a fully qualified path it is 2851 * treated as a path. 2852 */ 2853 cp = p = dollar_expand(&err, fwdspec); 2854 if (p == NULL || err) 2855 return 0; 2856 2857 /* skip leading spaces */ 2858 while (isspace((u_char)*cp)) 2859 cp++; 2860 2861 for (i = 0; i < 4; ++i) { 2862 if (parse_fwd_field(&cp, &fwdargs[i]) != 0) 2863 break; 2864 } 2865 2866 /* Check for trailing garbage */ 2867 if (cp != NULL && *cp != '\0') { 2868 i = 0; /* failure */ 2869 } 2870 2871 switch (i) { 2872 case 1: 2873 if (fwdargs[0].ispath) { 2874 fwd->listen_path = xstrdup(fwdargs[0].arg); 2875 fwd->listen_port = PORT_STREAMLOCAL; 2876 } else { 2877 fwd->listen_host = NULL; 2878 fwd->listen_port = a2port(fwdargs[0].arg); 2879 } 2880 fwd->connect_host = xstrdup("socks"); 2881 break; 2882 2883 case 2: 2884 if (fwdargs[0].ispath && fwdargs[1].ispath) { 2885 fwd->listen_path = xstrdup(fwdargs[0].arg); 2886 fwd->listen_port = PORT_STREAMLOCAL; 2887 fwd->connect_path = xstrdup(fwdargs[1].arg); 2888 fwd->connect_port = PORT_STREAMLOCAL; 2889 } else if (fwdargs[1].ispath) { 2890 fwd->listen_host = NULL; 2891 fwd->listen_port = a2port(fwdargs[0].arg); 2892 fwd->connect_path = xstrdup(fwdargs[1].arg); 2893 fwd->connect_port = PORT_STREAMLOCAL; 2894 } else { 2895 fwd->listen_host = xstrdup(fwdargs[0].arg); 2896 fwd->listen_port = a2port(fwdargs[1].arg); 2897 fwd->connect_host = xstrdup("socks"); 2898 } 2899 break; 2900 2901 case 3: 2902 if (fwdargs[0].ispath) { 2903 fwd->listen_path = xstrdup(fwdargs[0].arg); 2904 fwd->listen_port = PORT_STREAMLOCAL; 2905 fwd->connect_host = xstrdup(fwdargs[1].arg); 2906 fwd->connect_port = a2port(fwdargs[2].arg); 2907 } else if (fwdargs[2].ispath) { 2908 fwd->listen_host = xstrdup(fwdargs[0].arg); 2909 fwd->listen_port = a2port(fwdargs[1].arg); 2910 fwd->connect_path = xstrdup(fwdargs[2].arg); 2911 fwd->connect_port = PORT_STREAMLOCAL; 2912 } else { 2913 fwd->listen_host = NULL; 2914 fwd->listen_port = a2port(fwdargs[0].arg); 2915 fwd->connect_host = xstrdup(fwdargs[1].arg); 2916 fwd->connect_port = a2port(fwdargs[2].arg); 2917 } 2918 break; 2919 2920 case 4: 2921 fwd->listen_host = xstrdup(fwdargs[0].arg); 2922 fwd->listen_port = a2port(fwdargs[1].arg); 2923 fwd->connect_host = xstrdup(fwdargs[2].arg); 2924 fwd->connect_port = a2port(fwdargs[3].arg); 2925 break; 2926 default: 2927 i = 0; /* failure */ 2928 } 2929 2930 free(p); 2931 2932 if (dynamicfwd) { 2933 if (!(i == 1 || i == 2)) 2934 goto fail_free; 2935 } else { 2936 if (!(i == 3 || i == 4)) { 2937 if (fwd->connect_path == NULL && 2938 fwd->listen_path == NULL) 2939 goto fail_free; 2940 } 2941 if (fwd->connect_port <= 0 && fwd->connect_path == NULL) 2942 goto fail_free; 2943 } 2944 2945 if ((fwd->listen_port < 0 && fwd->listen_path == NULL) || 2946 (!remotefwd && fwd->listen_port == 0)) 2947 goto fail_free; 2948 if (fwd->connect_host != NULL && 2949 strlen(fwd->connect_host) >= NI_MAXHOST) 2950 goto fail_free; 2951 /* XXX - if connecting to a remote socket, max sun len may not match this host */ 2952 if (fwd->connect_path != NULL && 2953 strlen(fwd->connect_path) >= PATH_MAX_SUN) 2954 goto fail_free; 2955 if (fwd->listen_host != NULL && 2956 strlen(fwd->listen_host) >= NI_MAXHOST) 2957 goto fail_free; 2958 if (fwd->listen_path != NULL && 2959 strlen(fwd->listen_path) >= PATH_MAX_SUN) 2960 goto fail_free; 2961 2962 return (i); 2963 2964 fail_free: 2965 free(fwd->connect_host); 2966 fwd->connect_host = NULL; 2967 free(fwd->connect_path); 2968 fwd->connect_path = NULL; 2969 free(fwd->listen_host); 2970 fwd->listen_host = NULL; 2971 free(fwd->listen_path); 2972 fwd->listen_path = NULL; 2973 return (0); 2974 } 2975 2976 int 2977 parse_jump(const char *s, Options *o, int active) 2978 { 2979 char *orig, *sdup, *cp; 2980 char *host = NULL, *user = NULL; 2981 int r, ret = -1, port = -1, first; 2982 2983 active &= o->proxy_command == NULL && o->jump_host == NULL; 2984 2985 orig = sdup = xstrdup(s); 2986 first = active; 2987 do { 2988 if (strcasecmp(s, "none") == 0) 2989 break; 2990 if ((cp = strrchr(sdup, ',')) == NULL) 2991 cp = sdup; /* last */ 2992 else 2993 *cp++ = '\0'; 2994 2995 if (first) { 2996 /* First argument and configuration is active */ 2997 r = parse_ssh_uri(cp, &user, &host, &port); 2998 if (r == -1 || (r == 1 && 2999 parse_user_host_port(cp, &user, &host, &port) != 0)) 3000 goto out; 3001 } else { 3002 /* Subsequent argument or inactive configuration */ 3003 r = parse_ssh_uri(cp, NULL, NULL, NULL); 3004 if (r == -1 || (r == 1 && 3005 parse_user_host_port(cp, NULL, NULL, NULL) != 0)) 3006 goto out; 3007 } 3008 first = 0; /* only check syntax for subsequent hosts */ 3009 } while (cp != sdup); 3010 /* success */ 3011 if (active) { 3012 if (strcasecmp(s, "none") == 0) { 3013 o->jump_host = xstrdup("none"); 3014 o->jump_port = 0; 3015 } else { 3016 o->jump_user = user; 3017 o->jump_host = host; 3018 o->jump_port = port; 3019 o->proxy_command = xstrdup("none"); 3020 user = host = NULL; 3021 if ((cp = strrchr(s, ',')) != NULL && cp != s) { 3022 o->jump_extra = xstrdup(s); 3023 o->jump_extra[cp - s] = '\0'; 3024 } 3025 } 3026 } 3027 ret = 0; 3028 out: 3029 free(orig); 3030 free(user); 3031 free(host); 3032 return ret; 3033 } 3034 3035 int 3036 parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp) 3037 { 3038 char *user = NULL, *host = NULL, *path = NULL; 3039 int r, port; 3040 3041 r = parse_uri("ssh", uri, &user, &host, &port, &path); 3042 if (r == 0 && path != NULL) 3043 r = -1; /* path not allowed */ 3044 if (r == 0) { 3045 if (userp != NULL) { 3046 *userp = user; 3047 user = NULL; 3048 } 3049 if (hostp != NULL) { 3050 *hostp = host; 3051 host = NULL; 3052 } 3053 if (portp != NULL) 3054 *portp = port; 3055 } 3056 free(user); 3057 free(host); 3058 free(path); 3059 return r; 3060 } 3061 3062 /* XXX the following is a near-vebatim copy from servconf.c; refactor */ 3063 static const char * 3064 fmt_multistate_int(int val, const struct multistate *m) 3065 { 3066 u_int i; 3067 3068 for (i = 0; m[i].key != NULL; i++) { 3069 if (m[i].value == val) 3070 return m[i].key; 3071 } 3072 return "UNKNOWN"; 3073 } 3074 3075 static const char * 3076 fmt_intarg(OpCodes code, int val) 3077 { 3078 if (val == -1) 3079 return "unset"; 3080 switch (code) { 3081 case oAddressFamily: 3082 return fmt_multistate_int(val, multistate_addressfamily); 3083 case oVerifyHostKeyDNS: 3084 case oUpdateHostkeys: 3085 return fmt_multistate_int(val, multistate_yesnoask); 3086 case oStrictHostKeyChecking: 3087 return fmt_multistate_int(val, multistate_strict_hostkey); 3088 case oControlMaster: 3089 return fmt_multistate_int(val, multistate_controlmaster); 3090 case oTunnel: 3091 return fmt_multistate_int(val, multistate_tunnel); 3092 case oRequestTTY: 3093 return fmt_multistate_int(val, multistate_requesttty); 3094 case oCanonicalizeHostname: 3095 return fmt_multistate_int(val, multistate_canonicalizehostname); 3096 case oAddKeysToAgent: 3097 return fmt_multistate_int(val, multistate_yesnoaskconfirm); 3098 case oFingerprintHash: 3099 return ssh_digest_alg_name(val); 3100 default: 3101 switch (val) { 3102 case 0: 3103 return "no"; 3104 case 1: 3105 return "yes"; 3106 default: 3107 return "UNKNOWN"; 3108 } 3109 } 3110 } 3111 3112 static const char * 3113 lookup_opcode_name(OpCodes code) 3114 { 3115 u_int i; 3116 3117 for (i = 0; keywords[i].name != NULL; i++) 3118 if (keywords[i].opcode == code) 3119 return(keywords[i].name); 3120 return "UNKNOWN"; 3121 } 3122 3123 static void 3124 dump_cfg_int(OpCodes code, int val) 3125 { 3126 printf("%s %d\n", lookup_opcode_name(code), val); 3127 } 3128 3129 static void 3130 dump_cfg_fmtint(OpCodes code, int val) 3131 { 3132 printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val)); 3133 } 3134 3135 static void 3136 dump_cfg_string(OpCodes code, const char *val) 3137 { 3138 if (val == NULL) 3139 return; 3140 printf("%s %s\n", lookup_opcode_name(code), val); 3141 } 3142 3143 static void 3144 dump_cfg_strarray(OpCodes code, u_int count, char **vals) 3145 { 3146 u_int i; 3147 3148 for (i = 0; i < count; i++) 3149 printf("%s %s\n", lookup_opcode_name(code), vals[i]); 3150 } 3151 3152 static void 3153 dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals) 3154 { 3155 u_int i; 3156 3157 printf("%s", lookup_opcode_name(code)); 3158 for (i = 0; i < count; i++) 3159 printf(" %s", vals[i]); 3160 printf("\n"); 3161 } 3162 3163 static void 3164 dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds) 3165 { 3166 const struct Forward *fwd; 3167 u_int i; 3168 3169 /* oDynamicForward */ 3170 for (i = 0; i < count; i++) { 3171 fwd = &fwds[i]; 3172 if (code == oDynamicForward && fwd->connect_host != NULL && 3173 strcmp(fwd->connect_host, "socks") != 0) 3174 continue; 3175 if (code == oLocalForward && fwd->connect_host != NULL && 3176 strcmp(fwd->connect_host, "socks") == 0) 3177 continue; 3178 printf("%s", lookup_opcode_name(code)); 3179 if (fwd->listen_port == PORT_STREAMLOCAL) 3180 printf(" %s", fwd->listen_path); 3181 else if (fwd->listen_host == NULL) 3182 printf(" %d", fwd->listen_port); 3183 else { 3184 printf(" [%s]:%d", 3185 fwd->listen_host, fwd->listen_port); 3186 } 3187 if (code != oDynamicForward) { 3188 if (fwd->connect_port == PORT_STREAMLOCAL) 3189 printf(" %s", fwd->connect_path); 3190 else if (fwd->connect_host == NULL) 3191 printf(" %d", fwd->connect_port); 3192 else { 3193 printf(" [%s]:%d", 3194 fwd->connect_host, fwd->connect_port); 3195 } 3196 } 3197 printf("\n"); 3198 } 3199 } 3200 3201 void 3202 dump_client_config(Options *o, const char *host) 3203 { 3204 int i, r; 3205 char buf[8], *all_key; 3206 3207 /* 3208 * Expand HostKeyAlgorithms name lists. This isn't handled in 3209 * fill_default_options() like the other algorithm lists because 3210 * the host key algorithms are by default dynamically chosen based 3211 * on the host's keys found in known_hosts. 3212 */ 3213 all_key = sshkey_alg_list(0, 0, 1, ','); 3214 if ((r = kex_assemble_names(&o->hostkeyalgorithms, kex_default_pk_alg(), 3215 all_key)) != 0) 3216 fatal_fr(r, "expand HostKeyAlgorithms"); 3217 free(all_key); 3218 3219 /* Most interesting options first: user, host, port */ 3220 dump_cfg_string(oUser, o->user); 3221 dump_cfg_string(oHostname, host); 3222 dump_cfg_int(oPort, o->port); 3223 3224 /* Flag options */ 3225 dump_cfg_fmtint(oAddressFamily, o->address_family); 3226 dump_cfg_fmtint(oBatchMode, o->batch_mode); 3227 dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local); 3228 dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname); 3229 dump_cfg_fmtint(oChallengeResponseAuthentication, o->challenge_response_authentication); 3230 dump_cfg_fmtint(oCheckHostIP, o->check_host_ip); 3231 dump_cfg_fmtint(oCompression, o->compression); 3232 dump_cfg_fmtint(oControlMaster, o->control_master); 3233 dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign); 3234 dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings); 3235 dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure); 3236 dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash); 3237 dump_cfg_fmtint(oForwardX11, o->forward_x11); 3238 dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted); 3239 dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports); 3240 #ifdef GSSAPI 3241 dump_cfg_fmtint(oGssAuthentication, o->gss_authentication); 3242 dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds); 3243 #endif /* GSSAPI */ 3244 dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts); 3245 dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication); 3246 dump_cfg_fmtint(oIdentitiesOnly, o->identities_only); 3247 dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication); 3248 dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost); 3249 dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication); 3250 dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command); 3251 dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass); 3252 dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication); 3253 dump_cfg_fmtint(oRequestTTY, o->request_tty); 3254 dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink); 3255 dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking); 3256 dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive); 3257 dump_cfg_fmtint(oTunnel, o->tun_open); 3258 dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns); 3259 dump_cfg_fmtint(oVisualHostKey, o->visual_host_key); 3260 dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys); 3261 3262 /* Integer options */ 3263 dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots); 3264 dump_cfg_int(oConnectionAttempts, o->connection_attempts); 3265 dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout); 3266 dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts); 3267 dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max); 3268 dump_cfg_int(oServerAliveInterval, o->server_alive_interval); 3269 3270 /* String options */ 3271 dump_cfg_string(oBindAddress, o->bind_address); 3272 dump_cfg_string(oBindInterface, o->bind_interface); 3273 dump_cfg_string(oCiphers, o->ciphers); 3274 dump_cfg_string(oControlPath, o->control_path); 3275 dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms); 3276 dump_cfg_string(oHostKeyAlias, o->host_key_alias); 3277 dump_cfg_string(oHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos); 3278 dump_cfg_string(oIdentityAgent, o->identity_agent); 3279 dump_cfg_string(oIgnoreUnknown, o->ignored_unknown); 3280 dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices); 3281 dump_cfg_string(oKexAlgorithms, o->kex_algorithms); 3282 dump_cfg_string(oCASignatureAlgorithms, o->ca_sign_algorithms); 3283 dump_cfg_string(oLocalCommand, o->local_command); 3284 dump_cfg_string(oRemoteCommand, o->remote_command); 3285 dump_cfg_string(oLogLevel, log_level_name(o->log_level)); 3286 dump_cfg_string(oMacs, o->macs); 3287 #ifdef ENABLE_PKCS11 3288 dump_cfg_string(oPKCS11Provider, o->pkcs11_provider); 3289 #endif 3290 dump_cfg_string(oSecurityKeyProvider, o->sk_provider); 3291 dump_cfg_string(oPreferredAuthentications, o->preferred_authentications); 3292 dump_cfg_string(oPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos); 3293 dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys); 3294 dump_cfg_string(oXAuthLocation, o->xauth_location); 3295 dump_cfg_string(oKnownHostsCommand, o->known_hosts_command); 3296 3297 /* Forwards */ 3298 dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards); 3299 dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards); 3300 dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards); 3301 3302 /* String array options */ 3303 dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files); 3304 dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains); 3305 dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files); 3306 dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles); 3307 dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles); 3308 dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env); 3309 dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv); 3310 dump_cfg_strarray_oneline(oLogVerbose, 3311 o->num_log_verbose, o->log_verbose); 3312 3313 /* Special cases */ 3314 3315 /* PermitRemoteOpen */ 3316 if (o->num_permitted_remote_opens == 0) 3317 printf("%s any\n", lookup_opcode_name(oPermitRemoteOpen)); 3318 else 3319 dump_cfg_strarray_oneline(oPermitRemoteOpen, 3320 o->num_permitted_remote_opens, o->permitted_remote_opens); 3321 3322 /* AddKeysToAgent */ 3323 if (o->add_keys_to_agent_lifespan <= 0) 3324 dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent); 3325 else { 3326 printf("addkeystoagent%s %d\n", 3327 o->add_keys_to_agent == 3 ? " confirm" : "", 3328 o->add_keys_to_agent_lifespan); 3329 } 3330 3331 /* oForwardAgent */ 3332 if (o->forward_agent_sock_path == NULL) 3333 dump_cfg_fmtint(oForwardAgent, o->forward_agent); 3334 else 3335 dump_cfg_string(oForwardAgent, o->forward_agent_sock_path); 3336 3337 /* oConnectTimeout */ 3338 if (o->connection_timeout == -1) 3339 printf("connecttimeout none\n"); 3340 else 3341 dump_cfg_int(oConnectTimeout, o->connection_timeout); 3342 3343 /* oTunnelDevice */ 3344 printf("tunneldevice"); 3345 if (o->tun_local == SSH_TUNID_ANY) 3346 printf(" any"); 3347 else 3348 printf(" %d", o->tun_local); 3349 if (o->tun_remote == SSH_TUNID_ANY) 3350 printf(":any"); 3351 else 3352 printf(":%d", o->tun_remote); 3353 printf("\n"); 3354 3355 /* oCanonicalizePermittedCNAMEs */ 3356 if ( o->num_permitted_cnames > 0) { 3357 printf("canonicalizePermittedcnames"); 3358 for (i = 0; i < o->num_permitted_cnames; i++) { 3359 printf(" %s:%s", o->permitted_cnames[i].source_list, 3360 o->permitted_cnames[i].target_list); 3361 } 3362 printf("\n"); 3363 } 3364 3365 /* oControlPersist */ 3366 if (o->control_persist == 0 || o->control_persist_timeout == 0) 3367 dump_cfg_fmtint(oControlPersist, o->control_persist); 3368 else 3369 dump_cfg_int(oControlPersist, o->control_persist_timeout); 3370 3371 /* oEscapeChar */ 3372 if (o->escape_char == SSH_ESCAPECHAR_NONE) 3373 printf("escapechar none\n"); 3374 else { 3375 vis(buf, o->escape_char, VIS_WHITE, 0); 3376 printf("escapechar %s\n", buf); 3377 } 3378 3379 /* oIPQoS */ 3380 printf("ipqos %s ", iptos2str(o->ip_qos_interactive)); 3381 printf("%s\n", iptos2str(o->ip_qos_bulk)); 3382 3383 /* oRekeyLimit */ 3384 printf("rekeylimit %llu %d\n", 3385 (unsigned long long)o->rekey_limit, o->rekey_interval); 3386 3387 /* oStreamLocalBindMask */ 3388 printf("streamlocalbindmask 0%o\n", 3389 o->fwd_opts.streamlocal_bind_mask); 3390 3391 /* oLogFacility */ 3392 printf("syslogfacility %s\n", log_facility_name(o->log_facility)); 3393 3394 /* oProxyCommand / oProxyJump */ 3395 if (o->jump_host == NULL) 3396 dump_cfg_string(oProxyCommand, o->proxy_command); 3397 else { 3398 /* Check for numeric addresses */ 3399 i = strchr(o->jump_host, ':') != NULL || 3400 strspn(o->jump_host, "1234567890.") == strlen(o->jump_host); 3401 snprintf(buf, sizeof(buf), "%d", o->jump_port); 3402 printf("proxyjump %s%s%s%s%s%s%s%s%s\n", 3403 /* optional additional jump spec */ 3404 o->jump_extra == NULL ? "" : o->jump_extra, 3405 o->jump_extra == NULL ? "" : ",", 3406 /* optional user */ 3407 o->jump_user == NULL ? "" : o->jump_user, 3408 o->jump_user == NULL ? "" : "@", 3409 /* opening [ if hostname is numeric */ 3410 i ? "[" : "", 3411 /* mandatory hostname */ 3412 o->jump_host, 3413 /* closing ] if hostname is numeric */ 3414 i ? "]" : "", 3415 /* optional port number */ 3416 o->jump_port <= 0 ? "" : ":", 3417 o->jump_port <= 0 ? "" : buf); 3418 } 3419 } 3420