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