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