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