1 /* $OpenBSD: readconf.c,v 1.377 2023/06/21 05:10:26 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, ca_only = 0; 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 ca_only = 0; 1431 parse_pubkey_algos: 1432 arg = argv_next(&ac, &av); 1433 if (!arg || *arg == '\0') { 1434 error("%.200s line %d: Missing argument.", 1435 filename, linenum); 1436 goto out; 1437 } 1438 if (*arg != '-' && 1439 !sshkey_names_valid2(*arg == '+' || *arg == '^' ? 1440 arg + 1 : arg, 1, ca_only)) { 1441 error("%s line %d: Bad key types '%s'.", 1442 filename, linenum, arg ? arg : "<NONE>"); 1443 goto out; 1444 } 1445 if (*activep && *charptr == NULL) 1446 *charptr = xstrdup(arg); 1447 break; 1448 1449 case oCASignatureAlgorithms: 1450 charptr = &options->ca_sign_algorithms; 1451 ca_only = 1; 1452 goto parse_pubkey_algos; 1453 1454 case oLogLevel: 1455 log_level_ptr = &options->log_level; 1456 arg = argv_next(&ac, &av); 1457 value = log_level_number(arg); 1458 if (value == SYSLOG_LEVEL_NOT_SET) { 1459 error("%.200s line %d: unsupported log level '%s'", 1460 filename, linenum, arg ? arg : "<NONE>"); 1461 goto out; 1462 } 1463 if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET) 1464 *log_level_ptr = (LogLevel) value; 1465 break; 1466 1467 case oLogFacility: 1468 log_facility_ptr = &options->log_facility; 1469 arg = argv_next(&ac, &av); 1470 value = log_facility_number(arg); 1471 if (value == SYSLOG_FACILITY_NOT_SET) { 1472 error("%.200s line %d: unsupported log facility '%s'", 1473 filename, linenum, arg ? arg : "<NONE>"); 1474 goto out; 1475 } 1476 if (*log_facility_ptr == -1) 1477 *log_facility_ptr = (SyslogFacility) value; 1478 break; 1479 1480 case oLogVerbose: 1481 cppptr = &options->log_verbose; 1482 uintptr = &options->num_log_verbose; 1483 i = 0; 1484 while ((arg = argv_next(&ac, &av)) != NULL) { 1485 if (*arg == '\0') { 1486 error("%s line %d: keyword %s empty argument", 1487 filename, linenum, keyword); 1488 goto out; 1489 } 1490 /* Allow "none" only in first position */ 1491 if (strcasecmp(arg, "none") == 0) { 1492 if (i > 0 || ac > 0) { 1493 error("%s line %d: keyword %s \"none\" " 1494 "argument must appear alone.", 1495 filename, linenum, keyword); 1496 goto out; 1497 } 1498 } 1499 i++; 1500 if (*activep && *uintptr == 0) { 1501 *cppptr = xrecallocarray(*cppptr, *uintptr, 1502 *uintptr + 1, sizeof(**cppptr)); 1503 (*cppptr)[(*uintptr)++] = xstrdup(arg); 1504 } 1505 } 1506 break; 1507 1508 case oLocalForward: 1509 case oRemoteForward: 1510 case oDynamicForward: 1511 arg = argv_next(&ac, &av); 1512 if (!arg || *arg == '\0') { 1513 error("%.200s line %d: Missing argument.", 1514 filename, linenum); 1515 goto out; 1516 } 1517 1518 remotefwd = (opcode == oRemoteForward); 1519 dynamicfwd = (opcode == oDynamicForward); 1520 1521 if (!dynamicfwd) { 1522 arg2 = argv_next(&ac, &av); 1523 if (arg2 == NULL || *arg2 == '\0') { 1524 if (remotefwd) 1525 dynamicfwd = 1; 1526 else { 1527 error("%.200s line %d: Missing target " 1528 "argument.", filename, linenum); 1529 goto out; 1530 } 1531 } else { 1532 /* construct a string for parse_forward */ 1533 snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, 1534 arg2); 1535 } 1536 } 1537 if (dynamicfwd) 1538 strlcpy(fwdarg, arg, sizeof(fwdarg)); 1539 1540 if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0) { 1541 error("%.200s line %d: Bad forwarding specification.", 1542 filename, linenum); 1543 goto out; 1544 } 1545 1546 if (*activep) { 1547 if (remotefwd) { 1548 add_remote_forward(options, &fwd); 1549 } else { 1550 add_local_forward(options, &fwd); 1551 } 1552 } 1553 break; 1554 1555 case oPermitRemoteOpen: 1556 uintptr = &options->num_permitted_remote_opens; 1557 cppptr = &options->permitted_remote_opens; 1558 uvalue = *uintptr; /* modified later */ 1559 i = 0; 1560 while ((arg = argv_next(&ac, &av)) != NULL) { 1561 arg2 = xstrdup(arg); 1562 /* Allow any/none only in first position */ 1563 if (strcasecmp(arg, "none") == 0 || 1564 strcasecmp(arg, "any") == 0) { 1565 if (i > 0 || ac > 0) { 1566 error("%s line %d: keyword %s \"%s\" " 1567 "argument must appear alone.", 1568 filename, linenum, keyword, arg); 1569 free(arg2); 1570 goto out; 1571 } 1572 } else { 1573 p = hpdelim(&arg); 1574 if (p == NULL) { 1575 fatal("%s line %d: missing host in %s", 1576 filename, linenum, 1577 lookup_opcode_name(opcode)); 1578 } 1579 p = cleanhostname(p); 1580 /* 1581 * don't want to use permitopen_port to avoid 1582 * dependency on channels.[ch] here. 1583 */ 1584 if (arg == NULL || (strcmp(arg, "*") != 0 && 1585 a2port(arg) <= 0)) { 1586 fatal("%s line %d: bad port number " 1587 "in %s", filename, linenum, 1588 lookup_opcode_name(opcode)); 1589 } 1590 } 1591 if (*activep && uvalue == 0) { 1592 opt_array_append(filename, linenum, 1593 lookup_opcode_name(opcode), 1594 cppptr, uintptr, arg2); 1595 } 1596 free(arg2); 1597 i++; 1598 } 1599 if (i == 0) 1600 fatal("%s line %d: missing %s specification", 1601 filename, linenum, lookup_opcode_name(opcode)); 1602 break; 1603 1604 case oClearAllForwardings: 1605 intptr = &options->clear_forwardings; 1606 goto parse_flag; 1607 1608 case oHost: 1609 if (cmdline) { 1610 error("Host directive not supported as a command-line " 1611 "option"); 1612 goto out; 1613 } 1614 *activep = 0; 1615 arg2 = NULL; 1616 while ((arg = argv_next(&ac, &av)) != NULL) { 1617 if (*arg == '\0') { 1618 error("%s line %d: keyword %s empty argument", 1619 filename, linenum, keyword); 1620 goto out; 1621 } 1622 if ((flags & SSHCONF_NEVERMATCH) != 0) { 1623 argv_consume(&ac); 1624 break; 1625 } 1626 negated = *arg == '!'; 1627 if (negated) 1628 arg++; 1629 if (match_pattern(host, arg)) { 1630 if (negated) { 1631 debug("%.200s line %d: Skipping Host " 1632 "block because of negated match " 1633 "for %.100s", filename, linenum, 1634 arg); 1635 *activep = 0; 1636 argv_consume(&ac); 1637 break; 1638 } 1639 if (!*activep) 1640 arg2 = arg; /* logged below */ 1641 *activep = 1; 1642 } 1643 } 1644 if (*activep) 1645 debug("%.200s line %d: Applying options for %.100s", 1646 filename, linenum, arg2); 1647 break; 1648 1649 case oMatch: 1650 if (cmdline) { 1651 error("Host directive not supported as a command-line " 1652 "option"); 1653 goto out; 1654 } 1655 value = match_cfg_line(options, &str, pw, host, original_host, 1656 flags & SSHCONF_FINAL, want_final_pass, 1657 filename, linenum); 1658 if (value < 0) { 1659 error("%.200s line %d: Bad Match condition", filename, 1660 linenum); 1661 goto out; 1662 } 1663 *activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value; 1664 /* 1665 * If match_cfg_line() didn't consume all its arguments then 1666 * arrange for the extra arguments check below to fail. 1667 */ 1668 1669 if (str == NULL || *str == '\0') 1670 argv_consume(&ac); 1671 break; 1672 1673 case oEscapeChar: 1674 intptr = &options->escape_char; 1675 arg = argv_next(&ac, &av); 1676 if (!arg || *arg == '\0') { 1677 error("%.200s line %d: Missing argument.", 1678 filename, linenum); 1679 goto out; 1680 } 1681 if (strcmp(arg, "none") == 0) 1682 value = SSH_ESCAPECHAR_NONE; 1683 else if (arg[1] == '\0') 1684 value = (u_char) arg[0]; 1685 else if (arg[0] == '^' && arg[2] == 0 && 1686 (u_char) arg[1] >= 64 && (u_char) arg[1] < 128) 1687 value = (u_char) arg[1] & 31; 1688 else { 1689 error("%.200s line %d: Bad escape character.", 1690 filename, linenum); 1691 goto out; 1692 } 1693 if (*activep && *intptr == -1) 1694 *intptr = value; 1695 break; 1696 1697 case oAddressFamily: 1698 intptr = &options->address_family; 1699 multistate_ptr = multistate_addressfamily; 1700 goto parse_multistate; 1701 1702 case oEnableSSHKeysign: 1703 intptr = &options->enable_ssh_keysign; 1704 goto parse_flag; 1705 1706 case oIdentitiesOnly: 1707 intptr = &options->identities_only; 1708 goto parse_flag; 1709 1710 case oServerAliveInterval: 1711 intptr = &options->server_alive_interval; 1712 goto parse_time; 1713 1714 case oServerAliveCountMax: 1715 intptr = &options->server_alive_count_max; 1716 goto parse_int; 1717 1718 case oSendEnv: 1719 while ((arg = argv_next(&ac, &av)) != NULL) { 1720 if (*arg == '\0' || strchr(arg, '=') != NULL) { 1721 error("%s line %d: Invalid environment name.", 1722 filename, linenum); 1723 goto out; 1724 } 1725 if (!*activep) 1726 continue; 1727 if (*arg == '-') { 1728 /* Removing an env var */ 1729 rm_env(options, arg, filename, linenum); 1730 continue; 1731 } 1732 opt_array_append(filename, linenum, 1733 lookup_opcode_name(opcode), 1734 &options->send_env, &options->num_send_env, arg); 1735 } 1736 break; 1737 1738 case oSetEnv: 1739 value = options->num_setenv; 1740 while ((arg = argv_next(&ac, &av)) != NULL) { 1741 if (strchr(arg, '=') == NULL) { 1742 error("%s line %d: Invalid SetEnv.", 1743 filename, linenum); 1744 goto out; 1745 } 1746 if (!*activep || value != 0) 1747 continue; 1748 if (lookup_setenv_in_list(arg, options->setenv, 1749 options->num_setenv) != NULL) { 1750 debug2("%s line %d: ignoring duplicate env " 1751 "name \"%.64s\"", filename, linenum, arg); 1752 continue; 1753 } 1754 opt_array_append(filename, linenum, 1755 lookup_opcode_name(opcode), 1756 &options->setenv, &options->num_setenv, arg); 1757 } 1758 break; 1759 1760 case oControlPath: 1761 charptr = &options->control_path; 1762 goto parse_string; 1763 1764 case oControlMaster: 1765 intptr = &options->control_master; 1766 multistate_ptr = multistate_controlmaster; 1767 goto parse_multistate; 1768 1769 case oControlPersist: 1770 /* no/false/yes/true, or a time spec */ 1771 intptr = &options->control_persist; 1772 arg = argv_next(&ac, &av); 1773 if (!arg || *arg == '\0') { 1774 error("%.200s line %d: Missing ControlPersist" 1775 " argument.", filename, linenum); 1776 goto out; 1777 } 1778 value = 0; 1779 value2 = 0; /* timeout */ 1780 if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 1781 value = 0; 1782 else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 1783 value = 1; 1784 else if ((value2 = convtime(arg)) >= 0) 1785 value = 1; 1786 else { 1787 error("%.200s line %d: Bad ControlPersist argument.", 1788 filename, linenum); 1789 goto out; 1790 } 1791 if (*activep && *intptr == -1) { 1792 *intptr = value; 1793 options->control_persist_timeout = value2; 1794 } 1795 break; 1796 1797 case oHashKnownHosts: 1798 intptr = &options->hash_known_hosts; 1799 goto parse_flag; 1800 1801 case oTunnel: 1802 intptr = &options->tun_open; 1803 multistate_ptr = multistate_tunnel; 1804 goto parse_multistate; 1805 1806 case oTunnelDevice: 1807 arg = argv_next(&ac, &av); 1808 if (!arg || *arg == '\0') { 1809 error("%.200s line %d: Missing argument.", 1810 filename, linenum); 1811 goto out; 1812 } 1813 value = a2tun(arg, &value2); 1814 if (value == SSH_TUNID_ERR) { 1815 error("%.200s line %d: Bad tun device.", 1816 filename, linenum); 1817 goto out; 1818 } 1819 if (*activep && options->tun_local == -1) { 1820 options->tun_local = value; 1821 options->tun_remote = value2; 1822 } 1823 break; 1824 1825 case oLocalCommand: 1826 charptr = &options->local_command; 1827 goto parse_command; 1828 1829 case oPermitLocalCommand: 1830 intptr = &options->permit_local_command; 1831 goto parse_flag; 1832 1833 case oRemoteCommand: 1834 charptr = &options->remote_command; 1835 goto parse_command; 1836 1837 case oVisualHostKey: 1838 intptr = &options->visual_host_key; 1839 goto parse_flag; 1840 1841 case oInclude: 1842 if (cmdline) { 1843 error("Include directive not supported as a " 1844 "command-line option"); 1845 goto out; 1846 } 1847 value = 0; 1848 while ((arg = argv_next(&ac, &av)) != NULL) { 1849 if (*arg == '\0') { 1850 error("%s line %d: keyword %s empty argument", 1851 filename, linenum, keyword); 1852 goto out; 1853 } 1854 /* 1855 * Ensure all paths are anchored. User configuration 1856 * files may begin with '~/' but system configurations 1857 * must not. If the path is relative, then treat it 1858 * as living in ~/.ssh for user configurations or 1859 * /etc/ssh for system ones. 1860 */ 1861 if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0) { 1862 error("%.200s line %d: bad include path %s.", 1863 filename, linenum, arg); 1864 goto out; 1865 } 1866 if (!path_absolute(arg) && *arg != '~') { 1867 xasprintf(&arg2, "%s/%s", 1868 (flags & SSHCONF_USERCONF) ? 1869 "~/" _PATH_SSH_USER_DIR : SSHDIR, arg); 1870 } else 1871 arg2 = xstrdup(arg); 1872 memset(&gl, 0, sizeof(gl)); 1873 r = glob(arg2, GLOB_TILDE, NULL, &gl); 1874 if (r == GLOB_NOMATCH) { 1875 debug("%.200s line %d: include %s matched no " 1876 "files",filename, linenum, arg2); 1877 free(arg2); 1878 continue; 1879 } else if (r != 0) { 1880 error("%.200s line %d: glob failed for %s.", 1881 filename, linenum, arg2); 1882 goto out; 1883 } 1884 free(arg2); 1885 oactive = *activep; 1886 for (i = 0; i < gl.gl_pathc; i++) { 1887 debug3("%.200s line %d: Including file %s " 1888 "depth %d%s", filename, linenum, 1889 gl.gl_pathv[i], depth, 1890 oactive ? "" : " (parse only)"); 1891 r = read_config_file_depth(gl.gl_pathv[i], 1892 pw, host, original_host, options, 1893 flags | SSHCONF_CHECKPERM | 1894 (oactive ? 0 : SSHCONF_NEVERMATCH), 1895 activep, want_final_pass, depth + 1); 1896 if (r != 1 && errno != ENOENT) { 1897 error("Can't open user config file " 1898 "%.100s: %.100s", gl.gl_pathv[i], 1899 strerror(errno)); 1900 globfree(&gl); 1901 goto out; 1902 } 1903 /* 1904 * don't let Match in includes clobber the 1905 * containing file's Match state. 1906 */ 1907 *activep = oactive; 1908 if (r != 1) 1909 value = -1; 1910 } 1911 globfree(&gl); 1912 } 1913 if (value != 0) 1914 ret = value; 1915 break; 1916 1917 case oIPQoS: 1918 arg = argv_next(&ac, &av); 1919 if ((value = parse_ipqos(arg)) == -1) { 1920 error("%s line %d: Bad IPQoS value: %s", 1921 filename, linenum, arg); 1922 goto out; 1923 } 1924 arg = argv_next(&ac, &av); 1925 if (arg == NULL) 1926 value2 = value; 1927 else if ((value2 = parse_ipqos(arg)) == -1) { 1928 error("%s line %d: Bad IPQoS value: %s", 1929 filename, linenum, arg); 1930 goto out; 1931 } 1932 if (*activep && options->ip_qos_interactive == -1) { 1933 options->ip_qos_interactive = value; 1934 options->ip_qos_bulk = value2; 1935 } 1936 break; 1937 1938 case oRequestTTY: 1939 intptr = &options->request_tty; 1940 multistate_ptr = multistate_requesttty; 1941 goto parse_multistate; 1942 1943 case oSessionType: 1944 intptr = &options->session_type; 1945 multistate_ptr = multistate_sessiontype; 1946 goto parse_multistate; 1947 1948 case oStdinNull: 1949 intptr = &options->stdin_null; 1950 goto parse_flag; 1951 1952 case oForkAfterAuthentication: 1953 intptr = &options->fork_after_authentication; 1954 goto parse_flag; 1955 1956 case oIgnoreUnknown: 1957 charptr = &options->ignored_unknown; 1958 goto parse_string; 1959 1960 case oProxyUseFdpass: 1961 intptr = &options->proxy_use_fdpass; 1962 goto parse_flag; 1963 1964 case oCanonicalDomains: 1965 value = options->num_canonical_domains != 0; 1966 i = 0; 1967 while ((arg = argv_next(&ac, &av)) != NULL) { 1968 if (*arg == '\0') { 1969 error("%s line %d: keyword %s empty argument", 1970 filename, linenum, keyword); 1971 goto out; 1972 } 1973 /* Allow "none" only in first position */ 1974 if (strcasecmp(arg, "none") == 0) { 1975 if (i > 0 || ac > 0) { 1976 error("%s line %d: keyword %s \"none\" " 1977 "argument must appear alone.", 1978 filename, linenum, keyword); 1979 goto out; 1980 } 1981 } 1982 i++; 1983 if (!valid_domain(arg, 1, &errstr)) { 1984 error("%s line %d: %s", filename, linenum, 1985 errstr); 1986 goto out; 1987 } 1988 if (!*activep || value) 1989 continue; 1990 if (options->num_canonical_domains >= 1991 MAX_CANON_DOMAINS) { 1992 error("%s line %d: too many hostname suffixes.", 1993 filename, linenum); 1994 goto out; 1995 } 1996 options->canonical_domains[ 1997 options->num_canonical_domains++] = xstrdup(arg); 1998 } 1999 break; 2000 2001 case oCanonicalizePermittedCNAMEs: 2002 value = options->num_permitted_cnames != 0; 2003 i = 0; 2004 while ((arg = argv_next(&ac, &av)) != NULL) { 2005 /* 2006 * Either 'none' (only in first position), '*' for 2007 * everything or 'list:list' 2008 */ 2009 if (strcasecmp(arg, "none") == 0) { 2010 if (i > 0 || ac > 0) { 2011 error("%s line %d: keyword %s \"none\" " 2012 "argument must appear alone.", 2013 filename, linenum, keyword); 2014 goto out; 2015 } 2016 arg2 = ""; 2017 } else if (strcmp(arg, "*") == 0) { 2018 arg2 = arg; 2019 } else { 2020 lowercase(arg); 2021 if ((arg2 = strchr(arg, ':')) == NULL || 2022 arg2[1] == '\0') { 2023 error("%s line %d: " 2024 "Invalid permitted CNAME \"%s\"", 2025 filename, linenum, arg); 2026 goto out; 2027 } 2028 *arg2 = '\0'; 2029 arg2++; 2030 } 2031 i++; 2032 if (!*activep || value) 2033 continue; 2034 if (options->num_permitted_cnames >= 2035 MAX_CANON_DOMAINS) { 2036 error("%s line %d: too many permitted CNAMEs.", 2037 filename, linenum); 2038 goto out; 2039 } 2040 cname = options->permitted_cnames + 2041 options->num_permitted_cnames++; 2042 cname->source_list = xstrdup(arg); 2043 cname->target_list = xstrdup(arg2); 2044 } 2045 break; 2046 2047 case oCanonicalizeHostname: 2048 intptr = &options->canonicalize_hostname; 2049 multistate_ptr = multistate_canonicalizehostname; 2050 goto parse_multistate; 2051 2052 case oCanonicalizeMaxDots: 2053 intptr = &options->canonicalize_max_dots; 2054 goto parse_int; 2055 2056 case oCanonicalizeFallbackLocal: 2057 intptr = &options->canonicalize_fallback_local; 2058 goto parse_flag; 2059 2060 case oStreamLocalBindMask: 2061 arg = argv_next(&ac, &av); 2062 if (!arg || *arg == '\0') { 2063 error("%.200s line %d: Missing StreamLocalBindMask " 2064 "argument.", filename, linenum); 2065 goto out; 2066 } 2067 /* Parse mode in octal format */ 2068 value = strtol(arg, &endofnumber, 8); 2069 if (arg == endofnumber || value < 0 || value > 0777) { 2070 error("%.200s line %d: Bad mask.", filename, linenum); 2071 goto out; 2072 } 2073 options->fwd_opts.streamlocal_bind_mask = (mode_t)value; 2074 break; 2075 2076 case oStreamLocalBindUnlink: 2077 intptr = &options->fwd_opts.streamlocal_bind_unlink; 2078 goto parse_flag; 2079 2080 case oRevokedHostKeys: 2081 charptr = &options->revoked_host_keys; 2082 goto parse_string; 2083 2084 case oFingerprintHash: 2085 intptr = &options->fingerprint_hash; 2086 arg = argv_next(&ac, &av); 2087 if (!arg || *arg == '\0') { 2088 error("%.200s line %d: Missing argument.", 2089 filename, linenum); 2090 goto out; 2091 } 2092 if ((value = ssh_digest_alg_by_name(arg)) == -1) { 2093 error("%.200s line %d: Invalid hash algorithm \"%s\".", 2094 filename, linenum, arg); 2095 goto out; 2096 } 2097 if (*activep && *intptr == -1) 2098 *intptr = value; 2099 break; 2100 2101 case oUpdateHostkeys: 2102 intptr = &options->update_hostkeys; 2103 multistate_ptr = multistate_yesnoask; 2104 goto parse_multistate; 2105 2106 case oHostbasedAcceptedAlgorithms: 2107 charptr = &options->hostbased_accepted_algos; 2108 ca_only = 0; 2109 goto parse_pubkey_algos; 2110 2111 case oPubkeyAcceptedAlgorithms: 2112 charptr = &options->pubkey_accepted_algos; 2113 ca_only = 0; 2114 goto parse_pubkey_algos; 2115 2116 case oAddKeysToAgent: 2117 arg = argv_next(&ac, &av); 2118 arg2 = argv_next(&ac, &av); 2119 value = parse_multistate_value(arg, filename, linenum, 2120 multistate_yesnoaskconfirm); 2121 value2 = 0; /* unlimited lifespan by default */ 2122 if (value == 3 && arg2 != NULL) { 2123 /* allow "AddKeysToAgent confirm 5m" */ 2124 if ((value2 = convtime(arg2)) == -1) { 2125 error("%s line %d: invalid time value.", 2126 filename, linenum); 2127 goto out; 2128 } 2129 } else if (value == -1 && arg2 == NULL) { 2130 if ((value2 = convtime(arg)) == -1) { 2131 error("%s line %d: unsupported option", 2132 filename, linenum); 2133 goto out; 2134 } 2135 value = 1; /* yes */ 2136 } else if (value == -1 || arg2 != NULL) { 2137 error("%s line %d: unsupported option", 2138 filename, linenum); 2139 goto out; 2140 } 2141 if (*activep && options->add_keys_to_agent == -1) { 2142 options->add_keys_to_agent = value; 2143 options->add_keys_to_agent_lifespan = value2; 2144 } 2145 break; 2146 2147 case oIdentityAgent: 2148 charptr = &options->identity_agent; 2149 arg = argv_next(&ac, &av); 2150 if (!arg || *arg == '\0') { 2151 error("%.200s line %d: Missing argument.", 2152 filename, linenum); 2153 goto out; 2154 } 2155 parse_agent_path: 2156 /* Extra validation if the string represents an env var. */ 2157 if ((arg2 = dollar_expand(&r, arg)) == NULL || r) { 2158 error("%.200s line %d: Invalid environment expansion " 2159 "%s.", filename, linenum, arg); 2160 goto out; 2161 } 2162 free(arg2); 2163 /* check for legacy environment format */ 2164 if (arg[0] == '$' && arg[1] != '{' && 2165 !valid_env_name(arg + 1)) { 2166 error("%.200s line %d: Invalid environment name %s.", 2167 filename, linenum, arg); 2168 goto out; 2169 } 2170 if (*activep && *charptr == NULL) 2171 *charptr = xstrdup(arg); 2172 break; 2173 2174 case oEnableEscapeCommandline: 2175 intptr = &options->enable_escape_commandline; 2176 goto parse_flag; 2177 2178 case oRequiredRSASize: 2179 intptr = &options->required_rsa_size; 2180 goto parse_int; 2181 2182 case oDeprecated: 2183 debug("%s line %d: Deprecated option \"%s\"", 2184 filename, linenum, keyword); 2185 argv_consume(&ac); 2186 break; 2187 2188 case oUnsupported: 2189 error("%s line %d: Unsupported option \"%s\"", 2190 filename, linenum, keyword); 2191 argv_consume(&ac); 2192 break; 2193 2194 default: 2195 error("%s line %d: Unimplemented opcode %d", 2196 filename, linenum, opcode); 2197 goto out; 2198 } 2199 2200 /* Check that there is no garbage at end of line. */ 2201 if (ac > 0) { 2202 error("%.200s line %d: keyword %s extra arguments " 2203 "at end of line", filename, linenum, keyword); 2204 goto out; 2205 } 2206 2207 /* success */ 2208 ret = 0; 2209 out: 2210 argv_free(oav, oac); 2211 return ret; 2212 } 2213 2214 /* 2215 * Reads the config file and modifies the options accordingly. Options 2216 * should already be initialized before this call. This never returns if 2217 * there is an error. If the file does not exist, this returns 0. 2218 */ 2219 int 2220 read_config_file(const char *filename, struct passwd *pw, const char *host, 2221 const char *original_host, Options *options, int flags, 2222 int *want_final_pass) 2223 { 2224 int active = 1; 2225 2226 return read_config_file_depth(filename, pw, host, original_host, 2227 options, flags, &active, want_final_pass, 0); 2228 } 2229 2230 #define READCONF_MAX_DEPTH 16 2231 static int 2232 read_config_file_depth(const char *filename, struct passwd *pw, 2233 const char *host, const char *original_host, Options *options, 2234 int flags, int *activep, int *want_final_pass, int depth) 2235 { 2236 FILE *f; 2237 char *line = NULL; 2238 size_t linesize = 0; 2239 int linenum; 2240 int bad_options = 0; 2241 2242 if (depth < 0 || depth > READCONF_MAX_DEPTH) 2243 fatal("Too many recursive configuration includes"); 2244 2245 if ((f = fopen(filename, "r")) == NULL) 2246 return 0; 2247 2248 if (flags & SSHCONF_CHECKPERM) { 2249 struct stat sb; 2250 2251 if (fstat(fileno(f), &sb) == -1) 2252 fatal("fstat %s: %s", filename, strerror(errno)); 2253 if (((sb.st_uid != 0 && sb.st_uid != getuid()) || 2254 (sb.st_mode & 022) != 0)) 2255 fatal("Bad owner or permissions on %s", filename); 2256 } 2257 2258 debug("Reading configuration data %.200s", filename); 2259 2260 /* 2261 * Mark that we are now processing the options. This flag is turned 2262 * on/off by Host specifications. 2263 */ 2264 linenum = 0; 2265 while (getline(&line, &linesize, f) != -1) { 2266 /* Update line number counter. */ 2267 linenum++; 2268 /* 2269 * Trim out comments and strip whitespace. 2270 * NB - preserve newlines, they are needed to reproduce 2271 * line numbers later for error messages. 2272 */ 2273 if (process_config_line_depth(options, pw, host, original_host, 2274 line, filename, linenum, activep, flags, want_final_pass, 2275 depth) != 0) 2276 bad_options++; 2277 } 2278 free(line); 2279 fclose(f); 2280 if (bad_options > 0) 2281 fatal("%s: terminating, %d bad configuration options", 2282 filename, bad_options); 2283 return 1; 2284 } 2285 2286 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ 2287 int 2288 option_clear_or_none(const char *o) 2289 { 2290 return o == NULL || strcasecmp(o, "none") == 0; 2291 } 2292 2293 /* 2294 * Returns 1 if CanonicalizePermittedCNAMEs have been specified, 0 otherwise. 2295 * Allowed to be called on non-final configuration. 2296 */ 2297 int 2298 config_has_permitted_cnames(Options *options) 2299 { 2300 if (options->num_permitted_cnames == 1 && 2301 strcasecmp(options->permitted_cnames[0].source_list, "none") == 0 && 2302 strcmp(options->permitted_cnames[0].target_list, "") == 0) 2303 return 0; 2304 return options->num_permitted_cnames > 0; 2305 } 2306 2307 /* 2308 * Initializes options to special values that indicate that they have not yet 2309 * been set. Read_config_file will only set options with this value. Options 2310 * are processed in the following order: command line, user config file, 2311 * system config file. Last, fill_default_options is called. 2312 */ 2313 2314 void 2315 initialize_options(Options * options) 2316 { 2317 memset(options, 'X', sizeof(*options)); 2318 options->host_arg = NULL; 2319 options->forward_agent = -1; 2320 options->forward_agent_sock_path = NULL; 2321 options->forward_x11 = -1; 2322 options->forward_x11_trusted = -1; 2323 options->forward_x11_timeout = -1; 2324 options->stdio_forward_host = NULL; 2325 options->stdio_forward_port = 0; 2326 options->clear_forwardings = -1; 2327 options->exit_on_forward_failure = -1; 2328 options->xauth_location = NULL; 2329 options->fwd_opts.gateway_ports = -1; 2330 options->fwd_opts.streamlocal_bind_mask = (mode_t)-1; 2331 options->fwd_opts.streamlocal_bind_unlink = -1; 2332 options->pubkey_authentication = -1; 2333 options->gss_authentication = -1; 2334 options->gss_deleg_creds = -1; 2335 options->password_authentication = -1; 2336 options->kbd_interactive_authentication = -1; 2337 options->kbd_interactive_devices = NULL; 2338 options->hostbased_authentication = -1; 2339 options->batch_mode = -1; 2340 options->check_host_ip = -1; 2341 options->strict_host_key_checking = -1; 2342 options->compression = -1; 2343 options->tcp_keep_alive = -1; 2344 options->port = -1; 2345 options->address_family = -1; 2346 options->connection_attempts = -1; 2347 options->connection_timeout = -1; 2348 options->number_of_password_prompts = -1; 2349 options->ciphers = NULL; 2350 options->macs = NULL; 2351 options->kex_algorithms = NULL; 2352 options->hostkeyalgorithms = NULL; 2353 options->ca_sign_algorithms = NULL; 2354 options->num_identity_files = 0; 2355 memset(options->identity_keys, 0, sizeof(options->identity_keys)); 2356 options->num_certificate_files = 0; 2357 memset(options->certificates, 0, sizeof(options->certificates)); 2358 options->hostname = NULL; 2359 options->host_key_alias = NULL; 2360 options->proxy_command = NULL; 2361 options->jump_user = NULL; 2362 options->jump_host = NULL; 2363 options->jump_port = -1; 2364 options->jump_extra = NULL; 2365 options->user = NULL; 2366 options->escape_char = -1; 2367 options->num_system_hostfiles = 0; 2368 options->num_user_hostfiles = 0; 2369 options->local_forwards = NULL; 2370 options->num_local_forwards = 0; 2371 options->remote_forwards = NULL; 2372 options->num_remote_forwards = 0; 2373 options->permitted_remote_opens = NULL; 2374 options->num_permitted_remote_opens = 0; 2375 options->log_facility = SYSLOG_FACILITY_NOT_SET; 2376 options->log_level = SYSLOG_LEVEL_NOT_SET; 2377 options->num_log_verbose = 0; 2378 options->log_verbose = NULL; 2379 options->preferred_authentications = NULL; 2380 options->bind_address = NULL; 2381 options->bind_interface = NULL; 2382 options->pkcs11_provider = NULL; 2383 options->sk_provider = NULL; 2384 options->enable_ssh_keysign = - 1; 2385 options->no_host_authentication_for_localhost = - 1; 2386 options->identities_only = - 1; 2387 options->rekey_limit = - 1; 2388 options->rekey_interval = -1; 2389 options->verify_host_key_dns = -1; 2390 options->server_alive_interval = -1; 2391 options->server_alive_count_max = -1; 2392 options->send_env = NULL; 2393 options->num_send_env = 0; 2394 options->setenv = NULL; 2395 options->num_setenv = 0; 2396 options->control_path = NULL; 2397 options->control_master = -1; 2398 options->control_persist = -1; 2399 options->control_persist_timeout = 0; 2400 options->hash_known_hosts = -1; 2401 options->tun_open = -1; 2402 options->tun_local = -1; 2403 options->tun_remote = -1; 2404 options->local_command = NULL; 2405 options->permit_local_command = -1; 2406 options->remote_command = NULL; 2407 options->add_keys_to_agent = -1; 2408 options->add_keys_to_agent_lifespan = -1; 2409 options->identity_agent = NULL; 2410 options->visual_host_key = -1; 2411 options->ip_qos_interactive = -1; 2412 options->ip_qos_bulk = -1; 2413 options->request_tty = -1; 2414 options->session_type = -1; 2415 options->stdin_null = -1; 2416 options->fork_after_authentication = -1; 2417 options->proxy_use_fdpass = -1; 2418 options->ignored_unknown = NULL; 2419 options->num_canonical_domains = 0; 2420 options->num_permitted_cnames = 0; 2421 options->canonicalize_max_dots = -1; 2422 options->canonicalize_fallback_local = -1; 2423 options->canonicalize_hostname = -1; 2424 options->revoked_host_keys = NULL; 2425 options->fingerprint_hash = -1; 2426 options->update_hostkeys = -1; 2427 options->hostbased_accepted_algos = NULL; 2428 options->pubkey_accepted_algos = NULL; 2429 options->known_hosts_command = NULL; 2430 options->required_rsa_size = -1; 2431 options->enable_escape_commandline = -1; 2432 } 2433 2434 /* 2435 * A petite version of fill_default_options() that just fills the options 2436 * needed for hostname canonicalization to proceed. 2437 */ 2438 void 2439 fill_default_options_for_canonicalization(Options *options) 2440 { 2441 if (options->canonicalize_max_dots == -1) 2442 options->canonicalize_max_dots = 1; 2443 if (options->canonicalize_fallback_local == -1) 2444 options->canonicalize_fallback_local = 1; 2445 if (options->canonicalize_hostname == -1) 2446 options->canonicalize_hostname = SSH_CANONICALISE_NO; 2447 } 2448 2449 /* 2450 * Called after processing other sources of option data, this fills those 2451 * options for which no value has been specified with their default values. 2452 */ 2453 int 2454 fill_default_options(Options * options) 2455 { 2456 char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig; 2457 char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig; 2458 int ret = 0, r; 2459 2460 if (options->forward_agent == -1) 2461 options->forward_agent = 0; 2462 if (options->forward_x11 == -1) 2463 options->forward_x11 = 0; 2464 if (options->forward_x11_trusted == -1) 2465 options->forward_x11_trusted = 0; 2466 if (options->forward_x11_timeout == -1) 2467 options->forward_x11_timeout = 1200; 2468 /* 2469 * stdio forwarding (-W) changes the default for these but we defer 2470 * setting the values so they can be overridden. 2471 */ 2472 if (options->exit_on_forward_failure == -1) 2473 options->exit_on_forward_failure = 2474 options->stdio_forward_host != NULL ? 1 : 0; 2475 if (options->clear_forwardings == -1) 2476 options->clear_forwardings = 2477 options->stdio_forward_host != NULL ? 1 : 0; 2478 if (options->clear_forwardings == 1) 2479 clear_forwardings(options); 2480 2481 if (options->xauth_location == NULL) 2482 options->xauth_location = xstrdup(_PATH_XAUTH); 2483 if (options->fwd_opts.gateway_ports == -1) 2484 options->fwd_opts.gateway_ports = 0; 2485 if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1) 2486 options->fwd_opts.streamlocal_bind_mask = 0177; 2487 if (options->fwd_opts.streamlocal_bind_unlink == -1) 2488 options->fwd_opts.streamlocal_bind_unlink = 0; 2489 if (options->pubkey_authentication == -1) 2490 options->pubkey_authentication = SSH_PUBKEY_AUTH_ALL; 2491 if (options->gss_authentication == -1) 2492 options->gss_authentication = 0; 2493 if (options->gss_deleg_creds == -1) 2494 options->gss_deleg_creds = 0; 2495 if (options->password_authentication == -1) 2496 options->password_authentication = 1; 2497 if (options->kbd_interactive_authentication == -1) 2498 options->kbd_interactive_authentication = 1; 2499 if (options->hostbased_authentication == -1) 2500 options->hostbased_authentication = 0; 2501 if (options->batch_mode == -1) 2502 options->batch_mode = 0; 2503 if (options->check_host_ip == -1) 2504 options->check_host_ip = 0; 2505 if (options->strict_host_key_checking == -1) 2506 options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK; 2507 if (options->compression == -1) 2508 options->compression = 0; 2509 if (options->tcp_keep_alive == -1) 2510 options->tcp_keep_alive = 1; 2511 if (options->port == -1) 2512 options->port = 0; /* Filled in ssh_connect. */ 2513 if (options->address_family == -1) 2514 options->address_family = AF_UNSPEC; 2515 if (options->connection_attempts == -1) 2516 options->connection_attempts = 1; 2517 if (options->number_of_password_prompts == -1) 2518 options->number_of_password_prompts = 3; 2519 /* options->hostkeyalgorithms, default set in myproposals.h */ 2520 if (options->add_keys_to_agent == -1) { 2521 options->add_keys_to_agent = 0; 2522 options->add_keys_to_agent_lifespan = 0; 2523 } 2524 if (options->num_identity_files == 0) { 2525 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0); 2526 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0); 2527 add_identity_file(options, "~/", 2528 _PATH_SSH_CLIENT_ID_ECDSA_SK, 0); 2529 add_identity_file(options, "~/", 2530 _PATH_SSH_CLIENT_ID_ED25519, 0); 2531 add_identity_file(options, "~/", 2532 _PATH_SSH_CLIENT_ID_ED25519_SK, 0); 2533 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0); 2534 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0); 2535 } 2536 if (options->escape_char == -1) 2537 options->escape_char = '~'; 2538 if (options->num_system_hostfiles == 0) { 2539 options->system_hostfiles[options->num_system_hostfiles++] = 2540 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE); 2541 options->system_hostfiles[options->num_system_hostfiles++] = 2542 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2); 2543 } 2544 if (options->update_hostkeys == -1) { 2545 if (options->verify_host_key_dns <= 0 && 2546 (options->num_user_hostfiles == 0 || 2547 (options->num_user_hostfiles == 1 && strcmp(options-> 2548 user_hostfiles[0], _PATH_SSH_USER_HOSTFILE) == 0))) 2549 options->update_hostkeys = SSH_UPDATE_HOSTKEYS_YES; 2550 else 2551 options->update_hostkeys = SSH_UPDATE_HOSTKEYS_NO; 2552 } 2553 if (options->num_user_hostfiles == 0) { 2554 options->user_hostfiles[options->num_user_hostfiles++] = 2555 xstrdup(_PATH_SSH_USER_HOSTFILE); 2556 options->user_hostfiles[options->num_user_hostfiles++] = 2557 xstrdup(_PATH_SSH_USER_HOSTFILE2); 2558 } 2559 if (options->log_level == SYSLOG_LEVEL_NOT_SET) 2560 options->log_level = SYSLOG_LEVEL_INFO; 2561 if (options->log_facility == SYSLOG_FACILITY_NOT_SET) 2562 options->log_facility = SYSLOG_FACILITY_USER; 2563 if (options->no_host_authentication_for_localhost == - 1) 2564 options->no_host_authentication_for_localhost = 0; 2565 if (options->identities_only == -1) 2566 options->identities_only = 0; 2567 if (options->enable_ssh_keysign == -1) 2568 options->enable_ssh_keysign = 0; 2569 if (options->rekey_limit == -1) 2570 options->rekey_limit = 0; 2571 if (options->rekey_interval == -1) 2572 options->rekey_interval = 0; 2573 if (options->verify_host_key_dns == -1) 2574 options->verify_host_key_dns = 0; 2575 if (options->server_alive_interval == -1) 2576 options->server_alive_interval = 0; 2577 if (options->server_alive_count_max == -1) 2578 options->server_alive_count_max = 3; 2579 if (options->control_master == -1) 2580 options->control_master = 0; 2581 if (options->control_persist == -1) { 2582 options->control_persist = 0; 2583 options->control_persist_timeout = 0; 2584 } 2585 if (options->hash_known_hosts == -1) 2586 options->hash_known_hosts = 0; 2587 if (options->tun_open == -1) 2588 options->tun_open = SSH_TUNMODE_NO; 2589 if (options->tun_local == -1) 2590 options->tun_local = SSH_TUNID_ANY; 2591 if (options->tun_remote == -1) 2592 options->tun_remote = SSH_TUNID_ANY; 2593 if (options->permit_local_command == -1) 2594 options->permit_local_command = 0; 2595 if (options->visual_host_key == -1) 2596 options->visual_host_key = 0; 2597 if (options->ip_qos_interactive == -1) 2598 options->ip_qos_interactive = IPTOS_DSCP_AF21; 2599 if (options->ip_qos_bulk == -1) 2600 options->ip_qos_bulk = IPTOS_DSCP_CS1; 2601 if (options->request_tty == -1) 2602 options->request_tty = REQUEST_TTY_AUTO; 2603 if (options->session_type == -1) 2604 options->session_type = SESSION_TYPE_DEFAULT; 2605 if (options->stdin_null == -1) 2606 options->stdin_null = 0; 2607 if (options->fork_after_authentication == -1) 2608 options->fork_after_authentication = 0; 2609 if (options->proxy_use_fdpass == -1) 2610 options->proxy_use_fdpass = 0; 2611 if (options->canonicalize_max_dots == -1) 2612 options->canonicalize_max_dots = 1; 2613 if (options->canonicalize_fallback_local == -1) 2614 options->canonicalize_fallback_local = 1; 2615 if (options->canonicalize_hostname == -1) 2616 options->canonicalize_hostname = SSH_CANONICALISE_NO; 2617 if (options->fingerprint_hash == -1) 2618 options->fingerprint_hash = SSH_FP_HASH_DEFAULT; 2619 if (options->sk_provider == NULL) 2620 options->sk_provider = xstrdup("internal"); 2621 if (options->required_rsa_size == -1) 2622 options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE; 2623 if (options->enable_escape_commandline == -1) 2624 options->enable_escape_commandline = 0; 2625 2626 /* Expand KEX name lists */ 2627 all_cipher = cipher_alg_list(',', 0); 2628 all_mac = mac_alg_list(','); 2629 all_kex = kex_alg_list(','); 2630 all_key = sshkey_alg_list(0, 0, 1, ','); 2631 all_sig = sshkey_alg_list(0, 1, 1, ','); 2632 /* remove unsupported algos from default lists */ 2633 def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher); 2634 def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac); 2635 def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex); 2636 def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key); 2637 def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig); 2638 #define ASSEMBLE(what, defaults, all) \ 2639 do { \ 2640 if ((r = kex_assemble_names(&options->what, \ 2641 defaults, all)) != 0) { \ 2642 error_fr(r, "%s", #what); \ 2643 goto fail; \ 2644 } \ 2645 } while (0) 2646 ASSEMBLE(ciphers, def_cipher, all_cipher); 2647 ASSEMBLE(macs, def_mac, all_mac); 2648 ASSEMBLE(kex_algorithms, def_kex, all_kex); 2649 ASSEMBLE(hostbased_accepted_algos, def_key, all_key); 2650 ASSEMBLE(pubkey_accepted_algos, def_key, all_key); 2651 ASSEMBLE(ca_sign_algorithms, def_sig, all_sig); 2652 #undef ASSEMBLE 2653 2654 #define CLEAR_ON_NONE(v) \ 2655 do { \ 2656 if (option_clear_or_none(v)) { \ 2657 free(v); \ 2658 v = NULL; \ 2659 } \ 2660 } while(0) 2661 CLEAR_ON_NONE(options->local_command); 2662 CLEAR_ON_NONE(options->remote_command); 2663 CLEAR_ON_NONE(options->proxy_command); 2664 CLEAR_ON_NONE(options->control_path); 2665 CLEAR_ON_NONE(options->revoked_host_keys); 2666 CLEAR_ON_NONE(options->pkcs11_provider); 2667 CLEAR_ON_NONE(options->sk_provider); 2668 CLEAR_ON_NONE(options->known_hosts_command); 2669 if (options->jump_host != NULL && 2670 strcmp(options->jump_host, "none") == 0 && 2671 options->jump_port == 0 && options->jump_user == NULL) { 2672 free(options->jump_host); 2673 options->jump_host = NULL; 2674 } 2675 if (options->num_permitted_cnames == 1 && 2676 !config_has_permitted_cnames(options)) { 2677 /* clean up CanonicalizePermittedCNAMEs=none */ 2678 free(options->permitted_cnames[0].source_list); 2679 free(options->permitted_cnames[0].target_list); 2680 memset(options->permitted_cnames, '\0', 2681 sizeof(*options->permitted_cnames)); 2682 options->num_permitted_cnames = 0; 2683 } 2684 /* options->identity_agent distinguishes NULL from 'none' */ 2685 /* options->user will be set in the main program if appropriate */ 2686 /* options->hostname will be set in the main program if appropriate */ 2687 /* options->host_key_alias should not be set by default */ 2688 /* options->preferred_authentications will be set in ssh */ 2689 2690 /* success */ 2691 ret = 0; 2692 fail: 2693 free(all_cipher); 2694 free(all_mac); 2695 free(all_kex); 2696 free(all_key); 2697 free(all_sig); 2698 free(def_cipher); 2699 free(def_mac); 2700 free(def_kex); 2701 free(def_key); 2702 free(def_sig); 2703 return ret; 2704 } 2705 2706 void 2707 free_options(Options *o) 2708 { 2709 int i; 2710 2711 if (o == NULL) 2712 return; 2713 2714 #define FREE_ARRAY(type, n, a) \ 2715 do { \ 2716 type _i; \ 2717 for (_i = 0; _i < (n); _i++) \ 2718 free((a)[_i]); \ 2719 } while (0) 2720 2721 free(o->forward_agent_sock_path); 2722 free(o->xauth_location); 2723 FREE_ARRAY(u_int, o->num_log_verbose, o->log_verbose); 2724 free(o->log_verbose); 2725 free(o->ciphers); 2726 free(o->macs); 2727 free(o->hostkeyalgorithms); 2728 free(o->kex_algorithms); 2729 free(o->ca_sign_algorithms); 2730 free(o->hostname); 2731 free(o->host_key_alias); 2732 free(o->proxy_command); 2733 free(o->user); 2734 FREE_ARRAY(u_int, o->num_system_hostfiles, o->system_hostfiles); 2735 FREE_ARRAY(u_int, o->num_user_hostfiles, o->user_hostfiles); 2736 free(o->preferred_authentications); 2737 free(o->bind_address); 2738 free(o->bind_interface); 2739 free(o->pkcs11_provider); 2740 free(o->sk_provider); 2741 for (i = 0; i < o->num_identity_files; i++) { 2742 free(o->identity_files[i]); 2743 sshkey_free(o->identity_keys[i]); 2744 } 2745 for (i = 0; i < o->num_certificate_files; i++) { 2746 free(o->certificate_files[i]); 2747 sshkey_free(o->certificates[i]); 2748 } 2749 free(o->identity_agent); 2750 for (i = 0; i < o->num_local_forwards; i++) { 2751 free(o->local_forwards[i].listen_host); 2752 free(o->local_forwards[i].listen_path); 2753 free(o->local_forwards[i].connect_host); 2754 free(o->local_forwards[i].connect_path); 2755 } 2756 free(o->local_forwards); 2757 for (i = 0; i < o->num_remote_forwards; i++) { 2758 free(o->remote_forwards[i].listen_host); 2759 free(o->remote_forwards[i].listen_path); 2760 free(o->remote_forwards[i].connect_host); 2761 free(o->remote_forwards[i].connect_path); 2762 } 2763 free(o->remote_forwards); 2764 free(o->stdio_forward_host); 2765 FREE_ARRAY(u_int, o->num_send_env, o->send_env); 2766 free(o->send_env); 2767 FREE_ARRAY(u_int, o->num_setenv, o->setenv); 2768 free(o->setenv); 2769 free(o->control_path); 2770 free(o->local_command); 2771 free(o->remote_command); 2772 FREE_ARRAY(int, o->num_canonical_domains, o->canonical_domains); 2773 for (i = 0; i < o->num_permitted_cnames; i++) { 2774 free(o->permitted_cnames[i].source_list); 2775 free(o->permitted_cnames[i].target_list); 2776 } 2777 free(o->revoked_host_keys); 2778 free(o->hostbased_accepted_algos); 2779 free(o->pubkey_accepted_algos); 2780 free(o->jump_user); 2781 free(o->jump_host); 2782 free(o->jump_extra); 2783 free(o->ignored_unknown); 2784 explicit_bzero(o, sizeof(*o)); 2785 #undef FREE_ARRAY 2786 } 2787 2788 struct fwdarg { 2789 char *arg; 2790 int ispath; 2791 }; 2792 2793 /* 2794 * parse_fwd_field 2795 * parses the next field in a port forwarding specification. 2796 * sets fwd to the parsed field and advances p past the colon 2797 * or sets it to NULL at end of string. 2798 * returns 0 on success, else non-zero. 2799 */ 2800 static int 2801 parse_fwd_field(char **p, struct fwdarg *fwd) 2802 { 2803 char *ep, *cp = *p; 2804 int ispath = 0; 2805 2806 if (*cp == '\0') { 2807 *p = NULL; 2808 return -1; /* end of string */ 2809 } 2810 2811 /* 2812 * A field escaped with square brackets is used literally. 2813 * XXX - allow ']' to be escaped via backslash? 2814 */ 2815 if (*cp == '[') { 2816 /* find matching ']' */ 2817 for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) { 2818 if (*ep == '/') 2819 ispath = 1; 2820 } 2821 /* no matching ']' or not at end of field. */ 2822 if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0')) 2823 return -1; 2824 /* NUL terminate the field and advance p past the colon */ 2825 *ep++ = '\0'; 2826 if (*ep != '\0') 2827 *ep++ = '\0'; 2828 fwd->arg = cp + 1; 2829 fwd->ispath = ispath; 2830 *p = ep; 2831 return 0; 2832 } 2833 2834 for (cp = *p; *cp != '\0'; cp++) { 2835 switch (*cp) { 2836 case '\\': 2837 memmove(cp, cp + 1, strlen(cp + 1) + 1); 2838 if (*cp == '\0') 2839 return -1; 2840 break; 2841 case '/': 2842 ispath = 1; 2843 break; 2844 case ':': 2845 *cp++ = '\0'; 2846 goto done; 2847 } 2848 } 2849 done: 2850 fwd->arg = *p; 2851 fwd->ispath = ispath; 2852 *p = cp; 2853 return 0; 2854 } 2855 2856 /* 2857 * parse_forward 2858 * parses a string containing a port forwarding specification of the form: 2859 * dynamicfwd == 0 2860 * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath 2861 * listenpath:connectpath 2862 * dynamicfwd == 1 2863 * [listenhost:]listenport 2864 * returns number of arguments parsed or zero on error 2865 */ 2866 int 2867 parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) 2868 { 2869 struct fwdarg fwdargs[4]; 2870 char *p, *cp; 2871 int i, err; 2872 2873 memset(fwd, 0, sizeof(*fwd)); 2874 memset(fwdargs, 0, sizeof(fwdargs)); 2875 2876 /* 2877 * We expand environment variables before checking if we think they're 2878 * paths so that if ${VAR} expands to a fully qualified path it is 2879 * treated as a path. 2880 */ 2881 cp = p = dollar_expand(&err, fwdspec); 2882 if (p == NULL || err) 2883 return 0; 2884 2885 /* skip leading spaces */ 2886 while (isspace((u_char)*cp)) 2887 cp++; 2888 2889 for (i = 0; i < 4; ++i) { 2890 if (parse_fwd_field(&cp, &fwdargs[i]) != 0) 2891 break; 2892 } 2893 2894 /* Check for trailing garbage */ 2895 if (cp != NULL && *cp != '\0') { 2896 i = 0; /* failure */ 2897 } 2898 2899 switch (i) { 2900 case 1: 2901 if (fwdargs[0].ispath) { 2902 fwd->listen_path = xstrdup(fwdargs[0].arg); 2903 fwd->listen_port = PORT_STREAMLOCAL; 2904 } else { 2905 fwd->listen_host = NULL; 2906 fwd->listen_port = a2port(fwdargs[0].arg); 2907 } 2908 fwd->connect_host = xstrdup("socks"); 2909 break; 2910 2911 case 2: 2912 if (fwdargs[0].ispath && fwdargs[1].ispath) { 2913 fwd->listen_path = xstrdup(fwdargs[0].arg); 2914 fwd->listen_port = PORT_STREAMLOCAL; 2915 fwd->connect_path = xstrdup(fwdargs[1].arg); 2916 fwd->connect_port = PORT_STREAMLOCAL; 2917 } else if (fwdargs[1].ispath) { 2918 fwd->listen_host = NULL; 2919 fwd->listen_port = a2port(fwdargs[0].arg); 2920 fwd->connect_path = xstrdup(fwdargs[1].arg); 2921 fwd->connect_port = PORT_STREAMLOCAL; 2922 } else { 2923 fwd->listen_host = xstrdup(fwdargs[0].arg); 2924 fwd->listen_port = a2port(fwdargs[1].arg); 2925 fwd->connect_host = xstrdup("socks"); 2926 } 2927 break; 2928 2929 case 3: 2930 if (fwdargs[0].ispath) { 2931 fwd->listen_path = xstrdup(fwdargs[0].arg); 2932 fwd->listen_port = PORT_STREAMLOCAL; 2933 fwd->connect_host = xstrdup(fwdargs[1].arg); 2934 fwd->connect_port = a2port(fwdargs[2].arg); 2935 } else if (fwdargs[2].ispath) { 2936 fwd->listen_host = xstrdup(fwdargs[0].arg); 2937 fwd->listen_port = a2port(fwdargs[1].arg); 2938 fwd->connect_path = xstrdup(fwdargs[2].arg); 2939 fwd->connect_port = PORT_STREAMLOCAL; 2940 } else { 2941 fwd->listen_host = NULL; 2942 fwd->listen_port = a2port(fwdargs[0].arg); 2943 fwd->connect_host = xstrdup(fwdargs[1].arg); 2944 fwd->connect_port = a2port(fwdargs[2].arg); 2945 } 2946 break; 2947 2948 case 4: 2949 fwd->listen_host = xstrdup(fwdargs[0].arg); 2950 fwd->listen_port = a2port(fwdargs[1].arg); 2951 fwd->connect_host = xstrdup(fwdargs[2].arg); 2952 fwd->connect_port = a2port(fwdargs[3].arg); 2953 break; 2954 default: 2955 i = 0; /* failure */ 2956 } 2957 2958 free(p); 2959 2960 if (dynamicfwd) { 2961 if (!(i == 1 || i == 2)) 2962 goto fail_free; 2963 } else { 2964 if (!(i == 3 || i == 4)) { 2965 if (fwd->connect_path == NULL && 2966 fwd->listen_path == NULL) 2967 goto fail_free; 2968 } 2969 if (fwd->connect_port <= 0 && fwd->connect_path == NULL) 2970 goto fail_free; 2971 } 2972 2973 if ((fwd->listen_port < 0 && fwd->listen_path == NULL) || 2974 (!remotefwd && fwd->listen_port == 0)) 2975 goto fail_free; 2976 if (fwd->connect_host != NULL && 2977 strlen(fwd->connect_host) >= NI_MAXHOST) 2978 goto fail_free; 2979 /* 2980 * XXX - if connecting to a remote socket, max sun len may not 2981 * match this host 2982 */ 2983 if (fwd->connect_path != NULL && 2984 strlen(fwd->connect_path) >= PATH_MAX_SUN) 2985 goto fail_free; 2986 if (fwd->listen_host != NULL && 2987 strlen(fwd->listen_host) >= NI_MAXHOST) 2988 goto fail_free; 2989 if (fwd->listen_path != NULL && 2990 strlen(fwd->listen_path) >= PATH_MAX_SUN) 2991 goto fail_free; 2992 2993 return (i); 2994 2995 fail_free: 2996 free(fwd->connect_host); 2997 fwd->connect_host = NULL; 2998 free(fwd->connect_path); 2999 fwd->connect_path = NULL; 3000 free(fwd->listen_host); 3001 fwd->listen_host = NULL; 3002 free(fwd->listen_path); 3003 fwd->listen_path = NULL; 3004 return (0); 3005 } 3006 3007 int 3008 parse_jump(const char *s, Options *o, int active) 3009 { 3010 char *orig, *sdup, *cp; 3011 char *host = NULL, *user = NULL; 3012 int r, ret = -1, port = -1, first; 3013 3014 active &= o->proxy_command == NULL && o->jump_host == NULL; 3015 3016 orig = sdup = xstrdup(s); 3017 3018 /* Remove comment and trailing whitespace */ 3019 if ((cp = strchr(orig, '#')) != NULL) 3020 *cp = '\0'; 3021 rtrim(orig); 3022 3023 first = active; 3024 do { 3025 if (strcasecmp(s, "none") == 0) 3026 break; 3027 if ((cp = strrchr(sdup, ',')) == NULL) 3028 cp = sdup; /* last */ 3029 else 3030 *cp++ = '\0'; 3031 3032 if (first) { 3033 /* First argument and configuration is active */ 3034 r = parse_ssh_uri(cp, &user, &host, &port); 3035 if (r == -1 || (r == 1 && 3036 parse_user_host_port(cp, &user, &host, &port) != 0)) 3037 goto out; 3038 } else { 3039 /* Subsequent argument or inactive configuration */ 3040 r = parse_ssh_uri(cp, NULL, NULL, NULL); 3041 if (r == -1 || (r == 1 && 3042 parse_user_host_port(cp, NULL, NULL, NULL) != 0)) 3043 goto out; 3044 } 3045 first = 0; /* only check syntax for subsequent hosts */ 3046 } while (cp != sdup); 3047 /* success */ 3048 if (active) { 3049 if (strcasecmp(s, "none") == 0) { 3050 o->jump_host = xstrdup("none"); 3051 o->jump_port = 0; 3052 } else { 3053 o->jump_user = user; 3054 o->jump_host = host; 3055 o->jump_port = port; 3056 o->proxy_command = xstrdup("none"); 3057 user = host = NULL; 3058 if ((cp = strrchr(s, ',')) != NULL && cp != s) { 3059 o->jump_extra = xstrdup(s); 3060 o->jump_extra[cp - s] = '\0'; 3061 } 3062 } 3063 } 3064 ret = 0; 3065 out: 3066 free(orig); 3067 free(user); 3068 free(host); 3069 return ret; 3070 } 3071 3072 int 3073 parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp) 3074 { 3075 char *user = NULL, *host = NULL, *path = NULL; 3076 int r, port; 3077 3078 r = parse_uri("ssh", uri, &user, &host, &port, &path); 3079 if (r == 0 && path != NULL) 3080 r = -1; /* path not allowed */ 3081 if (r == 0) { 3082 if (userp != NULL) { 3083 *userp = user; 3084 user = NULL; 3085 } 3086 if (hostp != NULL) { 3087 *hostp = host; 3088 host = NULL; 3089 } 3090 if (portp != NULL) 3091 *portp = port; 3092 } 3093 free(user); 3094 free(host); 3095 free(path); 3096 return r; 3097 } 3098 3099 /* XXX the following is a near-vebatim copy from servconf.c; refactor */ 3100 static const char * 3101 fmt_multistate_int(int val, const struct multistate *m) 3102 { 3103 u_int i; 3104 3105 for (i = 0; m[i].key != NULL; i++) { 3106 if (m[i].value == val) 3107 return m[i].key; 3108 } 3109 return "UNKNOWN"; 3110 } 3111 3112 static const char * 3113 fmt_intarg(OpCodes code, int val) 3114 { 3115 if (val == -1) 3116 return "unset"; 3117 switch (code) { 3118 case oAddressFamily: 3119 return fmt_multistate_int(val, multistate_addressfamily); 3120 case oVerifyHostKeyDNS: 3121 case oUpdateHostkeys: 3122 return fmt_multistate_int(val, multistate_yesnoask); 3123 case oStrictHostKeyChecking: 3124 return fmt_multistate_int(val, multistate_strict_hostkey); 3125 case oControlMaster: 3126 return fmt_multistate_int(val, multistate_controlmaster); 3127 case oTunnel: 3128 return fmt_multistate_int(val, multistate_tunnel); 3129 case oRequestTTY: 3130 return fmt_multistate_int(val, multistate_requesttty); 3131 case oSessionType: 3132 return fmt_multistate_int(val, multistate_sessiontype); 3133 case oCanonicalizeHostname: 3134 return fmt_multistate_int(val, multistate_canonicalizehostname); 3135 case oAddKeysToAgent: 3136 return fmt_multistate_int(val, multistate_yesnoaskconfirm); 3137 case oPubkeyAuthentication: 3138 return fmt_multistate_int(val, multistate_pubkey_auth); 3139 case oFingerprintHash: 3140 return ssh_digest_alg_name(val); 3141 default: 3142 switch (val) { 3143 case 0: 3144 return "no"; 3145 case 1: 3146 return "yes"; 3147 default: 3148 return "UNKNOWN"; 3149 } 3150 } 3151 } 3152 3153 static const char * 3154 lookup_opcode_name(OpCodes code) 3155 { 3156 u_int i; 3157 3158 for (i = 0; keywords[i].name != NULL; i++) 3159 if (keywords[i].opcode == code) 3160 return(keywords[i].name); 3161 return "UNKNOWN"; 3162 } 3163 3164 static void 3165 dump_cfg_int(OpCodes code, int val) 3166 { 3167 printf("%s %d\n", lookup_opcode_name(code), val); 3168 } 3169 3170 static void 3171 dump_cfg_fmtint(OpCodes code, int val) 3172 { 3173 printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val)); 3174 } 3175 3176 static void 3177 dump_cfg_string(OpCodes code, const char *val) 3178 { 3179 if (val == NULL) 3180 return; 3181 printf("%s %s\n", lookup_opcode_name(code), val); 3182 } 3183 3184 static void 3185 dump_cfg_strarray(OpCodes code, u_int count, char **vals) 3186 { 3187 u_int i; 3188 3189 for (i = 0; i < count; i++) 3190 printf("%s %s\n", lookup_opcode_name(code), vals[i]); 3191 } 3192 3193 static void 3194 dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals) 3195 { 3196 u_int i; 3197 3198 printf("%s", lookup_opcode_name(code)); 3199 if (count == 0) 3200 printf(" none"); 3201 for (i = 0; i < count; i++) 3202 printf(" %s", vals[i]); 3203 printf("\n"); 3204 } 3205 3206 static void 3207 dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds) 3208 { 3209 const struct Forward *fwd; 3210 u_int i; 3211 3212 /* oDynamicForward */ 3213 for (i = 0; i < count; i++) { 3214 fwd = &fwds[i]; 3215 if (code == oDynamicForward && fwd->connect_host != NULL && 3216 strcmp(fwd->connect_host, "socks") != 0) 3217 continue; 3218 if (code == oLocalForward && fwd->connect_host != NULL && 3219 strcmp(fwd->connect_host, "socks") == 0) 3220 continue; 3221 printf("%s", lookup_opcode_name(code)); 3222 if (fwd->listen_port == PORT_STREAMLOCAL) 3223 printf(" %s", fwd->listen_path); 3224 else if (fwd->listen_host == NULL) 3225 printf(" %d", fwd->listen_port); 3226 else { 3227 printf(" [%s]:%d", 3228 fwd->listen_host, fwd->listen_port); 3229 } 3230 if (code != oDynamicForward) { 3231 if (fwd->connect_port == PORT_STREAMLOCAL) 3232 printf(" %s", fwd->connect_path); 3233 else if (fwd->connect_host == NULL) 3234 printf(" %d", fwd->connect_port); 3235 else { 3236 printf(" [%s]:%d", 3237 fwd->connect_host, fwd->connect_port); 3238 } 3239 } 3240 printf("\n"); 3241 } 3242 } 3243 3244 void 3245 dump_client_config(Options *o, const char *host) 3246 { 3247 int i, r; 3248 char buf[8], *all_key; 3249 3250 /* 3251 * Expand HostKeyAlgorithms name lists. This isn't handled in 3252 * fill_default_options() like the other algorithm lists because 3253 * the host key algorithms are by default dynamically chosen based 3254 * on the host's keys found in known_hosts. 3255 */ 3256 all_key = sshkey_alg_list(0, 0, 1, ','); 3257 if ((r = kex_assemble_names(&o->hostkeyalgorithms, kex_default_pk_alg(), 3258 all_key)) != 0) 3259 fatal_fr(r, "expand HostKeyAlgorithms"); 3260 free(all_key); 3261 3262 /* Most interesting options first: user, host, port */ 3263 dump_cfg_string(oHost, o->host_arg); 3264 dump_cfg_string(oUser, o->user); 3265 dump_cfg_string(oHostname, host); 3266 dump_cfg_int(oPort, o->port); 3267 3268 /* Flag options */ 3269 dump_cfg_fmtint(oAddressFamily, o->address_family); 3270 dump_cfg_fmtint(oBatchMode, o->batch_mode); 3271 dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local); 3272 dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname); 3273 dump_cfg_fmtint(oCheckHostIP, o->check_host_ip); 3274 dump_cfg_fmtint(oCompression, o->compression); 3275 dump_cfg_fmtint(oControlMaster, o->control_master); 3276 dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign); 3277 dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings); 3278 dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure); 3279 dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash); 3280 dump_cfg_fmtint(oForwardX11, o->forward_x11); 3281 dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted); 3282 dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports); 3283 #ifdef GSSAPI 3284 dump_cfg_fmtint(oGssAuthentication, o->gss_authentication); 3285 dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds); 3286 #endif /* GSSAPI */ 3287 dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts); 3288 dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication); 3289 dump_cfg_fmtint(oIdentitiesOnly, o->identities_only); 3290 dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication); 3291 dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost); 3292 dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication); 3293 dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command); 3294 dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass); 3295 dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication); 3296 dump_cfg_fmtint(oRequestTTY, o->request_tty); 3297 dump_cfg_fmtint(oSessionType, o->session_type); 3298 dump_cfg_fmtint(oStdinNull, o->stdin_null); 3299 dump_cfg_fmtint(oForkAfterAuthentication, o->fork_after_authentication); 3300 dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink); 3301 dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking); 3302 dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive); 3303 dump_cfg_fmtint(oTunnel, o->tun_open); 3304 dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns); 3305 dump_cfg_fmtint(oVisualHostKey, o->visual_host_key); 3306 dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys); 3307 dump_cfg_fmtint(oEnableEscapeCommandline, o->enable_escape_commandline); 3308 3309 /* Integer options */ 3310 dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots); 3311 dump_cfg_int(oConnectionAttempts, o->connection_attempts); 3312 dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout); 3313 dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts); 3314 dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max); 3315 dump_cfg_int(oServerAliveInterval, o->server_alive_interval); 3316 dump_cfg_int(oRequiredRSASize, o->required_rsa_size); 3317 3318 /* String options */ 3319 dump_cfg_string(oBindAddress, o->bind_address); 3320 dump_cfg_string(oBindInterface, o->bind_interface); 3321 dump_cfg_string(oCiphers, o->ciphers); 3322 dump_cfg_string(oControlPath, o->control_path); 3323 dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms); 3324 dump_cfg_string(oHostKeyAlias, o->host_key_alias); 3325 dump_cfg_string(oHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos); 3326 dump_cfg_string(oIdentityAgent, o->identity_agent); 3327 dump_cfg_string(oIgnoreUnknown, o->ignored_unknown); 3328 dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices); 3329 dump_cfg_string(oKexAlgorithms, o->kex_algorithms); 3330 dump_cfg_string(oCASignatureAlgorithms, o->ca_sign_algorithms); 3331 dump_cfg_string(oLocalCommand, o->local_command); 3332 dump_cfg_string(oRemoteCommand, o->remote_command); 3333 dump_cfg_string(oLogLevel, log_level_name(o->log_level)); 3334 dump_cfg_string(oMacs, o->macs); 3335 #ifdef ENABLE_PKCS11 3336 dump_cfg_string(oPKCS11Provider, o->pkcs11_provider); 3337 #endif 3338 dump_cfg_string(oSecurityKeyProvider, o->sk_provider); 3339 dump_cfg_string(oPreferredAuthentications, o->preferred_authentications); 3340 dump_cfg_string(oPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos); 3341 dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys); 3342 dump_cfg_string(oXAuthLocation, o->xauth_location); 3343 dump_cfg_string(oKnownHostsCommand, o->known_hosts_command); 3344 3345 /* Forwards */ 3346 dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards); 3347 dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards); 3348 dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards); 3349 3350 /* String array options */ 3351 dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files); 3352 dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains); 3353 dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files); 3354 dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles); 3355 dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles); 3356 dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env); 3357 dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv); 3358 dump_cfg_strarray_oneline(oLogVerbose, 3359 o->num_log_verbose, o->log_verbose); 3360 3361 /* Special cases */ 3362 3363 /* PermitRemoteOpen */ 3364 if (o->num_permitted_remote_opens == 0) 3365 printf("%s any\n", lookup_opcode_name(oPermitRemoteOpen)); 3366 else 3367 dump_cfg_strarray_oneline(oPermitRemoteOpen, 3368 o->num_permitted_remote_opens, o->permitted_remote_opens); 3369 3370 /* AddKeysToAgent */ 3371 if (o->add_keys_to_agent_lifespan <= 0) 3372 dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent); 3373 else { 3374 printf("addkeystoagent%s %d\n", 3375 o->add_keys_to_agent == 3 ? " confirm" : "", 3376 o->add_keys_to_agent_lifespan); 3377 } 3378 3379 /* oForwardAgent */ 3380 if (o->forward_agent_sock_path == NULL) 3381 dump_cfg_fmtint(oForwardAgent, o->forward_agent); 3382 else 3383 dump_cfg_string(oForwardAgent, o->forward_agent_sock_path); 3384 3385 /* oConnectTimeout */ 3386 if (o->connection_timeout == -1) 3387 printf("connecttimeout none\n"); 3388 else 3389 dump_cfg_int(oConnectTimeout, o->connection_timeout); 3390 3391 /* oTunnelDevice */ 3392 printf("tunneldevice"); 3393 if (o->tun_local == SSH_TUNID_ANY) 3394 printf(" any"); 3395 else 3396 printf(" %d", o->tun_local); 3397 if (o->tun_remote == SSH_TUNID_ANY) 3398 printf(":any"); 3399 else 3400 printf(":%d", o->tun_remote); 3401 printf("\n"); 3402 3403 /* oCanonicalizePermittedCNAMEs */ 3404 printf("canonicalizePermittedcnames"); 3405 if (o->num_permitted_cnames == 0) 3406 printf(" none"); 3407 for (i = 0; i < o->num_permitted_cnames; i++) { 3408 printf(" %s:%s", o->permitted_cnames[i].source_list, 3409 o->permitted_cnames[i].target_list); 3410 } 3411 printf("\n"); 3412 3413 /* oControlPersist */ 3414 if (o->control_persist == 0 || o->control_persist_timeout == 0) 3415 dump_cfg_fmtint(oControlPersist, o->control_persist); 3416 else 3417 dump_cfg_int(oControlPersist, o->control_persist_timeout); 3418 3419 /* oEscapeChar */ 3420 if (o->escape_char == SSH_ESCAPECHAR_NONE) 3421 printf("escapechar none\n"); 3422 else { 3423 vis(buf, o->escape_char, VIS_WHITE, 0); 3424 printf("escapechar %s\n", buf); 3425 } 3426 3427 /* oIPQoS */ 3428 printf("ipqos %s ", iptos2str(o->ip_qos_interactive)); 3429 printf("%s\n", iptos2str(o->ip_qos_bulk)); 3430 3431 /* oRekeyLimit */ 3432 printf("rekeylimit %llu %d\n", 3433 (unsigned long long)o->rekey_limit, o->rekey_interval); 3434 3435 /* oStreamLocalBindMask */ 3436 printf("streamlocalbindmask 0%o\n", 3437 o->fwd_opts.streamlocal_bind_mask); 3438 3439 /* oLogFacility */ 3440 printf("syslogfacility %s\n", log_facility_name(o->log_facility)); 3441 3442 /* oProxyCommand / oProxyJump */ 3443 if (o->jump_host == NULL) 3444 dump_cfg_string(oProxyCommand, o->proxy_command); 3445 else { 3446 /* Check for numeric addresses */ 3447 i = strchr(o->jump_host, ':') != NULL || 3448 strspn(o->jump_host, "1234567890.") == strlen(o->jump_host); 3449 snprintf(buf, sizeof(buf), "%d", o->jump_port); 3450 printf("proxyjump %s%s%s%s%s%s%s%s%s\n", 3451 /* optional additional jump spec */ 3452 o->jump_extra == NULL ? "" : o->jump_extra, 3453 o->jump_extra == NULL ? "" : ",", 3454 /* optional user */ 3455 o->jump_user == NULL ? "" : o->jump_user, 3456 o->jump_user == NULL ? "" : "@", 3457 /* opening [ if hostname is numeric */ 3458 i ? "[" : "", 3459 /* mandatory hostname */ 3460 o->jump_host, 3461 /* closing ] if hostname is numeric */ 3462 i ? "]" : "", 3463 /* optional port number */ 3464 o->jump_port <= 0 ? "" : ":", 3465 o->jump_port <= 0 ? "" : buf); 3466 } 3467 } 3468