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