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