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