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