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