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