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