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