1 /* $OpenBSD: readconf.c,v 1.384 2024/01/11 01:45:36 djm Exp $ */ 2 /* 3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 5 * All rights reserved 6 * Functions for reading the configuration files. 7 * 8 * As far as I am concerned, the code I have written for this software 9 * can be used freely for any purpose. Any derived versions of this 10 * software must be clearly marked as such, and if the derived work is 11 * incompatible with the protocol description in the RFC file, it must be 12 * called by a name other than "ssh" or "Secure Shell". 13 */ 14 15 #include <sys/types.h> 16 #include <sys/stat.h> 17 #include <sys/socket.h> 18 #include <sys/wait.h> 19 #include <sys/un.h> 20 21 #include <net/if.h> 22 #include <netinet/in.h> 23 #include <netinet/ip.h> 24 25 #include <ctype.h> 26 #include <errno.h> 27 #include <fcntl.h> 28 #include <glob.h> 29 #include <ifaddrs.h> 30 #include <netdb.h> 31 #include <paths.h> 32 #include <pwd.h> 33 #include <signal.h> 34 #include <stdio.h> 35 #include <string.h> 36 #include <stdarg.h> 37 #include <unistd.h> 38 #include <limits.h> 39 #include <util.h> 40 #include <vis.h> 41 42 #include "xmalloc.h" 43 #include "ssh.h" 44 #include "ssherr.h" 45 #include "cipher.h" 46 #include "pathnames.h" 47 #include "log.h" 48 #include "sshkey.h" 49 #include "misc.h" 50 #include "readconf.h" 51 #include "match.h" 52 #include "kex.h" 53 #include "mac.h" 54 #include "uidswap.h" 55 #include "myproposal.h" 56 #include "digest.h" 57 58 /* Format of the configuration file: 59 60 # Configuration data is parsed as follows: 61 # 1. command line options 62 # 2. user-specific file 63 # 3. system-wide file 64 # Any configuration value is only changed the first time it is set. 65 # Thus, host-specific definitions should be at the beginning of the 66 # configuration file, and defaults at the end. 67 68 # Host-specific declarations. These may override anything above. A single 69 # host may match multiple declarations; these are processed in the order 70 # that they are given in. 71 72 Host *.ngs.fi ngs.fi 73 User foo 74 75 Host fake.com 76 Hostname another.host.name.real.org 77 User blaah 78 Port 34289 79 ForwardX11 no 80 ForwardAgent no 81 82 Host books.com 83 RemoteForward 9999 shadows.cs.hut.fi:9999 84 Ciphers 3des-cbc 85 86 Host fascist.blob.com 87 Port 23123 88 User tylonen 89 PasswordAuthentication no 90 91 Host puukko.hut.fi 92 User t35124p 93 ProxyCommand ssh-proxy %h %p 94 95 Host *.fr 96 PublicKeyAuthentication no 97 98 Host *.su 99 Ciphers aes128-ctr 100 PasswordAuthentication no 101 102 Host vpn.fake.com 103 Tunnel yes 104 TunnelDevice 3 105 106 # Defaults for various options 107 Host * 108 ForwardAgent no 109 ForwardX11 no 110 PasswordAuthentication yes 111 StrictHostKeyChecking yes 112 TcpKeepAlive no 113 IdentityFile ~/.ssh/identity 114 Port 22 115 EscapeChar ~ 116 117 */ 118 119 static int read_config_file_depth(const char *filename, struct passwd *pw, 120 const char *host, const char *original_host, Options *options, 121 int flags, int *activep, int *want_final_pass, int depth); 122 static int process_config_line_depth(Options *options, struct passwd *pw, 123 const char *host, const char *original_host, char *line, 124 const char *filename, int linenum, int *activep, int flags, 125 int *want_final_pass, int depth); 126 127 /* Keyword tokens. */ 128 129 typedef enum { 130 oBadOption, 131 oHost, oMatch, oInclude, oTag, 132 oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout, 133 oGatewayPorts, oExitOnForwardFailure, 134 oPasswordAuthentication, 135 oXAuthLocation, 136 oIdentityFile, oHostname, oPort, oRemoteForward, oLocalForward, 137 oPermitRemoteOpen, 138 oCertificateFile, oAddKeysToAgent, oIdentityAgent, 139 oUser, oEscapeChar, oProxyCommand, 140 oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, 141 oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, 142 oTCPKeepAlive, oNumberOfPasswordPrompts, 143 oLogFacility, oLogLevel, oLogVerbose, oCiphers, oMacs, 144 oPubkeyAuthentication, 145 oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, 146 oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, 147 oHostKeyAlgorithms, oBindAddress, oBindInterface, oPKCS11Provider, 148 oClearAllForwardings, oNoHostAuthenticationForLocalhost, 149 oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, 150 oAddressFamily, oGssAuthentication, oGssDelegateCreds, 151 oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, 152 oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist, 153 oHashKnownHosts, 154 oTunnel, oTunnelDevice, 155 oLocalCommand, oPermitLocalCommand, oRemoteCommand, 156 oVisualHostKey, 157 oKexAlgorithms, oIPQoS, oRequestTTY, oSessionType, oStdinNull, 158 oForkAfterAuthentication, oIgnoreUnknown, oProxyUseFdpass, 159 oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, 160 oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, 161 oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys, 162 oFingerprintHash, oUpdateHostkeys, oHostbasedAcceptedAlgorithms, 163 oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump, 164 oSecurityKeyProvider, oKnownHostsCommand, oRequiredRSASize, 165 oEnableEscapeCommandline, oObscureKeystrokeTiming, oChannelTimeout, 166 oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported 167 } OpCodes; 168 169 /* Textual representations of the tokens. */ 170 171 static struct { 172 const char *name; 173 OpCodes opcode; 174 } keywords[] = { 175 /* Deprecated options */ 176 { "protocol", oIgnore }, /* NB. silently ignored */ 177 { "cipher", oDeprecated }, 178 { "fallbacktorsh", oDeprecated }, 179 { "globalknownhostsfile2", oDeprecated }, 180 { "rhostsauthentication", oDeprecated }, 181 { "userknownhostsfile2", oDeprecated }, 182 { "useroaming", oDeprecated }, 183 { "usersh", oDeprecated }, 184 { "useprivilegedport", oDeprecated }, 185 186 /* Unsupported options */ 187 { "afstokenpassing", oUnsupported }, 188 { "kerberosauthentication", oUnsupported }, 189 { "kerberostgtpassing", oUnsupported }, 190 { "rsaauthentication", oUnsupported }, 191 { "rhostsrsaauthentication", oUnsupported }, 192 { "compressionlevel", oUnsupported }, 193 194 /* Sometimes-unsupported options */ 195 #if defined(GSSAPI) 196 { "gssapiauthentication", oGssAuthentication }, 197 { "gssapidelegatecredentials", oGssDelegateCreds }, 198 # else 199 { "gssapiauthentication", oUnsupported }, 200 { "gssapidelegatecredentials", oUnsupported }, 201 #endif 202 #ifdef ENABLE_PKCS11 203 { "pkcs11provider", oPKCS11Provider }, 204 { "smartcarddevice", oPKCS11Provider }, 205 # else 206 { "smartcarddevice", oUnsupported }, 207 { "pkcs11provider", oUnsupported }, 208 #endif 209 210 { "forwardagent", oForwardAgent }, 211 { "forwardx11", oForwardX11 }, 212 { "forwardx11trusted", oForwardX11Trusted }, 213 { "forwardx11timeout", oForwardX11Timeout }, 214 { "exitonforwardfailure", oExitOnForwardFailure }, 215 { "xauthlocation", oXAuthLocation }, 216 { "gatewayports", oGatewayPorts }, 217 { "passwordauthentication", oPasswordAuthentication }, 218 { "kbdinteractiveauthentication", oKbdInteractiveAuthentication }, 219 { "kbdinteractivedevices", oKbdInteractiveDevices }, 220 { "challengeresponseauthentication", oKbdInteractiveAuthentication }, /* alias */ 221 { "skeyauthentication", oKbdInteractiveAuthentication }, /* alias */ 222 { "tisauthentication", oKbdInteractiveAuthentication }, /* alias */ 223 { "pubkeyauthentication", oPubkeyAuthentication }, 224 { "dsaauthentication", oPubkeyAuthentication }, /* alias */ 225 { "hostbasedauthentication", oHostbasedAuthentication }, 226 { "identityfile", oIdentityFile }, 227 { "identityfile2", oIdentityFile }, /* obsolete */ 228 { "identitiesonly", oIdentitiesOnly }, 229 { "certificatefile", oCertificateFile }, 230 { "addkeystoagent", oAddKeysToAgent }, 231 { "identityagent", oIdentityAgent }, 232 { "hostname", oHostname }, 233 { "hostkeyalias", oHostKeyAlias }, 234 { "proxycommand", oProxyCommand }, 235 { "port", oPort }, 236 { "ciphers", oCiphers }, 237 { "macs", oMacs }, 238 { "remoteforward", oRemoteForward }, 239 { "localforward", oLocalForward }, 240 { "permitremoteopen", oPermitRemoteOpen }, 241 { "user", oUser }, 242 { "host", oHost }, 243 { "match", oMatch }, 244 { "tag", oTag }, 245 { "escapechar", oEscapeChar }, 246 { "globalknownhostsfile", oGlobalKnownHostsFile }, 247 { "userknownhostsfile", oUserKnownHostsFile }, 248 { "connectionattempts", oConnectionAttempts }, 249 { "batchmode", oBatchMode }, 250 { "checkhostip", oCheckHostIP }, 251 { "stricthostkeychecking", oStrictHostKeyChecking }, 252 { "compression", oCompression }, 253 { "tcpkeepalive", oTCPKeepAlive }, 254 { "keepalive", oTCPKeepAlive }, /* obsolete */ 255 { "numberofpasswordprompts", oNumberOfPasswordPrompts }, 256 { "syslogfacility", oLogFacility }, 257 { "loglevel", oLogLevel }, 258 { "logverbose", oLogVerbose }, 259 { "dynamicforward", oDynamicForward }, 260 { "preferredauthentications", oPreferredAuthentications }, 261 { "hostkeyalgorithms", oHostKeyAlgorithms }, 262 { "casignaturealgorithms", oCASignatureAlgorithms }, 263 { "bindaddress", oBindAddress }, 264 { "bindinterface", oBindInterface }, 265 { "clearallforwardings", oClearAllForwardings }, 266 { "enablesshkeysign", oEnableSSHKeysign }, 267 { "verifyhostkeydns", oVerifyHostKeyDNS }, 268 { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost }, 269 { "rekeylimit", oRekeyLimit }, 270 { "connecttimeout", oConnectTimeout }, 271 { "addressfamily", oAddressFamily }, 272 { "serveraliveinterval", oServerAliveInterval }, 273 { "serveralivecountmax", oServerAliveCountMax }, 274 { "sendenv", oSendEnv }, 275 { "setenv", oSetEnv }, 276 { "controlpath", oControlPath }, 277 { "controlmaster", oControlMaster }, 278 { "controlpersist", oControlPersist }, 279 { "hashknownhosts", oHashKnownHosts }, 280 { "include", oInclude }, 281 { "tunnel", oTunnel }, 282 { "tunneldevice", oTunnelDevice }, 283 { "localcommand", oLocalCommand }, 284 { "permitlocalcommand", oPermitLocalCommand }, 285 { "remotecommand", oRemoteCommand }, 286 { "visualhostkey", oVisualHostKey }, 287 { "kexalgorithms", oKexAlgorithms }, 288 { "ipqos", oIPQoS }, 289 { "requesttty", oRequestTTY }, 290 { "sessiontype", oSessionType }, 291 { "stdinnull", oStdinNull }, 292 { "forkafterauthentication", oForkAfterAuthentication }, 293 { "proxyusefdpass", oProxyUseFdpass }, 294 { "canonicaldomains", oCanonicalDomains }, 295 { "canonicalizefallbacklocal", oCanonicalizeFallbackLocal }, 296 { "canonicalizehostname", oCanonicalizeHostname }, 297 { "canonicalizemaxdots", oCanonicalizeMaxDots }, 298 { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs }, 299 { "streamlocalbindmask", oStreamLocalBindMask }, 300 { "streamlocalbindunlink", oStreamLocalBindUnlink }, 301 { "revokedhostkeys", oRevokedHostKeys }, 302 { "fingerprinthash", oFingerprintHash }, 303 { "updatehostkeys", oUpdateHostkeys }, 304 { "hostbasedacceptedalgorithms", oHostbasedAcceptedAlgorithms }, 305 { "hostbasedkeytypes", oHostbasedAcceptedAlgorithms }, /* obsolete */ 306 { "pubkeyacceptedalgorithms", oPubkeyAcceptedAlgorithms }, 307 { "pubkeyacceptedkeytypes", oPubkeyAcceptedAlgorithms }, /* obsolete */ 308 { "ignoreunknown", oIgnoreUnknown }, 309 { "proxyjump", oProxyJump }, 310 { "securitykeyprovider", oSecurityKeyProvider }, 311 { "knownhostscommand", oKnownHostsCommand }, 312 { "requiredrsasize", oRequiredRSASize }, 313 { "enableescapecommandline", oEnableEscapeCommandline }, 314 { "obscurekeystroketiming", oObscureKeystrokeTiming }, 315 { "channeltimeout", oChannelTimeout }, 316 317 { NULL, oBadOption } 318 }; 319 320 static const char *lookup_opcode_name(OpCodes code); 321 322 const char * 323 kex_default_pk_alg(void) 324 { 325 static char *pkalgs; 326 327 if (pkalgs == NULL) { 328 char *all_key; 329 330 all_key = sshkey_alg_list(0, 0, 1, ','); 331 pkalgs = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key); 332 free(all_key); 333 } 334 return pkalgs; 335 } 336 337 char * 338 ssh_connection_hash(const char *thishost, const char *host, const char *portstr, 339 const char *user, const char *jumphost) 340 { 341 struct ssh_digest_ctx *md; 342 u_char conn_hash[SSH_DIGEST_MAX_LENGTH]; 343 344 if ((md = ssh_digest_start(SSH_DIGEST_SHA1)) == NULL || 345 ssh_digest_update(md, thishost, strlen(thishost)) < 0 || 346 ssh_digest_update(md, host, strlen(host)) < 0 || 347 ssh_digest_update(md, portstr, strlen(portstr)) < 0 || 348 ssh_digest_update(md, user, strlen(user)) < 0 || 349 ssh_digest_update(md, jumphost, strlen(jumphost)) < 0 || 350 ssh_digest_final(md, conn_hash, sizeof(conn_hash)) < 0) 351 fatal_f("mux digest failed"); 352 ssh_digest_free(md); 353 return tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1)); 354 } 355 356 /* 357 * Adds a local TCP/IP port forward to options. Never returns if there is an 358 * error. 359 */ 360 361 void 362 add_local_forward(Options *options, const struct Forward *newfwd) 363 { 364 struct Forward *fwd; 365 int i; 366 367 /* Don't add duplicates */ 368 for (i = 0; i < options->num_local_forwards; i++) { 369 if (forward_equals(newfwd, options->local_forwards + i)) 370 return; 371 } 372 options->local_forwards = xreallocarray(options->local_forwards, 373 options->num_local_forwards + 1, 374 sizeof(*options->local_forwards)); 375 fwd = &options->local_forwards[options->num_local_forwards++]; 376 377 fwd->listen_host = newfwd->listen_host; 378 fwd->listen_port = newfwd->listen_port; 379 fwd->listen_path = newfwd->listen_path; 380 fwd->connect_host = newfwd->connect_host; 381 fwd->connect_port = newfwd->connect_port; 382 fwd->connect_path = newfwd->connect_path; 383 } 384 385 /* 386 * Adds a remote TCP/IP port forward to options. Never returns if there is 387 * an error. 388 */ 389 390 void 391 add_remote_forward(Options *options, const struct Forward *newfwd) 392 { 393 struct Forward *fwd; 394 int i; 395 396 /* Don't add duplicates */ 397 for (i = 0; i < options->num_remote_forwards; i++) { 398 if (forward_equals(newfwd, options->remote_forwards + i)) 399 return; 400 } 401 options->remote_forwards = xreallocarray(options->remote_forwards, 402 options->num_remote_forwards + 1, 403 sizeof(*options->remote_forwards)); 404 fwd = &options->remote_forwards[options->num_remote_forwards++]; 405 406 fwd->listen_host = newfwd->listen_host; 407 fwd->listen_port = newfwd->listen_port; 408 fwd->listen_path = newfwd->listen_path; 409 fwd->connect_host = newfwd->connect_host; 410 fwd->connect_port = newfwd->connect_port; 411 fwd->connect_path = newfwd->connect_path; 412 fwd->handle = newfwd->handle; 413 fwd->allocated_port = 0; 414 } 415 416 static void 417 clear_forwardings(Options *options) 418 { 419 int i; 420 421 for (i = 0; i < options->num_local_forwards; i++) { 422 free(options->local_forwards[i].listen_host); 423 free(options->local_forwards[i].listen_path); 424 free(options->local_forwards[i].connect_host); 425 free(options->local_forwards[i].connect_path); 426 } 427 if (options->num_local_forwards > 0) { 428 free(options->local_forwards); 429 options->local_forwards = NULL; 430 } 431 options->num_local_forwards = 0; 432 for (i = 0; i < options->num_remote_forwards; i++) { 433 free(options->remote_forwards[i].listen_host); 434 free(options->remote_forwards[i].listen_path); 435 free(options->remote_forwards[i].connect_host); 436 free(options->remote_forwards[i].connect_path); 437 } 438 if (options->num_remote_forwards > 0) { 439 free(options->remote_forwards); 440 options->remote_forwards = NULL; 441 } 442 options->num_remote_forwards = 0; 443 options->tun_open = SSH_TUNMODE_NO; 444 } 445 446 void 447 add_certificate_file(Options *options, const char *path, int userprovided) 448 { 449 int i; 450 451 if (options->num_certificate_files >= SSH_MAX_CERTIFICATE_FILES) 452 fatal("Too many certificate files specified (max %d)", 453 SSH_MAX_CERTIFICATE_FILES); 454 455 /* Avoid registering duplicates */ 456 for (i = 0; i < options->num_certificate_files; i++) { 457 if (options->certificate_file_userprovided[i] == userprovided && 458 strcmp(options->certificate_files[i], path) == 0) { 459 debug2_f("ignoring duplicate key %s", path); 460 return; 461 } 462 } 463 464 options->certificate_file_userprovided[options->num_certificate_files] = 465 userprovided; 466 options->certificate_files[options->num_certificate_files++] = 467 xstrdup(path); 468 } 469 470 void 471 add_identity_file(Options *options, const char *dir, const char *filename, 472 int userprovided) 473 { 474 char *path; 475 int i; 476 477 if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES) 478 fatal("Too many identity files specified (max %d)", 479 SSH_MAX_IDENTITY_FILES); 480 481 if (dir == NULL) /* no dir, filename is absolute */ 482 path = xstrdup(filename); 483 else if (xasprintf(&path, "%s%s", dir, filename) >= PATH_MAX) 484 fatal("Identity file path %s too long", path); 485 486 /* Avoid registering duplicates */ 487 for (i = 0; i < options->num_identity_files; i++) { 488 if (options->identity_file_userprovided[i] == userprovided && 489 strcmp(options->identity_files[i], path) == 0) { 490 debug2_f("ignoring duplicate key %s", path); 491 free(path); 492 return; 493 } 494 } 495 496 options->identity_file_userprovided[options->num_identity_files] = 497 userprovided; 498 options->identity_files[options->num_identity_files++] = path; 499 } 500 501 int 502 default_ssh_port(void) 503 { 504 static int port; 505 struct servent *sp; 506 507 if (port == 0) { 508 sp = getservbyname(SSH_SERVICE_NAME, "tcp"); 509 port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT; 510 } 511 return port; 512 } 513 514 /* 515 * Execute a command in a shell. 516 * Return its exit status or -1 on abnormal exit. 517 */ 518 static int 519 execute_in_shell(const char *cmd) 520 { 521 char *shell; 522 pid_t pid; 523 int status; 524 525 if ((shell = getenv("SHELL")) == NULL) 526 shell = _PATH_BSHELL; 527 528 if (access(shell, X_OK) == -1) { 529 fatal("Shell \"%s\" is not executable: %s", 530 shell, strerror(errno)); 531 } 532 533 debug("Executing command: '%.500s'", cmd); 534 535 /* Fork and execute the command. */ 536 if ((pid = fork()) == 0) { 537 char *argv[4]; 538 539 if (stdfd_devnull(1, 1, 0) == -1) 540 fatal_f("stdfd_devnull failed"); 541 closefrom(STDERR_FILENO + 1); 542 543 argv[0] = shell; 544 argv[1] = "-c"; 545 argv[2] = xstrdup(cmd); 546 argv[3] = NULL; 547 548 execv(argv[0], argv); 549 error("Unable to execute '%.100s': %s", cmd, strerror(errno)); 550 /* Die with signal to make this error apparent to parent. */ 551 ssh_signal(SIGTERM, SIG_DFL); 552 kill(getpid(), SIGTERM); 553 _exit(1); 554 } 555 /* Parent. */ 556 if (pid == -1) 557 fatal_f("fork: %.100s", strerror(errno)); 558 559 while (waitpid(pid, &status, 0) == -1) { 560 if (errno != EINTR && errno != EAGAIN) 561 fatal_f("waitpid: %s", 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 * Check whether a local network interface address appears in CIDR pattern- 573 * list 'addrlist'. Returns 1 if matched or 0 otherwise. 574 */ 575 static int 576 check_match_ifaddrs(const char *addrlist) 577 { 578 struct ifaddrs *ifa, *ifaddrs = NULL; 579 int r, found = 0; 580 char addr[NI_MAXHOST]; 581 socklen_t salen; 582 583 if (getifaddrs(&ifaddrs) != 0) { 584 error("match localnetwork: getifaddrs failed: %s", 585 strerror(errno)); 586 return 0; 587 } 588 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) { 589 if (ifa->ifa_addr == NULL || ifa->ifa_name == NULL || 590 (ifa->ifa_flags & IFF_UP) == 0) 591 continue; 592 switch (ifa->ifa_addr->sa_family) { 593 case AF_INET: 594 salen = sizeof(struct sockaddr_in); 595 break; 596 case AF_INET6: 597 salen = sizeof(struct sockaddr_in6); 598 break; 599 case AF_LINK: 600 /* ignore */ 601 continue; 602 default: 603 debug2_f("interface %s: unsupported address family %d", 604 ifa->ifa_name, ifa->ifa_addr->sa_family); 605 continue; 606 } 607 if ((r = getnameinfo(ifa->ifa_addr, salen, addr, sizeof(addr), 608 NULL, 0, NI_NUMERICHOST)) != 0) { 609 debug2_f("interface %s getnameinfo failed: %s", 610 ifa->ifa_name, gai_strerror(r)); 611 continue; 612 } 613 debug3_f("interface %s addr %s", ifa->ifa_name, addr); 614 if (addr_match_cidr_list(addr, addrlist) == 1) { 615 debug3_f("matched interface %s: address %s in %s", 616 ifa->ifa_name, addr, addrlist); 617 found = 1; 618 break; 619 } 620 } 621 freeifaddrs(ifaddrs); 622 return found; 623 } 624 625 /* 626 * Parse and execute a Match directive. 627 */ 628 static int 629 match_cfg_line(Options *options, char **condition, struct passwd *pw, 630 const char *host_arg, const char *original_host, int final_pass, 631 int *want_final_pass, const char *filename, int linenum) 632 { 633 char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria; 634 const char *ruser; 635 int r, port, this_result, result = 1, attributes = 0, negate; 636 char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; 637 char uidstr[32]; 638 639 /* 640 * Configuration is likely to be incomplete at this point so we 641 * must be prepared to use default values. 642 */ 643 port = options->port <= 0 ? default_ssh_port() : options->port; 644 ruser = options->user == NULL ? pw->pw_name : options->user; 645 if (final_pass) { 646 host = xstrdup(options->hostname); 647 } else if (options->hostname != NULL) { 648 /* NB. Please keep in sync with ssh.c:main() */ 649 host = percent_expand(options->hostname, 650 "h", host_arg, (char *)NULL); 651 } else { 652 host = xstrdup(host_arg); 653 } 654 655 debug2("checking match for '%s' host %s originally %s", 656 cp, host, original_host); 657 while ((oattrib = attrib = strdelim(&cp)) && *attrib != '\0') { 658 /* Terminate on comment */ 659 if (*attrib == '#') { 660 cp = NULL; /* mark all arguments consumed */ 661 break; 662 } 663 arg = criteria = NULL; 664 this_result = 1; 665 if ((negate = (attrib[0] == '!'))) 666 attrib++; 667 /* Criterion "all" has no argument and must appear alone */ 668 if (strcasecmp(attrib, "all") == 0) { 669 if (attributes > 1 || ((arg = strdelim(&cp)) != NULL && 670 *arg != '\0' && *arg != '#')) { 671 error("%.200s line %d: '%s' cannot be combined " 672 "with other Match attributes", 673 filename, linenum, oattrib); 674 result = -1; 675 goto out; 676 } 677 if (arg != NULL && *arg == '#') 678 cp = NULL; /* mark all arguments consumed */ 679 if (result) 680 result = negate ? 0 : 1; 681 goto out; 682 } 683 attributes++; 684 /* criteria "final" and "canonical" have no argument */ 685 if (strcasecmp(attrib, "canonical") == 0 || 686 strcasecmp(attrib, "final") == 0) { 687 /* 688 * If the config requests "Match final" then remember 689 * this so we can perform a second pass later. 690 */ 691 if (strcasecmp(attrib, "final") == 0 && 692 want_final_pass != NULL) 693 *want_final_pass = 1; 694 r = !!final_pass; /* force bitmask member to boolean */ 695 if (r == (negate ? 1 : 0)) 696 this_result = result = 0; 697 debug3("%.200s line %d: %smatched '%s'", 698 filename, linenum, 699 this_result ? "" : "not ", oattrib); 700 continue; 701 } 702 /* All other criteria require an argument */ 703 if ((arg = strdelim(&cp)) == NULL || 704 *arg == '\0' || *arg == '#') { 705 error("Missing Match criteria for %s", attrib); 706 result = -1; 707 goto out; 708 } 709 if (strcasecmp(attrib, "host") == 0) { 710 criteria = xstrdup(host); 711 r = match_hostname(host, arg) == 1; 712 if (r == (negate ? 1 : 0)) 713 this_result = result = 0; 714 } else if (strcasecmp(attrib, "originalhost") == 0) { 715 criteria = xstrdup(original_host); 716 r = match_hostname(original_host, arg) == 1; 717 if (r == (negate ? 1 : 0)) 718 this_result = result = 0; 719 } else if (strcasecmp(attrib, "user") == 0) { 720 criteria = xstrdup(ruser); 721 r = match_pattern_list(ruser, arg, 0) == 1; 722 if (r == (negate ? 1 : 0)) 723 this_result = result = 0; 724 } else if (strcasecmp(attrib, "localuser") == 0) { 725 criteria = xstrdup(pw->pw_name); 726 r = match_pattern_list(pw->pw_name, arg, 0) == 1; 727 if (r == (negate ? 1 : 0)) 728 this_result = result = 0; 729 } else if (strcasecmp(attrib, "localnetwork") == 0) { 730 if (addr_match_cidr_list(NULL, arg) == -1) { 731 /* Error already printed */ 732 result = -1; 733 goto out; 734 } 735 r = check_match_ifaddrs(arg) == 1; 736 if (r == (negate ? 1 : 0)) 737 this_result = result = 0; 738 } else if (strcasecmp(attrib, "tagged") == 0) { 739 criteria = xstrdup(options->tag == NULL ? "" : 740 options->tag); 741 r = match_pattern_list(criteria, arg, 0) == 1; 742 if (r == (negate ? 1 : 0)) 743 this_result = result = 0; 744 } else if (strcasecmp(attrib, "exec") == 0) { 745 char *conn_hash_hex, *keyalias, *jmphost; 746 747 if (gethostname(thishost, sizeof(thishost)) == -1) 748 fatal("gethostname: %s", strerror(errno)); 749 jmphost = option_clear_or_none(options->jump_host) ? 750 "" : options->jump_host; 751 strlcpy(shorthost, thishost, sizeof(shorthost)); 752 shorthost[strcspn(thishost, ".")] = '\0'; 753 snprintf(portstr, sizeof(portstr), "%d", port); 754 snprintf(uidstr, sizeof(uidstr), "%llu", 755 (unsigned long long)pw->pw_uid); 756 conn_hash_hex = ssh_connection_hash(thishost, host, 757 portstr, ruser, jmphost); 758 keyalias = options->host_key_alias ? 759 options->host_key_alias : host; 760 761 cmd = percent_expand(arg, 762 "C", conn_hash_hex, 763 "L", shorthost, 764 "d", pw->pw_dir, 765 "h", host, 766 "k", keyalias, 767 "l", thishost, 768 "n", original_host, 769 "p", portstr, 770 "r", ruser, 771 "u", pw->pw_name, 772 "i", uidstr, 773 "j", jmphost, 774 (char *)NULL); 775 free(conn_hash_hex); 776 if (result != 1) { 777 /* skip execution if prior predicate failed */ 778 debug3("%.200s line %d: skipped exec " 779 "\"%.100s\"", filename, linenum, cmd); 780 free(cmd); 781 continue; 782 } 783 r = execute_in_shell(cmd); 784 if (r == -1) { 785 fatal("%.200s line %d: match exec " 786 "'%.100s' error", filename, 787 linenum, cmd); 788 } 789 criteria = xstrdup(cmd); 790 free(cmd); 791 /* Force exit status to boolean */ 792 r = r == 0; 793 if (r == (negate ? 1 : 0)) 794 this_result = result = 0; 795 } else { 796 error("Unsupported Match attribute %s", attrib); 797 result = -1; 798 goto out; 799 } 800 debug3("%.200s line %d: %smatched '%s%s%.100s%s' ", 801 filename, linenum, this_result ? "": "not ", oattrib, 802 criteria == NULL ? "" : " \"", 803 criteria == NULL ? "" : criteria, 804 criteria == NULL ? "" : "\""); 805 free(criteria); 806 } 807 if (attributes == 0) { 808 error("One or more attributes required for Match"); 809 result = -1; 810 goto out; 811 } 812 out: 813 if (result != -1) 814 debug2("match %sfound", result ? "" : "not "); 815 *condition = cp; 816 free(host); 817 return result; 818 } 819 820 /* Remove environment variable by pattern */ 821 static void 822 rm_env(Options *options, const char *arg, const char *filename, int linenum) 823 { 824 u_int i, j, onum_send_env = options->num_send_env; 825 826 /* Remove an environment variable */ 827 for (i = 0; i < options->num_send_env; ) { 828 if (!match_pattern(options->send_env[i], arg + 1)) { 829 i++; 830 continue; 831 } 832 debug3("%s line %d: removing environment %s", 833 filename, linenum, options->send_env[i]); 834 free(options->send_env[i]); 835 options->send_env[i] = NULL; 836 for (j = i; j < options->num_send_env - 1; j++) { 837 options->send_env[j] = options->send_env[j + 1]; 838 options->send_env[j + 1] = NULL; 839 } 840 options->num_send_env--; 841 /* NB. don't increment i */ 842 } 843 if (onum_send_env != options->num_send_env) { 844 options->send_env = xrecallocarray(options->send_env, 845 onum_send_env, options->num_send_env, 846 sizeof(*options->send_env)); 847 } 848 } 849 850 /* 851 * Returns the number of the token pointed to by cp or oBadOption. 852 */ 853 static OpCodes 854 parse_token(const char *cp, const char *filename, int linenum, 855 const char *ignored_unknown) 856 { 857 int i; 858 859 for (i = 0; keywords[i].name; i++) 860 if (strcmp(cp, keywords[i].name) == 0) 861 return keywords[i].opcode; 862 if (ignored_unknown != NULL && 863 match_pattern_list(cp, ignored_unknown, 1) == 1) 864 return oIgnoredUnknownOption; 865 error("%s: line %d: Bad configuration option: %s", 866 filename, linenum, cp); 867 return oBadOption; 868 } 869 870 /* Multistate option parsing */ 871 struct multistate { 872 char *key; 873 int value; 874 }; 875 static const struct multistate multistate_flag[] = { 876 { "true", 1 }, 877 { "false", 0 }, 878 { "yes", 1 }, 879 { "no", 0 }, 880 { NULL, -1 } 881 }; 882 static const struct multistate multistate_yesnoask[] = { 883 { "true", 1 }, 884 { "false", 0 }, 885 { "yes", 1 }, 886 { "no", 0 }, 887 { "ask", 2 }, 888 { NULL, -1 } 889 }; 890 static const struct multistate multistate_strict_hostkey[] = { 891 { "true", SSH_STRICT_HOSTKEY_YES }, 892 { "false", SSH_STRICT_HOSTKEY_OFF }, 893 { "yes", SSH_STRICT_HOSTKEY_YES }, 894 { "no", SSH_STRICT_HOSTKEY_OFF }, 895 { "ask", SSH_STRICT_HOSTKEY_ASK }, 896 { "off", SSH_STRICT_HOSTKEY_OFF }, 897 { "accept-new", SSH_STRICT_HOSTKEY_NEW }, 898 { NULL, -1 } 899 }; 900 static const struct multistate multistate_yesnoaskconfirm[] = { 901 { "true", 1 }, 902 { "false", 0 }, 903 { "yes", 1 }, 904 { "no", 0 }, 905 { "ask", 2 }, 906 { "confirm", 3 }, 907 { NULL, -1 } 908 }; 909 static const struct multistate multistate_addressfamily[] = { 910 { "inet", AF_INET }, 911 { "inet6", AF_INET6 }, 912 { "any", AF_UNSPEC }, 913 { NULL, -1 } 914 }; 915 static const struct multistate multistate_controlmaster[] = { 916 { "true", SSHCTL_MASTER_YES }, 917 { "yes", SSHCTL_MASTER_YES }, 918 { "false", SSHCTL_MASTER_NO }, 919 { "no", SSHCTL_MASTER_NO }, 920 { "auto", SSHCTL_MASTER_AUTO }, 921 { "ask", SSHCTL_MASTER_ASK }, 922 { "autoask", SSHCTL_MASTER_AUTO_ASK }, 923 { NULL, -1 } 924 }; 925 static const struct multistate multistate_tunnel[] = { 926 { "ethernet", SSH_TUNMODE_ETHERNET }, 927 { "point-to-point", SSH_TUNMODE_POINTOPOINT }, 928 { "true", SSH_TUNMODE_DEFAULT }, 929 { "yes", SSH_TUNMODE_DEFAULT }, 930 { "false", SSH_TUNMODE_NO }, 931 { "no", SSH_TUNMODE_NO }, 932 { NULL, -1 } 933 }; 934 static const struct multistate multistate_requesttty[] = { 935 { "true", REQUEST_TTY_YES }, 936 { "yes", REQUEST_TTY_YES }, 937 { "false", REQUEST_TTY_NO }, 938 { "no", REQUEST_TTY_NO }, 939 { "force", REQUEST_TTY_FORCE }, 940 { "auto", REQUEST_TTY_AUTO }, 941 { NULL, -1 } 942 }; 943 static const struct multistate multistate_sessiontype[] = { 944 { "none", SESSION_TYPE_NONE }, 945 { "subsystem", SESSION_TYPE_SUBSYSTEM }, 946 { "default", SESSION_TYPE_DEFAULT }, 947 { NULL, -1 } 948 }; 949 static const struct multistate multistate_canonicalizehostname[] = { 950 { "true", SSH_CANONICALISE_YES }, 951 { "false", SSH_CANONICALISE_NO }, 952 { "yes", SSH_CANONICALISE_YES }, 953 { "no", SSH_CANONICALISE_NO }, 954 { "always", SSH_CANONICALISE_ALWAYS }, 955 { NULL, -1 } 956 }; 957 static const struct multistate multistate_pubkey_auth[] = { 958 { "true", SSH_PUBKEY_AUTH_ALL }, 959 { "false", SSH_PUBKEY_AUTH_NO }, 960 { "yes", SSH_PUBKEY_AUTH_ALL }, 961 { "no", SSH_PUBKEY_AUTH_NO }, 962 { "unbound", SSH_PUBKEY_AUTH_UNBOUND }, 963 { "host-bound", SSH_PUBKEY_AUTH_HBOUND }, 964 { NULL, -1 } 965 }; 966 static const struct multistate multistate_compression[] = { 967 #ifdef WITH_ZLIB 968 { "yes", COMP_ZLIB }, 969 #endif 970 { "no", COMP_NONE }, 971 { NULL, -1 } 972 }; 973 974 static int 975 parse_multistate_value(const char *arg, const char *filename, int linenum, 976 const struct multistate *multistate_ptr) 977 { 978 int i; 979 980 if (!arg || *arg == '\0') { 981 error("%s line %d: missing argument.", filename, linenum); 982 return -1; 983 } 984 for (i = 0; multistate_ptr[i].key != NULL; i++) { 985 if (strcasecmp(arg, multistate_ptr[i].key) == 0) 986 return multistate_ptr[i].value; 987 } 988 return -1; 989 } 990 991 /* 992 * Processes a single option line as used in the configuration files. This 993 * only sets those values that have not already been set. 994 */ 995 int 996 process_config_line(Options *options, struct passwd *pw, const char *host, 997 const char *original_host, char *line, const char *filename, 998 int linenum, int *activep, int flags) 999 { 1000 return process_config_line_depth(options, pw, host, original_host, 1001 line, filename, linenum, activep, flags, NULL, 0); 1002 } 1003 1004 #define WHITESPACE " \t\r\n" 1005 static int 1006 process_config_line_depth(Options *options, struct passwd *pw, const char *host, 1007 const char *original_host, char *line, const char *filename, 1008 int linenum, int *activep, int flags, int *want_final_pass, int depth) 1009 { 1010 char *str, **charptr, *endofnumber, *keyword, *arg, *arg2, *p; 1011 char **cpptr, ***cppptr, fwdarg[256]; 1012 u_int i, *uintptr, uvalue, max_entries = 0; 1013 int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0; 1014 int remotefwd, dynamicfwd, ca_only = 0; 1015 LogLevel *log_level_ptr; 1016 SyslogFacility *log_facility_ptr; 1017 long long val64; 1018 size_t len; 1019 struct Forward fwd; 1020 const struct multistate *multistate_ptr; 1021 struct allowed_cname *cname; 1022 glob_t gl; 1023 const char *errstr; 1024 char **oav = NULL, **av; 1025 int oac = 0, ac; 1026 int ret = -1; 1027 1028 if (activep == NULL) { /* We are processing a command line directive */ 1029 cmdline = 1; 1030 activep = &cmdline; 1031 } 1032 1033 /* Strip trailing whitespace. Allow \f (form feed) at EOL only */ 1034 if ((len = strlen(line)) == 0) 1035 return 0; 1036 for (len--; len > 0; len--) { 1037 if (strchr(WHITESPACE "\f", line[len]) == NULL) 1038 break; 1039 line[len] = '\0'; 1040 } 1041 1042 str = line; 1043 /* Get the keyword. (Each line is supposed to begin with a keyword). */ 1044 if ((keyword = strdelim(&str)) == NULL) 1045 return 0; 1046 /* Ignore leading whitespace. */ 1047 if (*keyword == '\0') 1048 keyword = strdelim(&str); 1049 if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#') 1050 return 0; 1051 /* Match lowercase keyword */ 1052 lowercase(keyword); 1053 1054 /* Prepare to parse remainder of line */ 1055 if (str != NULL) 1056 str += strspn(str, WHITESPACE); 1057 if (str == NULL || *str == '\0') { 1058 error("%s line %d: no argument after keyword \"%s\"", 1059 filename, linenum, keyword); 1060 return -1; 1061 } 1062 opcode = parse_token(keyword, filename, linenum, 1063 options->ignored_unknown); 1064 if (argv_split(str, &oac, &oav, 1) != 0) { 1065 error("%s line %d: invalid quotes", filename, linenum); 1066 return -1; 1067 } 1068 ac = oac; 1069 av = oav; 1070 1071 switch (opcode) { 1072 case oBadOption: 1073 /* don't panic, but count bad options */ 1074 goto out; 1075 case oIgnore: 1076 argv_consume(&ac); 1077 break; 1078 case oIgnoredUnknownOption: 1079 debug("%s line %d: Ignored unknown option \"%s\"", 1080 filename, linenum, keyword); 1081 argv_consume(&ac); 1082 break; 1083 case oConnectTimeout: 1084 intptr = &options->connection_timeout; 1085 parse_time: 1086 arg = argv_next(&ac, &av); 1087 if (!arg || *arg == '\0') { 1088 error("%s line %d: missing time value.", 1089 filename, linenum); 1090 goto out; 1091 } 1092 if (strcmp(arg, "none") == 0) 1093 value = -1; 1094 else if ((value = convtime(arg)) == -1) { 1095 error("%s line %d: invalid time value.", 1096 filename, linenum); 1097 goto out; 1098 } 1099 if (*activep && *intptr == -1) 1100 *intptr = value; 1101 break; 1102 1103 case oForwardAgent: 1104 intptr = &options->forward_agent; 1105 1106 arg = argv_next(&ac, &av); 1107 if (!arg || *arg == '\0') { 1108 error("%s line %d: missing argument.", 1109 filename, linenum); 1110 goto out; 1111 } 1112 1113 value = -1; 1114 multistate_ptr = multistate_flag; 1115 for (i = 0; multistate_ptr[i].key != NULL; i++) { 1116 if (strcasecmp(arg, multistate_ptr[i].key) == 0) { 1117 value = multistate_ptr[i].value; 1118 break; 1119 } 1120 } 1121 if (value != -1) { 1122 if (*activep && *intptr == -1) 1123 *intptr = value; 1124 break; 1125 } 1126 /* ForwardAgent wasn't 'yes' or 'no', assume a path */ 1127 if (*activep && *intptr == -1) 1128 *intptr = 1; 1129 1130 charptr = &options->forward_agent_sock_path; 1131 goto parse_agent_path; 1132 1133 case oForwardX11: 1134 intptr = &options->forward_x11; 1135 parse_flag: 1136 multistate_ptr = multistate_flag; 1137 parse_multistate: 1138 arg = argv_next(&ac, &av); 1139 if ((value = parse_multistate_value(arg, filename, linenum, 1140 multistate_ptr)) == -1) { 1141 error("%s line %d: unsupported option \"%s\".", 1142 filename, linenum, arg); 1143 goto out; 1144 } 1145 if (*activep && *intptr == -1) 1146 *intptr = value; 1147 break; 1148 1149 case oForwardX11Trusted: 1150 intptr = &options->forward_x11_trusted; 1151 goto parse_flag; 1152 1153 case oForwardX11Timeout: 1154 intptr = &options->forward_x11_timeout; 1155 goto parse_time; 1156 1157 case oGatewayPorts: 1158 intptr = &options->fwd_opts.gateway_ports; 1159 goto parse_flag; 1160 1161 case oExitOnForwardFailure: 1162 intptr = &options->exit_on_forward_failure; 1163 goto parse_flag; 1164 1165 case oPasswordAuthentication: 1166 intptr = &options->password_authentication; 1167 goto parse_flag; 1168 1169 case oKbdInteractiveAuthentication: 1170 intptr = &options->kbd_interactive_authentication; 1171 goto parse_flag; 1172 1173 case oKbdInteractiveDevices: 1174 charptr = &options->kbd_interactive_devices; 1175 goto parse_string; 1176 1177 case oPubkeyAuthentication: 1178 multistate_ptr = multistate_pubkey_auth; 1179 intptr = &options->pubkey_authentication; 1180 goto parse_multistate; 1181 1182 case oHostbasedAuthentication: 1183 intptr = &options->hostbased_authentication; 1184 goto parse_flag; 1185 1186 case oGssAuthentication: 1187 intptr = &options->gss_authentication; 1188 goto parse_flag; 1189 1190 case oGssDelegateCreds: 1191 intptr = &options->gss_deleg_creds; 1192 goto parse_flag; 1193 1194 case oBatchMode: 1195 intptr = &options->batch_mode; 1196 goto parse_flag; 1197 1198 case oCheckHostIP: 1199 intptr = &options->check_host_ip; 1200 goto parse_flag; 1201 1202 case oVerifyHostKeyDNS: 1203 intptr = &options->verify_host_key_dns; 1204 multistate_ptr = multistate_yesnoask; 1205 goto parse_multistate; 1206 1207 case oStrictHostKeyChecking: 1208 intptr = &options->strict_host_key_checking; 1209 multistate_ptr = multistate_strict_hostkey; 1210 goto parse_multistate; 1211 1212 case oCompression: 1213 intptr = &options->compression; 1214 multistate_ptr = multistate_compression; 1215 goto parse_multistate; 1216 1217 case oTCPKeepAlive: 1218 intptr = &options->tcp_keep_alive; 1219 goto parse_flag; 1220 1221 case oNoHostAuthenticationForLocalhost: 1222 intptr = &options->no_host_authentication_for_localhost; 1223 goto parse_flag; 1224 1225 case oNumberOfPasswordPrompts: 1226 intptr = &options->number_of_password_prompts; 1227 goto parse_int; 1228 1229 case oRekeyLimit: 1230 arg = argv_next(&ac, &av); 1231 if (!arg || *arg == '\0') { 1232 error("%.200s line %d: Missing argument.", filename, 1233 linenum); 1234 goto out; 1235 } 1236 if (strcmp(arg, "default") == 0) { 1237 val64 = 0; 1238 } else { 1239 if (scan_scaled(arg, &val64) == -1) { 1240 error("%.200s line %d: Bad number '%s': %s", 1241 filename, linenum, arg, strerror(errno)); 1242 goto out; 1243 } 1244 if (val64 != 0 && val64 < 16) { 1245 error("%.200s line %d: RekeyLimit too small", 1246 filename, linenum); 1247 goto out; 1248 } 1249 } 1250 if (*activep && options->rekey_limit == -1) 1251 options->rekey_limit = val64; 1252 if (ac != 0) { /* optional rekey interval present */ 1253 if (strcmp(av[0], "none") == 0) { 1254 (void)argv_next(&ac, &av); /* discard */ 1255 break; 1256 } 1257 intptr = &options->rekey_interval; 1258 goto parse_time; 1259 } 1260 break; 1261 1262 case oIdentityFile: 1263 arg = argv_next(&ac, &av); 1264 if (!arg || *arg == '\0') { 1265 error("%.200s line %d: Missing argument.", 1266 filename, linenum); 1267 goto out; 1268 } 1269 if (*activep) { 1270 intptr = &options->num_identity_files; 1271 if (*intptr >= SSH_MAX_IDENTITY_FILES) { 1272 error("%.200s line %d: Too many identity files " 1273 "specified (max %d).", filename, linenum, 1274 SSH_MAX_IDENTITY_FILES); 1275 goto out; 1276 } 1277 add_identity_file(options, NULL, 1278 arg, flags & SSHCONF_USERCONF); 1279 } 1280 break; 1281 1282 case oCertificateFile: 1283 arg = argv_next(&ac, &av); 1284 if (!arg || *arg == '\0') { 1285 error("%.200s line %d: Missing argument.", 1286 filename, linenum); 1287 goto out; 1288 } 1289 if (*activep) { 1290 intptr = &options->num_certificate_files; 1291 if (*intptr >= SSH_MAX_CERTIFICATE_FILES) { 1292 error("%.200s line %d: Too many certificate " 1293 "files specified (max %d).", 1294 filename, linenum, 1295 SSH_MAX_CERTIFICATE_FILES); 1296 goto out; 1297 } 1298 add_certificate_file(options, arg, 1299 flags & SSHCONF_USERCONF); 1300 } 1301 break; 1302 1303 case oXAuthLocation: 1304 charptr=&options->xauth_location; 1305 goto parse_string; 1306 1307 case oUser: 1308 charptr = &options->user; 1309 parse_string: 1310 arg = argv_next(&ac, &av); 1311 if (!arg || *arg == '\0') { 1312 error("%.200s line %d: Missing argument.", 1313 filename, linenum); 1314 goto out; 1315 } 1316 if (*activep && *charptr == NULL) 1317 *charptr = xstrdup(arg); 1318 break; 1319 1320 case oGlobalKnownHostsFile: 1321 cpptr = (char **)&options->system_hostfiles; 1322 uintptr = &options->num_system_hostfiles; 1323 max_entries = SSH_MAX_HOSTS_FILES; 1324 parse_char_array: 1325 i = 0; 1326 value = *uintptr == 0; /* was array empty when we started? */ 1327 while ((arg = argv_next(&ac, &av)) != NULL) { 1328 if (*arg == '\0') { 1329 error("%s line %d: keyword %s empty argument", 1330 filename, linenum, keyword); 1331 goto out; 1332 } 1333 /* Allow "none" only in first position */ 1334 if (strcasecmp(arg, "none") == 0) { 1335 if (i > 0 || ac > 0) { 1336 error("%s line %d: keyword %s \"none\" " 1337 "argument must appear alone.", 1338 filename, linenum, keyword); 1339 goto out; 1340 } 1341 } 1342 i++; 1343 if (*activep && value) { 1344 if ((*uintptr) >= max_entries) { 1345 error("%s line %d: too many %s " 1346 "entries.", filename, linenum, 1347 keyword); 1348 goto out; 1349 } 1350 cpptr[(*uintptr)++] = xstrdup(arg); 1351 } 1352 } 1353 break; 1354 1355 case oUserKnownHostsFile: 1356 cpptr = (char **)&options->user_hostfiles; 1357 uintptr = &options->num_user_hostfiles; 1358 max_entries = SSH_MAX_HOSTS_FILES; 1359 goto parse_char_array; 1360 1361 case oHostname: 1362 charptr = &options->hostname; 1363 goto parse_string; 1364 1365 case oTag: 1366 charptr = &options->tag; 1367 goto parse_string; 1368 1369 case oHostKeyAlias: 1370 charptr = &options->host_key_alias; 1371 goto parse_string; 1372 1373 case oPreferredAuthentications: 1374 charptr = &options->preferred_authentications; 1375 goto parse_string; 1376 1377 case oBindAddress: 1378 charptr = &options->bind_address; 1379 goto parse_string; 1380 1381 case oBindInterface: 1382 charptr = &options->bind_interface; 1383 goto parse_string; 1384 1385 case oPKCS11Provider: 1386 charptr = &options->pkcs11_provider; 1387 goto parse_string; 1388 1389 case oSecurityKeyProvider: 1390 charptr = &options->sk_provider; 1391 goto parse_string; 1392 1393 case oKnownHostsCommand: 1394 charptr = &options->known_hosts_command; 1395 goto parse_command; 1396 1397 case oProxyCommand: 1398 charptr = &options->proxy_command; 1399 /* Ignore ProxyCommand if ProxyJump already specified */ 1400 if (options->jump_host != NULL) 1401 charptr = &options->jump_host; /* Skip below */ 1402 parse_command: 1403 if (str == NULL) { 1404 error("%.200s line %d: Missing argument.", 1405 filename, linenum); 1406 goto out; 1407 } 1408 len = strspn(str, WHITESPACE "="); 1409 if (*activep && *charptr == NULL) 1410 *charptr = xstrdup(str + len); 1411 argv_consume(&ac); 1412 break; 1413 1414 case oProxyJump: 1415 if (str == NULL) { 1416 error("%.200s line %d: Missing argument.", 1417 filename, linenum); 1418 goto out; 1419 } 1420 len = strspn(str, WHITESPACE "="); 1421 /* XXX use argv? */ 1422 if (parse_jump(str + len, options, *activep) == -1) { 1423 error("%.200s line %d: Invalid ProxyJump \"%s\"", 1424 filename, linenum, str + len); 1425 goto out; 1426 } 1427 argv_consume(&ac); 1428 break; 1429 1430 case oPort: 1431 arg = argv_next(&ac, &av); 1432 if (!arg || *arg == '\0') { 1433 error("%.200s line %d: Missing argument.", 1434 filename, linenum); 1435 goto out; 1436 } 1437 value = a2port(arg); 1438 if (value <= 0) { 1439 error("%.200s line %d: Bad port '%s'.", 1440 filename, linenum, arg); 1441 goto out; 1442 } 1443 if (*activep && options->port == -1) 1444 options->port = value; 1445 break; 1446 1447 case oConnectionAttempts: 1448 intptr = &options->connection_attempts; 1449 parse_int: 1450 arg = argv_next(&ac, &av); 1451 if ((errstr = atoi_err(arg, &value)) != NULL) { 1452 error("%s line %d: integer value %s.", 1453 filename, linenum, errstr); 1454 goto out; 1455 } 1456 if (*activep && *intptr == -1) 1457 *intptr = value; 1458 break; 1459 1460 case oCiphers: 1461 arg = argv_next(&ac, &av); 1462 if (!arg || *arg == '\0') { 1463 error("%.200s line %d: Missing argument.", 1464 filename, linenum); 1465 goto out; 1466 } 1467 if (*arg != '-' && 1468 !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)){ 1469 error("%.200s line %d: Bad SSH2 cipher spec '%s'.", 1470 filename, linenum, arg ? arg : "<NONE>"); 1471 goto out; 1472 } 1473 if (*activep && options->ciphers == NULL) 1474 options->ciphers = xstrdup(arg); 1475 break; 1476 1477 case oMacs: 1478 arg = argv_next(&ac, &av); 1479 if (!arg || *arg == '\0') { 1480 error("%.200s line %d: Missing argument.", 1481 filename, linenum); 1482 goto out; 1483 } 1484 if (*arg != '-' && 1485 !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) { 1486 error("%.200s line %d: Bad SSH2 MAC spec '%s'.", 1487 filename, linenum, arg ? arg : "<NONE>"); 1488 goto out; 1489 } 1490 if (*activep && options->macs == NULL) 1491 options->macs = xstrdup(arg); 1492 break; 1493 1494 case oKexAlgorithms: 1495 arg = argv_next(&ac, &av); 1496 if (!arg || *arg == '\0') { 1497 error("%.200s line %d: Missing argument.", 1498 filename, linenum); 1499 goto out; 1500 } 1501 if (*arg != '-' && 1502 !kex_names_valid(*arg == '+' || *arg == '^' ? 1503 arg + 1 : arg)) { 1504 error("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.", 1505 filename, linenum, arg ? arg : "<NONE>"); 1506 goto out; 1507 } 1508 if (*activep && options->kex_algorithms == NULL) 1509 options->kex_algorithms = xstrdup(arg); 1510 break; 1511 1512 case oHostKeyAlgorithms: 1513 charptr = &options->hostkeyalgorithms; 1514 ca_only = 0; 1515 parse_pubkey_algos: 1516 arg = argv_next(&ac, &av); 1517 if (!arg || *arg == '\0') { 1518 error("%.200s line %d: Missing argument.", 1519 filename, linenum); 1520 goto out; 1521 } 1522 if (*arg != '-' && 1523 !sshkey_names_valid2(*arg == '+' || *arg == '^' ? 1524 arg + 1 : arg, 1, ca_only)) { 1525 error("%s line %d: Bad key types '%s'.", 1526 filename, linenum, arg ? arg : "<NONE>"); 1527 goto out; 1528 } 1529 if (*activep && *charptr == NULL) 1530 *charptr = xstrdup(arg); 1531 break; 1532 1533 case oCASignatureAlgorithms: 1534 charptr = &options->ca_sign_algorithms; 1535 ca_only = 1; 1536 goto parse_pubkey_algos; 1537 1538 case oLogLevel: 1539 log_level_ptr = &options->log_level; 1540 arg = argv_next(&ac, &av); 1541 value = log_level_number(arg); 1542 if (value == SYSLOG_LEVEL_NOT_SET) { 1543 error("%.200s line %d: unsupported log level '%s'", 1544 filename, linenum, arg ? arg : "<NONE>"); 1545 goto out; 1546 } 1547 if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET) 1548 *log_level_ptr = (LogLevel) value; 1549 break; 1550 1551 case oLogFacility: 1552 log_facility_ptr = &options->log_facility; 1553 arg = argv_next(&ac, &av); 1554 value = log_facility_number(arg); 1555 if (value == SYSLOG_FACILITY_NOT_SET) { 1556 error("%.200s line %d: unsupported log facility '%s'", 1557 filename, linenum, arg ? arg : "<NONE>"); 1558 goto out; 1559 } 1560 if (*log_facility_ptr == -1) 1561 *log_facility_ptr = (SyslogFacility) value; 1562 break; 1563 1564 case oLogVerbose: 1565 cppptr = &options->log_verbose; 1566 uintptr = &options->num_log_verbose; 1567 i = 0; 1568 while ((arg = argv_next(&ac, &av)) != NULL) { 1569 if (*arg == '\0') { 1570 error("%s line %d: keyword %s empty argument", 1571 filename, linenum, keyword); 1572 goto out; 1573 } 1574 /* Allow "none" only in first position */ 1575 if (strcasecmp(arg, "none") == 0) { 1576 if (i > 0 || ac > 0) { 1577 error("%s line %d: keyword %s \"none\" " 1578 "argument must appear alone.", 1579 filename, linenum, keyword); 1580 goto out; 1581 } 1582 } 1583 i++; 1584 if (*activep && *uintptr == 0) { 1585 *cppptr = xrecallocarray(*cppptr, *uintptr, 1586 *uintptr + 1, sizeof(**cppptr)); 1587 (*cppptr)[(*uintptr)++] = xstrdup(arg); 1588 } 1589 } 1590 break; 1591 1592 case oLocalForward: 1593 case oRemoteForward: 1594 case oDynamicForward: 1595 arg = argv_next(&ac, &av); 1596 if (!arg || *arg == '\0') { 1597 error("%.200s line %d: Missing argument.", 1598 filename, linenum); 1599 goto out; 1600 } 1601 1602 remotefwd = (opcode == oRemoteForward); 1603 dynamicfwd = (opcode == oDynamicForward); 1604 1605 if (!dynamicfwd) { 1606 arg2 = argv_next(&ac, &av); 1607 if (arg2 == NULL || *arg2 == '\0') { 1608 if (remotefwd) 1609 dynamicfwd = 1; 1610 else { 1611 error("%.200s line %d: Missing target " 1612 "argument.", filename, linenum); 1613 goto out; 1614 } 1615 } else { 1616 /* construct a string for parse_forward */ 1617 snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, 1618 arg2); 1619 } 1620 } 1621 if (dynamicfwd) 1622 strlcpy(fwdarg, arg, sizeof(fwdarg)); 1623 1624 if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0) { 1625 error("%.200s line %d: Bad forwarding specification.", 1626 filename, linenum); 1627 goto out; 1628 } 1629 1630 if (*activep) { 1631 if (remotefwd) { 1632 add_remote_forward(options, &fwd); 1633 } else { 1634 add_local_forward(options, &fwd); 1635 } 1636 } 1637 break; 1638 1639 case oPermitRemoteOpen: 1640 uintptr = &options->num_permitted_remote_opens; 1641 cppptr = &options->permitted_remote_opens; 1642 uvalue = *uintptr; /* modified later */ 1643 i = 0; 1644 while ((arg = argv_next(&ac, &av)) != NULL) { 1645 arg2 = xstrdup(arg); 1646 /* Allow any/none only in first position */ 1647 if (strcasecmp(arg, "none") == 0 || 1648 strcasecmp(arg, "any") == 0) { 1649 if (i > 0 || ac > 0) { 1650 error("%s line %d: keyword %s \"%s\" " 1651 "argument must appear alone.", 1652 filename, linenum, keyword, arg); 1653 free(arg2); 1654 goto out; 1655 } 1656 } else { 1657 p = hpdelim(&arg); 1658 if (p == NULL) { 1659 fatal("%s line %d: missing host in %s", 1660 filename, linenum, 1661 lookup_opcode_name(opcode)); 1662 } 1663 p = cleanhostname(p); 1664 /* 1665 * don't want to use permitopen_port to avoid 1666 * dependency on channels.[ch] here. 1667 */ 1668 if (arg == NULL || (strcmp(arg, "*") != 0 && 1669 a2port(arg) <= 0)) { 1670 fatal("%s line %d: bad port number " 1671 "in %s", filename, linenum, 1672 lookup_opcode_name(opcode)); 1673 } 1674 } 1675 if (*activep && uvalue == 0) { 1676 opt_array_append(filename, linenum, 1677 lookup_opcode_name(opcode), 1678 cppptr, uintptr, arg2); 1679 } 1680 free(arg2); 1681 i++; 1682 } 1683 if (i == 0) 1684 fatal("%s line %d: missing %s specification", 1685 filename, linenum, lookup_opcode_name(opcode)); 1686 break; 1687 1688 case oClearAllForwardings: 1689 intptr = &options->clear_forwardings; 1690 goto parse_flag; 1691 1692 case oHost: 1693 if (cmdline) { 1694 error("Host directive not supported as a command-line " 1695 "option"); 1696 goto out; 1697 } 1698 *activep = 0; 1699 arg2 = NULL; 1700 while ((arg = argv_next(&ac, &av)) != NULL) { 1701 if (*arg == '\0') { 1702 error("%s line %d: keyword %s empty argument", 1703 filename, linenum, keyword); 1704 goto out; 1705 } 1706 if ((flags & SSHCONF_NEVERMATCH) != 0) { 1707 argv_consume(&ac); 1708 break; 1709 } 1710 negated = *arg == '!'; 1711 if (negated) 1712 arg++; 1713 if (match_pattern(host, arg)) { 1714 if (negated) { 1715 debug("%.200s line %d: Skipping Host " 1716 "block because of negated match " 1717 "for %.100s", filename, linenum, 1718 arg); 1719 *activep = 0; 1720 argv_consume(&ac); 1721 break; 1722 } 1723 if (!*activep) 1724 arg2 = arg; /* logged below */ 1725 *activep = 1; 1726 } 1727 } 1728 if (*activep) 1729 debug("%.200s line %d: Applying options for %.100s", 1730 filename, linenum, arg2); 1731 break; 1732 1733 case oMatch: 1734 if (cmdline) { 1735 error("Host directive not supported as a command-line " 1736 "option"); 1737 goto out; 1738 } 1739 value = match_cfg_line(options, &str, pw, host, original_host, 1740 flags & SSHCONF_FINAL, want_final_pass, 1741 filename, linenum); 1742 if (value < 0) { 1743 error("%.200s line %d: Bad Match condition", filename, 1744 linenum); 1745 goto out; 1746 } 1747 *activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value; 1748 /* 1749 * If match_cfg_line() didn't consume all its arguments then 1750 * arrange for the extra arguments check below to fail. 1751 */ 1752 1753 if (str == NULL || *str == '\0') 1754 argv_consume(&ac); 1755 break; 1756 1757 case oEscapeChar: 1758 intptr = &options->escape_char; 1759 arg = argv_next(&ac, &av); 1760 if (!arg || *arg == '\0') { 1761 error("%.200s line %d: Missing argument.", 1762 filename, linenum); 1763 goto out; 1764 } 1765 if (strcmp(arg, "none") == 0) 1766 value = SSH_ESCAPECHAR_NONE; 1767 else if (arg[1] == '\0') 1768 value = (u_char) arg[0]; 1769 else if (arg[0] == '^' && arg[2] == 0 && 1770 (u_char) arg[1] >= 64 && (u_char) arg[1] < 128) 1771 value = (u_char) arg[1] & 31; 1772 else { 1773 error("%.200s line %d: Bad escape character.", 1774 filename, linenum); 1775 goto out; 1776 } 1777 if (*activep && *intptr == -1) 1778 *intptr = value; 1779 break; 1780 1781 case oAddressFamily: 1782 intptr = &options->address_family; 1783 multistate_ptr = multistate_addressfamily; 1784 goto parse_multistate; 1785 1786 case oEnableSSHKeysign: 1787 intptr = &options->enable_ssh_keysign; 1788 goto parse_flag; 1789 1790 case oIdentitiesOnly: 1791 intptr = &options->identities_only; 1792 goto parse_flag; 1793 1794 case oServerAliveInterval: 1795 intptr = &options->server_alive_interval; 1796 goto parse_time; 1797 1798 case oServerAliveCountMax: 1799 intptr = &options->server_alive_count_max; 1800 goto parse_int; 1801 1802 case oSendEnv: 1803 while ((arg = argv_next(&ac, &av)) != NULL) { 1804 if (*arg == '\0' || strchr(arg, '=') != NULL) { 1805 error("%s line %d: Invalid environment name.", 1806 filename, linenum); 1807 goto out; 1808 } 1809 if (!*activep) 1810 continue; 1811 if (*arg == '-') { 1812 /* Removing an env var */ 1813 rm_env(options, arg, filename, linenum); 1814 continue; 1815 } 1816 opt_array_append(filename, linenum, 1817 lookup_opcode_name(opcode), 1818 &options->send_env, &options->num_send_env, arg); 1819 } 1820 break; 1821 1822 case oSetEnv: 1823 value = options->num_setenv; 1824 while ((arg = argv_next(&ac, &av)) != NULL) { 1825 if (strchr(arg, '=') == NULL) { 1826 error("%s line %d: Invalid SetEnv.", 1827 filename, linenum); 1828 goto out; 1829 } 1830 if (!*activep || value != 0) 1831 continue; 1832 if (lookup_setenv_in_list(arg, options->setenv, 1833 options->num_setenv) != NULL) { 1834 debug2("%s line %d: ignoring duplicate env " 1835 "name \"%.64s\"", filename, linenum, arg); 1836 continue; 1837 } 1838 opt_array_append(filename, linenum, 1839 lookup_opcode_name(opcode), 1840 &options->setenv, &options->num_setenv, arg); 1841 } 1842 break; 1843 1844 case oControlPath: 1845 charptr = &options->control_path; 1846 goto parse_string; 1847 1848 case oControlMaster: 1849 intptr = &options->control_master; 1850 multistate_ptr = multistate_controlmaster; 1851 goto parse_multistate; 1852 1853 case oControlPersist: 1854 /* no/false/yes/true, or a time spec */ 1855 intptr = &options->control_persist; 1856 arg = argv_next(&ac, &av); 1857 if (!arg || *arg == '\0') { 1858 error("%.200s line %d: Missing ControlPersist" 1859 " argument.", filename, linenum); 1860 goto out; 1861 } 1862 value = 0; 1863 value2 = 0; /* timeout */ 1864 if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 1865 value = 0; 1866 else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 1867 value = 1; 1868 else if ((value2 = convtime(arg)) >= 0) 1869 value = 1; 1870 else { 1871 error("%.200s line %d: Bad ControlPersist argument.", 1872 filename, linenum); 1873 goto out; 1874 } 1875 if (*activep && *intptr == -1) { 1876 *intptr = value; 1877 options->control_persist_timeout = value2; 1878 } 1879 break; 1880 1881 case oHashKnownHosts: 1882 intptr = &options->hash_known_hosts; 1883 goto parse_flag; 1884 1885 case oTunnel: 1886 intptr = &options->tun_open; 1887 multistate_ptr = multistate_tunnel; 1888 goto parse_multistate; 1889 1890 case oTunnelDevice: 1891 arg = argv_next(&ac, &av); 1892 if (!arg || *arg == '\0') { 1893 error("%.200s line %d: Missing argument.", 1894 filename, linenum); 1895 goto out; 1896 } 1897 value = a2tun(arg, &value2); 1898 if (value == SSH_TUNID_ERR) { 1899 error("%.200s line %d: Bad tun device.", 1900 filename, linenum); 1901 goto out; 1902 } 1903 if (*activep && options->tun_local == -1) { 1904 options->tun_local = value; 1905 options->tun_remote = value2; 1906 } 1907 break; 1908 1909 case oLocalCommand: 1910 charptr = &options->local_command; 1911 goto parse_command; 1912 1913 case oPermitLocalCommand: 1914 intptr = &options->permit_local_command; 1915 goto parse_flag; 1916 1917 case oRemoteCommand: 1918 charptr = &options->remote_command; 1919 goto parse_command; 1920 1921 case oVisualHostKey: 1922 intptr = &options->visual_host_key; 1923 goto parse_flag; 1924 1925 case oInclude: 1926 if (cmdline) { 1927 error("Include directive not supported as a " 1928 "command-line option"); 1929 goto out; 1930 } 1931 value = 0; 1932 while ((arg = argv_next(&ac, &av)) != NULL) { 1933 if (*arg == '\0') { 1934 error("%s line %d: keyword %s empty argument", 1935 filename, linenum, keyword); 1936 goto out; 1937 } 1938 /* 1939 * Ensure all paths are anchored. User configuration 1940 * files may begin with '~/' but system configurations 1941 * must not. If the path is relative, then treat it 1942 * as living in ~/.ssh for user configurations or 1943 * /etc/ssh for system ones. 1944 */ 1945 if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0) { 1946 error("%.200s line %d: bad include path %s.", 1947 filename, linenum, arg); 1948 goto out; 1949 } 1950 if (!path_absolute(arg) && *arg != '~') { 1951 xasprintf(&arg2, "%s/%s", 1952 (flags & SSHCONF_USERCONF) ? 1953 "~/" _PATH_SSH_USER_DIR : SSHDIR, arg); 1954 } else 1955 arg2 = xstrdup(arg); 1956 memset(&gl, 0, sizeof(gl)); 1957 r = glob(arg2, GLOB_TILDE, NULL, &gl); 1958 if (r == GLOB_NOMATCH) { 1959 debug("%.200s line %d: include %s matched no " 1960 "files",filename, linenum, arg2); 1961 free(arg2); 1962 continue; 1963 } else if (r != 0) { 1964 error("%.200s line %d: glob failed for %s.", 1965 filename, linenum, arg2); 1966 goto out; 1967 } 1968 free(arg2); 1969 oactive = *activep; 1970 for (i = 0; i < gl.gl_pathc; i++) { 1971 debug3("%.200s line %d: Including file %s " 1972 "depth %d%s", filename, linenum, 1973 gl.gl_pathv[i], depth, 1974 oactive ? "" : " (parse only)"); 1975 r = read_config_file_depth(gl.gl_pathv[i], 1976 pw, host, original_host, options, 1977 flags | SSHCONF_CHECKPERM | 1978 (oactive ? 0 : SSHCONF_NEVERMATCH), 1979 activep, want_final_pass, depth + 1); 1980 if (r != 1 && errno != ENOENT) { 1981 error("Can't open user config file " 1982 "%.100s: %.100s", gl.gl_pathv[i], 1983 strerror(errno)); 1984 globfree(&gl); 1985 goto out; 1986 } 1987 /* 1988 * don't let Match in includes clobber the 1989 * containing file's Match state. 1990 */ 1991 *activep = oactive; 1992 if (r != 1) 1993 value = -1; 1994 } 1995 globfree(&gl); 1996 } 1997 if (value != 0) 1998 ret = value; 1999 break; 2000 2001 case oIPQoS: 2002 arg = argv_next(&ac, &av); 2003 if ((value = parse_ipqos(arg)) == -1) { 2004 error("%s line %d: Bad IPQoS value: %s", 2005 filename, linenum, arg); 2006 goto out; 2007 } 2008 arg = argv_next(&ac, &av); 2009 if (arg == NULL) 2010 value2 = value; 2011 else if ((value2 = parse_ipqos(arg)) == -1) { 2012 error("%s line %d: Bad IPQoS value: %s", 2013 filename, linenum, arg); 2014 goto out; 2015 } 2016 if (*activep && options->ip_qos_interactive == -1) { 2017 options->ip_qos_interactive = value; 2018 options->ip_qos_bulk = value2; 2019 } 2020 break; 2021 2022 case oRequestTTY: 2023 intptr = &options->request_tty; 2024 multistate_ptr = multistate_requesttty; 2025 goto parse_multistate; 2026 2027 case oSessionType: 2028 intptr = &options->session_type; 2029 multistate_ptr = multistate_sessiontype; 2030 goto parse_multistate; 2031 2032 case oStdinNull: 2033 intptr = &options->stdin_null; 2034 goto parse_flag; 2035 2036 case oForkAfterAuthentication: 2037 intptr = &options->fork_after_authentication; 2038 goto parse_flag; 2039 2040 case oIgnoreUnknown: 2041 charptr = &options->ignored_unknown; 2042 goto parse_string; 2043 2044 case oProxyUseFdpass: 2045 intptr = &options->proxy_use_fdpass; 2046 goto parse_flag; 2047 2048 case oCanonicalDomains: 2049 value = options->num_canonical_domains != 0; 2050 i = 0; 2051 while ((arg = argv_next(&ac, &av)) != NULL) { 2052 if (*arg == '\0') { 2053 error("%s line %d: keyword %s empty argument", 2054 filename, linenum, keyword); 2055 goto out; 2056 } 2057 /* Allow "none" only in first position */ 2058 if (strcasecmp(arg, "none") == 0) { 2059 if (i > 0 || ac > 0) { 2060 error("%s line %d: keyword %s \"none\" " 2061 "argument must appear alone.", 2062 filename, linenum, keyword); 2063 goto out; 2064 } 2065 } 2066 i++; 2067 if (!valid_domain(arg, 1, &errstr)) { 2068 error("%s line %d: %s", filename, linenum, 2069 errstr); 2070 goto out; 2071 } 2072 if (!*activep || value) 2073 continue; 2074 if (options->num_canonical_domains >= 2075 MAX_CANON_DOMAINS) { 2076 error("%s line %d: too many hostname suffixes.", 2077 filename, linenum); 2078 goto out; 2079 } 2080 options->canonical_domains[ 2081 options->num_canonical_domains++] = xstrdup(arg); 2082 } 2083 break; 2084 2085 case oCanonicalizePermittedCNAMEs: 2086 value = options->num_permitted_cnames != 0; 2087 i = 0; 2088 while ((arg = argv_next(&ac, &av)) != NULL) { 2089 /* 2090 * Either 'none' (only in first position), '*' for 2091 * everything or 'list:list' 2092 */ 2093 if (strcasecmp(arg, "none") == 0) { 2094 if (i > 0 || ac > 0) { 2095 error("%s line %d: keyword %s \"none\" " 2096 "argument must appear alone.", 2097 filename, linenum, keyword); 2098 goto out; 2099 } 2100 arg2 = ""; 2101 } else if (strcmp(arg, "*") == 0) { 2102 arg2 = arg; 2103 } else { 2104 lowercase(arg); 2105 if ((arg2 = strchr(arg, ':')) == NULL || 2106 arg2[1] == '\0') { 2107 error("%s line %d: " 2108 "Invalid permitted CNAME \"%s\"", 2109 filename, linenum, arg); 2110 goto out; 2111 } 2112 *arg2 = '\0'; 2113 arg2++; 2114 } 2115 i++; 2116 if (!*activep || value) 2117 continue; 2118 if (options->num_permitted_cnames >= 2119 MAX_CANON_DOMAINS) { 2120 error("%s line %d: too many permitted CNAMEs.", 2121 filename, linenum); 2122 goto out; 2123 } 2124 cname = options->permitted_cnames + 2125 options->num_permitted_cnames++; 2126 cname->source_list = xstrdup(arg); 2127 cname->target_list = xstrdup(arg2); 2128 } 2129 break; 2130 2131 case oCanonicalizeHostname: 2132 intptr = &options->canonicalize_hostname; 2133 multistate_ptr = multistate_canonicalizehostname; 2134 goto parse_multistate; 2135 2136 case oCanonicalizeMaxDots: 2137 intptr = &options->canonicalize_max_dots; 2138 goto parse_int; 2139 2140 case oCanonicalizeFallbackLocal: 2141 intptr = &options->canonicalize_fallback_local; 2142 goto parse_flag; 2143 2144 case oStreamLocalBindMask: 2145 arg = argv_next(&ac, &av); 2146 if (!arg || *arg == '\0') { 2147 error("%.200s line %d: Missing StreamLocalBindMask " 2148 "argument.", filename, linenum); 2149 goto out; 2150 } 2151 /* Parse mode in octal format */ 2152 value = strtol(arg, &endofnumber, 8); 2153 if (arg == endofnumber || value < 0 || value > 0777) { 2154 error("%.200s line %d: Bad mask.", filename, linenum); 2155 goto out; 2156 } 2157 options->fwd_opts.streamlocal_bind_mask = (mode_t)value; 2158 break; 2159 2160 case oStreamLocalBindUnlink: 2161 intptr = &options->fwd_opts.streamlocal_bind_unlink; 2162 goto parse_flag; 2163 2164 case oRevokedHostKeys: 2165 charptr = &options->revoked_host_keys; 2166 goto parse_string; 2167 2168 case oFingerprintHash: 2169 intptr = &options->fingerprint_hash; 2170 arg = argv_next(&ac, &av); 2171 if (!arg || *arg == '\0') { 2172 error("%.200s line %d: Missing argument.", 2173 filename, linenum); 2174 goto out; 2175 } 2176 if ((value = ssh_digest_alg_by_name(arg)) == -1) { 2177 error("%.200s line %d: Invalid hash algorithm \"%s\".", 2178 filename, linenum, arg); 2179 goto out; 2180 } 2181 if (*activep && *intptr == -1) 2182 *intptr = value; 2183 break; 2184 2185 case oUpdateHostkeys: 2186 intptr = &options->update_hostkeys; 2187 multistate_ptr = multistate_yesnoask; 2188 goto parse_multistate; 2189 2190 case oHostbasedAcceptedAlgorithms: 2191 charptr = &options->hostbased_accepted_algos; 2192 ca_only = 0; 2193 goto parse_pubkey_algos; 2194 2195 case oPubkeyAcceptedAlgorithms: 2196 charptr = &options->pubkey_accepted_algos; 2197 ca_only = 0; 2198 goto parse_pubkey_algos; 2199 2200 case oAddKeysToAgent: 2201 arg = argv_next(&ac, &av); 2202 arg2 = argv_next(&ac, &av); 2203 value = parse_multistate_value(arg, filename, linenum, 2204 multistate_yesnoaskconfirm); 2205 value2 = 0; /* unlimited lifespan by default */ 2206 if (value == 3 && arg2 != NULL) { 2207 /* allow "AddKeysToAgent confirm 5m" */ 2208 if ((value2 = convtime(arg2)) == -1) { 2209 error("%s line %d: invalid time value.", 2210 filename, linenum); 2211 goto out; 2212 } 2213 } else if (value == -1 && arg2 == NULL) { 2214 if ((value2 = convtime(arg)) == -1) { 2215 error("%s line %d: unsupported option", 2216 filename, linenum); 2217 goto out; 2218 } 2219 value = 1; /* yes */ 2220 } else if (value == -1 || arg2 != NULL) { 2221 error("%s line %d: unsupported option", 2222 filename, linenum); 2223 goto out; 2224 } 2225 if (*activep && options->add_keys_to_agent == -1) { 2226 options->add_keys_to_agent = value; 2227 options->add_keys_to_agent_lifespan = value2; 2228 } 2229 break; 2230 2231 case oIdentityAgent: 2232 charptr = &options->identity_agent; 2233 arg = argv_next(&ac, &av); 2234 if (!arg || *arg == '\0') { 2235 error("%.200s line %d: Missing argument.", 2236 filename, linenum); 2237 goto out; 2238 } 2239 parse_agent_path: 2240 /* Extra validation if the string represents an env var. */ 2241 if ((arg2 = dollar_expand(&r, arg)) == NULL || r) { 2242 error("%.200s line %d: Invalid environment expansion " 2243 "%s.", filename, linenum, arg); 2244 goto out; 2245 } 2246 free(arg2); 2247 /* check for legacy environment format */ 2248 if (arg[0] == '$' && arg[1] != '{' && 2249 !valid_env_name(arg + 1)) { 2250 error("%.200s line %d: Invalid environment name %s.", 2251 filename, linenum, arg); 2252 goto out; 2253 } 2254 if (*activep && *charptr == NULL) 2255 *charptr = xstrdup(arg); 2256 break; 2257 2258 case oEnableEscapeCommandline: 2259 intptr = &options->enable_escape_commandline; 2260 goto parse_flag; 2261 2262 case oRequiredRSASize: 2263 intptr = &options->required_rsa_size; 2264 goto parse_int; 2265 2266 case oObscureKeystrokeTiming: 2267 value = -1; 2268 while ((arg = argv_next(&ac, &av)) != NULL) { 2269 if (value != -1) { 2270 error("%s line %d: invalid arguments", 2271 filename, linenum); 2272 goto out; 2273 } 2274 if (strcmp(arg, "yes") == 0 || 2275 strcmp(arg, "true") == 0) 2276 value = SSH_KEYSTROKE_DEFAULT_INTERVAL_MS; 2277 else if (strcmp(arg, "no") == 0 || 2278 strcmp(arg, "false") == 0) 2279 value = 0; 2280 else if (strncmp(arg, "interval:", 9) == 0) { 2281 if ((errstr = atoi_err(arg + 9, 2282 &value)) != NULL) { 2283 error("%s line %d: integer value %s.", 2284 filename, linenum, errstr); 2285 goto out; 2286 } 2287 if (value <= 0 || value > 1000) { 2288 error("%s line %d: value out of range.", 2289 filename, linenum); 2290 goto out; 2291 } 2292 } else { 2293 error("%s line %d: unsupported argument \"%s\"", 2294 filename, linenum, arg); 2295 goto out; 2296 } 2297 } 2298 if (value == -1) { 2299 error("%s line %d: missing argument", 2300 filename, linenum); 2301 goto out; 2302 } 2303 intptr = &options->obscure_keystroke_timing_interval; 2304 if (*activep && *intptr == -1) 2305 *intptr = value; 2306 break; 2307 2308 case oChannelTimeout: 2309 uvalue = options->num_channel_timeouts; 2310 i = 0; 2311 while ((arg = argv_next(&ac, &av)) != NULL) { 2312 /* Allow "none" only in first position */ 2313 if (strcasecmp(arg, "none") == 0) { 2314 if (i > 0 || ac > 0) { 2315 error("%s line %d: keyword %s \"none\" " 2316 "argument must appear alone.", 2317 filename, linenum, keyword); 2318 goto out; 2319 } 2320 } else if (parse_pattern_interval(arg, 2321 NULL, NULL) != 0) { 2322 fatal("%s line %d: invalid channel timeout %s", 2323 filename, linenum, arg); 2324 } 2325 if (!*activep || uvalue != 0) 2326 continue; 2327 opt_array_append(filename, linenum, keyword, 2328 &options->channel_timeouts, 2329 &options->num_channel_timeouts, arg); 2330 } 2331 break; 2332 2333 case oDeprecated: 2334 debug("%s line %d: Deprecated option \"%s\"", 2335 filename, linenum, keyword); 2336 argv_consume(&ac); 2337 break; 2338 2339 case oUnsupported: 2340 error("%s line %d: Unsupported option \"%s\"", 2341 filename, linenum, keyword); 2342 argv_consume(&ac); 2343 break; 2344 2345 default: 2346 error("%s line %d: Unimplemented opcode %d", 2347 filename, linenum, opcode); 2348 goto out; 2349 } 2350 2351 /* Check that there is no garbage at end of line. */ 2352 if (ac > 0) { 2353 error("%.200s line %d: keyword %s extra arguments " 2354 "at end of line", filename, linenum, keyword); 2355 goto out; 2356 } 2357 2358 /* success */ 2359 ret = 0; 2360 out: 2361 argv_free(oav, oac); 2362 return ret; 2363 } 2364 2365 /* 2366 * Reads the config file and modifies the options accordingly. Options 2367 * should already be initialized before this call. This never returns if 2368 * there is an error. If the file does not exist, this returns 0. 2369 */ 2370 int 2371 read_config_file(const char *filename, struct passwd *pw, const char *host, 2372 const char *original_host, Options *options, int flags, 2373 int *want_final_pass) 2374 { 2375 int active = 1; 2376 2377 return read_config_file_depth(filename, pw, host, original_host, 2378 options, flags, &active, want_final_pass, 0); 2379 } 2380 2381 #define READCONF_MAX_DEPTH 16 2382 static int 2383 read_config_file_depth(const char *filename, struct passwd *pw, 2384 const char *host, const char *original_host, Options *options, 2385 int flags, int *activep, int *want_final_pass, int depth) 2386 { 2387 FILE *f; 2388 char *line = NULL; 2389 size_t linesize = 0; 2390 int linenum; 2391 int bad_options = 0; 2392 2393 if (depth < 0 || depth > READCONF_MAX_DEPTH) 2394 fatal("Too many recursive configuration includes"); 2395 2396 if ((f = fopen(filename, "r")) == NULL) 2397 return 0; 2398 2399 if (flags & SSHCONF_CHECKPERM) { 2400 struct stat sb; 2401 2402 if (fstat(fileno(f), &sb) == -1) 2403 fatal("fstat %s: %s", filename, strerror(errno)); 2404 if (((sb.st_uid != 0 && sb.st_uid != getuid()) || 2405 (sb.st_mode & 022) != 0)) 2406 fatal("Bad owner or permissions on %s", filename); 2407 } 2408 2409 debug("Reading configuration data %.200s", filename); 2410 2411 /* 2412 * Mark that we are now processing the options. This flag is turned 2413 * on/off by Host specifications. 2414 */ 2415 linenum = 0; 2416 while (getline(&line, &linesize, f) != -1) { 2417 /* Update line number counter. */ 2418 linenum++; 2419 /* 2420 * Trim out comments and strip whitespace. 2421 * NB - preserve newlines, they are needed to reproduce 2422 * line numbers later for error messages. 2423 */ 2424 if (process_config_line_depth(options, pw, host, original_host, 2425 line, filename, linenum, activep, flags, want_final_pass, 2426 depth) != 0) 2427 bad_options++; 2428 } 2429 free(line); 2430 fclose(f); 2431 if (bad_options > 0) 2432 fatal("%s: terminating, %d bad configuration options", 2433 filename, bad_options); 2434 return 1; 2435 } 2436 2437 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ 2438 int 2439 option_clear_or_none(const char *o) 2440 { 2441 return o == NULL || strcasecmp(o, "none") == 0; 2442 } 2443 2444 /* 2445 * Returns 1 if CanonicalizePermittedCNAMEs have been specified, 0 otherwise. 2446 * Allowed to be called on non-final configuration. 2447 */ 2448 int 2449 config_has_permitted_cnames(Options *options) 2450 { 2451 if (options->num_permitted_cnames == 1 && 2452 strcasecmp(options->permitted_cnames[0].source_list, "none") == 0 && 2453 strcmp(options->permitted_cnames[0].target_list, "") == 0) 2454 return 0; 2455 return options->num_permitted_cnames > 0; 2456 } 2457 2458 /* 2459 * Initializes options to special values that indicate that they have not yet 2460 * been set. Read_config_file will only set options with this value. Options 2461 * are processed in the following order: command line, user config file, 2462 * system config file. Last, fill_default_options is called. 2463 */ 2464 2465 void 2466 initialize_options(Options * options) 2467 { 2468 memset(options, 'X', sizeof(*options)); 2469 options->host_arg = NULL; 2470 options->forward_agent = -1; 2471 options->forward_agent_sock_path = NULL; 2472 options->forward_x11 = -1; 2473 options->forward_x11_trusted = -1; 2474 options->forward_x11_timeout = -1; 2475 options->stdio_forward_host = NULL; 2476 options->stdio_forward_port = 0; 2477 options->clear_forwardings = -1; 2478 options->exit_on_forward_failure = -1; 2479 options->xauth_location = NULL; 2480 options->fwd_opts.gateway_ports = -1; 2481 options->fwd_opts.streamlocal_bind_mask = (mode_t)-1; 2482 options->fwd_opts.streamlocal_bind_unlink = -1; 2483 options->pubkey_authentication = -1; 2484 options->gss_authentication = -1; 2485 options->gss_deleg_creds = -1; 2486 options->password_authentication = -1; 2487 options->kbd_interactive_authentication = -1; 2488 options->kbd_interactive_devices = NULL; 2489 options->hostbased_authentication = -1; 2490 options->batch_mode = -1; 2491 options->check_host_ip = -1; 2492 options->strict_host_key_checking = -1; 2493 options->compression = -1; 2494 options->tcp_keep_alive = -1; 2495 options->port = -1; 2496 options->address_family = -1; 2497 options->connection_attempts = -1; 2498 options->connection_timeout = -1; 2499 options->number_of_password_prompts = -1; 2500 options->ciphers = NULL; 2501 options->macs = NULL; 2502 options->kex_algorithms = NULL; 2503 options->hostkeyalgorithms = NULL; 2504 options->ca_sign_algorithms = NULL; 2505 options->num_identity_files = 0; 2506 memset(options->identity_keys, 0, sizeof(options->identity_keys)); 2507 options->num_certificate_files = 0; 2508 memset(options->certificates, 0, sizeof(options->certificates)); 2509 options->hostname = NULL; 2510 options->host_key_alias = NULL; 2511 options->proxy_command = NULL; 2512 options->jump_user = NULL; 2513 options->jump_host = NULL; 2514 options->jump_port = -1; 2515 options->jump_extra = NULL; 2516 options->user = NULL; 2517 options->escape_char = -1; 2518 options->num_system_hostfiles = 0; 2519 options->num_user_hostfiles = 0; 2520 options->local_forwards = NULL; 2521 options->num_local_forwards = 0; 2522 options->remote_forwards = NULL; 2523 options->num_remote_forwards = 0; 2524 options->permitted_remote_opens = NULL; 2525 options->num_permitted_remote_opens = 0; 2526 options->log_facility = SYSLOG_FACILITY_NOT_SET; 2527 options->log_level = SYSLOG_LEVEL_NOT_SET; 2528 options->num_log_verbose = 0; 2529 options->log_verbose = NULL; 2530 options->preferred_authentications = NULL; 2531 options->bind_address = NULL; 2532 options->bind_interface = NULL; 2533 options->pkcs11_provider = NULL; 2534 options->sk_provider = NULL; 2535 options->enable_ssh_keysign = - 1; 2536 options->no_host_authentication_for_localhost = - 1; 2537 options->identities_only = - 1; 2538 options->rekey_limit = - 1; 2539 options->rekey_interval = -1; 2540 options->verify_host_key_dns = -1; 2541 options->server_alive_interval = -1; 2542 options->server_alive_count_max = -1; 2543 options->send_env = NULL; 2544 options->num_send_env = 0; 2545 options->setenv = NULL; 2546 options->num_setenv = 0; 2547 options->control_path = NULL; 2548 options->control_master = -1; 2549 options->control_persist = -1; 2550 options->control_persist_timeout = 0; 2551 options->hash_known_hosts = -1; 2552 options->tun_open = -1; 2553 options->tun_local = -1; 2554 options->tun_remote = -1; 2555 options->local_command = NULL; 2556 options->permit_local_command = -1; 2557 options->remote_command = NULL; 2558 options->add_keys_to_agent = -1; 2559 options->add_keys_to_agent_lifespan = -1; 2560 options->identity_agent = NULL; 2561 options->visual_host_key = -1; 2562 options->ip_qos_interactive = -1; 2563 options->ip_qos_bulk = -1; 2564 options->request_tty = -1; 2565 options->session_type = -1; 2566 options->stdin_null = -1; 2567 options->fork_after_authentication = -1; 2568 options->proxy_use_fdpass = -1; 2569 options->ignored_unknown = NULL; 2570 options->num_canonical_domains = 0; 2571 options->num_permitted_cnames = 0; 2572 options->canonicalize_max_dots = -1; 2573 options->canonicalize_fallback_local = -1; 2574 options->canonicalize_hostname = -1; 2575 options->revoked_host_keys = NULL; 2576 options->fingerprint_hash = -1; 2577 options->update_hostkeys = -1; 2578 options->hostbased_accepted_algos = NULL; 2579 options->pubkey_accepted_algos = NULL; 2580 options->known_hosts_command = NULL; 2581 options->required_rsa_size = -1; 2582 options->enable_escape_commandline = -1; 2583 options->obscure_keystroke_timing_interval = -1; 2584 options->tag = NULL; 2585 options->channel_timeouts = NULL; 2586 options->num_channel_timeouts = 0; 2587 } 2588 2589 /* 2590 * A petite version of fill_default_options() that just fills the options 2591 * needed for hostname canonicalization to proceed. 2592 */ 2593 void 2594 fill_default_options_for_canonicalization(Options *options) 2595 { 2596 if (options->canonicalize_max_dots == -1) 2597 options->canonicalize_max_dots = 1; 2598 if (options->canonicalize_fallback_local == -1) 2599 options->canonicalize_fallback_local = 1; 2600 if (options->canonicalize_hostname == -1) 2601 options->canonicalize_hostname = SSH_CANONICALISE_NO; 2602 } 2603 2604 /* 2605 * Called after processing other sources of option data, this fills those 2606 * options for which no value has been specified with their default values. 2607 */ 2608 int 2609 fill_default_options(Options * options) 2610 { 2611 char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig; 2612 char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig; 2613 int ret = 0, r; 2614 2615 if (options->forward_agent == -1) 2616 options->forward_agent = 0; 2617 if (options->forward_x11 == -1) 2618 options->forward_x11 = 0; 2619 if (options->forward_x11_trusted == -1) 2620 options->forward_x11_trusted = 0; 2621 if (options->forward_x11_timeout == -1) 2622 options->forward_x11_timeout = 1200; 2623 /* 2624 * stdio forwarding (-W) changes the default for these but we defer 2625 * setting the values so they can be overridden. 2626 */ 2627 if (options->exit_on_forward_failure == -1) 2628 options->exit_on_forward_failure = 2629 options->stdio_forward_host != NULL ? 1 : 0; 2630 if (options->clear_forwardings == -1) 2631 options->clear_forwardings = 2632 options->stdio_forward_host != NULL ? 1 : 0; 2633 if (options->clear_forwardings == 1) 2634 clear_forwardings(options); 2635 2636 if (options->xauth_location == NULL) 2637 options->xauth_location = xstrdup(_PATH_XAUTH); 2638 if (options->fwd_opts.gateway_ports == -1) 2639 options->fwd_opts.gateway_ports = 0; 2640 if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1) 2641 options->fwd_opts.streamlocal_bind_mask = 0177; 2642 if (options->fwd_opts.streamlocal_bind_unlink == -1) 2643 options->fwd_opts.streamlocal_bind_unlink = 0; 2644 if (options->pubkey_authentication == -1) 2645 options->pubkey_authentication = SSH_PUBKEY_AUTH_ALL; 2646 if (options->gss_authentication == -1) 2647 options->gss_authentication = 0; 2648 if (options->gss_deleg_creds == -1) 2649 options->gss_deleg_creds = 0; 2650 if (options->password_authentication == -1) 2651 options->password_authentication = 1; 2652 if (options->kbd_interactive_authentication == -1) 2653 options->kbd_interactive_authentication = 1; 2654 if (options->hostbased_authentication == -1) 2655 options->hostbased_authentication = 0; 2656 if (options->batch_mode == -1) 2657 options->batch_mode = 0; 2658 if (options->check_host_ip == -1) 2659 options->check_host_ip = 0; 2660 if (options->strict_host_key_checking == -1) 2661 options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK; 2662 if (options->compression == -1) 2663 options->compression = 0; 2664 if (options->tcp_keep_alive == -1) 2665 options->tcp_keep_alive = 1; 2666 if (options->port == -1) 2667 options->port = 0; /* Filled in ssh_connect. */ 2668 if (options->address_family == -1) 2669 options->address_family = AF_UNSPEC; 2670 if (options->connection_attempts == -1) 2671 options->connection_attempts = 1; 2672 if (options->number_of_password_prompts == -1) 2673 options->number_of_password_prompts = 3; 2674 /* options->hostkeyalgorithms, default set in myproposals.h */ 2675 if (options->add_keys_to_agent == -1) { 2676 options->add_keys_to_agent = 0; 2677 options->add_keys_to_agent_lifespan = 0; 2678 } 2679 if (options->num_identity_files == 0) { 2680 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0); 2681 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0); 2682 add_identity_file(options, "~/", 2683 _PATH_SSH_CLIENT_ID_ECDSA_SK, 0); 2684 add_identity_file(options, "~/", 2685 _PATH_SSH_CLIENT_ID_ED25519, 0); 2686 add_identity_file(options, "~/", 2687 _PATH_SSH_CLIENT_ID_ED25519_SK, 0); 2688 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0); 2689 #ifdef WITH_DSA 2690 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0); 2691 #endif 2692 } 2693 if (options->escape_char == -1) 2694 options->escape_char = '~'; 2695 if (options->num_system_hostfiles == 0) { 2696 options->system_hostfiles[options->num_system_hostfiles++] = 2697 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE); 2698 options->system_hostfiles[options->num_system_hostfiles++] = 2699 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2); 2700 } 2701 if (options->update_hostkeys == -1) { 2702 if (options->verify_host_key_dns <= 0 && 2703 (options->num_user_hostfiles == 0 || 2704 (options->num_user_hostfiles == 1 && strcmp(options-> 2705 user_hostfiles[0], _PATH_SSH_USER_HOSTFILE) == 0))) 2706 options->update_hostkeys = SSH_UPDATE_HOSTKEYS_YES; 2707 else 2708 options->update_hostkeys = SSH_UPDATE_HOSTKEYS_NO; 2709 } 2710 if (options->num_user_hostfiles == 0) { 2711 options->user_hostfiles[options->num_user_hostfiles++] = 2712 xstrdup(_PATH_SSH_USER_HOSTFILE); 2713 options->user_hostfiles[options->num_user_hostfiles++] = 2714 xstrdup(_PATH_SSH_USER_HOSTFILE2); 2715 } 2716 if (options->log_level == SYSLOG_LEVEL_NOT_SET) 2717 options->log_level = SYSLOG_LEVEL_INFO; 2718 if (options->log_facility == SYSLOG_FACILITY_NOT_SET) 2719 options->log_facility = SYSLOG_FACILITY_USER; 2720 if (options->no_host_authentication_for_localhost == - 1) 2721 options->no_host_authentication_for_localhost = 0; 2722 if (options->identities_only == -1) 2723 options->identities_only = 0; 2724 if (options->enable_ssh_keysign == -1) 2725 options->enable_ssh_keysign = 0; 2726 if (options->rekey_limit == -1) 2727 options->rekey_limit = 0; 2728 if (options->rekey_interval == -1) 2729 options->rekey_interval = 0; 2730 if (options->verify_host_key_dns == -1) 2731 options->verify_host_key_dns = 0; 2732 if (options->server_alive_interval == -1) 2733 options->server_alive_interval = 0; 2734 if (options->server_alive_count_max == -1) 2735 options->server_alive_count_max = 3; 2736 if (options->control_master == -1) 2737 options->control_master = 0; 2738 if (options->control_persist == -1) { 2739 options->control_persist = 0; 2740 options->control_persist_timeout = 0; 2741 } 2742 if (options->hash_known_hosts == -1) 2743 options->hash_known_hosts = 0; 2744 if (options->tun_open == -1) 2745 options->tun_open = SSH_TUNMODE_NO; 2746 if (options->tun_local == -1) 2747 options->tun_local = SSH_TUNID_ANY; 2748 if (options->tun_remote == -1) 2749 options->tun_remote = SSH_TUNID_ANY; 2750 if (options->permit_local_command == -1) 2751 options->permit_local_command = 0; 2752 if (options->visual_host_key == -1) 2753 options->visual_host_key = 0; 2754 if (options->ip_qos_interactive == -1) 2755 options->ip_qos_interactive = IPTOS_DSCP_AF21; 2756 if (options->ip_qos_bulk == -1) 2757 options->ip_qos_bulk = IPTOS_DSCP_CS1; 2758 if (options->request_tty == -1) 2759 options->request_tty = REQUEST_TTY_AUTO; 2760 if (options->session_type == -1) 2761 options->session_type = SESSION_TYPE_DEFAULT; 2762 if (options->stdin_null == -1) 2763 options->stdin_null = 0; 2764 if (options->fork_after_authentication == -1) 2765 options->fork_after_authentication = 0; 2766 if (options->proxy_use_fdpass == -1) 2767 options->proxy_use_fdpass = 0; 2768 if (options->canonicalize_max_dots == -1) 2769 options->canonicalize_max_dots = 1; 2770 if (options->canonicalize_fallback_local == -1) 2771 options->canonicalize_fallback_local = 1; 2772 if (options->canonicalize_hostname == -1) 2773 options->canonicalize_hostname = SSH_CANONICALISE_NO; 2774 if (options->fingerprint_hash == -1) 2775 options->fingerprint_hash = SSH_FP_HASH_DEFAULT; 2776 if (options->sk_provider == NULL) 2777 options->sk_provider = xstrdup("internal"); 2778 if (options->required_rsa_size == -1) 2779 options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE; 2780 if (options->enable_escape_commandline == -1) 2781 options->enable_escape_commandline = 0; 2782 if (options->obscure_keystroke_timing_interval == -1) { 2783 options->obscure_keystroke_timing_interval = 2784 SSH_KEYSTROKE_DEFAULT_INTERVAL_MS; 2785 } 2786 2787 /* Expand KEX name lists */ 2788 all_cipher = cipher_alg_list(',', 0); 2789 all_mac = mac_alg_list(','); 2790 all_kex = kex_alg_list(','); 2791 all_key = sshkey_alg_list(0, 0, 1, ','); 2792 all_sig = sshkey_alg_list(0, 1, 1, ','); 2793 /* remove unsupported algos from default lists */ 2794 def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher); 2795 def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac); 2796 def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex); 2797 def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key); 2798 def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig); 2799 #define ASSEMBLE(what, defaults, all) \ 2800 do { \ 2801 if ((r = kex_assemble_names(&options->what, \ 2802 defaults, all)) != 0) { \ 2803 error_fr(r, "%s", #what); \ 2804 goto fail; \ 2805 } \ 2806 } while (0) 2807 ASSEMBLE(ciphers, def_cipher, all_cipher); 2808 ASSEMBLE(macs, def_mac, all_mac); 2809 ASSEMBLE(kex_algorithms, def_kex, all_kex); 2810 ASSEMBLE(hostbased_accepted_algos, def_key, all_key); 2811 ASSEMBLE(pubkey_accepted_algos, def_key, all_key); 2812 ASSEMBLE(ca_sign_algorithms, def_sig, all_sig); 2813 #undef ASSEMBLE 2814 2815 #define CLEAR_ON_NONE(v) \ 2816 do { \ 2817 if (option_clear_or_none(v)) { \ 2818 free(v); \ 2819 v = NULL; \ 2820 } \ 2821 } while(0) 2822 #define CLEAR_ON_NONE_ARRAY(v, nv, none) \ 2823 do { \ 2824 if (options->nv == 1 && \ 2825 strcasecmp(options->v[0], none) == 0) { \ 2826 free(options->v[0]); \ 2827 free(options->v); \ 2828 options->v = NULL; \ 2829 options->nv = 0; \ 2830 } \ 2831 } while (0) 2832 CLEAR_ON_NONE(options->local_command); 2833 CLEAR_ON_NONE(options->remote_command); 2834 CLEAR_ON_NONE(options->proxy_command); 2835 CLEAR_ON_NONE(options->control_path); 2836 CLEAR_ON_NONE(options->revoked_host_keys); 2837 CLEAR_ON_NONE(options->pkcs11_provider); 2838 CLEAR_ON_NONE(options->sk_provider); 2839 CLEAR_ON_NONE(options->known_hosts_command); 2840 CLEAR_ON_NONE_ARRAY(channel_timeouts, num_channel_timeouts, "none"); 2841 #undef CLEAR_ON_NONE 2842 #undef CLEAR_ON_NONE_ARRAY 2843 if (options->jump_host != NULL && 2844 strcmp(options->jump_host, "none") == 0 && 2845 options->jump_port == 0 && options->jump_user == NULL) { 2846 free(options->jump_host); 2847 options->jump_host = NULL; 2848 } 2849 if (options->num_permitted_cnames == 1 && 2850 !config_has_permitted_cnames(options)) { 2851 /* clean up CanonicalizePermittedCNAMEs=none */ 2852 free(options->permitted_cnames[0].source_list); 2853 free(options->permitted_cnames[0].target_list); 2854 memset(options->permitted_cnames, '\0', 2855 sizeof(*options->permitted_cnames)); 2856 options->num_permitted_cnames = 0; 2857 } 2858 /* options->identity_agent distinguishes NULL from 'none' */ 2859 /* options->user will be set in the main program if appropriate */ 2860 /* options->hostname will be set in the main program if appropriate */ 2861 /* options->host_key_alias should not be set by default */ 2862 /* options->preferred_authentications will be set in ssh */ 2863 2864 /* success */ 2865 ret = 0; 2866 fail: 2867 free(all_cipher); 2868 free(all_mac); 2869 free(all_kex); 2870 free(all_key); 2871 free(all_sig); 2872 free(def_cipher); 2873 free(def_mac); 2874 free(def_kex); 2875 free(def_key); 2876 free(def_sig); 2877 return ret; 2878 } 2879 2880 void 2881 free_options(Options *o) 2882 { 2883 int i; 2884 2885 if (o == NULL) 2886 return; 2887 2888 #define FREE_ARRAY(type, n, a) \ 2889 do { \ 2890 type _i; \ 2891 for (_i = 0; _i < (n); _i++) \ 2892 free((a)[_i]); \ 2893 } while (0) 2894 2895 free(o->forward_agent_sock_path); 2896 free(o->xauth_location); 2897 FREE_ARRAY(u_int, o->num_log_verbose, o->log_verbose); 2898 free(o->log_verbose); 2899 free(o->ciphers); 2900 free(o->macs); 2901 free(o->hostkeyalgorithms); 2902 free(o->kex_algorithms); 2903 free(o->ca_sign_algorithms); 2904 free(o->hostname); 2905 free(o->host_key_alias); 2906 free(o->proxy_command); 2907 free(o->user); 2908 FREE_ARRAY(u_int, o->num_system_hostfiles, o->system_hostfiles); 2909 FREE_ARRAY(u_int, o->num_user_hostfiles, o->user_hostfiles); 2910 free(o->preferred_authentications); 2911 free(o->bind_address); 2912 free(o->bind_interface); 2913 free(o->pkcs11_provider); 2914 free(o->sk_provider); 2915 for (i = 0; i < o->num_identity_files; i++) { 2916 free(o->identity_files[i]); 2917 sshkey_free(o->identity_keys[i]); 2918 } 2919 for (i = 0; i < o->num_certificate_files; i++) { 2920 free(o->certificate_files[i]); 2921 sshkey_free(o->certificates[i]); 2922 } 2923 free(o->identity_agent); 2924 for (i = 0; i < o->num_local_forwards; i++) { 2925 free(o->local_forwards[i].listen_host); 2926 free(o->local_forwards[i].listen_path); 2927 free(o->local_forwards[i].connect_host); 2928 free(o->local_forwards[i].connect_path); 2929 } 2930 free(o->local_forwards); 2931 for (i = 0; i < o->num_remote_forwards; i++) { 2932 free(o->remote_forwards[i].listen_host); 2933 free(o->remote_forwards[i].listen_path); 2934 free(o->remote_forwards[i].connect_host); 2935 free(o->remote_forwards[i].connect_path); 2936 } 2937 free(o->remote_forwards); 2938 free(o->stdio_forward_host); 2939 FREE_ARRAY(u_int, o->num_send_env, o->send_env); 2940 free(o->send_env); 2941 FREE_ARRAY(u_int, o->num_setenv, o->setenv); 2942 free(o->setenv); 2943 free(o->control_path); 2944 free(o->local_command); 2945 free(o->remote_command); 2946 FREE_ARRAY(int, o->num_canonical_domains, o->canonical_domains); 2947 for (i = 0; i < o->num_permitted_cnames; i++) { 2948 free(o->permitted_cnames[i].source_list); 2949 free(o->permitted_cnames[i].target_list); 2950 } 2951 free(o->revoked_host_keys); 2952 free(o->hostbased_accepted_algos); 2953 free(o->pubkey_accepted_algos); 2954 free(o->jump_user); 2955 free(o->jump_host); 2956 free(o->jump_extra); 2957 free(o->ignored_unknown); 2958 explicit_bzero(o, sizeof(*o)); 2959 #undef FREE_ARRAY 2960 } 2961 2962 struct fwdarg { 2963 char *arg; 2964 int ispath; 2965 }; 2966 2967 /* 2968 * parse_fwd_field 2969 * parses the next field in a port forwarding specification. 2970 * sets fwd to the parsed field and advances p past the colon 2971 * or sets it to NULL at end of string. 2972 * returns 0 on success, else non-zero. 2973 */ 2974 static int 2975 parse_fwd_field(char **p, struct fwdarg *fwd) 2976 { 2977 char *ep, *cp = *p; 2978 int ispath = 0; 2979 2980 if (*cp == '\0') { 2981 *p = NULL; 2982 return -1; /* end of string */ 2983 } 2984 2985 /* 2986 * A field escaped with square brackets is used literally. 2987 * XXX - allow ']' to be escaped via backslash? 2988 */ 2989 if (*cp == '[') { 2990 /* find matching ']' */ 2991 for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) { 2992 if (*ep == '/') 2993 ispath = 1; 2994 } 2995 /* no matching ']' or not at end of field. */ 2996 if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0')) 2997 return -1; 2998 /* NUL terminate the field and advance p past the colon */ 2999 *ep++ = '\0'; 3000 if (*ep != '\0') 3001 *ep++ = '\0'; 3002 fwd->arg = cp + 1; 3003 fwd->ispath = ispath; 3004 *p = ep; 3005 return 0; 3006 } 3007 3008 for (cp = *p; *cp != '\0'; cp++) { 3009 switch (*cp) { 3010 case '\\': 3011 memmove(cp, cp + 1, strlen(cp + 1) + 1); 3012 if (*cp == '\0') 3013 return -1; 3014 break; 3015 case '/': 3016 ispath = 1; 3017 break; 3018 case ':': 3019 *cp++ = '\0'; 3020 goto done; 3021 } 3022 } 3023 done: 3024 fwd->arg = *p; 3025 fwd->ispath = ispath; 3026 *p = cp; 3027 return 0; 3028 } 3029 3030 /* 3031 * parse_forward 3032 * parses a string containing a port forwarding specification of the form: 3033 * dynamicfwd == 0 3034 * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath 3035 * listenpath:connectpath 3036 * dynamicfwd == 1 3037 * [listenhost:]listenport 3038 * returns number of arguments parsed or zero on error 3039 */ 3040 int 3041 parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) 3042 { 3043 struct fwdarg fwdargs[4]; 3044 char *p, *cp; 3045 int i, err; 3046 3047 memset(fwd, 0, sizeof(*fwd)); 3048 memset(fwdargs, 0, sizeof(fwdargs)); 3049 3050 /* 3051 * We expand environment variables before checking if we think they're 3052 * paths so that if ${VAR} expands to a fully qualified path it is 3053 * treated as a path. 3054 */ 3055 cp = p = dollar_expand(&err, fwdspec); 3056 if (p == NULL || err) 3057 return 0; 3058 3059 /* skip leading spaces */ 3060 while (isspace((u_char)*cp)) 3061 cp++; 3062 3063 for (i = 0; i < 4; ++i) { 3064 if (parse_fwd_field(&cp, &fwdargs[i]) != 0) 3065 break; 3066 } 3067 3068 /* Check for trailing garbage */ 3069 if (cp != NULL && *cp != '\0') { 3070 i = 0; /* failure */ 3071 } 3072 3073 switch (i) { 3074 case 1: 3075 if (fwdargs[0].ispath) { 3076 fwd->listen_path = xstrdup(fwdargs[0].arg); 3077 fwd->listen_port = PORT_STREAMLOCAL; 3078 } else { 3079 fwd->listen_host = NULL; 3080 fwd->listen_port = a2port(fwdargs[0].arg); 3081 } 3082 fwd->connect_host = xstrdup("socks"); 3083 break; 3084 3085 case 2: 3086 if (fwdargs[0].ispath && fwdargs[1].ispath) { 3087 fwd->listen_path = xstrdup(fwdargs[0].arg); 3088 fwd->listen_port = PORT_STREAMLOCAL; 3089 fwd->connect_path = xstrdup(fwdargs[1].arg); 3090 fwd->connect_port = PORT_STREAMLOCAL; 3091 } else if (fwdargs[1].ispath) { 3092 fwd->listen_host = NULL; 3093 fwd->listen_port = a2port(fwdargs[0].arg); 3094 fwd->connect_path = xstrdup(fwdargs[1].arg); 3095 fwd->connect_port = PORT_STREAMLOCAL; 3096 } else { 3097 fwd->listen_host = xstrdup(fwdargs[0].arg); 3098 fwd->listen_port = a2port(fwdargs[1].arg); 3099 fwd->connect_host = xstrdup("socks"); 3100 } 3101 break; 3102 3103 case 3: 3104 if (fwdargs[0].ispath) { 3105 fwd->listen_path = xstrdup(fwdargs[0].arg); 3106 fwd->listen_port = PORT_STREAMLOCAL; 3107 fwd->connect_host = xstrdup(fwdargs[1].arg); 3108 fwd->connect_port = a2port(fwdargs[2].arg); 3109 } else if (fwdargs[2].ispath) { 3110 fwd->listen_host = xstrdup(fwdargs[0].arg); 3111 fwd->listen_port = a2port(fwdargs[1].arg); 3112 fwd->connect_path = xstrdup(fwdargs[2].arg); 3113 fwd->connect_port = PORT_STREAMLOCAL; 3114 } else { 3115 fwd->listen_host = NULL; 3116 fwd->listen_port = a2port(fwdargs[0].arg); 3117 fwd->connect_host = xstrdup(fwdargs[1].arg); 3118 fwd->connect_port = a2port(fwdargs[2].arg); 3119 } 3120 break; 3121 3122 case 4: 3123 fwd->listen_host = xstrdup(fwdargs[0].arg); 3124 fwd->listen_port = a2port(fwdargs[1].arg); 3125 fwd->connect_host = xstrdup(fwdargs[2].arg); 3126 fwd->connect_port = a2port(fwdargs[3].arg); 3127 break; 3128 default: 3129 i = 0; /* failure */ 3130 } 3131 3132 free(p); 3133 3134 if (dynamicfwd) { 3135 if (!(i == 1 || i == 2)) 3136 goto fail_free; 3137 } else { 3138 if (!(i == 3 || i == 4)) { 3139 if (fwd->connect_path == NULL && 3140 fwd->listen_path == NULL) 3141 goto fail_free; 3142 } 3143 if (fwd->connect_port <= 0 && fwd->connect_path == NULL) 3144 goto fail_free; 3145 } 3146 3147 if ((fwd->listen_port < 0 && fwd->listen_path == NULL) || 3148 (!remotefwd && fwd->listen_port == 0)) 3149 goto fail_free; 3150 if (fwd->connect_host != NULL && 3151 strlen(fwd->connect_host) >= NI_MAXHOST) 3152 goto fail_free; 3153 /* 3154 * XXX - if connecting to a remote socket, max sun len may not 3155 * match this host 3156 */ 3157 if (fwd->connect_path != NULL && 3158 strlen(fwd->connect_path) >= PATH_MAX_SUN) 3159 goto fail_free; 3160 if (fwd->listen_host != NULL && 3161 strlen(fwd->listen_host) >= NI_MAXHOST) 3162 goto fail_free; 3163 if (fwd->listen_path != NULL && 3164 strlen(fwd->listen_path) >= PATH_MAX_SUN) 3165 goto fail_free; 3166 3167 return (i); 3168 3169 fail_free: 3170 free(fwd->connect_host); 3171 fwd->connect_host = NULL; 3172 free(fwd->connect_path); 3173 fwd->connect_path = NULL; 3174 free(fwd->listen_host); 3175 fwd->listen_host = NULL; 3176 free(fwd->listen_path); 3177 fwd->listen_path = NULL; 3178 return (0); 3179 } 3180 3181 int 3182 parse_jump(const char *s, Options *o, int active) 3183 { 3184 char *orig, *sdup, *cp; 3185 char *host = NULL, *user = NULL; 3186 int r, ret = -1, port = -1, first; 3187 3188 active &= o->proxy_command == NULL && o->jump_host == NULL; 3189 3190 orig = sdup = xstrdup(s); 3191 3192 /* Remove comment and trailing whitespace */ 3193 if ((cp = strchr(orig, '#')) != NULL) 3194 *cp = '\0'; 3195 rtrim(orig); 3196 3197 first = active; 3198 do { 3199 if (strcasecmp(s, "none") == 0) 3200 break; 3201 if ((cp = strrchr(sdup, ',')) == NULL) 3202 cp = sdup; /* last */ 3203 else 3204 *cp++ = '\0'; 3205 3206 if (first) { 3207 /* First argument and configuration is active */ 3208 r = parse_ssh_uri(cp, &user, &host, &port); 3209 if (r == -1 || (r == 1 && 3210 parse_user_host_port(cp, &user, &host, &port) != 0)) 3211 goto out; 3212 } else { 3213 /* Subsequent argument or inactive configuration */ 3214 r = parse_ssh_uri(cp, NULL, NULL, NULL); 3215 if (r == -1 || (r == 1 && 3216 parse_user_host_port(cp, NULL, NULL, NULL) != 0)) 3217 goto out; 3218 } 3219 first = 0; /* only check syntax for subsequent hosts */ 3220 } while (cp != sdup); 3221 /* success */ 3222 if (active) { 3223 if (strcasecmp(s, "none") == 0) { 3224 o->jump_host = xstrdup("none"); 3225 o->jump_port = 0; 3226 } else { 3227 o->jump_user = user; 3228 o->jump_host = host; 3229 o->jump_port = port; 3230 o->proxy_command = xstrdup("none"); 3231 user = host = NULL; 3232 if ((cp = strrchr(s, ',')) != NULL && cp != s) { 3233 o->jump_extra = xstrdup(s); 3234 o->jump_extra[cp - s] = '\0'; 3235 } 3236 } 3237 } 3238 ret = 0; 3239 out: 3240 free(orig); 3241 free(user); 3242 free(host); 3243 return ret; 3244 } 3245 3246 int 3247 parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp) 3248 { 3249 char *user = NULL, *host = NULL, *path = NULL; 3250 int r, port; 3251 3252 r = parse_uri("ssh", uri, &user, &host, &port, &path); 3253 if (r == 0 && path != NULL) 3254 r = -1; /* path not allowed */ 3255 if (r == 0) { 3256 if (userp != NULL) { 3257 *userp = user; 3258 user = NULL; 3259 } 3260 if (hostp != NULL) { 3261 *hostp = host; 3262 host = NULL; 3263 } 3264 if (portp != NULL) 3265 *portp = port; 3266 } 3267 free(user); 3268 free(host); 3269 free(path); 3270 return r; 3271 } 3272 3273 /* XXX the following is a near-vebatim copy from servconf.c; refactor */ 3274 static const char * 3275 fmt_multistate_int(int val, const struct multistate *m) 3276 { 3277 u_int i; 3278 3279 for (i = 0; m[i].key != NULL; i++) { 3280 if (m[i].value == val) 3281 return m[i].key; 3282 } 3283 return "UNKNOWN"; 3284 } 3285 3286 static const char * 3287 fmt_intarg(OpCodes code, int val) 3288 { 3289 if (val == -1) 3290 return "unset"; 3291 switch (code) { 3292 case oAddressFamily: 3293 return fmt_multistate_int(val, multistate_addressfamily); 3294 case oVerifyHostKeyDNS: 3295 case oUpdateHostkeys: 3296 return fmt_multistate_int(val, multistate_yesnoask); 3297 case oStrictHostKeyChecking: 3298 return fmt_multistate_int(val, multistate_strict_hostkey); 3299 case oControlMaster: 3300 return fmt_multistate_int(val, multistate_controlmaster); 3301 case oTunnel: 3302 return fmt_multistate_int(val, multistate_tunnel); 3303 case oRequestTTY: 3304 return fmt_multistate_int(val, multistate_requesttty); 3305 case oSessionType: 3306 return fmt_multistate_int(val, multistate_sessiontype); 3307 case oCanonicalizeHostname: 3308 return fmt_multistate_int(val, multistate_canonicalizehostname); 3309 case oAddKeysToAgent: 3310 return fmt_multistate_int(val, multistate_yesnoaskconfirm); 3311 case oPubkeyAuthentication: 3312 return fmt_multistate_int(val, multistate_pubkey_auth); 3313 case oFingerprintHash: 3314 return ssh_digest_alg_name(val); 3315 default: 3316 switch (val) { 3317 case 0: 3318 return "no"; 3319 case 1: 3320 return "yes"; 3321 default: 3322 return "UNKNOWN"; 3323 } 3324 } 3325 } 3326 3327 static const char * 3328 lookup_opcode_name(OpCodes code) 3329 { 3330 u_int i; 3331 3332 for (i = 0; keywords[i].name != NULL; i++) 3333 if (keywords[i].opcode == code) 3334 return(keywords[i].name); 3335 return "UNKNOWN"; 3336 } 3337 3338 static void 3339 dump_cfg_int(OpCodes code, int val) 3340 { 3341 if (code == oObscureKeystrokeTiming) { 3342 if (val == 0) { 3343 printf("%s no\n", lookup_opcode_name(code)); 3344 return; 3345 } else if (val == SSH_KEYSTROKE_DEFAULT_INTERVAL_MS) { 3346 printf("%s yes\n", lookup_opcode_name(code)); 3347 return; 3348 } 3349 /* FALLTHROUGH */ 3350 } 3351 printf("%s %d\n", lookup_opcode_name(code), val); 3352 } 3353 3354 static void 3355 dump_cfg_fmtint(OpCodes code, int val) 3356 { 3357 printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val)); 3358 } 3359 3360 static void 3361 dump_cfg_string(OpCodes code, const char *val) 3362 { 3363 if (val == NULL) 3364 return; 3365 printf("%s %s\n", lookup_opcode_name(code), val); 3366 } 3367 3368 static void 3369 dump_cfg_strarray(OpCodes code, u_int count, char **vals) 3370 { 3371 u_int i; 3372 3373 for (i = 0; i < count; i++) 3374 printf("%s %s\n", lookup_opcode_name(code), vals[i]); 3375 } 3376 3377 static void 3378 dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals) 3379 { 3380 u_int i; 3381 3382 printf("%s", lookup_opcode_name(code)); 3383 if (count == 0) 3384 printf(" none"); 3385 for (i = 0; i < count; i++) 3386 printf(" %s", vals[i]); 3387 printf("\n"); 3388 } 3389 3390 static void 3391 dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds) 3392 { 3393 const struct Forward *fwd; 3394 u_int i; 3395 3396 /* oDynamicForward */ 3397 for (i = 0; i < count; i++) { 3398 fwd = &fwds[i]; 3399 if (code == oDynamicForward && fwd->connect_host != NULL && 3400 strcmp(fwd->connect_host, "socks") != 0) 3401 continue; 3402 if (code == oLocalForward && fwd->connect_host != NULL && 3403 strcmp(fwd->connect_host, "socks") == 0) 3404 continue; 3405 printf("%s", lookup_opcode_name(code)); 3406 if (fwd->listen_port == PORT_STREAMLOCAL) 3407 printf(" %s", fwd->listen_path); 3408 else if (fwd->listen_host == NULL) 3409 printf(" %d", fwd->listen_port); 3410 else { 3411 printf(" [%s]:%d", 3412 fwd->listen_host, fwd->listen_port); 3413 } 3414 if (code != oDynamicForward) { 3415 if (fwd->connect_port == PORT_STREAMLOCAL) 3416 printf(" %s", fwd->connect_path); 3417 else if (fwd->connect_host == NULL) 3418 printf(" %d", fwd->connect_port); 3419 else { 3420 printf(" [%s]:%d", 3421 fwd->connect_host, fwd->connect_port); 3422 } 3423 } 3424 printf("\n"); 3425 } 3426 } 3427 3428 void 3429 dump_client_config(Options *o, const char *host) 3430 { 3431 int i, r; 3432 char buf[8], *all_key; 3433 3434 /* 3435 * Expand HostKeyAlgorithms name lists. This isn't handled in 3436 * fill_default_options() like the other algorithm lists because 3437 * the host key algorithms are by default dynamically chosen based 3438 * on the host's keys found in known_hosts. 3439 */ 3440 all_key = sshkey_alg_list(0, 0, 1, ','); 3441 if ((r = kex_assemble_names(&o->hostkeyalgorithms, kex_default_pk_alg(), 3442 all_key)) != 0) 3443 fatal_fr(r, "expand HostKeyAlgorithms"); 3444 free(all_key); 3445 3446 /* Most interesting options first: user, host, port */ 3447 dump_cfg_string(oHost, o->host_arg); 3448 dump_cfg_string(oUser, o->user); 3449 dump_cfg_string(oHostname, host); 3450 dump_cfg_int(oPort, o->port); 3451 3452 /* Flag options */ 3453 dump_cfg_fmtint(oAddressFamily, o->address_family); 3454 dump_cfg_fmtint(oBatchMode, o->batch_mode); 3455 dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local); 3456 dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname); 3457 dump_cfg_fmtint(oCheckHostIP, o->check_host_ip); 3458 dump_cfg_fmtint(oCompression, o->compression); 3459 dump_cfg_fmtint(oControlMaster, o->control_master); 3460 dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign); 3461 dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings); 3462 dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure); 3463 dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash); 3464 dump_cfg_fmtint(oForwardX11, o->forward_x11); 3465 dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted); 3466 dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports); 3467 #ifdef GSSAPI 3468 dump_cfg_fmtint(oGssAuthentication, o->gss_authentication); 3469 dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds); 3470 #endif /* GSSAPI */ 3471 dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts); 3472 dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication); 3473 dump_cfg_fmtint(oIdentitiesOnly, o->identities_only); 3474 dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication); 3475 dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost); 3476 dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication); 3477 dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command); 3478 dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass); 3479 dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication); 3480 dump_cfg_fmtint(oRequestTTY, o->request_tty); 3481 dump_cfg_fmtint(oSessionType, o->session_type); 3482 dump_cfg_fmtint(oStdinNull, o->stdin_null); 3483 dump_cfg_fmtint(oForkAfterAuthentication, o->fork_after_authentication); 3484 dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink); 3485 dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking); 3486 dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive); 3487 dump_cfg_fmtint(oTunnel, o->tun_open); 3488 dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns); 3489 dump_cfg_fmtint(oVisualHostKey, o->visual_host_key); 3490 dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys); 3491 dump_cfg_fmtint(oEnableEscapeCommandline, o->enable_escape_commandline); 3492 3493 /* Integer options */ 3494 dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots); 3495 dump_cfg_int(oConnectionAttempts, o->connection_attempts); 3496 dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout); 3497 dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts); 3498 dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max); 3499 dump_cfg_int(oServerAliveInterval, o->server_alive_interval); 3500 dump_cfg_int(oRequiredRSASize, o->required_rsa_size); 3501 dump_cfg_int(oObscureKeystrokeTiming, 3502 o->obscure_keystroke_timing_interval); 3503 3504 /* String options */ 3505 dump_cfg_string(oBindAddress, o->bind_address); 3506 dump_cfg_string(oBindInterface, o->bind_interface); 3507 dump_cfg_string(oCiphers, o->ciphers); 3508 dump_cfg_string(oControlPath, o->control_path); 3509 dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms); 3510 dump_cfg_string(oHostKeyAlias, o->host_key_alias); 3511 dump_cfg_string(oHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos); 3512 dump_cfg_string(oIdentityAgent, o->identity_agent); 3513 dump_cfg_string(oIgnoreUnknown, o->ignored_unknown); 3514 dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices); 3515 dump_cfg_string(oKexAlgorithms, o->kex_algorithms); 3516 dump_cfg_string(oCASignatureAlgorithms, o->ca_sign_algorithms); 3517 dump_cfg_string(oLocalCommand, o->local_command); 3518 dump_cfg_string(oRemoteCommand, o->remote_command); 3519 dump_cfg_string(oLogLevel, log_level_name(o->log_level)); 3520 dump_cfg_string(oMacs, o->macs); 3521 #ifdef ENABLE_PKCS11 3522 dump_cfg_string(oPKCS11Provider, o->pkcs11_provider); 3523 #endif 3524 dump_cfg_string(oSecurityKeyProvider, o->sk_provider); 3525 dump_cfg_string(oPreferredAuthentications, o->preferred_authentications); 3526 dump_cfg_string(oPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos); 3527 dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys); 3528 dump_cfg_string(oXAuthLocation, o->xauth_location); 3529 dump_cfg_string(oKnownHostsCommand, o->known_hosts_command); 3530 dump_cfg_string(oTag, o->tag); 3531 3532 /* Forwards */ 3533 dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards); 3534 dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards); 3535 dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards); 3536 3537 /* String array options */ 3538 dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files); 3539 dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains); 3540 dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files); 3541 dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles); 3542 dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles); 3543 dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env); 3544 dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv); 3545 dump_cfg_strarray_oneline(oLogVerbose, 3546 o->num_log_verbose, o->log_verbose); 3547 dump_cfg_strarray_oneline(oChannelTimeout, 3548 o->num_channel_timeouts, o->channel_timeouts); 3549 3550 /* Special cases */ 3551 3552 /* PermitRemoteOpen */ 3553 if (o->num_permitted_remote_opens == 0) 3554 printf("%s any\n", lookup_opcode_name(oPermitRemoteOpen)); 3555 else 3556 dump_cfg_strarray_oneline(oPermitRemoteOpen, 3557 o->num_permitted_remote_opens, o->permitted_remote_opens); 3558 3559 /* AddKeysToAgent */ 3560 if (o->add_keys_to_agent_lifespan <= 0) 3561 dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent); 3562 else { 3563 printf("addkeystoagent%s %d\n", 3564 o->add_keys_to_agent == 3 ? " confirm" : "", 3565 o->add_keys_to_agent_lifespan); 3566 } 3567 3568 /* oForwardAgent */ 3569 if (o->forward_agent_sock_path == NULL) 3570 dump_cfg_fmtint(oForwardAgent, o->forward_agent); 3571 else 3572 dump_cfg_string(oForwardAgent, o->forward_agent_sock_path); 3573 3574 /* oConnectTimeout */ 3575 if (o->connection_timeout == -1) 3576 printf("connecttimeout none\n"); 3577 else 3578 dump_cfg_int(oConnectTimeout, o->connection_timeout); 3579 3580 /* oTunnelDevice */ 3581 printf("tunneldevice"); 3582 if (o->tun_local == SSH_TUNID_ANY) 3583 printf(" any"); 3584 else 3585 printf(" %d", o->tun_local); 3586 if (o->tun_remote == SSH_TUNID_ANY) 3587 printf(":any"); 3588 else 3589 printf(":%d", o->tun_remote); 3590 printf("\n"); 3591 3592 /* oCanonicalizePermittedCNAMEs */ 3593 printf("canonicalizePermittedcnames"); 3594 if (o->num_permitted_cnames == 0) 3595 printf(" none"); 3596 for (i = 0; i < o->num_permitted_cnames; i++) { 3597 printf(" %s:%s", o->permitted_cnames[i].source_list, 3598 o->permitted_cnames[i].target_list); 3599 } 3600 printf("\n"); 3601 3602 /* oControlPersist */ 3603 if (o->control_persist == 0 || o->control_persist_timeout == 0) 3604 dump_cfg_fmtint(oControlPersist, o->control_persist); 3605 else 3606 dump_cfg_int(oControlPersist, o->control_persist_timeout); 3607 3608 /* oEscapeChar */ 3609 if (o->escape_char == SSH_ESCAPECHAR_NONE) 3610 printf("escapechar none\n"); 3611 else { 3612 vis(buf, o->escape_char, VIS_WHITE, 0); 3613 printf("escapechar %s\n", buf); 3614 } 3615 3616 /* oIPQoS */ 3617 printf("ipqos %s ", iptos2str(o->ip_qos_interactive)); 3618 printf("%s\n", iptos2str(o->ip_qos_bulk)); 3619 3620 /* oRekeyLimit */ 3621 printf("rekeylimit %llu %d\n", 3622 (unsigned long long)o->rekey_limit, o->rekey_interval); 3623 3624 /* oStreamLocalBindMask */ 3625 printf("streamlocalbindmask 0%o\n", 3626 o->fwd_opts.streamlocal_bind_mask); 3627 3628 /* oLogFacility */ 3629 printf("syslogfacility %s\n", log_facility_name(o->log_facility)); 3630 3631 /* oProxyCommand / oProxyJump */ 3632 if (o->jump_host == NULL) 3633 dump_cfg_string(oProxyCommand, o->proxy_command); 3634 else { 3635 /* Check for numeric addresses */ 3636 i = strchr(o->jump_host, ':') != NULL || 3637 strspn(o->jump_host, "1234567890.") == strlen(o->jump_host); 3638 snprintf(buf, sizeof(buf), "%d", o->jump_port); 3639 printf("proxyjump %s%s%s%s%s%s%s%s%s\n", 3640 /* optional additional jump spec */ 3641 o->jump_extra == NULL ? "" : o->jump_extra, 3642 o->jump_extra == NULL ? "" : ",", 3643 /* optional user */ 3644 o->jump_user == NULL ? "" : o->jump_user, 3645 o->jump_user == NULL ? "" : "@", 3646 /* opening [ if hostname is numeric */ 3647 i ? "[" : "", 3648 /* mandatory hostname */ 3649 o->jump_host, 3650 /* closing ] if hostname is numeric */ 3651 i ? "]" : "", 3652 /* optional port number */ 3653 o->jump_port <= 0 ? "" : ":", 3654 o->jump_port <= 0 ? "" : buf); 3655 } 3656 } 3657