1 /* $OpenBSD: readconf.c,v 1.339 2020/10/16 13:26:13 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("%s: mux digest failed", __func__); 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("%s: ignoring duplicate key %s", __func__, 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("%s: ignoring duplicate key %s", __func__, 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("%s: stdfd_devnull failed", __func__); 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("%s: fork: %.100s", __func__, strerror(errno)); 534 535 while (waitpid(pid, &status, 0) == -1) { 536 if (errno != EINTR && errno != EAGAIN) 537 fatal("%s: waitpid: %s", __func__, 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 fatal("%.200s line %d: Bad escape character.", 1455 filename, linenum); 1456 /* NOTREACHED */ 1457 value = 0; /* Avoid compiler warning. */ 1458 } 1459 if (*activep && *intptr == -1) 1460 *intptr = value; 1461 break; 1462 1463 case oAddressFamily: 1464 intptr = &options->address_family; 1465 multistate_ptr = multistate_addressfamily; 1466 goto parse_multistate; 1467 1468 case oEnableSSHKeysign: 1469 intptr = &options->enable_ssh_keysign; 1470 goto parse_flag; 1471 1472 case oIdentitiesOnly: 1473 intptr = &options->identities_only; 1474 goto parse_flag; 1475 1476 case oServerAliveInterval: 1477 intptr = &options->server_alive_interval; 1478 goto parse_time; 1479 1480 case oServerAliveCountMax: 1481 intptr = &options->server_alive_count_max; 1482 goto parse_int; 1483 1484 case oSendEnv: 1485 while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1486 if (strchr(arg, '=') != NULL) 1487 fatal("%s line %d: Invalid environment name.", 1488 filename, linenum); 1489 if (!*activep) 1490 continue; 1491 if (*arg == '-') { 1492 /* Removing an env var */ 1493 rm_env(options, arg, filename, linenum); 1494 continue; 1495 } else { 1496 /* Adding an env var */ 1497 if (options->num_send_env >= INT_MAX) 1498 fatal("%s line %d: too many send env.", 1499 filename, linenum); 1500 options->send_env = xrecallocarray( 1501 options->send_env, options->num_send_env, 1502 options->num_send_env + 1, 1503 sizeof(*options->send_env)); 1504 options->send_env[options->num_send_env++] = 1505 xstrdup(arg); 1506 } 1507 } 1508 break; 1509 1510 case oSetEnv: 1511 value = options->num_setenv; 1512 while ((arg = strdelimw(&s)) != NULL && *arg != '\0') { 1513 if (strchr(arg, '=') == NULL) 1514 fatal("%s line %d: Invalid SetEnv.", 1515 filename, linenum); 1516 if (!*activep || value != 0) 1517 continue; 1518 /* Adding a setenv var */ 1519 if (options->num_setenv >= INT_MAX) 1520 fatal("%s line %d: too many SetEnv.", 1521 filename, linenum); 1522 options->setenv = xrecallocarray( 1523 options->setenv, options->num_setenv, 1524 options->num_setenv + 1, sizeof(*options->setenv)); 1525 options->setenv[options->num_setenv++] = xstrdup(arg); 1526 } 1527 break; 1528 1529 case oControlPath: 1530 charptr = &options->control_path; 1531 goto parse_string; 1532 1533 case oControlMaster: 1534 intptr = &options->control_master; 1535 multistate_ptr = multistate_controlmaster; 1536 goto parse_multistate; 1537 1538 case oControlPersist: 1539 /* no/false/yes/true, or a time spec */ 1540 intptr = &options->control_persist; 1541 arg = strdelim(&s); 1542 if (!arg || *arg == '\0') 1543 fatal("%.200s line %d: Missing ControlPersist" 1544 " argument.", filename, linenum); 1545 value = 0; 1546 value2 = 0; /* timeout */ 1547 if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 1548 value = 0; 1549 else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 1550 value = 1; 1551 else if ((value2 = convtime(arg)) >= 0) 1552 value = 1; 1553 else 1554 fatal("%.200s line %d: Bad ControlPersist argument.", 1555 filename, linenum); 1556 if (*activep && *intptr == -1) { 1557 *intptr = value; 1558 options->control_persist_timeout = value2; 1559 } 1560 break; 1561 1562 case oHashKnownHosts: 1563 intptr = &options->hash_known_hosts; 1564 goto parse_flag; 1565 1566 case oTunnel: 1567 intptr = &options->tun_open; 1568 multistate_ptr = multistate_tunnel; 1569 goto parse_multistate; 1570 1571 case oTunnelDevice: 1572 arg = strdelim(&s); 1573 if (!arg || *arg == '\0') 1574 fatal("%.200s line %d: Missing argument.", filename, linenum); 1575 value = a2tun(arg, &value2); 1576 if (value == SSH_TUNID_ERR) 1577 fatal("%.200s line %d: Bad tun device.", filename, linenum); 1578 if (*activep) { 1579 options->tun_local = value; 1580 options->tun_remote = value2; 1581 } 1582 break; 1583 1584 case oLocalCommand: 1585 charptr = &options->local_command; 1586 goto parse_command; 1587 1588 case oPermitLocalCommand: 1589 intptr = &options->permit_local_command; 1590 goto parse_flag; 1591 1592 case oRemoteCommand: 1593 charptr = &options->remote_command; 1594 goto parse_command; 1595 1596 case oVisualHostKey: 1597 intptr = &options->visual_host_key; 1598 goto parse_flag; 1599 1600 case oInclude: 1601 if (cmdline) 1602 fatal("Include directive not supported as a " 1603 "command-line option"); 1604 value = 0; 1605 while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1606 /* 1607 * Ensure all paths are anchored. User configuration 1608 * files may begin with '~/' but system configurations 1609 * must not. If the path is relative, then treat it 1610 * as living in ~/.ssh for user configurations or 1611 * /etc/ssh for system ones. 1612 */ 1613 if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0) 1614 fatal("%.200s line %d: bad include path %s.", 1615 filename, linenum, arg); 1616 if (!path_absolute(arg) && *arg != '~') { 1617 xasprintf(&arg2, "%s/%s", 1618 (flags & SSHCONF_USERCONF) ? 1619 "~/" _PATH_SSH_USER_DIR : SSHDIR, arg); 1620 } else 1621 arg2 = xstrdup(arg); 1622 memset(&gl, 0, sizeof(gl)); 1623 r = glob(arg2, GLOB_TILDE, NULL, &gl); 1624 if (r == GLOB_NOMATCH) { 1625 debug("%.200s line %d: include %s matched no " 1626 "files",filename, linenum, arg2); 1627 free(arg2); 1628 continue; 1629 } else if (r != 0) 1630 fatal("%.200s line %d: glob failed for %s.", 1631 filename, linenum, arg2); 1632 free(arg2); 1633 oactive = *activep; 1634 for (i = 0; i < gl.gl_pathc; i++) { 1635 debug3("%.200s line %d: Including file %s " 1636 "depth %d%s", filename, linenum, 1637 gl.gl_pathv[i], depth, 1638 oactive ? "" : " (parse only)"); 1639 r = read_config_file_depth(gl.gl_pathv[i], 1640 pw, host, original_host, options, 1641 flags | SSHCONF_CHECKPERM | 1642 (oactive ? 0 : SSHCONF_NEVERMATCH), 1643 activep, want_final_pass, depth + 1); 1644 if (r != 1 && errno != ENOENT) { 1645 fatal("Can't open user config file " 1646 "%.100s: %.100s", gl.gl_pathv[i], 1647 strerror(errno)); 1648 } 1649 /* 1650 * don't let Match in includes clobber the 1651 * containing file's Match state. 1652 */ 1653 *activep = oactive; 1654 if (r != 1) 1655 value = -1; 1656 } 1657 globfree(&gl); 1658 } 1659 if (value != 0) 1660 return value; 1661 break; 1662 1663 case oIPQoS: 1664 arg = strdelim(&s); 1665 if ((value = parse_ipqos(arg)) == -1) 1666 fatal("%s line %d: Bad IPQoS value: %s", 1667 filename, linenum, arg); 1668 arg = strdelim(&s); 1669 if (arg == NULL) 1670 value2 = value; 1671 else if ((value2 = parse_ipqos(arg)) == -1) 1672 fatal("%s line %d: Bad IPQoS value: %s", 1673 filename, linenum, arg); 1674 if (*activep) { 1675 options->ip_qos_interactive = value; 1676 options->ip_qos_bulk = value2; 1677 } 1678 break; 1679 1680 case oRequestTTY: 1681 intptr = &options->request_tty; 1682 multistate_ptr = multistate_requesttty; 1683 goto parse_multistate; 1684 1685 case oIgnoreUnknown: 1686 charptr = &options->ignored_unknown; 1687 goto parse_string; 1688 1689 case oProxyUseFdpass: 1690 intptr = &options->proxy_use_fdpass; 1691 goto parse_flag; 1692 1693 case oCanonicalDomains: 1694 value = options->num_canonical_domains != 0; 1695 while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1696 if (!valid_domain(arg, 1, &errstr)) { 1697 fatal("%s line %d: %s", filename, linenum, 1698 errstr); 1699 } 1700 if (!*activep || value) 1701 continue; 1702 if (options->num_canonical_domains >= MAX_CANON_DOMAINS) 1703 fatal("%s line %d: too many hostname suffixes.", 1704 filename, linenum); 1705 options->canonical_domains[ 1706 options->num_canonical_domains++] = xstrdup(arg); 1707 } 1708 break; 1709 1710 case oCanonicalizePermittedCNAMEs: 1711 value = options->num_permitted_cnames != 0; 1712 while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1713 /* Either '*' for everything or 'list:list' */ 1714 if (strcmp(arg, "*") == 0) 1715 arg2 = arg; 1716 else { 1717 lowercase(arg); 1718 if ((arg2 = strchr(arg, ':')) == NULL || 1719 arg2[1] == '\0') { 1720 fatal("%s line %d: " 1721 "Invalid permitted CNAME \"%s\"", 1722 filename, linenum, arg); 1723 } 1724 *arg2 = '\0'; 1725 arg2++; 1726 } 1727 if (!*activep || value) 1728 continue; 1729 if (options->num_permitted_cnames >= MAX_CANON_DOMAINS) 1730 fatal("%s line %d: too many permitted CNAMEs.", 1731 filename, linenum); 1732 cname = options->permitted_cnames + 1733 options->num_permitted_cnames++; 1734 cname->source_list = xstrdup(arg); 1735 cname->target_list = xstrdup(arg2); 1736 } 1737 break; 1738 1739 case oCanonicalizeHostname: 1740 intptr = &options->canonicalize_hostname; 1741 multistate_ptr = multistate_canonicalizehostname; 1742 goto parse_multistate; 1743 1744 case oCanonicalizeMaxDots: 1745 intptr = &options->canonicalize_max_dots; 1746 goto parse_int; 1747 1748 case oCanonicalizeFallbackLocal: 1749 intptr = &options->canonicalize_fallback_local; 1750 goto parse_flag; 1751 1752 case oStreamLocalBindMask: 1753 arg = strdelim(&s); 1754 if (!arg || *arg == '\0') 1755 fatal("%.200s line %d: Missing StreamLocalBindMask argument.", filename, linenum); 1756 /* Parse mode in octal format */ 1757 value = strtol(arg, &endofnumber, 8); 1758 if (arg == endofnumber || value < 0 || value > 0777) 1759 fatal("%.200s line %d: Bad mask.", filename, linenum); 1760 options->fwd_opts.streamlocal_bind_mask = (mode_t)value; 1761 break; 1762 1763 case oStreamLocalBindUnlink: 1764 intptr = &options->fwd_opts.streamlocal_bind_unlink; 1765 goto parse_flag; 1766 1767 case oRevokedHostKeys: 1768 charptr = &options->revoked_host_keys; 1769 goto parse_string; 1770 1771 case oFingerprintHash: 1772 intptr = &options->fingerprint_hash; 1773 arg = strdelim(&s); 1774 if (!arg || *arg == '\0') 1775 fatal("%.200s line %d: Missing argument.", 1776 filename, linenum); 1777 if ((value = ssh_digest_alg_by_name(arg)) == -1) 1778 fatal("%.200s line %d: Invalid hash algorithm \"%s\".", 1779 filename, linenum, arg); 1780 if (*activep && *intptr == -1) 1781 *intptr = value; 1782 break; 1783 1784 case oUpdateHostkeys: 1785 intptr = &options->update_hostkeys; 1786 multistate_ptr = multistate_yesnoask; 1787 goto parse_multistate; 1788 1789 case oHostbasedKeyTypes: 1790 charptr = &options->hostbased_key_types; 1791 goto parse_keytypes; 1792 1793 case oPubkeyAcceptedKeyTypes: 1794 charptr = &options->pubkey_key_types; 1795 goto parse_keytypes; 1796 1797 case oAddKeysToAgent: 1798 arg = strdelim(&s); 1799 arg2 = strdelim(&s); 1800 value = parse_multistate_value(arg, filename, linenum, 1801 multistate_yesnoaskconfirm); 1802 value2 = 0; /* unlimited lifespan by default */ 1803 if (value == 3 && arg2 != NULL) { 1804 /* allow "AddKeysToAgent confirm 5m" */ 1805 if ((value2 = convtime(arg2)) == -1 || value2 > INT_MAX) 1806 fatal("%s line %d: invalid time value.", 1807 filename, linenum); 1808 } else if (value == -1 && arg2 == NULL) { 1809 if ((value2 = convtime(arg)) == -1 || value2 > INT_MAX) 1810 fatal("%s line %d: unsupported option", 1811 filename, linenum); 1812 value = 1; /* yes */ 1813 } else if (value == -1 || arg2 != NULL) { 1814 fatal("%s line %d: unsupported option", 1815 filename, linenum); 1816 } 1817 if (*activep && options->add_keys_to_agent == -1) { 1818 options->add_keys_to_agent = value; 1819 options->add_keys_to_agent_lifespan = value2; 1820 } 1821 break; 1822 1823 case oIdentityAgent: 1824 charptr = &options->identity_agent; 1825 arg = strdelim(&s); 1826 if (!arg || *arg == '\0') 1827 fatal("%.200s line %d: Missing argument.", 1828 filename, linenum); 1829 parse_agent_path: 1830 /* Extra validation if the string represents an env var. */ 1831 if ((arg2 = dollar_expand(&r, arg)) == NULL || r) 1832 fatal("%.200s line %d: Invalid environment expansion " 1833 "%s.", filename, linenum, arg); 1834 free(arg2); 1835 /* check for legacy environment format */ 1836 if (arg[0] == '$' && arg[1] != '{' && !valid_env_name(arg + 1)) { 1837 fatal("%.200s line %d: Invalid environment name %s.", 1838 filename, linenum, arg); 1839 } 1840 if (*activep && *charptr == NULL) 1841 *charptr = xstrdup(arg); 1842 break; 1843 1844 case oDeprecated: 1845 debug("%s line %d: Deprecated option \"%s\"", 1846 filename, linenum, keyword); 1847 return 0; 1848 1849 case oUnsupported: 1850 error("%s line %d: Unsupported option \"%s\"", 1851 filename, linenum, keyword); 1852 return 0; 1853 1854 default: 1855 fatal("%s: Unimplemented opcode %d", __func__, opcode); 1856 } 1857 1858 /* Check that there is no garbage at end of line. */ 1859 if ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1860 fatal("%.200s line %d: garbage at end of line; \"%.200s\".", 1861 filename, linenum, arg); 1862 } 1863 return 0; 1864 } 1865 1866 /* 1867 * Reads the config file and modifies the options accordingly. Options 1868 * should already be initialized before this call. This never returns if 1869 * there is an error. If the file does not exist, this returns 0. 1870 */ 1871 int 1872 read_config_file(const char *filename, struct passwd *pw, const char *host, 1873 const char *original_host, Options *options, int flags, 1874 int *want_final_pass) 1875 { 1876 int active = 1; 1877 1878 return read_config_file_depth(filename, pw, host, original_host, 1879 options, flags, &active, want_final_pass, 0); 1880 } 1881 1882 #define READCONF_MAX_DEPTH 16 1883 static int 1884 read_config_file_depth(const char *filename, struct passwd *pw, 1885 const char *host, const char *original_host, Options *options, 1886 int flags, int *activep, int *want_final_pass, int depth) 1887 { 1888 FILE *f; 1889 char *line = NULL; 1890 size_t linesize = 0; 1891 int linenum; 1892 int bad_options = 0; 1893 1894 if (depth < 0 || depth > READCONF_MAX_DEPTH) 1895 fatal("Too many recursive configuration includes"); 1896 1897 if ((f = fopen(filename, "r")) == NULL) 1898 return 0; 1899 1900 if (flags & SSHCONF_CHECKPERM) { 1901 struct stat sb; 1902 1903 if (fstat(fileno(f), &sb) == -1) 1904 fatal("fstat %s: %s", filename, strerror(errno)); 1905 if (((sb.st_uid != 0 && sb.st_uid != getuid()) || 1906 (sb.st_mode & 022) != 0)) 1907 fatal("Bad owner or permissions on %s", filename); 1908 } 1909 1910 debug("Reading configuration data %.200s", filename); 1911 1912 /* 1913 * Mark that we are now processing the options. This flag is turned 1914 * on/off by Host specifications. 1915 */ 1916 linenum = 0; 1917 while (getline(&line, &linesize, f) != -1) { 1918 /* Update line number counter. */ 1919 linenum++; 1920 if (process_config_line_depth(options, pw, host, original_host, 1921 line, filename, linenum, activep, flags, want_final_pass, 1922 depth) != 0) 1923 bad_options++; 1924 } 1925 free(line); 1926 fclose(f); 1927 if (bad_options > 0) 1928 fatal("%s: terminating, %d bad configuration options", 1929 filename, bad_options); 1930 return 1; 1931 } 1932 1933 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ 1934 int 1935 option_clear_or_none(const char *o) 1936 { 1937 return o == NULL || strcasecmp(o, "none") == 0; 1938 } 1939 1940 /* 1941 * Initializes options to special values that indicate that they have not yet 1942 * been set. Read_config_file will only set options with this value. Options 1943 * are processed in the following order: command line, user config file, 1944 * system config file. Last, fill_default_options is called. 1945 */ 1946 1947 void 1948 initialize_options(Options * options) 1949 { 1950 memset(options, 'X', sizeof(*options)); 1951 options->forward_agent = -1; 1952 options->forward_agent_sock_path = NULL; 1953 options->forward_x11 = -1; 1954 options->forward_x11_trusted = -1; 1955 options->forward_x11_timeout = -1; 1956 options->stdio_forward_host = NULL; 1957 options->stdio_forward_port = 0; 1958 options->clear_forwardings = -1; 1959 options->exit_on_forward_failure = -1; 1960 options->xauth_location = NULL; 1961 options->fwd_opts.gateway_ports = -1; 1962 options->fwd_opts.streamlocal_bind_mask = (mode_t)-1; 1963 options->fwd_opts.streamlocal_bind_unlink = -1; 1964 options->pubkey_authentication = -1; 1965 options->challenge_response_authentication = -1; 1966 options->gss_authentication = -1; 1967 options->gss_deleg_creds = -1; 1968 options->password_authentication = -1; 1969 options->kbd_interactive_authentication = -1; 1970 options->kbd_interactive_devices = NULL; 1971 options->hostbased_authentication = -1; 1972 options->batch_mode = -1; 1973 options->check_host_ip = -1; 1974 options->strict_host_key_checking = -1; 1975 options->compression = -1; 1976 options->tcp_keep_alive = -1; 1977 options->port = -1; 1978 options->address_family = -1; 1979 options->connection_attempts = -1; 1980 options->connection_timeout = -1; 1981 options->number_of_password_prompts = -1; 1982 options->ciphers = NULL; 1983 options->macs = NULL; 1984 options->kex_algorithms = NULL; 1985 options->hostkeyalgorithms = NULL; 1986 options->ca_sign_algorithms = NULL; 1987 options->num_identity_files = 0; 1988 options->num_certificate_files = 0; 1989 options->hostname = NULL; 1990 options->host_key_alias = NULL; 1991 options->proxy_command = NULL; 1992 options->jump_user = NULL; 1993 options->jump_host = NULL; 1994 options->jump_port = -1; 1995 options->jump_extra = NULL; 1996 options->user = NULL; 1997 options->escape_char = -1; 1998 options->num_system_hostfiles = 0; 1999 options->num_user_hostfiles = 0; 2000 options->local_forwards = NULL; 2001 options->num_local_forwards = 0; 2002 options->remote_forwards = NULL; 2003 options->num_remote_forwards = 0; 2004 options->log_facility = SYSLOG_FACILITY_NOT_SET; 2005 options->log_level = SYSLOG_LEVEL_NOT_SET; 2006 options->num_log_verbose = 0; 2007 options->log_verbose = NULL; 2008 options->preferred_authentications = NULL; 2009 options->bind_address = NULL; 2010 options->bind_interface = NULL; 2011 options->pkcs11_provider = NULL; 2012 options->sk_provider = NULL; 2013 options->enable_ssh_keysign = - 1; 2014 options->no_host_authentication_for_localhost = - 1; 2015 options->identities_only = - 1; 2016 options->rekey_limit = - 1; 2017 options->rekey_interval = -1; 2018 options->verify_host_key_dns = -1; 2019 options->server_alive_interval = -1; 2020 options->server_alive_count_max = -1; 2021 options->send_env = NULL; 2022 options->num_send_env = 0; 2023 options->setenv = NULL; 2024 options->num_setenv = 0; 2025 options->control_path = NULL; 2026 options->control_master = -1; 2027 options->control_persist = -1; 2028 options->control_persist_timeout = 0; 2029 options->hash_known_hosts = -1; 2030 options->tun_open = -1; 2031 options->tun_local = -1; 2032 options->tun_remote = -1; 2033 options->local_command = NULL; 2034 options->permit_local_command = -1; 2035 options->remote_command = NULL; 2036 options->add_keys_to_agent = -1; 2037 options->add_keys_to_agent_lifespan = -1; 2038 options->identity_agent = NULL; 2039 options->visual_host_key = -1; 2040 options->ip_qos_interactive = -1; 2041 options->ip_qos_bulk = -1; 2042 options->request_tty = -1; 2043 options->proxy_use_fdpass = -1; 2044 options->ignored_unknown = NULL; 2045 options->num_canonical_domains = 0; 2046 options->num_permitted_cnames = 0; 2047 options->canonicalize_max_dots = -1; 2048 options->canonicalize_fallback_local = -1; 2049 options->canonicalize_hostname = -1; 2050 options->revoked_host_keys = NULL; 2051 options->fingerprint_hash = -1; 2052 options->update_hostkeys = -1; 2053 options->hostbased_key_types = NULL; 2054 options->pubkey_key_types = NULL; 2055 } 2056 2057 /* 2058 * A petite version of fill_default_options() that just fills the options 2059 * needed for hostname canonicalization to proceed. 2060 */ 2061 void 2062 fill_default_options_for_canonicalization(Options *options) 2063 { 2064 if (options->canonicalize_max_dots == -1) 2065 options->canonicalize_max_dots = 1; 2066 if (options->canonicalize_fallback_local == -1) 2067 options->canonicalize_fallback_local = 1; 2068 if (options->canonicalize_hostname == -1) 2069 options->canonicalize_hostname = SSH_CANONICALISE_NO; 2070 } 2071 2072 /* 2073 * Called after processing other sources of option data, this fills those 2074 * options for which no value has been specified with their default values. 2075 */ 2076 void 2077 fill_default_options(Options * options) 2078 { 2079 char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig; 2080 char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig; 2081 int r; 2082 2083 if (options->forward_agent == -1) 2084 options->forward_agent = 0; 2085 if (options->forward_x11 == -1) 2086 options->forward_x11 = 0; 2087 if (options->forward_x11_trusted == -1) 2088 options->forward_x11_trusted = 0; 2089 if (options->forward_x11_timeout == -1) 2090 options->forward_x11_timeout = 1200; 2091 /* 2092 * stdio forwarding (-W) changes the default for these but we defer 2093 * setting the values so they can be overridden. 2094 */ 2095 if (options->exit_on_forward_failure == -1) 2096 options->exit_on_forward_failure = 2097 options->stdio_forward_host != NULL ? 1 : 0; 2098 if (options->clear_forwardings == -1) 2099 options->clear_forwardings = 2100 options->stdio_forward_host != NULL ? 1 : 0; 2101 if (options->clear_forwardings == 1) 2102 clear_forwardings(options); 2103 2104 if (options->xauth_location == NULL) 2105 options->xauth_location = _PATH_XAUTH; 2106 if (options->fwd_opts.gateway_ports == -1) 2107 options->fwd_opts.gateway_ports = 0; 2108 if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1) 2109 options->fwd_opts.streamlocal_bind_mask = 0177; 2110 if (options->fwd_opts.streamlocal_bind_unlink == -1) 2111 options->fwd_opts.streamlocal_bind_unlink = 0; 2112 if (options->pubkey_authentication == -1) 2113 options->pubkey_authentication = 1; 2114 if (options->challenge_response_authentication == -1) 2115 options->challenge_response_authentication = 1; 2116 if (options->gss_authentication == -1) 2117 options->gss_authentication = 0; 2118 if (options->gss_deleg_creds == -1) 2119 options->gss_deleg_creds = 0; 2120 if (options->password_authentication == -1) 2121 options->password_authentication = 1; 2122 if (options->kbd_interactive_authentication == -1) 2123 options->kbd_interactive_authentication = 1; 2124 if (options->hostbased_authentication == -1) 2125 options->hostbased_authentication = 0; 2126 if (options->batch_mode == -1) 2127 options->batch_mode = 0; 2128 if (options->check_host_ip == -1) 2129 options->check_host_ip = 1; 2130 if (options->strict_host_key_checking == -1) 2131 options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK; 2132 if (options->compression == -1) 2133 options->compression = 0; 2134 if (options->tcp_keep_alive == -1) 2135 options->tcp_keep_alive = 1; 2136 if (options->port == -1) 2137 options->port = 0; /* Filled in ssh_connect. */ 2138 if (options->address_family == -1) 2139 options->address_family = AF_UNSPEC; 2140 if (options->connection_attempts == -1) 2141 options->connection_attempts = 1; 2142 if (options->number_of_password_prompts == -1) 2143 options->number_of_password_prompts = 3; 2144 /* options->hostkeyalgorithms, default set in myproposals.h */ 2145 if (options->add_keys_to_agent == -1) { 2146 options->add_keys_to_agent = 0; 2147 options->add_keys_to_agent_lifespan = 0; 2148 } 2149 if (options->num_identity_files == 0) { 2150 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0); 2151 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0); 2152 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0); 2153 add_identity_file(options, "~/", 2154 _PATH_SSH_CLIENT_ID_ECDSA_SK, 0); 2155 add_identity_file(options, "~/", 2156 _PATH_SSH_CLIENT_ID_ED25519, 0); 2157 add_identity_file(options, "~/", 2158 _PATH_SSH_CLIENT_ID_ED25519_SK, 0); 2159 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0); 2160 } 2161 if (options->escape_char == -1) 2162 options->escape_char = '~'; 2163 if (options->num_system_hostfiles == 0) { 2164 options->system_hostfiles[options->num_system_hostfiles++] = 2165 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE); 2166 options->system_hostfiles[options->num_system_hostfiles++] = 2167 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2); 2168 } 2169 if (options->update_hostkeys == -1) { 2170 if (options->verify_host_key_dns <= 0 && 2171 (options->num_user_hostfiles == 0 || 2172 (options->num_user_hostfiles == 1 && strcmp(options-> 2173 user_hostfiles[0], _PATH_SSH_USER_HOSTFILE) == 0))) 2174 options->update_hostkeys = SSH_UPDATE_HOSTKEYS_YES; 2175 else 2176 options->update_hostkeys = SSH_UPDATE_HOSTKEYS_NO; 2177 } 2178 if (options->num_user_hostfiles == 0) { 2179 options->user_hostfiles[options->num_user_hostfiles++] = 2180 xstrdup(_PATH_SSH_USER_HOSTFILE); 2181 options->user_hostfiles[options->num_user_hostfiles++] = 2182 xstrdup(_PATH_SSH_USER_HOSTFILE2); 2183 } 2184 if (options->log_level == SYSLOG_LEVEL_NOT_SET) 2185 options->log_level = SYSLOG_LEVEL_INFO; 2186 if (options->log_facility == SYSLOG_FACILITY_NOT_SET) 2187 options->log_facility = SYSLOG_FACILITY_USER; 2188 if (options->no_host_authentication_for_localhost == - 1) 2189 options->no_host_authentication_for_localhost = 0; 2190 if (options->identities_only == -1) 2191 options->identities_only = 0; 2192 if (options->enable_ssh_keysign == -1) 2193 options->enable_ssh_keysign = 0; 2194 if (options->rekey_limit == -1) 2195 options->rekey_limit = 0; 2196 if (options->rekey_interval == -1) 2197 options->rekey_interval = 0; 2198 if (options->verify_host_key_dns == -1) 2199 options->verify_host_key_dns = 0; 2200 if (options->server_alive_interval == -1) 2201 options->server_alive_interval = 0; 2202 if (options->server_alive_count_max == -1) 2203 options->server_alive_count_max = 3; 2204 if (options->control_master == -1) 2205 options->control_master = 0; 2206 if (options->control_persist == -1) { 2207 options->control_persist = 0; 2208 options->control_persist_timeout = 0; 2209 } 2210 if (options->hash_known_hosts == -1) 2211 options->hash_known_hosts = 0; 2212 if (options->tun_open == -1) 2213 options->tun_open = SSH_TUNMODE_NO; 2214 if (options->tun_local == -1) 2215 options->tun_local = SSH_TUNID_ANY; 2216 if (options->tun_remote == -1) 2217 options->tun_remote = SSH_TUNID_ANY; 2218 if (options->permit_local_command == -1) 2219 options->permit_local_command = 0; 2220 if (options->visual_host_key == -1) 2221 options->visual_host_key = 0; 2222 if (options->ip_qos_interactive == -1) 2223 options->ip_qos_interactive = IPTOS_DSCP_AF21; 2224 if (options->ip_qos_bulk == -1) 2225 options->ip_qos_bulk = IPTOS_DSCP_CS1; 2226 if (options->request_tty == -1) 2227 options->request_tty = REQUEST_TTY_AUTO; 2228 if (options->proxy_use_fdpass == -1) 2229 options->proxy_use_fdpass = 0; 2230 if (options->canonicalize_max_dots == -1) 2231 options->canonicalize_max_dots = 1; 2232 if (options->canonicalize_fallback_local == -1) 2233 options->canonicalize_fallback_local = 1; 2234 if (options->canonicalize_hostname == -1) 2235 options->canonicalize_hostname = SSH_CANONICALISE_NO; 2236 if (options->fingerprint_hash == -1) 2237 options->fingerprint_hash = SSH_FP_HASH_DEFAULT; 2238 if (options->sk_provider == NULL) 2239 options->sk_provider = xstrdup("internal"); 2240 2241 /* Expand KEX name lists */ 2242 all_cipher = cipher_alg_list(',', 0); 2243 all_mac = mac_alg_list(','); 2244 all_kex = kex_alg_list(','); 2245 all_key = sshkey_alg_list(0, 0, 1, ','); 2246 all_sig = sshkey_alg_list(0, 1, 1, ','); 2247 /* remove unsupported algos from default lists */ 2248 def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher); 2249 def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac); 2250 def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex); 2251 def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key); 2252 def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig); 2253 #define ASSEMBLE(what, defaults, all) \ 2254 do { \ 2255 if ((r = kex_assemble_names(&options->what, \ 2256 defaults, all)) != 0) \ 2257 fatal("%s: %s: %s", __func__, #what, ssh_err(r)); \ 2258 } while (0) 2259 ASSEMBLE(ciphers, def_cipher, all_cipher); 2260 ASSEMBLE(macs, def_mac, all_mac); 2261 ASSEMBLE(kex_algorithms, def_kex, all_kex); 2262 ASSEMBLE(hostbased_key_types, def_key, all_key); 2263 ASSEMBLE(pubkey_key_types, def_key, all_key); 2264 ASSEMBLE(ca_sign_algorithms, def_sig, all_sig); 2265 #undef ASSEMBLE 2266 free(all_cipher); 2267 free(all_mac); 2268 free(all_kex); 2269 free(all_key); 2270 free(all_sig); 2271 free(def_cipher); 2272 free(def_mac); 2273 free(def_kex); 2274 kex_default_pk_alg_filtered = def_key; /* save for later use */ 2275 free(def_sig); 2276 2277 #define CLEAR_ON_NONE(v) \ 2278 do { \ 2279 if (option_clear_or_none(v)) { \ 2280 free(v); \ 2281 v = NULL; \ 2282 } \ 2283 } while(0) 2284 CLEAR_ON_NONE(options->local_command); 2285 CLEAR_ON_NONE(options->remote_command); 2286 CLEAR_ON_NONE(options->proxy_command); 2287 CLEAR_ON_NONE(options->control_path); 2288 CLEAR_ON_NONE(options->revoked_host_keys); 2289 CLEAR_ON_NONE(options->pkcs11_provider); 2290 CLEAR_ON_NONE(options->sk_provider); 2291 if (options->jump_host != NULL && 2292 strcmp(options->jump_host, "none") == 0 && 2293 options->jump_port == 0 && options->jump_user == NULL) { 2294 free(options->jump_host); 2295 options->jump_host = NULL; 2296 } 2297 /* options->identity_agent distinguishes NULL from 'none' */ 2298 /* options->user will be set in the main program if appropriate */ 2299 /* options->hostname will be set in the main program if appropriate */ 2300 /* options->host_key_alias should not be set by default */ 2301 /* options->preferred_authentications will be set in ssh */ 2302 } 2303 2304 struct fwdarg { 2305 char *arg; 2306 int ispath; 2307 }; 2308 2309 /* 2310 * parse_fwd_field 2311 * parses the next field in a port forwarding specification. 2312 * sets fwd to the parsed field and advances p past the colon 2313 * or sets it to NULL at end of string. 2314 * returns 0 on success, else non-zero. 2315 */ 2316 static int 2317 parse_fwd_field(char **p, struct fwdarg *fwd) 2318 { 2319 char *ep, *cp = *p; 2320 int ispath = 0; 2321 2322 if (*cp == '\0') { 2323 *p = NULL; 2324 return -1; /* end of string */ 2325 } 2326 2327 /* 2328 * A field escaped with square brackets is used literally. 2329 * XXX - allow ']' to be escaped via backslash? 2330 */ 2331 if (*cp == '[') { 2332 /* find matching ']' */ 2333 for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) { 2334 if (*ep == '/') 2335 ispath = 1; 2336 } 2337 /* no matching ']' or not at end of field. */ 2338 if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0')) 2339 return -1; 2340 /* NUL terminate the field and advance p past the colon */ 2341 *ep++ = '\0'; 2342 if (*ep != '\0') 2343 *ep++ = '\0'; 2344 fwd->arg = cp + 1; 2345 fwd->ispath = ispath; 2346 *p = ep; 2347 return 0; 2348 } 2349 2350 for (cp = *p; *cp != '\0'; cp++) { 2351 switch (*cp) { 2352 case '\\': 2353 memmove(cp, cp + 1, strlen(cp + 1) + 1); 2354 if (*cp == '\0') 2355 return -1; 2356 break; 2357 case '/': 2358 ispath = 1; 2359 break; 2360 case ':': 2361 *cp++ = '\0'; 2362 goto done; 2363 } 2364 } 2365 done: 2366 fwd->arg = *p; 2367 fwd->ispath = ispath; 2368 *p = cp; 2369 return 0; 2370 } 2371 2372 /* 2373 * parse_forward 2374 * parses a string containing a port forwarding specification of the form: 2375 * dynamicfwd == 0 2376 * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath 2377 * listenpath:connectpath 2378 * dynamicfwd == 1 2379 * [listenhost:]listenport 2380 * returns number of arguments parsed or zero on error 2381 */ 2382 int 2383 parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) 2384 { 2385 struct fwdarg fwdargs[4]; 2386 char *p, *cp; 2387 int i, err; 2388 2389 memset(fwd, 0, sizeof(*fwd)); 2390 memset(fwdargs, 0, sizeof(fwdargs)); 2391 2392 /* 2393 * We expand environment variables before checking if we think they're 2394 * paths so that if ${VAR} expands to a fully qualified path it is 2395 * treated as a path. 2396 */ 2397 cp = p = dollar_expand(&err, fwdspec); 2398 if (p == NULL || err) 2399 return 0; 2400 2401 /* skip leading spaces */ 2402 while (isspace((u_char)*cp)) 2403 cp++; 2404 2405 for (i = 0; i < 4; ++i) { 2406 if (parse_fwd_field(&cp, &fwdargs[i]) != 0) 2407 break; 2408 } 2409 2410 /* Check for trailing garbage */ 2411 if (cp != NULL && *cp != '\0') { 2412 i = 0; /* failure */ 2413 } 2414 2415 switch (i) { 2416 case 1: 2417 if (fwdargs[0].ispath) { 2418 fwd->listen_path = xstrdup(fwdargs[0].arg); 2419 fwd->listen_port = PORT_STREAMLOCAL; 2420 } else { 2421 fwd->listen_host = NULL; 2422 fwd->listen_port = a2port(fwdargs[0].arg); 2423 } 2424 fwd->connect_host = xstrdup("socks"); 2425 break; 2426 2427 case 2: 2428 if (fwdargs[0].ispath && fwdargs[1].ispath) { 2429 fwd->listen_path = xstrdup(fwdargs[0].arg); 2430 fwd->listen_port = PORT_STREAMLOCAL; 2431 fwd->connect_path = xstrdup(fwdargs[1].arg); 2432 fwd->connect_port = PORT_STREAMLOCAL; 2433 } else if (fwdargs[1].ispath) { 2434 fwd->listen_host = NULL; 2435 fwd->listen_port = a2port(fwdargs[0].arg); 2436 fwd->connect_path = xstrdup(fwdargs[1].arg); 2437 fwd->connect_port = PORT_STREAMLOCAL; 2438 } else { 2439 fwd->listen_host = xstrdup(fwdargs[0].arg); 2440 fwd->listen_port = a2port(fwdargs[1].arg); 2441 fwd->connect_host = xstrdup("socks"); 2442 } 2443 break; 2444 2445 case 3: 2446 if (fwdargs[0].ispath) { 2447 fwd->listen_path = xstrdup(fwdargs[0].arg); 2448 fwd->listen_port = PORT_STREAMLOCAL; 2449 fwd->connect_host = xstrdup(fwdargs[1].arg); 2450 fwd->connect_port = a2port(fwdargs[2].arg); 2451 } else if (fwdargs[2].ispath) { 2452 fwd->listen_host = xstrdup(fwdargs[0].arg); 2453 fwd->listen_port = a2port(fwdargs[1].arg); 2454 fwd->connect_path = xstrdup(fwdargs[2].arg); 2455 fwd->connect_port = PORT_STREAMLOCAL; 2456 } else { 2457 fwd->listen_host = NULL; 2458 fwd->listen_port = a2port(fwdargs[0].arg); 2459 fwd->connect_host = xstrdup(fwdargs[1].arg); 2460 fwd->connect_port = a2port(fwdargs[2].arg); 2461 } 2462 break; 2463 2464 case 4: 2465 fwd->listen_host = xstrdup(fwdargs[0].arg); 2466 fwd->listen_port = a2port(fwdargs[1].arg); 2467 fwd->connect_host = xstrdup(fwdargs[2].arg); 2468 fwd->connect_port = a2port(fwdargs[3].arg); 2469 break; 2470 default: 2471 i = 0; /* failure */ 2472 } 2473 2474 free(p); 2475 2476 if (dynamicfwd) { 2477 if (!(i == 1 || i == 2)) 2478 goto fail_free; 2479 } else { 2480 if (!(i == 3 || i == 4)) { 2481 if (fwd->connect_path == NULL && 2482 fwd->listen_path == NULL) 2483 goto fail_free; 2484 } 2485 if (fwd->connect_port <= 0 && fwd->connect_path == NULL) 2486 goto fail_free; 2487 } 2488 2489 if ((fwd->listen_port < 0 && fwd->listen_path == NULL) || 2490 (!remotefwd && fwd->listen_port == 0)) 2491 goto fail_free; 2492 if (fwd->connect_host != NULL && 2493 strlen(fwd->connect_host) >= NI_MAXHOST) 2494 goto fail_free; 2495 /* XXX - if connecting to a remote socket, max sun len may not match this host */ 2496 if (fwd->connect_path != NULL && 2497 strlen(fwd->connect_path) >= PATH_MAX_SUN) 2498 goto fail_free; 2499 if (fwd->listen_host != NULL && 2500 strlen(fwd->listen_host) >= NI_MAXHOST) 2501 goto fail_free; 2502 if (fwd->listen_path != NULL && 2503 strlen(fwd->listen_path) >= PATH_MAX_SUN) 2504 goto fail_free; 2505 2506 return (i); 2507 2508 fail_free: 2509 free(fwd->connect_host); 2510 fwd->connect_host = NULL; 2511 free(fwd->connect_path); 2512 fwd->connect_path = NULL; 2513 free(fwd->listen_host); 2514 fwd->listen_host = NULL; 2515 free(fwd->listen_path); 2516 fwd->listen_path = NULL; 2517 return (0); 2518 } 2519 2520 int 2521 parse_jump(const char *s, Options *o, int active) 2522 { 2523 char *orig, *sdup, *cp; 2524 char *host = NULL, *user = NULL; 2525 int ret = -1, port = -1, first; 2526 2527 active &= o->proxy_command == NULL && o->jump_host == NULL; 2528 2529 orig = sdup = xstrdup(s); 2530 first = active; 2531 do { 2532 if (strcasecmp(s, "none") == 0) 2533 break; 2534 if ((cp = strrchr(sdup, ',')) == NULL) 2535 cp = sdup; /* last */ 2536 else 2537 *cp++ = '\0'; 2538 2539 if (first) { 2540 /* First argument and configuration is active */ 2541 if (parse_ssh_uri(cp, &user, &host, &port) == -1 || 2542 parse_user_host_port(cp, &user, &host, &port) != 0) 2543 goto out; 2544 } else { 2545 /* Subsequent argument or inactive configuration */ 2546 if (parse_ssh_uri(cp, NULL, NULL, NULL) == -1 || 2547 parse_user_host_port(cp, NULL, NULL, NULL) != 0) 2548 goto out; 2549 } 2550 first = 0; /* only check syntax for subsequent hosts */ 2551 } while (cp != sdup); 2552 /* success */ 2553 if (active) { 2554 if (strcasecmp(s, "none") == 0) { 2555 o->jump_host = xstrdup("none"); 2556 o->jump_port = 0; 2557 } else { 2558 o->jump_user = user; 2559 o->jump_host = host; 2560 o->jump_port = port; 2561 o->proxy_command = xstrdup("none"); 2562 user = host = NULL; 2563 if ((cp = strrchr(s, ',')) != NULL && cp != s) { 2564 o->jump_extra = xstrdup(s); 2565 o->jump_extra[cp - s] = '\0'; 2566 } 2567 } 2568 } 2569 ret = 0; 2570 out: 2571 free(orig); 2572 free(user); 2573 free(host); 2574 return ret; 2575 } 2576 2577 int 2578 parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp) 2579 { 2580 char *path; 2581 int r; 2582 2583 r = parse_uri("ssh", uri, userp, hostp, portp, &path); 2584 if (r == 0 && path != NULL) 2585 r = -1; /* path not allowed */ 2586 return r; 2587 } 2588 2589 /* XXX the following is a near-vebatim copy from servconf.c; refactor */ 2590 static const char * 2591 fmt_multistate_int(int val, const struct multistate *m) 2592 { 2593 u_int i; 2594 2595 for (i = 0; m[i].key != NULL; i++) { 2596 if (m[i].value == val) 2597 return m[i].key; 2598 } 2599 return "UNKNOWN"; 2600 } 2601 2602 static const char * 2603 fmt_intarg(OpCodes code, int val) 2604 { 2605 if (val == -1) 2606 return "unset"; 2607 switch (code) { 2608 case oAddressFamily: 2609 return fmt_multistate_int(val, multistate_addressfamily); 2610 case oVerifyHostKeyDNS: 2611 case oUpdateHostkeys: 2612 return fmt_multistate_int(val, multistate_yesnoask); 2613 case oStrictHostKeyChecking: 2614 return fmt_multistate_int(val, multistate_strict_hostkey); 2615 case oControlMaster: 2616 return fmt_multistate_int(val, multistate_controlmaster); 2617 case oTunnel: 2618 return fmt_multistate_int(val, multistate_tunnel); 2619 case oRequestTTY: 2620 return fmt_multistate_int(val, multistate_requesttty); 2621 case oCanonicalizeHostname: 2622 return fmt_multistate_int(val, multistate_canonicalizehostname); 2623 case oAddKeysToAgent: 2624 return fmt_multistate_int(val, multistate_yesnoaskconfirm); 2625 case oFingerprintHash: 2626 return ssh_digest_alg_name(val); 2627 default: 2628 switch (val) { 2629 case 0: 2630 return "no"; 2631 case 1: 2632 return "yes"; 2633 default: 2634 return "UNKNOWN"; 2635 } 2636 } 2637 } 2638 2639 static const char * 2640 lookup_opcode_name(OpCodes code) 2641 { 2642 u_int i; 2643 2644 for (i = 0; keywords[i].name != NULL; i++) 2645 if (keywords[i].opcode == code) 2646 return(keywords[i].name); 2647 return "UNKNOWN"; 2648 } 2649 2650 static void 2651 dump_cfg_int(OpCodes code, int val) 2652 { 2653 printf("%s %d\n", lookup_opcode_name(code), val); 2654 } 2655 2656 static void 2657 dump_cfg_fmtint(OpCodes code, int val) 2658 { 2659 printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val)); 2660 } 2661 2662 static void 2663 dump_cfg_string(OpCodes code, const char *val) 2664 { 2665 if (val == NULL) 2666 return; 2667 printf("%s %s\n", lookup_opcode_name(code), val); 2668 } 2669 2670 static void 2671 dump_cfg_strarray(OpCodes code, u_int count, char **vals) 2672 { 2673 u_int i; 2674 2675 for (i = 0; i < count; i++) 2676 printf("%s %s\n", lookup_opcode_name(code), vals[i]); 2677 } 2678 2679 static void 2680 dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals) 2681 { 2682 u_int i; 2683 2684 printf("%s", lookup_opcode_name(code)); 2685 for (i = 0; i < count; i++) 2686 printf(" %s", vals[i]); 2687 printf("\n"); 2688 } 2689 2690 static void 2691 dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds) 2692 { 2693 const struct Forward *fwd; 2694 u_int i; 2695 2696 /* oDynamicForward */ 2697 for (i = 0; i < count; i++) { 2698 fwd = &fwds[i]; 2699 if (code == oDynamicForward && fwd->connect_host != NULL && 2700 strcmp(fwd->connect_host, "socks") != 0) 2701 continue; 2702 if (code == oLocalForward && fwd->connect_host != NULL && 2703 strcmp(fwd->connect_host, "socks") == 0) 2704 continue; 2705 printf("%s", lookup_opcode_name(code)); 2706 if (fwd->listen_port == PORT_STREAMLOCAL) 2707 printf(" %s", fwd->listen_path); 2708 else if (fwd->listen_host == NULL) 2709 printf(" %d", fwd->listen_port); 2710 else { 2711 printf(" [%s]:%d", 2712 fwd->listen_host, fwd->listen_port); 2713 } 2714 if (code != oDynamicForward) { 2715 if (fwd->connect_port == PORT_STREAMLOCAL) 2716 printf(" %s", fwd->connect_path); 2717 else if (fwd->connect_host == NULL) 2718 printf(" %d", fwd->connect_port); 2719 else { 2720 printf(" [%s]:%d", 2721 fwd->connect_host, fwd->connect_port); 2722 } 2723 } 2724 printf("\n"); 2725 } 2726 } 2727 2728 void 2729 dump_client_config(Options *o, const char *host) 2730 { 2731 int i, r; 2732 char buf[8], *all_key; 2733 2734 /* 2735 * Expand HostKeyAlgorithms name lists. This isn't handled in 2736 * fill_default_options() like the other algorithm lists because 2737 * the host key algorithms are by default dynamically chosen based 2738 * on the host's keys found in known_hosts. 2739 */ 2740 all_key = sshkey_alg_list(0, 0, 1, ','); 2741 if ((r = kex_assemble_names(&o->hostkeyalgorithms, kex_default_pk_alg(), 2742 all_key)) != 0) 2743 fatal("%s: expand HostKeyAlgorithms: %s", __func__, ssh_err(r)); 2744 free(all_key); 2745 2746 /* Most interesting options first: user, host, port */ 2747 dump_cfg_string(oUser, o->user); 2748 dump_cfg_string(oHostname, host); 2749 dump_cfg_int(oPort, o->port); 2750 2751 /* Flag options */ 2752 dump_cfg_fmtint(oAddressFamily, o->address_family); 2753 dump_cfg_fmtint(oBatchMode, o->batch_mode); 2754 dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local); 2755 dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname); 2756 dump_cfg_fmtint(oChallengeResponseAuthentication, o->challenge_response_authentication); 2757 dump_cfg_fmtint(oCheckHostIP, o->check_host_ip); 2758 dump_cfg_fmtint(oCompression, o->compression); 2759 dump_cfg_fmtint(oControlMaster, o->control_master); 2760 dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign); 2761 dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings); 2762 dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure); 2763 dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash); 2764 dump_cfg_fmtint(oForwardX11, o->forward_x11); 2765 dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted); 2766 dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports); 2767 #ifdef GSSAPI 2768 dump_cfg_fmtint(oGssAuthentication, o->gss_authentication); 2769 dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds); 2770 #endif /* GSSAPI */ 2771 dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts); 2772 dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication); 2773 dump_cfg_fmtint(oIdentitiesOnly, o->identities_only); 2774 dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication); 2775 dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost); 2776 dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication); 2777 dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command); 2778 dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass); 2779 dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication); 2780 dump_cfg_fmtint(oRequestTTY, o->request_tty); 2781 dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink); 2782 dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking); 2783 dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive); 2784 dump_cfg_fmtint(oTunnel, o->tun_open); 2785 dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns); 2786 dump_cfg_fmtint(oVisualHostKey, o->visual_host_key); 2787 dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys); 2788 2789 /* Integer options */ 2790 dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots); 2791 dump_cfg_int(oConnectionAttempts, o->connection_attempts); 2792 dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout); 2793 dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts); 2794 dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max); 2795 dump_cfg_int(oServerAliveInterval, o->server_alive_interval); 2796 2797 /* String options */ 2798 dump_cfg_string(oBindAddress, o->bind_address); 2799 dump_cfg_string(oBindInterface, o->bind_interface); 2800 dump_cfg_string(oCiphers, o->ciphers); 2801 dump_cfg_string(oControlPath, o->control_path); 2802 dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms); 2803 dump_cfg_string(oHostKeyAlias, o->host_key_alias); 2804 dump_cfg_string(oHostbasedKeyTypes, o->hostbased_key_types); 2805 dump_cfg_string(oIdentityAgent, o->identity_agent); 2806 dump_cfg_string(oIgnoreUnknown, o->ignored_unknown); 2807 dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices); 2808 dump_cfg_string(oKexAlgorithms, o->kex_algorithms); 2809 dump_cfg_string(oCASignatureAlgorithms, o->ca_sign_algorithms); 2810 dump_cfg_string(oLocalCommand, o->local_command); 2811 dump_cfg_string(oRemoteCommand, o->remote_command); 2812 dump_cfg_string(oLogLevel, log_level_name(o->log_level)); 2813 dump_cfg_string(oMacs, o->macs); 2814 #ifdef ENABLE_PKCS11 2815 dump_cfg_string(oPKCS11Provider, o->pkcs11_provider); 2816 #endif 2817 dump_cfg_string(oSecurityKeyProvider, o->sk_provider); 2818 dump_cfg_string(oPreferredAuthentications, o->preferred_authentications); 2819 dump_cfg_string(oPubkeyAcceptedKeyTypes, o->pubkey_key_types); 2820 dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys); 2821 dump_cfg_string(oXAuthLocation, o->xauth_location); 2822 2823 /* Forwards */ 2824 dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards); 2825 dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards); 2826 dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards); 2827 2828 /* String array options */ 2829 dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files); 2830 dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains); 2831 dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files); 2832 dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles); 2833 dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles); 2834 dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env); 2835 dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv); 2836 dump_cfg_strarray_oneline(oLogVerbose, 2837 o->num_log_verbose, o->log_verbose); 2838 2839 /* Special cases */ 2840 2841 /* AddKeysToAgent */ 2842 if (o->add_keys_to_agent_lifespan <= 0) 2843 dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent); 2844 else { 2845 printf("addkeystoagent%s %d\n", 2846 o->add_keys_to_agent == 3 ? " confirm" : "", 2847 o->add_keys_to_agent_lifespan); 2848 } 2849 2850 /* oForwardAgent */ 2851 if (o->forward_agent_sock_path == NULL) 2852 dump_cfg_fmtint(oForwardAgent, o->forward_agent); 2853 else 2854 dump_cfg_string(oForwardAgent, o->forward_agent_sock_path); 2855 2856 /* oConnectTimeout */ 2857 if (o->connection_timeout == -1) 2858 printf("connecttimeout none\n"); 2859 else 2860 dump_cfg_int(oConnectTimeout, o->connection_timeout); 2861 2862 /* oTunnelDevice */ 2863 printf("tunneldevice"); 2864 if (o->tun_local == SSH_TUNID_ANY) 2865 printf(" any"); 2866 else 2867 printf(" %d", o->tun_local); 2868 if (o->tun_remote == SSH_TUNID_ANY) 2869 printf(":any"); 2870 else 2871 printf(":%d", o->tun_remote); 2872 printf("\n"); 2873 2874 /* oCanonicalizePermittedCNAMEs */ 2875 if ( o->num_permitted_cnames > 0) { 2876 printf("canonicalizePermittedcnames"); 2877 for (i = 0; i < o->num_permitted_cnames; i++) { 2878 printf(" %s:%s", o->permitted_cnames[i].source_list, 2879 o->permitted_cnames[i].target_list); 2880 } 2881 printf("\n"); 2882 } 2883 2884 /* oControlPersist */ 2885 if (o->control_persist == 0 || o->control_persist_timeout == 0) 2886 dump_cfg_fmtint(oControlPersist, o->control_persist); 2887 else 2888 dump_cfg_int(oControlPersist, o->control_persist_timeout); 2889 2890 /* oEscapeChar */ 2891 if (o->escape_char == SSH_ESCAPECHAR_NONE) 2892 printf("escapechar none\n"); 2893 else { 2894 vis(buf, o->escape_char, VIS_WHITE, 0); 2895 printf("escapechar %s\n", buf); 2896 } 2897 2898 /* oIPQoS */ 2899 printf("ipqos %s ", iptos2str(o->ip_qos_interactive)); 2900 printf("%s\n", iptos2str(o->ip_qos_bulk)); 2901 2902 /* oRekeyLimit */ 2903 printf("rekeylimit %llu %d\n", 2904 (unsigned long long)o->rekey_limit, o->rekey_interval); 2905 2906 /* oStreamLocalBindMask */ 2907 printf("streamlocalbindmask 0%o\n", 2908 o->fwd_opts.streamlocal_bind_mask); 2909 2910 /* oLogFacility */ 2911 printf("syslogfacility %s\n", log_facility_name(o->log_facility)); 2912 2913 /* oProxyCommand / oProxyJump */ 2914 if (o->jump_host == NULL) 2915 dump_cfg_string(oProxyCommand, o->proxy_command); 2916 else { 2917 /* Check for numeric addresses */ 2918 i = strchr(o->jump_host, ':') != NULL || 2919 strspn(o->jump_host, "1234567890.") == strlen(o->jump_host); 2920 snprintf(buf, sizeof(buf), "%d", o->jump_port); 2921 printf("proxyjump %s%s%s%s%s%s%s%s%s\n", 2922 /* optional additional jump spec */ 2923 o->jump_extra == NULL ? "" : o->jump_extra, 2924 o->jump_extra == NULL ? "" : ",", 2925 /* optional user */ 2926 o->jump_user == NULL ? "" : o->jump_user, 2927 o->jump_user == NULL ? "" : "@", 2928 /* opening [ if hostname is numeric */ 2929 i ? "[" : "", 2930 /* mandatory hostname */ 2931 o->jump_host, 2932 /* closing ] if hostname is numeric */ 2933 i ? "]" : "", 2934 /* optional port number */ 2935 o->jump_port <= 0 ? "" : ":", 2936 o->jump_port <= 0 ? "" : buf); 2937 } 2938 } 2939