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