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