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