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