1 /* $OpenBSD: readconf.c,v 1.383 2023/10/12 02:18:18 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 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0); 2690 } 2691 if (options->escape_char == -1) 2692 options->escape_char = '~'; 2693 if (options->num_system_hostfiles == 0) { 2694 options->system_hostfiles[options->num_system_hostfiles++] = 2695 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE); 2696 options->system_hostfiles[options->num_system_hostfiles++] = 2697 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2); 2698 } 2699 if (options->update_hostkeys == -1) { 2700 if (options->verify_host_key_dns <= 0 && 2701 (options->num_user_hostfiles == 0 || 2702 (options->num_user_hostfiles == 1 && strcmp(options-> 2703 user_hostfiles[0], _PATH_SSH_USER_HOSTFILE) == 0))) 2704 options->update_hostkeys = SSH_UPDATE_HOSTKEYS_YES; 2705 else 2706 options->update_hostkeys = SSH_UPDATE_HOSTKEYS_NO; 2707 } 2708 if (options->num_user_hostfiles == 0) { 2709 options->user_hostfiles[options->num_user_hostfiles++] = 2710 xstrdup(_PATH_SSH_USER_HOSTFILE); 2711 options->user_hostfiles[options->num_user_hostfiles++] = 2712 xstrdup(_PATH_SSH_USER_HOSTFILE2); 2713 } 2714 if (options->log_level == SYSLOG_LEVEL_NOT_SET) 2715 options->log_level = SYSLOG_LEVEL_INFO; 2716 if (options->log_facility == SYSLOG_FACILITY_NOT_SET) 2717 options->log_facility = SYSLOG_FACILITY_USER; 2718 if (options->no_host_authentication_for_localhost == - 1) 2719 options->no_host_authentication_for_localhost = 0; 2720 if (options->identities_only == -1) 2721 options->identities_only = 0; 2722 if (options->enable_ssh_keysign == -1) 2723 options->enable_ssh_keysign = 0; 2724 if (options->rekey_limit == -1) 2725 options->rekey_limit = 0; 2726 if (options->rekey_interval == -1) 2727 options->rekey_interval = 0; 2728 if (options->verify_host_key_dns == -1) 2729 options->verify_host_key_dns = 0; 2730 if (options->server_alive_interval == -1) 2731 options->server_alive_interval = 0; 2732 if (options->server_alive_count_max == -1) 2733 options->server_alive_count_max = 3; 2734 if (options->control_master == -1) 2735 options->control_master = 0; 2736 if (options->control_persist == -1) { 2737 options->control_persist = 0; 2738 options->control_persist_timeout = 0; 2739 } 2740 if (options->hash_known_hosts == -1) 2741 options->hash_known_hosts = 0; 2742 if (options->tun_open == -1) 2743 options->tun_open = SSH_TUNMODE_NO; 2744 if (options->tun_local == -1) 2745 options->tun_local = SSH_TUNID_ANY; 2746 if (options->tun_remote == -1) 2747 options->tun_remote = SSH_TUNID_ANY; 2748 if (options->permit_local_command == -1) 2749 options->permit_local_command = 0; 2750 if (options->visual_host_key == -1) 2751 options->visual_host_key = 0; 2752 if (options->ip_qos_interactive == -1) 2753 options->ip_qos_interactive = IPTOS_DSCP_AF21; 2754 if (options->ip_qos_bulk == -1) 2755 options->ip_qos_bulk = IPTOS_DSCP_CS1; 2756 if (options->request_tty == -1) 2757 options->request_tty = REQUEST_TTY_AUTO; 2758 if (options->session_type == -1) 2759 options->session_type = SESSION_TYPE_DEFAULT; 2760 if (options->stdin_null == -1) 2761 options->stdin_null = 0; 2762 if (options->fork_after_authentication == -1) 2763 options->fork_after_authentication = 0; 2764 if (options->proxy_use_fdpass == -1) 2765 options->proxy_use_fdpass = 0; 2766 if (options->canonicalize_max_dots == -1) 2767 options->canonicalize_max_dots = 1; 2768 if (options->canonicalize_fallback_local == -1) 2769 options->canonicalize_fallback_local = 1; 2770 if (options->canonicalize_hostname == -1) 2771 options->canonicalize_hostname = SSH_CANONICALISE_NO; 2772 if (options->fingerprint_hash == -1) 2773 options->fingerprint_hash = SSH_FP_HASH_DEFAULT; 2774 if (options->sk_provider == NULL) 2775 options->sk_provider = xstrdup("internal"); 2776 if (options->required_rsa_size == -1) 2777 options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE; 2778 if (options->enable_escape_commandline == -1) 2779 options->enable_escape_commandline = 0; 2780 if (options->obscure_keystroke_timing_interval == -1) { 2781 options->obscure_keystroke_timing_interval = 2782 SSH_KEYSTROKE_DEFAULT_INTERVAL_MS; 2783 } 2784 2785 /* Expand KEX name lists */ 2786 all_cipher = cipher_alg_list(',', 0); 2787 all_mac = mac_alg_list(','); 2788 all_kex = kex_alg_list(','); 2789 all_key = sshkey_alg_list(0, 0, 1, ','); 2790 all_sig = sshkey_alg_list(0, 1, 1, ','); 2791 /* remove unsupported algos from default lists */ 2792 def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher); 2793 def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac); 2794 def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex); 2795 def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key); 2796 def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig); 2797 #define ASSEMBLE(what, defaults, all) \ 2798 do { \ 2799 if ((r = kex_assemble_names(&options->what, \ 2800 defaults, all)) != 0) { \ 2801 error_fr(r, "%s", #what); \ 2802 goto fail; \ 2803 } \ 2804 } while (0) 2805 ASSEMBLE(ciphers, def_cipher, all_cipher); 2806 ASSEMBLE(macs, def_mac, all_mac); 2807 ASSEMBLE(kex_algorithms, def_kex, all_kex); 2808 ASSEMBLE(hostbased_accepted_algos, def_key, all_key); 2809 ASSEMBLE(pubkey_accepted_algos, def_key, all_key); 2810 ASSEMBLE(ca_sign_algorithms, def_sig, all_sig); 2811 #undef ASSEMBLE 2812 2813 #define CLEAR_ON_NONE(v) \ 2814 do { \ 2815 if (option_clear_or_none(v)) { \ 2816 free(v); \ 2817 v = NULL; \ 2818 } \ 2819 } while(0) 2820 #define CLEAR_ON_NONE_ARRAY(v, nv, none) \ 2821 do { \ 2822 if (options->nv == 1 && \ 2823 strcasecmp(options->v[0], none) == 0) { \ 2824 free(options->v[0]); \ 2825 free(options->v); \ 2826 options->v = NULL; \ 2827 options->nv = 0; \ 2828 } \ 2829 } while (0) 2830 CLEAR_ON_NONE(options->local_command); 2831 CLEAR_ON_NONE(options->remote_command); 2832 CLEAR_ON_NONE(options->proxy_command); 2833 CLEAR_ON_NONE(options->control_path); 2834 CLEAR_ON_NONE(options->revoked_host_keys); 2835 CLEAR_ON_NONE(options->pkcs11_provider); 2836 CLEAR_ON_NONE(options->sk_provider); 2837 CLEAR_ON_NONE(options->known_hosts_command); 2838 CLEAR_ON_NONE_ARRAY(channel_timeouts, num_channel_timeouts, "none"); 2839 #undef CLEAR_ON_NONE 2840 #undef CLEAR_ON_NONE_ARRAY 2841 if (options->jump_host != NULL && 2842 strcmp(options->jump_host, "none") == 0 && 2843 options->jump_port == 0 && options->jump_user == NULL) { 2844 free(options->jump_host); 2845 options->jump_host = NULL; 2846 } 2847 if (options->num_permitted_cnames == 1 && 2848 !config_has_permitted_cnames(options)) { 2849 /* clean up CanonicalizePermittedCNAMEs=none */ 2850 free(options->permitted_cnames[0].source_list); 2851 free(options->permitted_cnames[0].target_list); 2852 memset(options->permitted_cnames, '\0', 2853 sizeof(*options->permitted_cnames)); 2854 options->num_permitted_cnames = 0; 2855 } 2856 /* options->identity_agent distinguishes NULL from 'none' */ 2857 /* options->user will be set in the main program if appropriate */ 2858 /* options->hostname will be set in the main program if appropriate */ 2859 /* options->host_key_alias should not be set by default */ 2860 /* options->preferred_authentications will be set in ssh */ 2861 2862 /* success */ 2863 ret = 0; 2864 fail: 2865 free(all_cipher); 2866 free(all_mac); 2867 free(all_kex); 2868 free(all_key); 2869 free(all_sig); 2870 free(def_cipher); 2871 free(def_mac); 2872 free(def_kex); 2873 free(def_key); 2874 free(def_sig); 2875 return ret; 2876 } 2877 2878 void 2879 free_options(Options *o) 2880 { 2881 int i; 2882 2883 if (o == NULL) 2884 return; 2885 2886 #define FREE_ARRAY(type, n, a) \ 2887 do { \ 2888 type _i; \ 2889 for (_i = 0; _i < (n); _i++) \ 2890 free((a)[_i]); \ 2891 } while (0) 2892 2893 free(o->forward_agent_sock_path); 2894 free(o->xauth_location); 2895 FREE_ARRAY(u_int, o->num_log_verbose, o->log_verbose); 2896 free(o->log_verbose); 2897 free(o->ciphers); 2898 free(o->macs); 2899 free(o->hostkeyalgorithms); 2900 free(o->kex_algorithms); 2901 free(o->ca_sign_algorithms); 2902 free(o->hostname); 2903 free(o->host_key_alias); 2904 free(o->proxy_command); 2905 free(o->user); 2906 FREE_ARRAY(u_int, o->num_system_hostfiles, o->system_hostfiles); 2907 FREE_ARRAY(u_int, o->num_user_hostfiles, o->user_hostfiles); 2908 free(o->preferred_authentications); 2909 free(o->bind_address); 2910 free(o->bind_interface); 2911 free(o->pkcs11_provider); 2912 free(o->sk_provider); 2913 for (i = 0; i < o->num_identity_files; i++) { 2914 free(o->identity_files[i]); 2915 sshkey_free(o->identity_keys[i]); 2916 } 2917 for (i = 0; i < o->num_certificate_files; i++) { 2918 free(o->certificate_files[i]); 2919 sshkey_free(o->certificates[i]); 2920 } 2921 free(o->identity_agent); 2922 for (i = 0; i < o->num_local_forwards; i++) { 2923 free(o->local_forwards[i].listen_host); 2924 free(o->local_forwards[i].listen_path); 2925 free(o->local_forwards[i].connect_host); 2926 free(o->local_forwards[i].connect_path); 2927 } 2928 free(o->local_forwards); 2929 for (i = 0; i < o->num_remote_forwards; i++) { 2930 free(o->remote_forwards[i].listen_host); 2931 free(o->remote_forwards[i].listen_path); 2932 free(o->remote_forwards[i].connect_host); 2933 free(o->remote_forwards[i].connect_path); 2934 } 2935 free(o->remote_forwards); 2936 free(o->stdio_forward_host); 2937 FREE_ARRAY(u_int, o->num_send_env, o->send_env); 2938 free(o->send_env); 2939 FREE_ARRAY(u_int, o->num_setenv, o->setenv); 2940 free(o->setenv); 2941 free(o->control_path); 2942 free(o->local_command); 2943 free(o->remote_command); 2944 FREE_ARRAY(int, o->num_canonical_domains, o->canonical_domains); 2945 for (i = 0; i < o->num_permitted_cnames; i++) { 2946 free(o->permitted_cnames[i].source_list); 2947 free(o->permitted_cnames[i].target_list); 2948 } 2949 free(o->revoked_host_keys); 2950 free(o->hostbased_accepted_algos); 2951 free(o->pubkey_accepted_algos); 2952 free(o->jump_user); 2953 free(o->jump_host); 2954 free(o->jump_extra); 2955 free(o->ignored_unknown); 2956 explicit_bzero(o, sizeof(*o)); 2957 #undef FREE_ARRAY 2958 } 2959 2960 struct fwdarg { 2961 char *arg; 2962 int ispath; 2963 }; 2964 2965 /* 2966 * parse_fwd_field 2967 * parses the next field in a port forwarding specification. 2968 * sets fwd to the parsed field and advances p past the colon 2969 * or sets it to NULL at end of string. 2970 * returns 0 on success, else non-zero. 2971 */ 2972 static int 2973 parse_fwd_field(char **p, struct fwdarg *fwd) 2974 { 2975 char *ep, *cp = *p; 2976 int ispath = 0; 2977 2978 if (*cp == '\0') { 2979 *p = NULL; 2980 return -1; /* end of string */ 2981 } 2982 2983 /* 2984 * A field escaped with square brackets is used literally. 2985 * XXX - allow ']' to be escaped via backslash? 2986 */ 2987 if (*cp == '[') { 2988 /* find matching ']' */ 2989 for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) { 2990 if (*ep == '/') 2991 ispath = 1; 2992 } 2993 /* no matching ']' or not at end of field. */ 2994 if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0')) 2995 return -1; 2996 /* NUL terminate the field and advance p past the colon */ 2997 *ep++ = '\0'; 2998 if (*ep != '\0') 2999 *ep++ = '\0'; 3000 fwd->arg = cp + 1; 3001 fwd->ispath = ispath; 3002 *p = ep; 3003 return 0; 3004 } 3005 3006 for (cp = *p; *cp != '\0'; cp++) { 3007 switch (*cp) { 3008 case '\\': 3009 memmove(cp, cp + 1, strlen(cp + 1) + 1); 3010 if (*cp == '\0') 3011 return -1; 3012 break; 3013 case '/': 3014 ispath = 1; 3015 break; 3016 case ':': 3017 *cp++ = '\0'; 3018 goto done; 3019 } 3020 } 3021 done: 3022 fwd->arg = *p; 3023 fwd->ispath = ispath; 3024 *p = cp; 3025 return 0; 3026 } 3027 3028 /* 3029 * parse_forward 3030 * parses a string containing a port forwarding specification of the form: 3031 * dynamicfwd == 0 3032 * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath 3033 * listenpath:connectpath 3034 * dynamicfwd == 1 3035 * [listenhost:]listenport 3036 * returns number of arguments parsed or zero on error 3037 */ 3038 int 3039 parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) 3040 { 3041 struct fwdarg fwdargs[4]; 3042 char *p, *cp; 3043 int i, err; 3044 3045 memset(fwd, 0, sizeof(*fwd)); 3046 memset(fwdargs, 0, sizeof(fwdargs)); 3047 3048 /* 3049 * We expand environment variables before checking if we think they're 3050 * paths so that if ${VAR} expands to a fully qualified path it is 3051 * treated as a path. 3052 */ 3053 cp = p = dollar_expand(&err, fwdspec); 3054 if (p == NULL || err) 3055 return 0; 3056 3057 /* skip leading spaces */ 3058 while (isspace((u_char)*cp)) 3059 cp++; 3060 3061 for (i = 0; i < 4; ++i) { 3062 if (parse_fwd_field(&cp, &fwdargs[i]) != 0) 3063 break; 3064 } 3065 3066 /* Check for trailing garbage */ 3067 if (cp != NULL && *cp != '\0') { 3068 i = 0; /* failure */ 3069 } 3070 3071 switch (i) { 3072 case 1: 3073 if (fwdargs[0].ispath) { 3074 fwd->listen_path = xstrdup(fwdargs[0].arg); 3075 fwd->listen_port = PORT_STREAMLOCAL; 3076 } else { 3077 fwd->listen_host = NULL; 3078 fwd->listen_port = a2port(fwdargs[0].arg); 3079 } 3080 fwd->connect_host = xstrdup("socks"); 3081 break; 3082 3083 case 2: 3084 if (fwdargs[0].ispath && fwdargs[1].ispath) { 3085 fwd->listen_path = xstrdup(fwdargs[0].arg); 3086 fwd->listen_port = PORT_STREAMLOCAL; 3087 fwd->connect_path = xstrdup(fwdargs[1].arg); 3088 fwd->connect_port = PORT_STREAMLOCAL; 3089 } else if (fwdargs[1].ispath) { 3090 fwd->listen_host = NULL; 3091 fwd->listen_port = a2port(fwdargs[0].arg); 3092 fwd->connect_path = xstrdup(fwdargs[1].arg); 3093 fwd->connect_port = PORT_STREAMLOCAL; 3094 } else { 3095 fwd->listen_host = xstrdup(fwdargs[0].arg); 3096 fwd->listen_port = a2port(fwdargs[1].arg); 3097 fwd->connect_host = xstrdup("socks"); 3098 } 3099 break; 3100 3101 case 3: 3102 if (fwdargs[0].ispath) { 3103 fwd->listen_path = xstrdup(fwdargs[0].arg); 3104 fwd->listen_port = PORT_STREAMLOCAL; 3105 fwd->connect_host = xstrdup(fwdargs[1].arg); 3106 fwd->connect_port = a2port(fwdargs[2].arg); 3107 } else if (fwdargs[2].ispath) { 3108 fwd->listen_host = xstrdup(fwdargs[0].arg); 3109 fwd->listen_port = a2port(fwdargs[1].arg); 3110 fwd->connect_path = xstrdup(fwdargs[2].arg); 3111 fwd->connect_port = PORT_STREAMLOCAL; 3112 } else { 3113 fwd->listen_host = NULL; 3114 fwd->listen_port = a2port(fwdargs[0].arg); 3115 fwd->connect_host = xstrdup(fwdargs[1].arg); 3116 fwd->connect_port = a2port(fwdargs[2].arg); 3117 } 3118 break; 3119 3120 case 4: 3121 fwd->listen_host = xstrdup(fwdargs[0].arg); 3122 fwd->listen_port = a2port(fwdargs[1].arg); 3123 fwd->connect_host = xstrdup(fwdargs[2].arg); 3124 fwd->connect_port = a2port(fwdargs[3].arg); 3125 break; 3126 default: 3127 i = 0; /* failure */ 3128 } 3129 3130 free(p); 3131 3132 if (dynamicfwd) { 3133 if (!(i == 1 || i == 2)) 3134 goto fail_free; 3135 } else { 3136 if (!(i == 3 || i == 4)) { 3137 if (fwd->connect_path == NULL && 3138 fwd->listen_path == NULL) 3139 goto fail_free; 3140 } 3141 if (fwd->connect_port <= 0 && fwd->connect_path == NULL) 3142 goto fail_free; 3143 } 3144 3145 if ((fwd->listen_port < 0 && fwd->listen_path == NULL) || 3146 (!remotefwd && fwd->listen_port == 0)) 3147 goto fail_free; 3148 if (fwd->connect_host != NULL && 3149 strlen(fwd->connect_host) >= NI_MAXHOST) 3150 goto fail_free; 3151 /* 3152 * XXX - if connecting to a remote socket, max sun len may not 3153 * match this host 3154 */ 3155 if (fwd->connect_path != NULL && 3156 strlen(fwd->connect_path) >= PATH_MAX_SUN) 3157 goto fail_free; 3158 if (fwd->listen_host != NULL && 3159 strlen(fwd->listen_host) >= NI_MAXHOST) 3160 goto fail_free; 3161 if (fwd->listen_path != NULL && 3162 strlen(fwd->listen_path) >= PATH_MAX_SUN) 3163 goto fail_free; 3164 3165 return (i); 3166 3167 fail_free: 3168 free(fwd->connect_host); 3169 fwd->connect_host = NULL; 3170 free(fwd->connect_path); 3171 fwd->connect_path = NULL; 3172 free(fwd->listen_host); 3173 fwd->listen_host = NULL; 3174 free(fwd->listen_path); 3175 fwd->listen_path = NULL; 3176 return (0); 3177 } 3178 3179 int 3180 parse_jump(const char *s, Options *o, int active) 3181 { 3182 char *orig, *sdup, *cp; 3183 char *host = NULL, *user = NULL; 3184 int r, ret = -1, port = -1, first; 3185 3186 active &= o->proxy_command == NULL && o->jump_host == NULL; 3187 3188 orig = sdup = xstrdup(s); 3189 3190 /* Remove comment and trailing whitespace */ 3191 if ((cp = strchr(orig, '#')) != NULL) 3192 *cp = '\0'; 3193 rtrim(orig); 3194 3195 first = active; 3196 do { 3197 if (strcasecmp(s, "none") == 0) 3198 break; 3199 if ((cp = strrchr(sdup, ',')) == NULL) 3200 cp = sdup; /* last */ 3201 else 3202 *cp++ = '\0'; 3203 3204 if (first) { 3205 /* First argument and configuration is active */ 3206 r = parse_ssh_uri(cp, &user, &host, &port); 3207 if (r == -1 || (r == 1 && 3208 parse_user_host_port(cp, &user, &host, &port) != 0)) 3209 goto out; 3210 } else { 3211 /* Subsequent argument or inactive configuration */ 3212 r = parse_ssh_uri(cp, NULL, NULL, NULL); 3213 if (r == -1 || (r == 1 && 3214 parse_user_host_port(cp, NULL, NULL, NULL) != 0)) 3215 goto out; 3216 } 3217 first = 0; /* only check syntax for subsequent hosts */ 3218 } while (cp != sdup); 3219 /* success */ 3220 if (active) { 3221 if (strcasecmp(s, "none") == 0) { 3222 o->jump_host = xstrdup("none"); 3223 o->jump_port = 0; 3224 } else { 3225 o->jump_user = user; 3226 o->jump_host = host; 3227 o->jump_port = port; 3228 o->proxy_command = xstrdup("none"); 3229 user = host = NULL; 3230 if ((cp = strrchr(s, ',')) != NULL && cp != s) { 3231 o->jump_extra = xstrdup(s); 3232 o->jump_extra[cp - s] = '\0'; 3233 } 3234 } 3235 } 3236 ret = 0; 3237 out: 3238 free(orig); 3239 free(user); 3240 free(host); 3241 return ret; 3242 } 3243 3244 int 3245 parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp) 3246 { 3247 char *user = NULL, *host = NULL, *path = NULL; 3248 int r, port; 3249 3250 r = parse_uri("ssh", uri, &user, &host, &port, &path); 3251 if (r == 0 && path != NULL) 3252 r = -1; /* path not allowed */ 3253 if (r == 0) { 3254 if (userp != NULL) { 3255 *userp = user; 3256 user = NULL; 3257 } 3258 if (hostp != NULL) { 3259 *hostp = host; 3260 host = NULL; 3261 } 3262 if (portp != NULL) 3263 *portp = port; 3264 } 3265 free(user); 3266 free(host); 3267 free(path); 3268 return r; 3269 } 3270 3271 /* XXX the following is a near-vebatim copy from servconf.c; refactor */ 3272 static const char * 3273 fmt_multistate_int(int val, const struct multistate *m) 3274 { 3275 u_int i; 3276 3277 for (i = 0; m[i].key != NULL; i++) { 3278 if (m[i].value == val) 3279 return m[i].key; 3280 } 3281 return "UNKNOWN"; 3282 } 3283 3284 static const char * 3285 fmt_intarg(OpCodes code, int val) 3286 { 3287 if (val == -1) 3288 return "unset"; 3289 switch (code) { 3290 case oAddressFamily: 3291 return fmt_multistate_int(val, multistate_addressfamily); 3292 case oVerifyHostKeyDNS: 3293 case oUpdateHostkeys: 3294 return fmt_multistate_int(val, multistate_yesnoask); 3295 case oStrictHostKeyChecking: 3296 return fmt_multistate_int(val, multistate_strict_hostkey); 3297 case oControlMaster: 3298 return fmt_multistate_int(val, multistate_controlmaster); 3299 case oTunnel: 3300 return fmt_multistate_int(val, multistate_tunnel); 3301 case oRequestTTY: 3302 return fmt_multistate_int(val, multistate_requesttty); 3303 case oSessionType: 3304 return fmt_multistate_int(val, multistate_sessiontype); 3305 case oCanonicalizeHostname: 3306 return fmt_multistate_int(val, multistate_canonicalizehostname); 3307 case oAddKeysToAgent: 3308 return fmt_multistate_int(val, multistate_yesnoaskconfirm); 3309 case oPubkeyAuthentication: 3310 return fmt_multistate_int(val, multistate_pubkey_auth); 3311 case oFingerprintHash: 3312 return ssh_digest_alg_name(val); 3313 default: 3314 switch (val) { 3315 case 0: 3316 return "no"; 3317 case 1: 3318 return "yes"; 3319 default: 3320 return "UNKNOWN"; 3321 } 3322 } 3323 } 3324 3325 static const char * 3326 lookup_opcode_name(OpCodes code) 3327 { 3328 u_int i; 3329 3330 for (i = 0; keywords[i].name != NULL; i++) 3331 if (keywords[i].opcode == code) 3332 return(keywords[i].name); 3333 return "UNKNOWN"; 3334 } 3335 3336 static void 3337 dump_cfg_int(OpCodes code, int val) 3338 { 3339 if (code == oObscureKeystrokeTiming) { 3340 if (val == 0) { 3341 printf("%s no\n", lookup_opcode_name(code)); 3342 return; 3343 } else if (val == SSH_KEYSTROKE_DEFAULT_INTERVAL_MS) { 3344 printf("%s yes\n", lookup_opcode_name(code)); 3345 return; 3346 } 3347 /* FALLTHROUGH */ 3348 } 3349 printf("%s %d\n", lookup_opcode_name(code), val); 3350 } 3351 3352 static void 3353 dump_cfg_fmtint(OpCodes code, int val) 3354 { 3355 printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val)); 3356 } 3357 3358 static void 3359 dump_cfg_string(OpCodes code, const char *val) 3360 { 3361 if (val == NULL) 3362 return; 3363 printf("%s %s\n", lookup_opcode_name(code), val); 3364 } 3365 3366 static void 3367 dump_cfg_strarray(OpCodes code, u_int count, char **vals) 3368 { 3369 u_int i; 3370 3371 for (i = 0; i < count; i++) 3372 printf("%s %s\n", lookup_opcode_name(code), vals[i]); 3373 } 3374 3375 static void 3376 dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals) 3377 { 3378 u_int i; 3379 3380 printf("%s", lookup_opcode_name(code)); 3381 if (count == 0) 3382 printf(" none"); 3383 for (i = 0; i < count; i++) 3384 printf(" %s", vals[i]); 3385 printf("\n"); 3386 } 3387 3388 static void 3389 dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds) 3390 { 3391 const struct Forward *fwd; 3392 u_int i; 3393 3394 /* oDynamicForward */ 3395 for (i = 0; i < count; i++) { 3396 fwd = &fwds[i]; 3397 if (code == oDynamicForward && fwd->connect_host != NULL && 3398 strcmp(fwd->connect_host, "socks") != 0) 3399 continue; 3400 if (code == oLocalForward && fwd->connect_host != NULL && 3401 strcmp(fwd->connect_host, "socks") == 0) 3402 continue; 3403 printf("%s", lookup_opcode_name(code)); 3404 if (fwd->listen_port == PORT_STREAMLOCAL) 3405 printf(" %s", fwd->listen_path); 3406 else if (fwd->listen_host == NULL) 3407 printf(" %d", fwd->listen_port); 3408 else { 3409 printf(" [%s]:%d", 3410 fwd->listen_host, fwd->listen_port); 3411 } 3412 if (code != oDynamicForward) { 3413 if (fwd->connect_port == PORT_STREAMLOCAL) 3414 printf(" %s", fwd->connect_path); 3415 else if (fwd->connect_host == NULL) 3416 printf(" %d", fwd->connect_port); 3417 else { 3418 printf(" [%s]:%d", 3419 fwd->connect_host, fwd->connect_port); 3420 } 3421 } 3422 printf("\n"); 3423 } 3424 } 3425 3426 void 3427 dump_client_config(Options *o, const char *host) 3428 { 3429 int i, r; 3430 char buf[8], *all_key; 3431 3432 /* 3433 * Expand HostKeyAlgorithms name lists. This isn't handled in 3434 * fill_default_options() like the other algorithm lists because 3435 * the host key algorithms are by default dynamically chosen based 3436 * on the host's keys found in known_hosts. 3437 */ 3438 all_key = sshkey_alg_list(0, 0, 1, ','); 3439 if ((r = kex_assemble_names(&o->hostkeyalgorithms, kex_default_pk_alg(), 3440 all_key)) != 0) 3441 fatal_fr(r, "expand HostKeyAlgorithms"); 3442 free(all_key); 3443 3444 /* Most interesting options first: user, host, port */ 3445 dump_cfg_string(oHost, o->host_arg); 3446 dump_cfg_string(oUser, o->user); 3447 dump_cfg_string(oHostname, host); 3448 dump_cfg_int(oPort, o->port); 3449 3450 /* Flag options */ 3451 dump_cfg_fmtint(oAddressFamily, o->address_family); 3452 dump_cfg_fmtint(oBatchMode, o->batch_mode); 3453 dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local); 3454 dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname); 3455 dump_cfg_fmtint(oCheckHostIP, o->check_host_ip); 3456 dump_cfg_fmtint(oCompression, o->compression); 3457 dump_cfg_fmtint(oControlMaster, o->control_master); 3458 dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign); 3459 dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings); 3460 dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure); 3461 dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash); 3462 dump_cfg_fmtint(oForwardX11, o->forward_x11); 3463 dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted); 3464 dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports); 3465 #ifdef GSSAPI 3466 dump_cfg_fmtint(oGssAuthentication, o->gss_authentication); 3467 dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds); 3468 #endif /* GSSAPI */ 3469 dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts); 3470 dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication); 3471 dump_cfg_fmtint(oIdentitiesOnly, o->identities_only); 3472 dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication); 3473 dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost); 3474 dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication); 3475 dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command); 3476 dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass); 3477 dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication); 3478 dump_cfg_fmtint(oRequestTTY, o->request_tty); 3479 dump_cfg_fmtint(oSessionType, o->session_type); 3480 dump_cfg_fmtint(oStdinNull, o->stdin_null); 3481 dump_cfg_fmtint(oForkAfterAuthentication, o->fork_after_authentication); 3482 dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink); 3483 dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking); 3484 dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive); 3485 dump_cfg_fmtint(oTunnel, o->tun_open); 3486 dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns); 3487 dump_cfg_fmtint(oVisualHostKey, o->visual_host_key); 3488 dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys); 3489 dump_cfg_fmtint(oEnableEscapeCommandline, o->enable_escape_commandline); 3490 3491 /* Integer options */ 3492 dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots); 3493 dump_cfg_int(oConnectionAttempts, o->connection_attempts); 3494 dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout); 3495 dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts); 3496 dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max); 3497 dump_cfg_int(oServerAliveInterval, o->server_alive_interval); 3498 dump_cfg_int(oRequiredRSASize, o->required_rsa_size); 3499 dump_cfg_int(oObscureKeystrokeTiming, 3500 o->obscure_keystroke_timing_interval); 3501 3502 /* String options */ 3503 dump_cfg_string(oBindAddress, o->bind_address); 3504 dump_cfg_string(oBindInterface, o->bind_interface); 3505 dump_cfg_string(oCiphers, o->ciphers); 3506 dump_cfg_string(oControlPath, o->control_path); 3507 dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms); 3508 dump_cfg_string(oHostKeyAlias, o->host_key_alias); 3509 dump_cfg_string(oHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos); 3510 dump_cfg_string(oIdentityAgent, o->identity_agent); 3511 dump_cfg_string(oIgnoreUnknown, o->ignored_unknown); 3512 dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices); 3513 dump_cfg_string(oKexAlgorithms, o->kex_algorithms); 3514 dump_cfg_string(oCASignatureAlgorithms, o->ca_sign_algorithms); 3515 dump_cfg_string(oLocalCommand, o->local_command); 3516 dump_cfg_string(oRemoteCommand, o->remote_command); 3517 dump_cfg_string(oLogLevel, log_level_name(o->log_level)); 3518 dump_cfg_string(oMacs, o->macs); 3519 #ifdef ENABLE_PKCS11 3520 dump_cfg_string(oPKCS11Provider, o->pkcs11_provider); 3521 #endif 3522 dump_cfg_string(oSecurityKeyProvider, o->sk_provider); 3523 dump_cfg_string(oPreferredAuthentications, o->preferred_authentications); 3524 dump_cfg_string(oPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos); 3525 dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys); 3526 dump_cfg_string(oXAuthLocation, o->xauth_location); 3527 dump_cfg_string(oKnownHostsCommand, o->known_hosts_command); 3528 dump_cfg_string(oTag, o->tag); 3529 3530 /* Forwards */ 3531 dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards); 3532 dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards); 3533 dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards); 3534 3535 /* String array options */ 3536 dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files); 3537 dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains); 3538 dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files); 3539 dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles); 3540 dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles); 3541 dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env); 3542 dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv); 3543 dump_cfg_strarray_oneline(oLogVerbose, 3544 o->num_log_verbose, o->log_verbose); 3545 dump_cfg_strarray_oneline(oChannelTimeout, 3546 o->num_channel_timeouts, o->channel_timeouts); 3547 3548 /* Special cases */ 3549 3550 /* PermitRemoteOpen */ 3551 if (o->num_permitted_remote_opens == 0) 3552 printf("%s any\n", lookup_opcode_name(oPermitRemoteOpen)); 3553 else 3554 dump_cfg_strarray_oneline(oPermitRemoteOpen, 3555 o->num_permitted_remote_opens, o->permitted_remote_opens); 3556 3557 /* AddKeysToAgent */ 3558 if (o->add_keys_to_agent_lifespan <= 0) 3559 dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent); 3560 else { 3561 printf("addkeystoagent%s %d\n", 3562 o->add_keys_to_agent == 3 ? " confirm" : "", 3563 o->add_keys_to_agent_lifespan); 3564 } 3565 3566 /* oForwardAgent */ 3567 if (o->forward_agent_sock_path == NULL) 3568 dump_cfg_fmtint(oForwardAgent, o->forward_agent); 3569 else 3570 dump_cfg_string(oForwardAgent, o->forward_agent_sock_path); 3571 3572 /* oConnectTimeout */ 3573 if (o->connection_timeout == -1) 3574 printf("connecttimeout none\n"); 3575 else 3576 dump_cfg_int(oConnectTimeout, o->connection_timeout); 3577 3578 /* oTunnelDevice */ 3579 printf("tunneldevice"); 3580 if (o->tun_local == SSH_TUNID_ANY) 3581 printf(" any"); 3582 else 3583 printf(" %d", o->tun_local); 3584 if (o->tun_remote == SSH_TUNID_ANY) 3585 printf(":any"); 3586 else 3587 printf(":%d", o->tun_remote); 3588 printf("\n"); 3589 3590 /* oCanonicalizePermittedCNAMEs */ 3591 printf("canonicalizePermittedcnames"); 3592 if (o->num_permitted_cnames == 0) 3593 printf(" none"); 3594 for (i = 0; i < o->num_permitted_cnames; i++) { 3595 printf(" %s:%s", o->permitted_cnames[i].source_list, 3596 o->permitted_cnames[i].target_list); 3597 } 3598 printf("\n"); 3599 3600 /* oControlPersist */ 3601 if (o->control_persist == 0 || o->control_persist_timeout == 0) 3602 dump_cfg_fmtint(oControlPersist, o->control_persist); 3603 else 3604 dump_cfg_int(oControlPersist, o->control_persist_timeout); 3605 3606 /* oEscapeChar */ 3607 if (o->escape_char == SSH_ESCAPECHAR_NONE) 3608 printf("escapechar none\n"); 3609 else { 3610 vis(buf, o->escape_char, VIS_WHITE, 0); 3611 printf("escapechar %s\n", buf); 3612 } 3613 3614 /* oIPQoS */ 3615 printf("ipqos %s ", iptos2str(o->ip_qos_interactive)); 3616 printf("%s\n", iptos2str(o->ip_qos_bulk)); 3617 3618 /* oRekeyLimit */ 3619 printf("rekeylimit %llu %d\n", 3620 (unsigned long long)o->rekey_limit, o->rekey_interval); 3621 3622 /* oStreamLocalBindMask */ 3623 printf("streamlocalbindmask 0%o\n", 3624 o->fwd_opts.streamlocal_bind_mask); 3625 3626 /* oLogFacility */ 3627 printf("syslogfacility %s\n", log_facility_name(o->log_facility)); 3628 3629 /* oProxyCommand / oProxyJump */ 3630 if (o->jump_host == NULL) 3631 dump_cfg_string(oProxyCommand, o->proxy_command); 3632 else { 3633 /* Check for numeric addresses */ 3634 i = strchr(o->jump_host, ':') != NULL || 3635 strspn(o->jump_host, "1234567890.") == strlen(o->jump_host); 3636 snprintf(buf, sizeof(buf), "%d", o->jump_port); 3637 printf("proxyjump %s%s%s%s%s%s%s%s%s\n", 3638 /* optional additional jump spec */ 3639 o->jump_extra == NULL ? "" : o->jump_extra, 3640 o->jump_extra == NULL ? "" : ",", 3641 /* optional user */ 3642 o->jump_user == NULL ? "" : o->jump_user, 3643 o->jump_user == NULL ? "" : "@", 3644 /* opening [ if hostname is numeric */ 3645 i ? "[" : "", 3646 /* mandatory hostname */ 3647 o->jump_host, 3648 /* closing ] if hostname is numeric */ 3649 i ? "]" : "", 3650 /* optional port number */ 3651 o->jump_port <= 0 ? "" : ":", 3652 o->jump_port <= 0 ? "" : buf); 3653 } 3654 } 3655