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 HAVE_LDNS 2596 if (options->verify_host_key_dns == -1) 2597 /* automatically trust a verified SSHFP record */ 2598 options->verify_host_key_dns = 1; 2599 #else 2600 if (options->verify_host_key_dns == -1) 2601 options->verify_host_key_dns = 0; 2602 #endif 2603 if (options->server_alive_interval == -1) 2604 options->server_alive_interval = 0; 2605 if (options->server_alive_count_max == -1) 2606 options->server_alive_count_max = 3; 2607 if (options->control_master == -1) 2608 options->control_master = 0; 2609 if (options->control_persist == -1) { 2610 options->control_persist = 0; 2611 options->control_persist_timeout = 0; 2612 } 2613 if (options->hash_known_hosts == -1) 2614 options->hash_known_hosts = 0; 2615 if (options->tun_open == -1) 2616 options->tun_open = SSH_TUNMODE_NO; 2617 if (options->tun_local == -1) 2618 options->tun_local = SSH_TUNID_ANY; 2619 if (options->tun_remote == -1) 2620 options->tun_remote = SSH_TUNID_ANY; 2621 if (options->permit_local_command == -1) 2622 options->permit_local_command = 0; 2623 if (options->visual_host_key == -1) 2624 options->visual_host_key = 0; 2625 if (options->ip_qos_interactive == -1) 2626 options->ip_qos_interactive = IPTOS_DSCP_AF21; 2627 if (options->ip_qos_bulk == -1) 2628 options->ip_qos_bulk = IPTOS_DSCP_CS1; 2629 if (options->request_tty == -1) 2630 options->request_tty = REQUEST_TTY_AUTO; 2631 if (options->session_type == -1) 2632 options->session_type = SESSION_TYPE_DEFAULT; 2633 if (options->stdin_null == -1) 2634 options->stdin_null = 0; 2635 if (options->fork_after_authentication == -1) 2636 options->fork_after_authentication = 0; 2637 if (options->proxy_use_fdpass == -1) 2638 options->proxy_use_fdpass = 0; 2639 if (options->canonicalize_max_dots == -1) 2640 options->canonicalize_max_dots = 1; 2641 if (options->canonicalize_fallback_local == -1) 2642 options->canonicalize_fallback_local = 1; 2643 if (options->canonicalize_hostname == -1) 2644 options->canonicalize_hostname = SSH_CANONICALISE_NO; 2645 if (options->fingerprint_hash == -1) 2646 options->fingerprint_hash = SSH_FP_HASH_DEFAULT; 2647 #ifdef ENABLE_SK_INTERNAL 2648 if (options->sk_provider == NULL) 2649 options->sk_provider = xstrdup("internal"); 2650 #else 2651 if (options->sk_provider == NULL) 2652 options->sk_provider = xstrdup("$SSH_SK_PROVIDER"); 2653 #endif 2654 if (options->required_rsa_size == -1) 2655 options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE; 2656 if (options->enable_escape_commandline == -1) 2657 options->enable_escape_commandline = 0; 2658 2659 /* Expand KEX name lists */ 2660 all_cipher = cipher_alg_list(',', 0); 2661 all_mac = mac_alg_list(','); 2662 all_kex = kex_alg_list(','); 2663 all_key = sshkey_alg_list(0, 0, 1, ','); 2664 all_sig = sshkey_alg_list(0, 1, 1, ','); 2665 /* remove unsupported algos from default lists */ 2666 def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher); 2667 def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac); 2668 def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex); 2669 def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key); 2670 def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig); 2671 #define ASSEMBLE(what, defaults, all) \ 2672 do { \ 2673 if ((r = kex_assemble_names(&options->what, \ 2674 defaults, all)) != 0) { \ 2675 error_fr(r, "%s", #what); \ 2676 goto fail; \ 2677 } \ 2678 } while (0) 2679 ASSEMBLE(ciphers, def_cipher, all_cipher); 2680 ASSEMBLE(macs, def_mac, all_mac); 2681 ASSEMBLE(kex_algorithms, def_kex, all_kex); 2682 ASSEMBLE(hostbased_accepted_algos, def_key, all_key); 2683 ASSEMBLE(pubkey_accepted_algos, def_key, all_key); 2684 ASSEMBLE(ca_sign_algorithms, def_sig, all_sig); 2685 #undef ASSEMBLE 2686 2687 #define CLEAR_ON_NONE(v) \ 2688 do { \ 2689 if (option_clear_or_none(v)) { \ 2690 free(v); \ 2691 v = NULL; \ 2692 } \ 2693 } while(0) 2694 CLEAR_ON_NONE(options->local_command); 2695 CLEAR_ON_NONE(options->remote_command); 2696 CLEAR_ON_NONE(options->proxy_command); 2697 CLEAR_ON_NONE(options->control_path); 2698 CLEAR_ON_NONE(options->revoked_host_keys); 2699 CLEAR_ON_NONE(options->pkcs11_provider); 2700 CLEAR_ON_NONE(options->sk_provider); 2701 CLEAR_ON_NONE(options->known_hosts_command); 2702 if (options->jump_host != NULL && 2703 strcmp(options->jump_host, "none") == 0 && 2704 options->jump_port == 0 && options->jump_user == NULL) { 2705 free(options->jump_host); 2706 options->jump_host = NULL; 2707 } 2708 if (options->num_permitted_cnames == 1 && 2709 !config_has_permitted_cnames(options)) { 2710 /* clean up CanonicalizePermittedCNAMEs=none */ 2711 free(options->permitted_cnames[0].source_list); 2712 free(options->permitted_cnames[0].target_list); 2713 memset(options->permitted_cnames, '\0', 2714 sizeof(*options->permitted_cnames)); 2715 options->num_permitted_cnames = 0; 2716 } 2717 /* options->identity_agent distinguishes NULL from 'none' */ 2718 /* options->user will be set in the main program if appropriate */ 2719 /* options->hostname will be set in the main program if appropriate */ 2720 /* options->host_key_alias should not be set by default */ 2721 /* options->preferred_authentications will be set in ssh */ 2722 2723 /* success */ 2724 ret = 0; 2725 fail: 2726 free(all_cipher); 2727 free(all_mac); 2728 free(all_kex); 2729 free(all_key); 2730 free(all_sig); 2731 free(def_cipher); 2732 free(def_mac); 2733 free(def_kex); 2734 free(def_key); 2735 free(def_sig); 2736 return ret; 2737 } 2738 2739 void 2740 free_options(Options *o) 2741 { 2742 int i; 2743 2744 if (o == NULL) 2745 return; 2746 2747 #define FREE_ARRAY(type, n, a) \ 2748 do { \ 2749 type _i; \ 2750 for (_i = 0; _i < (n); _i++) \ 2751 free((a)[_i]); \ 2752 } while (0) 2753 2754 free(o->forward_agent_sock_path); 2755 free(o->xauth_location); 2756 FREE_ARRAY(u_int, o->num_log_verbose, o->log_verbose); 2757 free(o->log_verbose); 2758 free(o->ciphers); 2759 free(o->macs); 2760 free(o->hostkeyalgorithms); 2761 free(o->kex_algorithms); 2762 free(o->ca_sign_algorithms); 2763 free(o->hostname); 2764 free(o->host_key_alias); 2765 free(o->proxy_command); 2766 free(o->user); 2767 FREE_ARRAY(u_int, o->num_system_hostfiles, o->system_hostfiles); 2768 FREE_ARRAY(u_int, o->num_user_hostfiles, o->user_hostfiles); 2769 free(o->preferred_authentications); 2770 free(o->bind_address); 2771 free(o->bind_interface); 2772 free(o->pkcs11_provider); 2773 free(o->sk_provider); 2774 for (i = 0; i < o->num_identity_files; i++) { 2775 free(o->identity_files[i]); 2776 sshkey_free(o->identity_keys[i]); 2777 } 2778 for (i = 0; i < o->num_certificate_files; i++) { 2779 free(o->certificate_files[i]); 2780 sshkey_free(o->certificates[i]); 2781 } 2782 free(o->identity_agent); 2783 for (i = 0; i < o->num_local_forwards; i++) { 2784 free(o->local_forwards[i].listen_host); 2785 free(o->local_forwards[i].listen_path); 2786 free(o->local_forwards[i].connect_host); 2787 free(o->local_forwards[i].connect_path); 2788 } 2789 free(o->local_forwards); 2790 for (i = 0; i < o->num_remote_forwards; i++) { 2791 free(o->remote_forwards[i].listen_host); 2792 free(o->remote_forwards[i].listen_path); 2793 free(o->remote_forwards[i].connect_host); 2794 free(o->remote_forwards[i].connect_path); 2795 } 2796 free(o->remote_forwards); 2797 free(o->stdio_forward_host); 2798 FREE_ARRAY(u_int, o->num_send_env, o->send_env); 2799 free(o->send_env); 2800 FREE_ARRAY(u_int, o->num_setenv, o->setenv); 2801 free(o->setenv); 2802 free(o->control_path); 2803 free(o->local_command); 2804 free(o->remote_command); 2805 FREE_ARRAY(int, o->num_canonical_domains, o->canonical_domains); 2806 for (i = 0; i < o->num_permitted_cnames; i++) { 2807 free(o->permitted_cnames[i].source_list); 2808 free(o->permitted_cnames[i].target_list); 2809 } 2810 free(o->revoked_host_keys); 2811 free(o->hostbased_accepted_algos); 2812 free(o->pubkey_accepted_algos); 2813 free(o->jump_user); 2814 free(o->jump_host); 2815 free(o->jump_extra); 2816 free(o->ignored_unknown); 2817 explicit_bzero(o, sizeof(*o)); 2818 #undef FREE_ARRAY 2819 } 2820 2821 struct fwdarg { 2822 char *arg; 2823 int ispath; 2824 }; 2825 2826 /* 2827 * parse_fwd_field 2828 * parses the next field in a port forwarding specification. 2829 * sets fwd to the parsed field and advances p past the colon 2830 * or sets it to NULL at end of string. 2831 * returns 0 on success, else non-zero. 2832 */ 2833 static int 2834 parse_fwd_field(char **p, struct fwdarg *fwd) 2835 { 2836 char *ep, *cp = *p; 2837 int ispath = 0; 2838 2839 if (*cp == '\0') { 2840 *p = NULL; 2841 return -1; /* end of string */ 2842 } 2843 2844 /* 2845 * A field escaped with square brackets is used literally. 2846 * XXX - allow ']' to be escaped via backslash? 2847 */ 2848 if (*cp == '[') { 2849 /* find matching ']' */ 2850 for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) { 2851 if (*ep == '/') 2852 ispath = 1; 2853 } 2854 /* no matching ']' or not at end of field. */ 2855 if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0')) 2856 return -1; 2857 /* NUL terminate the field and advance p past the colon */ 2858 *ep++ = '\0'; 2859 if (*ep != '\0') 2860 *ep++ = '\0'; 2861 fwd->arg = cp + 1; 2862 fwd->ispath = ispath; 2863 *p = ep; 2864 return 0; 2865 } 2866 2867 for (cp = *p; *cp != '\0'; cp++) { 2868 switch (*cp) { 2869 case '\\': 2870 memmove(cp, cp + 1, strlen(cp + 1) + 1); 2871 if (*cp == '\0') 2872 return -1; 2873 break; 2874 case '/': 2875 ispath = 1; 2876 break; 2877 case ':': 2878 *cp++ = '\0'; 2879 goto done; 2880 } 2881 } 2882 done: 2883 fwd->arg = *p; 2884 fwd->ispath = ispath; 2885 *p = cp; 2886 return 0; 2887 } 2888 2889 /* 2890 * parse_forward 2891 * parses a string containing a port forwarding specification of the form: 2892 * dynamicfwd == 0 2893 * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath 2894 * listenpath:connectpath 2895 * dynamicfwd == 1 2896 * [listenhost:]listenport 2897 * returns number of arguments parsed or zero on error 2898 */ 2899 int 2900 parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) 2901 { 2902 struct fwdarg fwdargs[4]; 2903 char *p, *cp; 2904 int i, err; 2905 2906 memset(fwd, 0, sizeof(*fwd)); 2907 memset(fwdargs, 0, sizeof(fwdargs)); 2908 2909 /* 2910 * We expand environment variables before checking if we think they're 2911 * paths so that if ${VAR} expands to a fully qualified path it is 2912 * treated as a path. 2913 */ 2914 cp = p = dollar_expand(&err, fwdspec); 2915 if (p == NULL || err) 2916 return 0; 2917 2918 /* skip leading spaces */ 2919 while (isspace((u_char)*cp)) 2920 cp++; 2921 2922 for (i = 0; i < 4; ++i) { 2923 if (parse_fwd_field(&cp, &fwdargs[i]) != 0) 2924 break; 2925 } 2926 2927 /* Check for trailing garbage */ 2928 if (cp != NULL && *cp != '\0') { 2929 i = 0; /* failure */ 2930 } 2931 2932 switch (i) { 2933 case 1: 2934 if (fwdargs[0].ispath) { 2935 fwd->listen_path = xstrdup(fwdargs[0].arg); 2936 fwd->listen_port = PORT_STREAMLOCAL; 2937 } else { 2938 fwd->listen_host = NULL; 2939 fwd->listen_port = a2port(fwdargs[0].arg); 2940 } 2941 fwd->connect_host = xstrdup("socks"); 2942 break; 2943 2944 case 2: 2945 if (fwdargs[0].ispath && fwdargs[1].ispath) { 2946 fwd->listen_path = xstrdup(fwdargs[0].arg); 2947 fwd->listen_port = PORT_STREAMLOCAL; 2948 fwd->connect_path = xstrdup(fwdargs[1].arg); 2949 fwd->connect_port = PORT_STREAMLOCAL; 2950 } else if (fwdargs[1].ispath) { 2951 fwd->listen_host = NULL; 2952 fwd->listen_port = a2port(fwdargs[0].arg); 2953 fwd->connect_path = xstrdup(fwdargs[1].arg); 2954 fwd->connect_port = PORT_STREAMLOCAL; 2955 } else { 2956 fwd->listen_host = xstrdup(fwdargs[0].arg); 2957 fwd->listen_port = a2port(fwdargs[1].arg); 2958 fwd->connect_host = xstrdup("socks"); 2959 } 2960 break; 2961 2962 case 3: 2963 if (fwdargs[0].ispath) { 2964 fwd->listen_path = xstrdup(fwdargs[0].arg); 2965 fwd->listen_port = PORT_STREAMLOCAL; 2966 fwd->connect_host = xstrdup(fwdargs[1].arg); 2967 fwd->connect_port = a2port(fwdargs[2].arg); 2968 } else if (fwdargs[2].ispath) { 2969 fwd->listen_host = xstrdup(fwdargs[0].arg); 2970 fwd->listen_port = a2port(fwdargs[1].arg); 2971 fwd->connect_path = xstrdup(fwdargs[2].arg); 2972 fwd->connect_port = PORT_STREAMLOCAL; 2973 } else { 2974 fwd->listen_host = NULL; 2975 fwd->listen_port = a2port(fwdargs[0].arg); 2976 fwd->connect_host = xstrdup(fwdargs[1].arg); 2977 fwd->connect_port = a2port(fwdargs[2].arg); 2978 } 2979 break; 2980 2981 case 4: 2982 fwd->listen_host = xstrdup(fwdargs[0].arg); 2983 fwd->listen_port = a2port(fwdargs[1].arg); 2984 fwd->connect_host = xstrdup(fwdargs[2].arg); 2985 fwd->connect_port = a2port(fwdargs[3].arg); 2986 break; 2987 default: 2988 i = 0; /* failure */ 2989 } 2990 2991 free(p); 2992 2993 if (dynamicfwd) { 2994 if (!(i == 1 || i == 2)) 2995 goto fail_free; 2996 } else { 2997 if (!(i == 3 || i == 4)) { 2998 if (fwd->connect_path == NULL && 2999 fwd->listen_path == NULL) 3000 goto fail_free; 3001 } 3002 if (fwd->connect_port <= 0 && fwd->connect_path == NULL) 3003 goto fail_free; 3004 } 3005 3006 if ((fwd->listen_port < 0 && fwd->listen_path == NULL) || 3007 (!remotefwd && fwd->listen_port == 0)) 3008 goto fail_free; 3009 if (fwd->connect_host != NULL && 3010 strlen(fwd->connect_host) >= NI_MAXHOST) 3011 goto fail_free; 3012 /* 3013 * XXX - if connecting to a remote socket, max sun len may not 3014 * match this host 3015 */ 3016 if (fwd->connect_path != NULL && 3017 strlen(fwd->connect_path) >= PATH_MAX_SUN) 3018 goto fail_free; 3019 if (fwd->listen_host != NULL && 3020 strlen(fwd->listen_host) >= NI_MAXHOST) 3021 goto fail_free; 3022 if (fwd->listen_path != NULL && 3023 strlen(fwd->listen_path) >= PATH_MAX_SUN) 3024 goto fail_free; 3025 3026 return (i); 3027 3028 fail_free: 3029 free(fwd->connect_host); 3030 fwd->connect_host = NULL; 3031 free(fwd->connect_path); 3032 fwd->connect_path = NULL; 3033 free(fwd->listen_host); 3034 fwd->listen_host = NULL; 3035 free(fwd->listen_path); 3036 fwd->listen_path = NULL; 3037 return (0); 3038 } 3039 3040 int 3041 parse_jump(const char *s, Options *o, int active) 3042 { 3043 char *orig, *sdup, *cp; 3044 char *host = NULL, *user = NULL; 3045 int r, ret = -1, port = -1, first; 3046 3047 active &= o->proxy_command == NULL && o->jump_host == NULL; 3048 3049 orig = sdup = xstrdup(s); 3050 3051 /* Remove comment and trailing whitespace */ 3052 if ((cp = strchr(orig, '#')) != NULL) 3053 *cp = '\0'; 3054 rtrim(orig); 3055 3056 first = active; 3057 do { 3058 if (strcasecmp(s, "none") == 0) 3059 break; 3060 if ((cp = strrchr(sdup, ',')) == NULL) 3061 cp = sdup; /* last */ 3062 else 3063 *cp++ = '\0'; 3064 3065 if (first) { 3066 /* First argument and configuration is active */ 3067 r = parse_ssh_uri(cp, &user, &host, &port); 3068 if (r == -1 || (r == 1 && 3069 parse_user_host_port(cp, &user, &host, &port) != 0)) 3070 goto out; 3071 } else { 3072 /* Subsequent argument or inactive configuration */ 3073 r = parse_ssh_uri(cp, NULL, NULL, NULL); 3074 if (r == -1 || (r == 1 && 3075 parse_user_host_port(cp, NULL, NULL, NULL) != 0)) 3076 goto out; 3077 } 3078 first = 0; /* only check syntax for subsequent hosts */ 3079 } while (cp != sdup); 3080 /* success */ 3081 if (active) { 3082 if (strcasecmp(s, "none") == 0) { 3083 o->jump_host = xstrdup("none"); 3084 o->jump_port = 0; 3085 } else { 3086 o->jump_user = user; 3087 o->jump_host = host; 3088 o->jump_port = port; 3089 o->proxy_command = xstrdup("none"); 3090 user = host = NULL; 3091 if ((cp = strrchr(s, ',')) != NULL && cp != s) { 3092 o->jump_extra = xstrdup(s); 3093 o->jump_extra[cp - s] = '\0'; 3094 } 3095 } 3096 } 3097 ret = 0; 3098 out: 3099 free(orig); 3100 free(user); 3101 free(host); 3102 return ret; 3103 } 3104 3105 int 3106 parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp) 3107 { 3108 char *user = NULL, *host = NULL, *path = NULL; 3109 int r, port; 3110 3111 r = parse_uri("ssh", uri, &user, &host, &port, &path); 3112 if (r == 0 && path != NULL) 3113 r = -1; /* path not allowed */ 3114 if (r == 0) { 3115 if (userp != NULL) { 3116 *userp = user; 3117 user = NULL; 3118 } 3119 if (hostp != NULL) { 3120 *hostp = host; 3121 host = NULL; 3122 } 3123 if (portp != NULL) 3124 *portp = port; 3125 } 3126 free(user); 3127 free(host); 3128 free(path); 3129 return r; 3130 } 3131 3132 /* XXX the following is a near-vebatim copy from servconf.c; refactor */ 3133 static const char * 3134 fmt_multistate_int(int val, const struct multistate *m) 3135 { 3136 u_int i; 3137 3138 for (i = 0; m[i].key != NULL; i++) { 3139 if (m[i].value == val) 3140 return m[i].key; 3141 } 3142 return "UNKNOWN"; 3143 } 3144 3145 static const char * 3146 fmt_intarg(OpCodes code, int val) 3147 { 3148 if (val == -1) 3149 return "unset"; 3150 switch (code) { 3151 case oAddressFamily: 3152 return fmt_multistate_int(val, multistate_addressfamily); 3153 case oVerifyHostKeyDNS: 3154 case oUpdateHostkeys: 3155 return fmt_multistate_int(val, multistate_yesnoask); 3156 case oStrictHostKeyChecking: 3157 return fmt_multistate_int(val, multistate_strict_hostkey); 3158 case oControlMaster: 3159 return fmt_multistate_int(val, multistate_controlmaster); 3160 case oTunnel: 3161 return fmt_multistate_int(val, multistate_tunnel); 3162 case oRequestTTY: 3163 return fmt_multistate_int(val, multistate_requesttty); 3164 case oSessionType: 3165 return fmt_multistate_int(val, multistate_sessiontype); 3166 case oCanonicalizeHostname: 3167 return fmt_multistate_int(val, multistate_canonicalizehostname); 3168 case oAddKeysToAgent: 3169 return fmt_multistate_int(val, multistate_yesnoaskconfirm); 3170 case oPubkeyAuthentication: 3171 return fmt_multistate_int(val, multistate_pubkey_auth); 3172 case oFingerprintHash: 3173 return ssh_digest_alg_name(val); 3174 default: 3175 switch (val) { 3176 case 0: 3177 return "no"; 3178 case 1: 3179 return "yes"; 3180 default: 3181 return "UNKNOWN"; 3182 } 3183 } 3184 } 3185 3186 static const char * 3187 lookup_opcode_name(OpCodes code) 3188 { 3189 u_int i; 3190 3191 for (i = 0; keywords[i].name != NULL; i++) 3192 if (keywords[i].opcode == code) 3193 return(keywords[i].name); 3194 return "UNKNOWN"; 3195 } 3196 3197 static void 3198 dump_cfg_int(OpCodes code, int val) 3199 { 3200 printf("%s %d\n", lookup_opcode_name(code), val); 3201 } 3202 3203 static void 3204 dump_cfg_fmtint(OpCodes code, int val) 3205 { 3206 printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val)); 3207 } 3208 3209 static void 3210 dump_cfg_string(OpCodes code, const char *val) 3211 { 3212 if (val == NULL) 3213 return; 3214 printf("%s %s\n", lookup_opcode_name(code), val); 3215 } 3216 3217 static void 3218 dump_cfg_strarray(OpCodes code, u_int count, char **vals) 3219 { 3220 u_int i; 3221 3222 for (i = 0; i < count; i++) 3223 printf("%s %s\n", lookup_opcode_name(code), vals[i]); 3224 } 3225 3226 static void 3227 dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals) 3228 { 3229 u_int i; 3230 3231 printf("%s", lookup_opcode_name(code)); 3232 if (count == 0) 3233 printf(" none"); 3234 for (i = 0; i < count; i++) 3235 printf(" %s", vals[i]); 3236 printf("\n"); 3237 } 3238 3239 static void 3240 dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds) 3241 { 3242 const struct Forward *fwd; 3243 u_int i; 3244 3245 /* oDynamicForward */ 3246 for (i = 0; i < count; i++) { 3247 fwd = &fwds[i]; 3248 if (code == oDynamicForward && fwd->connect_host != NULL && 3249 strcmp(fwd->connect_host, "socks") != 0) 3250 continue; 3251 if (code == oLocalForward && fwd->connect_host != NULL && 3252 strcmp(fwd->connect_host, "socks") == 0) 3253 continue; 3254 printf("%s", lookup_opcode_name(code)); 3255 if (fwd->listen_port == PORT_STREAMLOCAL) 3256 printf(" %s", fwd->listen_path); 3257 else if (fwd->listen_host == NULL) 3258 printf(" %d", fwd->listen_port); 3259 else { 3260 printf(" [%s]:%d", 3261 fwd->listen_host, fwd->listen_port); 3262 } 3263 if (code != oDynamicForward) { 3264 if (fwd->connect_port == PORT_STREAMLOCAL) 3265 printf(" %s", fwd->connect_path); 3266 else if (fwd->connect_host == NULL) 3267 printf(" %d", fwd->connect_port); 3268 else { 3269 printf(" [%s]:%d", 3270 fwd->connect_host, fwd->connect_port); 3271 } 3272 } 3273 printf("\n"); 3274 } 3275 } 3276 3277 void 3278 dump_client_config(Options *o, const char *host) 3279 { 3280 int i, r; 3281 char buf[8], *all_key; 3282 3283 /* 3284 * Expand HostKeyAlgorithms name lists. This isn't handled in 3285 * fill_default_options() like the other algorithm lists because 3286 * the host key algorithms are by default dynamically chosen based 3287 * on the host's keys found in known_hosts. 3288 */ 3289 all_key = sshkey_alg_list(0, 0, 1, ','); 3290 if ((r = kex_assemble_names(&o->hostkeyalgorithms, kex_default_pk_alg(), 3291 all_key)) != 0) 3292 fatal_fr(r, "expand HostKeyAlgorithms"); 3293 free(all_key); 3294 3295 /* Most interesting options first: user, host, port */ 3296 dump_cfg_string(oHost, o->host_arg); 3297 dump_cfg_string(oUser, o->user); 3298 dump_cfg_string(oHostname, host); 3299 dump_cfg_int(oPort, o->port); 3300 3301 /* Flag options */ 3302 dump_cfg_fmtint(oAddressFamily, o->address_family); 3303 dump_cfg_fmtint(oBatchMode, o->batch_mode); 3304 dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local); 3305 dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname); 3306 dump_cfg_fmtint(oCheckHostIP, o->check_host_ip); 3307 dump_cfg_fmtint(oCompression, o->compression); 3308 dump_cfg_fmtint(oControlMaster, o->control_master); 3309 dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign); 3310 dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings); 3311 dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure); 3312 dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash); 3313 dump_cfg_fmtint(oForwardX11, o->forward_x11); 3314 dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted); 3315 dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports); 3316 #ifdef GSSAPI 3317 dump_cfg_fmtint(oGssAuthentication, o->gss_authentication); 3318 dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds); 3319 #endif /* GSSAPI */ 3320 dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts); 3321 dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication); 3322 dump_cfg_fmtint(oIdentitiesOnly, o->identities_only); 3323 dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication); 3324 dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost); 3325 dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication); 3326 dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command); 3327 dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass); 3328 dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication); 3329 dump_cfg_fmtint(oRequestTTY, o->request_tty); 3330 dump_cfg_fmtint(oSessionType, o->session_type); 3331 dump_cfg_fmtint(oStdinNull, o->stdin_null); 3332 dump_cfg_fmtint(oForkAfterAuthentication, o->fork_after_authentication); 3333 dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink); 3334 dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking); 3335 dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive); 3336 dump_cfg_fmtint(oTunnel, o->tun_open); 3337 dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns); 3338 dump_cfg_fmtint(oVisualHostKey, o->visual_host_key); 3339 dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys); 3340 dump_cfg_fmtint(oEnableEscapeCommandline, o->enable_escape_commandline); 3341 3342 /* Integer options */ 3343 dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots); 3344 dump_cfg_int(oConnectionAttempts, o->connection_attempts); 3345 dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout); 3346 dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts); 3347 dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max); 3348 dump_cfg_int(oServerAliveInterval, o->server_alive_interval); 3349 dump_cfg_int(oRequiredRSASize, o->required_rsa_size); 3350 3351 /* String options */ 3352 dump_cfg_string(oBindAddress, o->bind_address); 3353 dump_cfg_string(oBindInterface, o->bind_interface); 3354 dump_cfg_string(oCiphers, o->ciphers); 3355 dump_cfg_string(oControlPath, o->control_path); 3356 dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms); 3357 dump_cfg_string(oHostKeyAlias, o->host_key_alias); 3358 dump_cfg_string(oHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos); 3359 dump_cfg_string(oIdentityAgent, o->identity_agent); 3360 dump_cfg_string(oIgnoreUnknown, o->ignored_unknown); 3361 dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices); 3362 dump_cfg_string(oKexAlgorithms, o->kex_algorithms); 3363 dump_cfg_string(oCASignatureAlgorithms, o->ca_sign_algorithms); 3364 dump_cfg_string(oLocalCommand, o->local_command); 3365 dump_cfg_string(oRemoteCommand, o->remote_command); 3366 dump_cfg_string(oLogLevel, log_level_name(o->log_level)); 3367 dump_cfg_string(oMacs, o->macs); 3368 #ifdef ENABLE_PKCS11 3369 dump_cfg_string(oPKCS11Provider, o->pkcs11_provider); 3370 #endif 3371 dump_cfg_string(oSecurityKeyProvider, o->sk_provider); 3372 dump_cfg_string(oPreferredAuthentications, o->preferred_authentications); 3373 dump_cfg_string(oPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos); 3374 dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys); 3375 dump_cfg_string(oXAuthLocation, o->xauth_location); 3376 dump_cfg_string(oKnownHostsCommand, o->known_hosts_command); 3377 3378 /* Forwards */ 3379 dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards); 3380 dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards); 3381 dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards); 3382 3383 /* String array options */ 3384 dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files); 3385 dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains); 3386 dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files); 3387 dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles); 3388 dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles); 3389 dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env); 3390 dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv); 3391 dump_cfg_strarray_oneline(oLogVerbose, 3392 o->num_log_verbose, o->log_verbose); 3393 3394 /* Special cases */ 3395 3396 /* PermitRemoteOpen */ 3397 if (o->num_permitted_remote_opens == 0) 3398 printf("%s any\n", lookup_opcode_name(oPermitRemoteOpen)); 3399 else 3400 dump_cfg_strarray_oneline(oPermitRemoteOpen, 3401 o->num_permitted_remote_opens, o->permitted_remote_opens); 3402 3403 /* AddKeysToAgent */ 3404 if (o->add_keys_to_agent_lifespan <= 0) 3405 dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent); 3406 else { 3407 printf("addkeystoagent%s %d\n", 3408 o->add_keys_to_agent == 3 ? " confirm" : "", 3409 o->add_keys_to_agent_lifespan); 3410 } 3411 3412 /* oForwardAgent */ 3413 if (o->forward_agent_sock_path == NULL) 3414 dump_cfg_fmtint(oForwardAgent, o->forward_agent); 3415 else 3416 dump_cfg_string(oForwardAgent, o->forward_agent_sock_path); 3417 3418 /* oConnectTimeout */ 3419 if (o->connection_timeout == -1) 3420 printf("connecttimeout none\n"); 3421 else 3422 dump_cfg_int(oConnectTimeout, o->connection_timeout); 3423 3424 /* oTunnelDevice */ 3425 printf("tunneldevice"); 3426 if (o->tun_local == SSH_TUNID_ANY) 3427 printf(" any"); 3428 else 3429 printf(" %d", o->tun_local); 3430 if (o->tun_remote == SSH_TUNID_ANY) 3431 printf(":any"); 3432 else 3433 printf(":%d", o->tun_remote); 3434 printf("\n"); 3435 3436 /* oCanonicalizePermittedCNAMEs */ 3437 printf("canonicalizePermittedcnames"); 3438 if (o->num_permitted_cnames == 0) 3439 printf(" none"); 3440 for (i = 0; i < o->num_permitted_cnames; i++) { 3441 printf(" %s:%s", o->permitted_cnames[i].source_list, 3442 o->permitted_cnames[i].target_list); 3443 } 3444 printf("\n"); 3445 3446 /* oControlPersist */ 3447 if (o->control_persist == 0 || o->control_persist_timeout == 0) 3448 dump_cfg_fmtint(oControlPersist, o->control_persist); 3449 else 3450 dump_cfg_int(oControlPersist, o->control_persist_timeout); 3451 3452 /* oEscapeChar */ 3453 if (o->escape_char == SSH_ESCAPECHAR_NONE) 3454 printf("escapechar none\n"); 3455 else { 3456 vis(buf, o->escape_char, VIS_WHITE, 0); 3457 printf("escapechar %s\n", buf); 3458 } 3459 3460 /* oIPQoS */ 3461 printf("ipqos %s ", iptos2str(o->ip_qos_interactive)); 3462 printf("%s\n", iptos2str(o->ip_qos_bulk)); 3463 3464 /* oRekeyLimit */ 3465 printf("rekeylimit %llu %d\n", 3466 (unsigned long long)o->rekey_limit, o->rekey_interval); 3467 3468 /* oStreamLocalBindMask */ 3469 printf("streamlocalbindmask 0%o\n", 3470 o->fwd_opts.streamlocal_bind_mask); 3471 3472 /* oLogFacility */ 3473 printf("syslogfacility %s\n", log_facility_name(o->log_facility)); 3474 3475 /* oProxyCommand / oProxyJump */ 3476 if (o->jump_host == NULL) 3477 dump_cfg_string(oProxyCommand, o->proxy_command); 3478 else { 3479 /* Check for numeric addresses */ 3480 i = strchr(o->jump_host, ':') != NULL || 3481 strspn(o->jump_host, "1234567890.") == strlen(o->jump_host); 3482 snprintf(buf, sizeof(buf), "%d", o->jump_port); 3483 printf("proxyjump %s%s%s%s%s%s%s%s%s\n", 3484 /* optional additional jump spec */ 3485 o->jump_extra == NULL ? "" : o->jump_extra, 3486 o->jump_extra == NULL ? "" : ",", 3487 /* optional user */ 3488 o->jump_user == NULL ? "" : o->jump_user, 3489 o->jump_user == NULL ? "" : "@", 3490 /* opening [ if hostname is numeric */ 3491 i ? "[" : "", 3492 /* mandatory hostname */ 3493 o->jump_host, 3494 /* closing ] if hostname is numeric */ 3495 i ? "]" : "", 3496 /* optional port number */ 3497 o->jump_port <= 0 ? "" : ":", 3498 o->jump_port <= 0 ? "" : buf); 3499 } 3500 } 3501