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