1 /* $OpenBSD: readconf.c,v 1.342 2020/11/15 22:34:58 djm Exp $ */ 2 /* 3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 5 * All rights reserved 6 * Functions for reading the configuration files. 7 * 8 * As far as I am concerned, the code I have written for this software 9 * can be used freely for any purpose. Any derived versions of this 10 * software must be clearly marked as such, and if the derived work is 11 * incompatible with the protocol description in the RFC file, it must be 12 * called by a name other than "ssh" or "Secure Shell". 13 */ 14 15 #include <sys/types.h> 16 #include <sys/stat.h> 17 #include <sys/socket.h> 18 #include <sys/wait.h> 19 #include <sys/un.h> 20 21 #include <netinet/in.h> 22 #include <netinet/ip.h> 23 24 #include <ctype.h> 25 #include <errno.h> 26 #include <fcntl.h> 27 #include <glob.h> 28 #include <netdb.h> 29 #include <paths.h> 30 #include <pwd.h> 31 #include <signal.h> 32 #include <stdio.h> 33 #include <string.h> 34 #include <stdarg.h> 35 #include <unistd.h> 36 #include <limits.h> 37 #include <util.h> 38 #include <vis.h> 39 40 #include "xmalloc.h" 41 #include "ssh.h" 42 #include "ssherr.h" 43 #include "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 *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 if (process_config_line_depth(options, pw, host, original_host, 1920 line, filename, linenum, activep, flags, want_final_pass, 1921 depth) != 0) 1922 bad_options++; 1923 } 1924 free(line); 1925 fclose(f); 1926 if (bad_options > 0) 1927 fatal("%s: terminating, %d bad configuration options", 1928 filename, bad_options); 1929 return 1; 1930 } 1931 1932 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ 1933 int 1934 option_clear_or_none(const char *o) 1935 { 1936 return o == NULL || strcasecmp(o, "none") == 0; 1937 } 1938 1939 /* 1940 * Initializes options to special values that indicate that they have not yet 1941 * been set. Read_config_file will only set options with this value. Options 1942 * are processed in the following order: command line, user config file, 1943 * system config file. Last, fill_default_options is called. 1944 */ 1945 1946 void 1947 initialize_options(Options * options) 1948 { 1949 memset(options, 'X', sizeof(*options)); 1950 options->forward_agent = -1; 1951 options->forward_agent_sock_path = NULL; 1952 options->forward_x11 = -1; 1953 options->forward_x11_trusted = -1; 1954 options->forward_x11_timeout = -1; 1955 options->stdio_forward_host = NULL; 1956 options->stdio_forward_port = 0; 1957 options->clear_forwardings = -1; 1958 options->exit_on_forward_failure = -1; 1959 options->xauth_location = NULL; 1960 options->fwd_opts.gateway_ports = -1; 1961 options->fwd_opts.streamlocal_bind_mask = (mode_t)-1; 1962 options->fwd_opts.streamlocal_bind_unlink = -1; 1963 options->pubkey_authentication = -1; 1964 options->challenge_response_authentication = -1; 1965 options->gss_authentication = -1; 1966 options->gss_deleg_creds = -1; 1967 options->password_authentication = -1; 1968 options->kbd_interactive_authentication = -1; 1969 options->kbd_interactive_devices = NULL; 1970 options->hostbased_authentication = -1; 1971 options->batch_mode = -1; 1972 options->check_host_ip = -1; 1973 options->strict_host_key_checking = -1; 1974 options->compression = -1; 1975 options->tcp_keep_alive = -1; 1976 options->port = -1; 1977 options->address_family = -1; 1978 options->connection_attempts = -1; 1979 options->connection_timeout = -1; 1980 options->number_of_password_prompts = -1; 1981 options->ciphers = NULL; 1982 options->macs = NULL; 1983 options->kex_algorithms = NULL; 1984 options->hostkeyalgorithms = NULL; 1985 options->ca_sign_algorithms = NULL; 1986 options->num_identity_files = 0; 1987 options->num_certificate_files = 0; 1988 options->hostname = NULL; 1989 options->host_key_alias = NULL; 1990 options->proxy_command = NULL; 1991 options->jump_user = NULL; 1992 options->jump_host = NULL; 1993 options->jump_port = -1; 1994 options->jump_extra = NULL; 1995 options->user = NULL; 1996 options->escape_char = -1; 1997 options->num_system_hostfiles = 0; 1998 options->num_user_hostfiles = 0; 1999 options->local_forwards = NULL; 2000 options->num_local_forwards = 0; 2001 options->remote_forwards = NULL; 2002 options->num_remote_forwards = 0; 2003 options->log_facility = SYSLOG_FACILITY_NOT_SET; 2004 options->log_level = SYSLOG_LEVEL_NOT_SET; 2005 options->num_log_verbose = 0; 2006 options->log_verbose = NULL; 2007 options->preferred_authentications = NULL; 2008 options->bind_address = NULL; 2009 options->bind_interface = NULL; 2010 options->pkcs11_provider = NULL; 2011 options->sk_provider = NULL; 2012 options->enable_ssh_keysign = - 1; 2013 options->no_host_authentication_for_localhost = - 1; 2014 options->identities_only = - 1; 2015 options->rekey_limit = - 1; 2016 options->rekey_interval = -1; 2017 options->verify_host_key_dns = -1; 2018 options->server_alive_interval = -1; 2019 options->server_alive_count_max = -1; 2020 options->send_env = NULL; 2021 options->num_send_env = 0; 2022 options->setenv = NULL; 2023 options->num_setenv = 0; 2024 options->control_path = NULL; 2025 options->control_master = -1; 2026 options->control_persist = -1; 2027 options->control_persist_timeout = 0; 2028 options->hash_known_hosts = -1; 2029 options->tun_open = -1; 2030 options->tun_local = -1; 2031 options->tun_remote = -1; 2032 options->local_command = NULL; 2033 options->permit_local_command = -1; 2034 options->remote_command = NULL; 2035 options->add_keys_to_agent = -1; 2036 options->add_keys_to_agent_lifespan = -1; 2037 options->identity_agent = NULL; 2038 options->visual_host_key = -1; 2039 options->ip_qos_interactive = -1; 2040 options->ip_qos_bulk = -1; 2041 options->request_tty = -1; 2042 options->proxy_use_fdpass = -1; 2043 options->ignored_unknown = NULL; 2044 options->num_canonical_domains = 0; 2045 options->num_permitted_cnames = 0; 2046 options->canonicalize_max_dots = -1; 2047 options->canonicalize_fallback_local = -1; 2048 options->canonicalize_hostname = -1; 2049 options->revoked_host_keys = NULL; 2050 options->fingerprint_hash = -1; 2051 options->update_hostkeys = -1; 2052 options->hostbased_key_types = NULL; 2053 options->pubkey_key_types = NULL; 2054 } 2055 2056 /* 2057 * A petite version of fill_default_options() that just fills the options 2058 * needed for hostname canonicalization to proceed. 2059 */ 2060 void 2061 fill_default_options_for_canonicalization(Options *options) 2062 { 2063 if (options->canonicalize_max_dots == -1) 2064 options->canonicalize_max_dots = 1; 2065 if (options->canonicalize_fallback_local == -1) 2066 options->canonicalize_fallback_local = 1; 2067 if (options->canonicalize_hostname == -1) 2068 options->canonicalize_hostname = SSH_CANONICALISE_NO; 2069 } 2070 2071 /* 2072 * Called after processing other sources of option data, this fills those 2073 * options for which no value has been specified with their default values. 2074 */ 2075 void 2076 fill_default_options(Options * options) 2077 { 2078 char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig; 2079 char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig; 2080 int r; 2081 2082 if (options->forward_agent == -1) 2083 options->forward_agent = 0; 2084 if (options->forward_x11 == -1) 2085 options->forward_x11 = 0; 2086 if (options->forward_x11_trusted == -1) 2087 options->forward_x11_trusted = 0; 2088 if (options->forward_x11_timeout == -1) 2089 options->forward_x11_timeout = 1200; 2090 /* 2091 * stdio forwarding (-W) changes the default for these but we defer 2092 * setting the values so they can be overridden. 2093 */ 2094 if (options->exit_on_forward_failure == -1) 2095 options->exit_on_forward_failure = 2096 options->stdio_forward_host != NULL ? 1 : 0; 2097 if (options->clear_forwardings == -1) 2098 options->clear_forwardings = 2099 options->stdio_forward_host != NULL ? 1 : 0; 2100 if (options->clear_forwardings == 1) 2101 clear_forwardings(options); 2102 2103 if (options->xauth_location == NULL) 2104 options->xauth_location = _PATH_XAUTH; 2105 if (options->fwd_opts.gateway_ports == -1) 2106 options->fwd_opts.gateway_ports = 0; 2107 if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1) 2108 options->fwd_opts.streamlocal_bind_mask = 0177; 2109 if (options->fwd_opts.streamlocal_bind_unlink == -1) 2110 options->fwd_opts.streamlocal_bind_unlink = 0; 2111 if (options->pubkey_authentication == -1) 2112 options->pubkey_authentication = 1; 2113 if (options->challenge_response_authentication == -1) 2114 options->challenge_response_authentication = 1; 2115 if (options->gss_authentication == -1) 2116 options->gss_authentication = 0; 2117 if (options->gss_deleg_creds == -1) 2118 options->gss_deleg_creds = 0; 2119 if (options->password_authentication == -1) 2120 options->password_authentication = 1; 2121 if (options->kbd_interactive_authentication == -1) 2122 options->kbd_interactive_authentication = 1; 2123 if (options->hostbased_authentication == -1) 2124 options->hostbased_authentication = 0; 2125 if (options->batch_mode == -1) 2126 options->batch_mode = 0; 2127 if (options->check_host_ip == -1) 2128 options->check_host_ip = 1; 2129 if (options->strict_host_key_checking == -1) 2130 options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK; 2131 if (options->compression == -1) 2132 options->compression = 0; 2133 if (options->tcp_keep_alive == -1) 2134 options->tcp_keep_alive = 1; 2135 if (options->port == -1) 2136 options->port = 0; /* Filled in ssh_connect. */ 2137 if (options->address_family == -1) 2138 options->address_family = AF_UNSPEC; 2139 if (options->connection_attempts == -1) 2140 options->connection_attempts = 1; 2141 if (options->number_of_password_prompts == -1) 2142 options->number_of_password_prompts = 3; 2143 /* options->hostkeyalgorithms, default set in myproposals.h */ 2144 if (options->add_keys_to_agent == -1) { 2145 options->add_keys_to_agent = 0; 2146 options->add_keys_to_agent_lifespan = 0; 2147 } 2148 if (options->num_identity_files == 0) { 2149 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0); 2150 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0); 2151 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0); 2152 add_identity_file(options, "~/", 2153 _PATH_SSH_CLIENT_ID_ECDSA_SK, 0); 2154 add_identity_file(options, "~/", 2155 _PATH_SSH_CLIENT_ID_ED25519, 0); 2156 add_identity_file(options, "~/", 2157 _PATH_SSH_CLIENT_ID_ED25519_SK, 0); 2158 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0); 2159 } 2160 if (options->escape_char == -1) 2161 options->escape_char = '~'; 2162 if (options->num_system_hostfiles == 0) { 2163 options->system_hostfiles[options->num_system_hostfiles++] = 2164 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE); 2165 options->system_hostfiles[options->num_system_hostfiles++] = 2166 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2); 2167 } 2168 if (options->update_hostkeys == -1) { 2169 if (options->verify_host_key_dns <= 0 && 2170 (options->num_user_hostfiles == 0 || 2171 (options->num_user_hostfiles == 1 && strcmp(options-> 2172 user_hostfiles[0], _PATH_SSH_USER_HOSTFILE) == 0))) 2173 options->update_hostkeys = SSH_UPDATE_HOSTKEYS_YES; 2174 else 2175 options->update_hostkeys = SSH_UPDATE_HOSTKEYS_NO; 2176 } 2177 if (options->num_user_hostfiles == 0) { 2178 options->user_hostfiles[options->num_user_hostfiles++] = 2179 xstrdup(_PATH_SSH_USER_HOSTFILE); 2180 options->user_hostfiles[options->num_user_hostfiles++] = 2181 xstrdup(_PATH_SSH_USER_HOSTFILE2); 2182 } 2183 if (options->log_level == SYSLOG_LEVEL_NOT_SET) 2184 options->log_level = SYSLOG_LEVEL_INFO; 2185 if (options->log_facility == SYSLOG_FACILITY_NOT_SET) 2186 options->log_facility = SYSLOG_FACILITY_USER; 2187 if (options->no_host_authentication_for_localhost == - 1) 2188 options->no_host_authentication_for_localhost = 0; 2189 if (options->identities_only == -1) 2190 options->identities_only = 0; 2191 if (options->enable_ssh_keysign == -1) 2192 options->enable_ssh_keysign = 0; 2193 if (options->rekey_limit == -1) 2194 options->rekey_limit = 0; 2195 if (options->rekey_interval == -1) 2196 options->rekey_interval = 0; 2197 if (options->verify_host_key_dns == -1) 2198 options->verify_host_key_dns = 0; 2199 if (options->server_alive_interval == -1) 2200 options->server_alive_interval = 0; 2201 if (options->server_alive_count_max == -1) 2202 options->server_alive_count_max = 3; 2203 if (options->control_master == -1) 2204 options->control_master = 0; 2205 if (options->control_persist == -1) { 2206 options->control_persist = 0; 2207 options->control_persist_timeout = 0; 2208 } 2209 if (options->hash_known_hosts == -1) 2210 options->hash_known_hosts = 0; 2211 if (options->tun_open == -1) 2212 options->tun_open = SSH_TUNMODE_NO; 2213 if (options->tun_local == -1) 2214 options->tun_local = SSH_TUNID_ANY; 2215 if (options->tun_remote == -1) 2216 options->tun_remote = SSH_TUNID_ANY; 2217 if (options->permit_local_command == -1) 2218 options->permit_local_command = 0; 2219 if (options->visual_host_key == -1) 2220 options->visual_host_key = 0; 2221 if (options->ip_qos_interactive == -1) 2222 options->ip_qos_interactive = IPTOS_DSCP_AF21; 2223 if (options->ip_qos_bulk == -1) 2224 options->ip_qos_bulk = IPTOS_DSCP_CS1; 2225 if (options->request_tty == -1) 2226 options->request_tty = REQUEST_TTY_AUTO; 2227 if (options->proxy_use_fdpass == -1) 2228 options->proxy_use_fdpass = 0; 2229 if (options->canonicalize_max_dots == -1) 2230 options->canonicalize_max_dots = 1; 2231 if (options->canonicalize_fallback_local == -1) 2232 options->canonicalize_fallback_local = 1; 2233 if (options->canonicalize_hostname == -1) 2234 options->canonicalize_hostname = SSH_CANONICALISE_NO; 2235 if (options->fingerprint_hash == -1) 2236 options->fingerprint_hash = SSH_FP_HASH_DEFAULT; 2237 if (options->sk_provider == NULL) 2238 options->sk_provider = xstrdup("internal"); 2239 2240 /* Expand KEX name lists */ 2241 all_cipher = cipher_alg_list(',', 0); 2242 all_mac = mac_alg_list(','); 2243 all_kex = kex_alg_list(','); 2244 all_key = sshkey_alg_list(0, 0, 1, ','); 2245 all_sig = sshkey_alg_list(0, 1, 1, ','); 2246 /* remove unsupported algos from default lists */ 2247 def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher); 2248 def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac); 2249 def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex); 2250 def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key); 2251 def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig); 2252 #define ASSEMBLE(what, defaults, all) \ 2253 do { \ 2254 if ((r = kex_assemble_names(&options->what, \ 2255 defaults, all)) != 0) \ 2256 fatal_fr(r, "%s", #what); \ 2257 } while (0) 2258 ASSEMBLE(ciphers, def_cipher, all_cipher); 2259 ASSEMBLE(macs, def_mac, all_mac); 2260 ASSEMBLE(kex_algorithms, def_kex, all_kex); 2261 ASSEMBLE(hostbased_key_types, def_key, all_key); 2262 ASSEMBLE(pubkey_key_types, def_key, all_key); 2263 ASSEMBLE(ca_sign_algorithms, def_sig, all_sig); 2264 #undef ASSEMBLE 2265 free(all_cipher); 2266 free(all_mac); 2267 free(all_kex); 2268 free(all_key); 2269 free(all_sig); 2270 free(def_cipher); 2271 free(def_mac); 2272 free(def_kex); 2273 kex_default_pk_alg_filtered = def_key; /* save for later use */ 2274 free(def_sig); 2275 2276 #define CLEAR_ON_NONE(v) \ 2277 do { \ 2278 if (option_clear_or_none(v)) { \ 2279 free(v); \ 2280 v = NULL; \ 2281 } \ 2282 } while(0) 2283 CLEAR_ON_NONE(options->local_command); 2284 CLEAR_ON_NONE(options->remote_command); 2285 CLEAR_ON_NONE(options->proxy_command); 2286 CLEAR_ON_NONE(options->control_path); 2287 CLEAR_ON_NONE(options->revoked_host_keys); 2288 CLEAR_ON_NONE(options->pkcs11_provider); 2289 CLEAR_ON_NONE(options->sk_provider); 2290 if (options->jump_host != NULL && 2291 strcmp(options->jump_host, "none") == 0 && 2292 options->jump_port == 0 && options->jump_user == NULL) { 2293 free(options->jump_host); 2294 options->jump_host = NULL; 2295 } 2296 /* options->identity_agent distinguishes NULL from 'none' */ 2297 /* options->user will be set in the main program if appropriate */ 2298 /* options->hostname will be set in the main program if appropriate */ 2299 /* options->host_key_alias should not be set by default */ 2300 /* options->preferred_authentications will be set in ssh */ 2301 } 2302 2303 struct fwdarg { 2304 char *arg; 2305 int ispath; 2306 }; 2307 2308 /* 2309 * parse_fwd_field 2310 * parses the next field in a port forwarding specification. 2311 * sets fwd to the parsed field and advances p past the colon 2312 * or sets it to NULL at end of string. 2313 * returns 0 on success, else non-zero. 2314 */ 2315 static int 2316 parse_fwd_field(char **p, struct fwdarg *fwd) 2317 { 2318 char *ep, *cp = *p; 2319 int ispath = 0; 2320 2321 if (*cp == '\0') { 2322 *p = NULL; 2323 return -1; /* end of string */ 2324 } 2325 2326 /* 2327 * A field escaped with square brackets is used literally. 2328 * XXX - allow ']' to be escaped via backslash? 2329 */ 2330 if (*cp == '[') { 2331 /* find matching ']' */ 2332 for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) { 2333 if (*ep == '/') 2334 ispath = 1; 2335 } 2336 /* no matching ']' or not at end of field. */ 2337 if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0')) 2338 return -1; 2339 /* NUL terminate the field and advance p past the colon */ 2340 *ep++ = '\0'; 2341 if (*ep != '\0') 2342 *ep++ = '\0'; 2343 fwd->arg = cp + 1; 2344 fwd->ispath = ispath; 2345 *p = ep; 2346 return 0; 2347 } 2348 2349 for (cp = *p; *cp != '\0'; cp++) { 2350 switch (*cp) { 2351 case '\\': 2352 memmove(cp, cp + 1, strlen(cp + 1) + 1); 2353 if (*cp == '\0') 2354 return -1; 2355 break; 2356 case '/': 2357 ispath = 1; 2358 break; 2359 case ':': 2360 *cp++ = '\0'; 2361 goto done; 2362 } 2363 } 2364 done: 2365 fwd->arg = *p; 2366 fwd->ispath = ispath; 2367 *p = cp; 2368 return 0; 2369 } 2370 2371 /* 2372 * parse_forward 2373 * parses a string containing a port forwarding specification of the form: 2374 * dynamicfwd == 0 2375 * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath 2376 * listenpath:connectpath 2377 * dynamicfwd == 1 2378 * [listenhost:]listenport 2379 * returns number of arguments parsed or zero on error 2380 */ 2381 int 2382 parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) 2383 { 2384 struct fwdarg fwdargs[4]; 2385 char *p, *cp; 2386 int i, err; 2387 2388 memset(fwd, 0, sizeof(*fwd)); 2389 memset(fwdargs, 0, sizeof(fwdargs)); 2390 2391 /* 2392 * We expand environment variables before checking if we think they're 2393 * paths so that if ${VAR} expands to a fully qualified path it is 2394 * treated as a path. 2395 */ 2396 cp = p = dollar_expand(&err, fwdspec); 2397 if (p == NULL || err) 2398 return 0; 2399 2400 /* skip leading spaces */ 2401 while (isspace((u_char)*cp)) 2402 cp++; 2403 2404 for (i = 0; i < 4; ++i) { 2405 if (parse_fwd_field(&cp, &fwdargs[i]) != 0) 2406 break; 2407 } 2408 2409 /* Check for trailing garbage */ 2410 if (cp != NULL && *cp != '\0') { 2411 i = 0; /* failure */ 2412 } 2413 2414 switch (i) { 2415 case 1: 2416 if (fwdargs[0].ispath) { 2417 fwd->listen_path = xstrdup(fwdargs[0].arg); 2418 fwd->listen_port = PORT_STREAMLOCAL; 2419 } else { 2420 fwd->listen_host = NULL; 2421 fwd->listen_port = a2port(fwdargs[0].arg); 2422 } 2423 fwd->connect_host = xstrdup("socks"); 2424 break; 2425 2426 case 2: 2427 if (fwdargs[0].ispath && fwdargs[1].ispath) { 2428 fwd->listen_path = xstrdup(fwdargs[0].arg); 2429 fwd->listen_port = PORT_STREAMLOCAL; 2430 fwd->connect_path = xstrdup(fwdargs[1].arg); 2431 fwd->connect_port = PORT_STREAMLOCAL; 2432 } else if (fwdargs[1].ispath) { 2433 fwd->listen_host = NULL; 2434 fwd->listen_port = a2port(fwdargs[0].arg); 2435 fwd->connect_path = xstrdup(fwdargs[1].arg); 2436 fwd->connect_port = PORT_STREAMLOCAL; 2437 } else { 2438 fwd->listen_host = xstrdup(fwdargs[0].arg); 2439 fwd->listen_port = a2port(fwdargs[1].arg); 2440 fwd->connect_host = xstrdup("socks"); 2441 } 2442 break; 2443 2444 case 3: 2445 if (fwdargs[0].ispath) { 2446 fwd->listen_path = xstrdup(fwdargs[0].arg); 2447 fwd->listen_port = PORT_STREAMLOCAL; 2448 fwd->connect_host = xstrdup(fwdargs[1].arg); 2449 fwd->connect_port = a2port(fwdargs[2].arg); 2450 } else if (fwdargs[2].ispath) { 2451 fwd->listen_host = xstrdup(fwdargs[0].arg); 2452 fwd->listen_port = a2port(fwdargs[1].arg); 2453 fwd->connect_path = xstrdup(fwdargs[2].arg); 2454 fwd->connect_port = PORT_STREAMLOCAL; 2455 } else { 2456 fwd->listen_host = NULL; 2457 fwd->listen_port = a2port(fwdargs[0].arg); 2458 fwd->connect_host = xstrdup(fwdargs[1].arg); 2459 fwd->connect_port = a2port(fwdargs[2].arg); 2460 } 2461 break; 2462 2463 case 4: 2464 fwd->listen_host = xstrdup(fwdargs[0].arg); 2465 fwd->listen_port = a2port(fwdargs[1].arg); 2466 fwd->connect_host = xstrdup(fwdargs[2].arg); 2467 fwd->connect_port = a2port(fwdargs[3].arg); 2468 break; 2469 default: 2470 i = 0; /* failure */ 2471 } 2472 2473 free(p); 2474 2475 if (dynamicfwd) { 2476 if (!(i == 1 || i == 2)) 2477 goto fail_free; 2478 } else { 2479 if (!(i == 3 || i == 4)) { 2480 if (fwd->connect_path == NULL && 2481 fwd->listen_path == NULL) 2482 goto fail_free; 2483 } 2484 if (fwd->connect_port <= 0 && fwd->connect_path == NULL) 2485 goto fail_free; 2486 } 2487 2488 if ((fwd->listen_port < 0 && fwd->listen_path == NULL) || 2489 (!remotefwd && fwd->listen_port == 0)) 2490 goto fail_free; 2491 if (fwd->connect_host != NULL && 2492 strlen(fwd->connect_host) >= NI_MAXHOST) 2493 goto fail_free; 2494 /* XXX - if connecting to a remote socket, max sun len may not match this host */ 2495 if (fwd->connect_path != NULL && 2496 strlen(fwd->connect_path) >= PATH_MAX_SUN) 2497 goto fail_free; 2498 if (fwd->listen_host != NULL && 2499 strlen(fwd->listen_host) >= NI_MAXHOST) 2500 goto fail_free; 2501 if (fwd->listen_path != NULL && 2502 strlen(fwd->listen_path) >= PATH_MAX_SUN) 2503 goto fail_free; 2504 2505 return (i); 2506 2507 fail_free: 2508 free(fwd->connect_host); 2509 fwd->connect_host = NULL; 2510 free(fwd->connect_path); 2511 fwd->connect_path = NULL; 2512 free(fwd->listen_host); 2513 fwd->listen_host = NULL; 2514 free(fwd->listen_path); 2515 fwd->listen_path = NULL; 2516 return (0); 2517 } 2518 2519 int 2520 parse_jump(const char *s, Options *o, int active) 2521 { 2522 char *orig, *sdup, *cp; 2523 char *host = NULL, *user = NULL; 2524 int ret = -1, port = -1, first; 2525 2526 active &= o->proxy_command == NULL && o->jump_host == NULL; 2527 2528 orig = sdup = xstrdup(s); 2529 first = active; 2530 do { 2531 if (strcasecmp(s, "none") == 0) 2532 break; 2533 if ((cp = strrchr(sdup, ',')) == NULL) 2534 cp = sdup; /* last */ 2535 else 2536 *cp++ = '\0'; 2537 2538 if (first) { 2539 /* First argument and configuration is active */ 2540 if (parse_ssh_uri(cp, &user, &host, &port) == -1 || 2541 parse_user_host_port(cp, &user, &host, &port) != 0) 2542 goto out; 2543 } else { 2544 /* Subsequent argument or inactive configuration */ 2545 if (parse_ssh_uri(cp, NULL, NULL, NULL) == -1 || 2546 parse_user_host_port(cp, NULL, NULL, NULL) != 0) 2547 goto out; 2548 } 2549 first = 0; /* only check syntax for subsequent hosts */ 2550 } while (cp != sdup); 2551 /* success */ 2552 if (active) { 2553 if (strcasecmp(s, "none") == 0) { 2554 o->jump_host = xstrdup("none"); 2555 o->jump_port = 0; 2556 } else { 2557 o->jump_user = user; 2558 o->jump_host = host; 2559 o->jump_port = port; 2560 o->proxy_command = xstrdup("none"); 2561 user = host = NULL; 2562 if ((cp = strrchr(s, ',')) != NULL && cp != s) { 2563 o->jump_extra = xstrdup(s); 2564 o->jump_extra[cp - s] = '\0'; 2565 } 2566 } 2567 } 2568 ret = 0; 2569 out: 2570 free(orig); 2571 free(user); 2572 free(host); 2573 return ret; 2574 } 2575 2576 int 2577 parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp) 2578 { 2579 char *path; 2580 int r; 2581 2582 r = parse_uri("ssh", uri, userp, hostp, portp, &path); 2583 if (r == 0 && path != NULL) 2584 r = -1; /* path not allowed */ 2585 return r; 2586 } 2587 2588 /* XXX the following is a near-vebatim copy from servconf.c; refactor */ 2589 static const char * 2590 fmt_multistate_int(int val, const struct multistate *m) 2591 { 2592 u_int i; 2593 2594 for (i = 0; m[i].key != NULL; i++) { 2595 if (m[i].value == val) 2596 return m[i].key; 2597 } 2598 return "UNKNOWN"; 2599 } 2600 2601 static const char * 2602 fmt_intarg(OpCodes code, int val) 2603 { 2604 if (val == -1) 2605 return "unset"; 2606 switch (code) { 2607 case oAddressFamily: 2608 return fmt_multistate_int(val, multistate_addressfamily); 2609 case oVerifyHostKeyDNS: 2610 case oUpdateHostkeys: 2611 return fmt_multistate_int(val, multistate_yesnoask); 2612 case oStrictHostKeyChecking: 2613 return fmt_multistate_int(val, multistate_strict_hostkey); 2614 case oControlMaster: 2615 return fmt_multistate_int(val, multistate_controlmaster); 2616 case oTunnel: 2617 return fmt_multistate_int(val, multistate_tunnel); 2618 case oRequestTTY: 2619 return fmt_multistate_int(val, multistate_requesttty); 2620 case oCanonicalizeHostname: 2621 return fmt_multistate_int(val, multistate_canonicalizehostname); 2622 case oAddKeysToAgent: 2623 return fmt_multistate_int(val, multistate_yesnoaskconfirm); 2624 case oFingerprintHash: 2625 return ssh_digest_alg_name(val); 2626 default: 2627 switch (val) { 2628 case 0: 2629 return "no"; 2630 case 1: 2631 return "yes"; 2632 default: 2633 return "UNKNOWN"; 2634 } 2635 } 2636 } 2637 2638 static const char * 2639 lookup_opcode_name(OpCodes code) 2640 { 2641 u_int i; 2642 2643 for (i = 0; keywords[i].name != NULL; i++) 2644 if (keywords[i].opcode == code) 2645 return(keywords[i].name); 2646 return "UNKNOWN"; 2647 } 2648 2649 static void 2650 dump_cfg_int(OpCodes code, int val) 2651 { 2652 printf("%s %d\n", lookup_opcode_name(code), val); 2653 } 2654 2655 static void 2656 dump_cfg_fmtint(OpCodes code, int val) 2657 { 2658 printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val)); 2659 } 2660 2661 static void 2662 dump_cfg_string(OpCodes code, const char *val) 2663 { 2664 if (val == NULL) 2665 return; 2666 printf("%s %s\n", lookup_opcode_name(code), val); 2667 } 2668 2669 static void 2670 dump_cfg_strarray(OpCodes code, u_int count, char **vals) 2671 { 2672 u_int i; 2673 2674 for (i = 0; i < count; i++) 2675 printf("%s %s\n", lookup_opcode_name(code), vals[i]); 2676 } 2677 2678 static void 2679 dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals) 2680 { 2681 u_int i; 2682 2683 printf("%s", lookup_opcode_name(code)); 2684 for (i = 0; i < count; i++) 2685 printf(" %s", vals[i]); 2686 printf("\n"); 2687 } 2688 2689 static void 2690 dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds) 2691 { 2692 const struct Forward *fwd; 2693 u_int i; 2694 2695 /* oDynamicForward */ 2696 for (i = 0; i < count; i++) { 2697 fwd = &fwds[i]; 2698 if (code == oDynamicForward && fwd->connect_host != NULL && 2699 strcmp(fwd->connect_host, "socks") != 0) 2700 continue; 2701 if (code == oLocalForward && fwd->connect_host != NULL && 2702 strcmp(fwd->connect_host, "socks") == 0) 2703 continue; 2704 printf("%s", lookup_opcode_name(code)); 2705 if (fwd->listen_port == PORT_STREAMLOCAL) 2706 printf(" %s", fwd->listen_path); 2707 else if (fwd->listen_host == NULL) 2708 printf(" %d", fwd->listen_port); 2709 else { 2710 printf(" [%s]:%d", 2711 fwd->listen_host, fwd->listen_port); 2712 } 2713 if (code != oDynamicForward) { 2714 if (fwd->connect_port == PORT_STREAMLOCAL) 2715 printf(" %s", fwd->connect_path); 2716 else if (fwd->connect_host == NULL) 2717 printf(" %d", fwd->connect_port); 2718 else { 2719 printf(" [%s]:%d", 2720 fwd->connect_host, fwd->connect_port); 2721 } 2722 } 2723 printf("\n"); 2724 } 2725 } 2726 2727 void 2728 dump_client_config(Options *o, const char *host) 2729 { 2730 int i, r; 2731 char buf[8], *all_key; 2732 2733 /* 2734 * Expand HostKeyAlgorithms name lists. This isn't handled in 2735 * fill_default_options() like the other algorithm lists because 2736 * the host key algorithms are by default dynamically chosen based 2737 * on the host's keys found in known_hosts. 2738 */ 2739 all_key = sshkey_alg_list(0, 0, 1, ','); 2740 if ((r = kex_assemble_names(&o->hostkeyalgorithms, kex_default_pk_alg(), 2741 all_key)) != 0) 2742 fatal_fr(r, "expand HostKeyAlgorithms"); 2743 free(all_key); 2744 2745 /* Most interesting options first: user, host, port */ 2746 dump_cfg_string(oUser, o->user); 2747 dump_cfg_string(oHostname, host); 2748 dump_cfg_int(oPort, o->port); 2749 2750 /* Flag options */ 2751 dump_cfg_fmtint(oAddressFamily, o->address_family); 2752 dump_cfg_fmtint(oBatchMode, o->batch_mode); 2753 dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local); 2754 dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname); 2755 dump_cfg_fmtint(oChallengeResponseAuthentication, o->challenge_response_authentication); 2756 dump_cfg_fmtint(oCheckHostIP, o->check_host_ip); 2757 dump_cfg_fmtint(oCompression, o->compression); 2758 dump_cfg_fmtint(oControlMaster, o->control_master); 2759 dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign); 2760 dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings); 2761 dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure); 2762 dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash); 2763 dump_cfg_fmtint(oForwardX11, o->forward_x11); 2764 dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted); 2765 dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports); 2766 #ifdef GSSAPI 2767 dump_cfg_fmtint(oGssAuthentication, o->gss_authentication); 2768 dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds); 2769 #endif /* GSSAPI */ 2770 dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts); 2771 dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication); 2772 dump_cfg_fmtint(oIdentitiesOnly, o->identities_only); 2773 dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication); 2774 dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost); 2775 dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication); 2776 dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command); 2777 dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass); 2778 dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication); 2779 dump_cfg_fmtint(oRequestTTY, o->request_tty); 2780 dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink); 2781 dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking); 2782 dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive); 2783 dump_cfg_fmtint(oTunnel, o->tun_open); 2784 dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns); 2785 dump_cfg_fmtint(oVisualHostKey, o->visual_host_key); 2786 dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys); 2787 2788 /* Integer options */ 2789 dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots); 2790 dump_cfg_int(oConnectionAttempts, o->connection_attempts); 2791 dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout); 2792 dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts); 2793 dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max); 2794 dump_cfg_int(oServerAliveInterval, o->server_alive_interval); 2795 2796 /* String options */ 2797 dump_cfg_string(oBindAddress, o->bind_address); 2798 dump_cfg_string(oBindInterface, o->bind_interface); 2799 dump_cfg_string(oCiphers, o->ciphers); 2800 dump_cfg_string(oControlPath, o->control_path); 2801 dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms); 2802 dump_cfg_string(oHostKeyAlias, o->host_key_alias); 2803 dump_cfg_string(oHostbasedKeyTypes, o->hostbased_key_types); 2804 dump_cfg_string(oIdentityAgent, o->identity_agent); 2805 dump_cfg_string(oIgnoreUnknown, o->ignored_unknown); 2806 dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices); 2807 dump_cfg_string(oKexAlgorithms, o->kex_algorithms); 2808 dump_cfg_string(oCASignatureAlgorithms, o->ca_sign_algorithms); 2809 dump_cfg_string(oLocalCommand, o->local_command); 2810 dump_cfg_string(oRemoteCommand, o->remote_command); 2811 dump_cfg_string(oLogLevel, log_level_name(o->log_level)); 2812 dump_cfg_string(oMacs, o->macs); 2813 #ifdef ENABLE_PKCS11 2814 dump_cfg_string(oPKCS11Provider, o->pkcs11_provider); 2815 #endif 2816 dump_cfg_string(oSecurityKeyProvider, o->sk_provider); 2817 dump_cfg_string(oPreferredAuthentications, o->preferred_authentications); 2818 dump_cfg_string(oPubkeyAcceptedKeyTypes, o->pubkey_key_types); 2819 dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys); 2820 dump_cfg_string(oXAuthLocation, o->xauth_location); 2821 2822 /* Forwards */ 2823 dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards); 2824 dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards); 2825 dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards); 2826 2827 /* String array options */ 2828 dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files); 2829 dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains); 2830 dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files); 2831 dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles); 2832 dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles); 2833 dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env); 2834 dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv); 2835 dump_cfg_strarray_oneline(oLogVerbose, 2836 o->num_log_verbose, o->log_verbose); 2837 2838 /* Special cases */ 2839 2840 /* AddKeysToAgent */ 2841 if (o->add_keys_to_agent_lifespan <= 0) 2842 dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent); 2843 else { 2844 printf("addkeystoagent%s %d\n", 2845 o->add_keys_to_agent == 3 ? " confirm" : "", 2846 o->add_keys_to_agent_lifespan); 2847 } 2848 2849 /* oForwardAgent */ 2850 if (o->forward_agent_sock_path == NULL) 2851 dump_cfg_fmtint(oForwardAgent, o->forward_agent); 2852 else 2853 dump_cfg_string(oForwardAgent, o->forward_agent_sock_path); 2854 2855 /* oConnectTimeout */ 2856 if (o->connection_timeout == -1) 2857 printf("connecttimeout none\n"); 2858 else 2859 dump_cfg_int(oConnectTimeout, o->connection_timeout); 2860 2861 /* oTunnelDevice */ 2862 printf("tunneldevice"); 2863 if (o->tun_local == SSH_TUNID_ANY) 2864 printf(" any"); 2865 else 2866 printf(" %d", o->tun_local); 2867 if (o->tun_remote == SSH_TUNID_ANY) 2868 printf(":any"); 2869 else 2870 printf(":%d", o->tun_remote); 2871 printf("\n"); 2872 2873 /* oCanonicalizePermittedCNAMEs */ 2874 if ( o->num_permitted_cnames > 0) { 2875 printf("canonicalizePermittedcnames"); 2876 for (i = 0; i < o->num_permitted_cnames; i++) { 2877 printf(" %s:%s", o->permitted_cnames[i].source_list, 2878 o->permitted_cnames[i].target_list); 2879 } 2880 printf("\n"); 2881 } 2882 2883 /* oControlPersist */ 2884 if (o->control_persist == 0 || o->control_persist_timeout == 0) 2885 dump_cfg_fmtint(oControlPersist, o->control_persist); 2886 else 2887 dump_cfg_int(oControlPersist, o->control_persist_timeout); 2888 2889 /* oEscapeChar */ 2890 if (o->escape_char == SSH_ESCAPECHAR_NONE) 2891 printf("escapechar none\n"); 2892 else { 2893 vis(buf, o->escape_char, VIS_WHITE, 0); 2894 printf("escapechar %s\n", buf); 2895 } 2896 2897 /* oIPQoS */ 2898 printf("ipqos %s ", iptos2str(o->ip_qos_interactive)); 2899 printf("%s\n", iptos2str(o->ip_qos_bulk)); 2900 2901 /* oRekeyLimit */ 2902 printf("rekeylimit %llu %d\n", 2903 (unsigned long long)o->rekey_limit, o->rekey_interval); 2904 2905 /* oStreamLocalBindMask */ 2906 printf("streamlocalbindmask 0%o\n", 2907 o->fwd_opts.streamlocal_bind_mask); 2908 2909 /* oLogFacility */ 2910 printf("syslogfacility %s\n", log_facility_name(o->log_facility)); 2911 2912 /* oProxyCommand / oProxyJump */ 2913 if (o->jump_host == NULL) 2914 dump_cfg_string(oProxyCommand, o->proxy_command); 2915 else { 2916 /* Check for numeric addresses */ 2917 i = strchr(o->jump_host, ':') != NULL || 2918 strspn(o->jump_host, "1234567890.") == strlen(o->jump_host); 2919 snprintf(buf, sizeof(buf), "%d", o->jump_port); 2920 printf("proxyjump %s%s%s%s%s%s%s%s%s\n", 2921 /* optional additional jump spec */ 2922 o->jump_extra == NULL ? "" : o->jump_extra, 2923 o->jump_extra == NULL ? "" : ",", 2924 /* optional user */ 2925 o->jump_user == NULL ? "" : o->jump_user, 2926 o->jump_user == NULL ? "" : "@", 2927 /* opening [ if hostname is numeric */ 2928 i ? "[" : "", 2929 /* mandatory hostname */ 2930 o->jump_host, 2931 /* closing ] if hostname is numeric */ 2932 i ? "]" : "", 2933 /* optional port number */ 2934 o->jump_port <= 0 ? "" : ":", 2935 o->jump_port <= 0 ? "" : buf); 2936 } 2937 } 2938