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