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