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