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