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