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