1 /* $OpenBSD: readconf.c,v 1.361 2021/07/23 04:04:52 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 while ((arg = argv_next(&ac, &av)) != NULL) { 2042 /* Either '*' for everything or 'list:list' */ 2043 if (strcmp(arg, "*") == 0) 2044 arg2 = arg; 2045 else { 2046 lowercase(arg); 2047 if ((arg2 = strchr(arg, ':')) == NULL || 2048 arg2[1] == '\0') { 2049 error("%s line %d: " 2050 "Invalid permitted CNAME \"%s\"", 2051 filename, linenum, arg); 2052 goto out; 2053 } 2054 *arg2 = '\0'; 2055 arg2++; 2056 } 2057 if (!*activep || value) 2058 continue; 2059 if (options->num_permitted_cnames >= 2060 MAX_CANON_DOMAINS) { 2061 error("%s line %d: too many permitted CNAMEs.", 2062 filename, linenum); 2063 goto out; 2064 } 2065 cname = options->permitted_cnames + 2066 options->num_permitted_cnames++; 2067 cname->source_list = xstrdup(arg); 2068 cname->target_list = xstrdup(arg2); 2069 } 2070 break; 2071 2072 case oCanonicalizeHostname: 2073 intptr = &options->canonicalize_hostname; 2074 multistate_ptr = multistate_canonicalizehostname; 2075 goto parse_multistate; 2076 2077 case oCanonicalizeMaxDots: 2078 intptr = &options->canonicalize_max_dots; 2079 goto parse_int; 2080 2081 case oCanonicalizeFallbackLocal: 2082 intptr = &options->canonicalize_fallback_local; 2083 goto parse_flag; 2084 2085 case oStreamLocalBindMask: 2086 arg = argv_next(&ac, &av); 2087 if (!arg || *arg == '\0') { 2088 error("%.200s line %d: Missing StreamLocalBindMask " 2089 "argument.", filename, linenum); 2090 goto out; 2091 } 2092 /* Parse mode in octal format */ 2093 value = strtol(arg, &endofnumber, 8); 2094 if (arg == endofnumber || value < 0 || value > 0777) { 2095 error("%.200s line %d: Bad mask.", filename, linenum); 2096 goto out; 2097 } 2098 options->fwd_opts.streamlocal_bind_mask = (mode_t)value; 2099 break; 2100 2101 case oStreamLocalBindUnlink: 2102 intptr = &options->fwd_opts.streamlocal_bind_unlink; 2103 goto parse_flag; 2104 2105 case oRevokedHostKeys: 2106 charptr = &options->revoked_host_keys; 2107 goto parse_string; 2108 2109 case oFingerprintHash: 2110 intptr = &options->fingerprint_hash; 2111 arg = argv_next(&ac, &av); 2112 if (!arg || *arg == '\0') { 2113 error("%.200s line %d: Missing argument.", 2114 filename, linenum); 2115 goto out; 2116 } 2117 if ((value = ssh_digest_alg_by_name(arg)) == -1) { 2118 error("%.200s line %d: Invalid hash algorithm \"%s\".", 2119 filename, linenum, arg); 2120 goto out; 2121 } 2122 if (*activep && *intptr == -1) 2123 *intptr = value; 2124 break; 2125 2126 case oUpdateHostkeys: 2127 intptr = &options->update_hostkeys; 2128 multistate_ptr = multistate_yesnoask; 2129 goto parse_multistate; 2130 2131 case oHostbasedAcceptedAlgorithms: 2132 charptr = &options->hostbased_accepted_algos; 2133 goto parse_pubkey_algos; 2134 2135 case oPubkeyAcceptedAlgorithms: 2136 charptr = &options->pubkey_accepted_algos; 2137 goto parse_pubkey_algos; 2138 2139 case oAddKeysToAgent: 2140 arg = argv_next(&ac, &av); 2141 arg2 = argv_next(&ac, &av); 2142 value = parse_multistate_value(arg, filename, linenum, 2143 multistate_yesnoaskconfirm); 2144 value2 = 0; /* unlimited lifespan by default */ 2145 if (value == 3 && arg2 != NULL) { 2146 /* allow "AddKeysToAgent confirm 5m" */ 2147 if ((value2 = convtime(arg2)) == -1 || 2148 value2 > INT_MAX) { 2149 error("%s line %d: invalid time value.", 2150 filename, linenum); 2151 goto out; 2152 } 2153 } else if (value == -1 && arg2 == NULL) { 2154 if ((value2 = convtime(arg)) == -1 || 2155 value2 > INT_MAX) { 2156 error("%s line %d: unsupported option", 2157 filename, linenum); 2158 goto out; 2159 } 2160 value = 1; /* yes */ 2161 } else if (value == -1 || arg2 != NULL) { 2162 error("%s line %d: unsupported option", 2163 filename, linenum); 2164 goto out; 2165 } 2166 if (*activep && options->add_keys_to_agent == -1) { 2167 options->add_keys_to_agent = value; 2168 options->add_keys_to_agent_lifespan = value2; 2169 } 2170 break; 2171 2172 case oIdentityAgent: 2173 charptr = &options->identity_agent; 2174 arg = argv_next(&ac, &av); 2175 if (!arg || *arg == '\0') { 2176 error("%.200s line %d: Missing argument.", 2177 filename, linenum); 2178 goto out; 2179 } 2180 parse_agent_path: 2181 /* Extra validation if the string represents an env var. */ 2182 if ((arg2 = dollar_expand(&r, arg)) == NULL || r) { 2183 error("%.200s line %d: Invalid environment expansion " 2184 "%s.", filename, linenum, arg); 2185 goto out; 2186 } 2187 free(arg2); 2188 /* check for legacy environment format */ 2189 if (arg[0] == '$' && arg[1] != '{' && 2190 !valid_env_name(arg + 1)) { 2191 error("%.200s line %d: Invalid environment name %s.", 2192 filename, linenum, arg); 2193 goto out; 2194 } 2195 if (*activep && *charptr == NULL) 2196 *charptr = xstrdup(arg); 2197 break; 2198 2199 case oDeprecated: 2200 debug("%s line %d: Deprecated option \"%s\"", 2201 filename, linenum, keyword); 2202 argv_consume(&ac); 2203 break; 2204 2205 case oUnsupported: 2206 error("%s line %d: Unsupported option \"%s\"", 2207 filename, linenum, keyword); 2208 argv_consume(&ac); 2209 break; 2210 2211 default: 2212 error("%s line %d: Unimplemented opcode %d", 2213 filename, linenum, opcode); 2214 goto out; 2215 } 2216 2217 /* Check that there is no garbage at end of line. */ 2218 if (ac > 0) { 2219 error("%.200s line %d: keyword %s extra arguments " 2220 "at end of line", filename, linenum, keyword); 2221 goto out; 2222 } 2223 2224 /* success */ 2225 ret = 0; 2226 out: 2227 argv_free(oav, oac); 2228 return ret; 2229 } 2230 2231 /* 2232 * Reads the config file and modifies the options accordingly. Options 2233 * should already be initialized before this call. This never returns if 2234 * there is an error. If the file does not exist, this returns 0. 2235 */ 2236 int 2237 read_config_file(const char *filename, struct passwd *pw, const char *host, 2238 const char *original_host, Options *options, int flags, 2239 int *want_final_pass) 2240 { 2241 int active = 1; 2242 2243 return read_config_file_depth(filename, pw, host, original_host, 2244 options, flags, &active, want_final_pass, 0); 2245 } 2246 2247 #define READCONF_MAX_DEPTH 16 2248 static int 2249 read_config_file_depth(const char *filename, struct passwd *pw, 2250 const char *host, const char *original_host, Options *options, 2251 int flags, int *activep, int *want_final_pass, int depth) 2252 { 2253 FILE *f; 2254 char *line = NULL; 2255 size_t linesize = 0; 2256 int linenum; 2257 int bad_options = 0; 2258 2259 if (depth < 0 || depth > READCONF_MAX_DEPTH) 2260 fatal("Too many recursive configuration includes"); 2261 2262 if ((f = fopen(filename, "r")) == NULL) 2263 return 0; 2264 2265 if (flags & SSHCONF_CHECKPERM) { 2266 struct stat sb; 2267 2268 if (fstat(fileno(f), &sb) == -1) 2269 fatal("fstat %s: %s", filename, strerror(errno)); 2270 if (((sb.st_uid != 0 && sb.st_uid != getuid()) || 2271 (sb.st_mode & 022) != 0)) 2272 fatal("Bad owner or permissions on %s", filename); 2273 } 2274 2275 debug("Reading configuration data %.200s", filename); 2276 2277 /* 2278 * Mark that we are now processing the options. This flag is turned 2279 * on/off by Host specifications. 2280 */ 2281 linenum = 0; 2282 while (getline(&line, &linesize, f) != -1) { 2283 /* Update line number counter. */ 2284 linenum++; 2285 /* 2286 * Trim out comments and strip whitespace. 2287 * NB - preserve newlines, they are needed to reproduce 2288 * line numbers later for error messages. 2289 */ 2290 if (process_config_line_depth(options, pw, host, original_host, 2291 line, filename, linenum, activep, flags, want_final_pass, 2292 depth) != 0) 2293 bad_options++; 2294 } 2295 free(line); 2296 fclose(f); 2297 if (bad_options > 0) 2298 fatal("%s: terminating, %d bad configuration options", 2299 filename, bad_options); 2300 return 1; 2301 } 2302 2303 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ 2304 int 2305 option_clear_or_none(const char *o) 2306 { 2307 return o == NULL || strcasecmp(o, "none") == 0; 2308 } 2309 2310 /* 2311 * Initializes options to special values that indicate that they have not yet 2312 * been set. Read_config_file will only set options with this value. Options 2313 * are processed in the following order: command line, user config file, 2314 * system config file. Last, fill_default_options is called. 2315 */ 2316 2317 void 2318 initialize_options(Options * options) 2319 { 2320 memset(options, 'X', sizeof(*options)); 2321 options->version_addendum = NULL; 2322 options->forward_agent = -1; 2323 options->forward_agent_sock_path = NULL; 2324 options->forward_x11 = -1; 2325 options->forward_x11_trusted = -1; 2326 options->forward_x11_timeout = -1; 2327 options->stdio_forward_host = NULL; 2328 options->stdio_forward_port = 0; 2329 options->clear_forwardings = -1; 2330 options->exit_on_forward_failure = -1; 2331 options->xauth_location = NULL; 2332 options->fwd_opts.gateway_ports = -1; 2333 options->fwd_opts.streamlocal_bind_mask = (mode_t)-1; 2334 options->fwd_opts.streamlocal_bind_unlink = -1; 2335 options->pubkey_authentication = -1; 2336 options->gss_authentication = -1; 2337 options->gss_deleg_creds = -1; 2338 options->password_authentication = -1; 2339 options->kbd_interactive_authentication = -1; 2340 options->kbd_interactive_devices = NULL; 2341 options->hostbased_authentication = -1; 2342 options->batch_mode = -1; 2343 options->check_host_ip = -1; 2344 options->strict_host_key_checking = -1; 2345 options->compression = -1; 2346 options->tcp_keep_alive = -1; 2347 options->port = -1; 2348 options->address_family = -1; 2349 options->connection_attempts = -1; 2350 options->connection_timeout = -1; 2351 options->number_of_password_prompts = -1; 2352 options->ciphers = NULL; 2353 options->macs = NULL; 2354 options->kex_algorithms = NULL; 2355 options->hostkeyalgorithms = NULL; 2356 options->ca_sign_algorithms = NULL; 2357 options->num_identity_files = 0; 2358 memset(options->identity_keys, 0, sizeof(options->identity_keys)); 2359 options->num_certificate_files = 0; 2360 memset(options->certificates, 0, sizeof(options->certificates)); 2361 options->hostname = NULL; 2362 options->host_key_alias = NULL; 2363 options->proxy_command = NULL; 2364 options->jump_user = NULL; 2365 options->jump_host = NULL; 2366 options->jump_port = -1; 2367 options->jump_extra = NULL; 2368 options->user = NULL; 2369 options->escape_char = -1; 2370 options->num_system_hostfiles = 0; 2371 options->num_user_hostfiles = 0; 2372 options->local_forwards = NULL; 2373 options->num_local_forwards = 0; 2374 options->remote_forwards = NULL; 2375 options->num_remote_forwards = 0; 2376 options->permitted_remote_opens = NULL; 2377 options->num_permitted_remote_opens = 0; 2378 options->log_facility = SYSLOG_FACILITY_NOT_SET; 2379 options->log_level = SYSLOG_LEVEL_NOT_SET; 2380 options->num_log_verbose = 0; 2381 options->log_verbose = NULL; 2382 options->preferred_authentications = NULL; 2383 options->bind_address = NULL; 2384 options->bind_interface = NULL; 2385 options->pkcs11_provider = NULL; 2386 options->sk_provider = NULL; 2387 options->enable_ssh_keysign = - 1; 2388 options->no_host_authentication_for_localhost = - 1; 2389 options->identities_only = - 1; 2390 options->rekey_limit = - 1; 2391 options->rekey_interval = -1; 2392 options->verify_host_key_dns = -1; 2393 options->server_alive_interval = -1; 2394 options->server_alive_count_max = -1; 2395 options->send_env = NULL; 2396 options->num_send_env = 0; 2397 options->setenv = NULL; 2398 options->num_setenv = 0; 2399 options->control_path = NULL; 2400 options->control_master = -1; 2401 options->control_persist = -1; 2402 options->control_persist_timeout = 0; 2403 options->hash_known_hosts = -1; 2404 options->tun_open = -1; 2405 options->tun_local = -1; 2406 options->tun_remote = -1; 2407 options->local_command = NULL; 2408 options->permit_local_command = -1; 2409 options->remote_command = NULL; 2410 options->add_keys_to_agent = -1; 2411 options->add_keys_to_agent_lifespan = -1; 2412 options->identity_agent = NULL; 2413 options->visual_host_key = -1; 2414 options->ip_qos_interactive = -1; 2415 options->ip_qos_bulk = -1; 2416 options->request_tty = -1; 2417 options->session_type = -1; 2418 options->stdin_null = -1; 2419 options->fork_after_authentication = -1; 2420 options->proxy_use_fdpass = -1; 2421 options->ignored_unknown = NULL; 2422 options->num_canonical_domains = 0; 2423 options->num_permitted_cnames = 0; 2424 options->canonicalize_max_dots = -1; 2425 options->canonicalize_fallback_local = -1; 2426 options->canonicalize_hostname = -1; 2427 options->revoked_host_keys = NULL; 2428 options->fingerprint_hash = -1; 2429 options->update_hostkeys = -1; 2430 options->hostbased_accepted_algos = NULL; 2431 options->pubkey_accepted_algos = NULL; 2432 options->known_hosts_command = NULL; 2433 } 2434 2435 /* 2436 * A petite version of fill_default_options() that just fills the options 2437 * needed for hostname canonicalization to proceed. 2438 */ 2439 void 2440 fill_default_options_for_canonicalization(Options *options) 2441 { 2442 if (options->canonicalize_max_dots == -1) 2443 options->canonicalize_max_dots = 1; 2444 if (options->canonicalize_fallback_local == -1) 2445 options->canonicalize_fallback_local = 1; 2446 if (options->canonicalize_hostname == -1) 2447 options->canonicalize_hostname = SSH_CANONICALISE_NO; 2448 } 2449 2450 /* 2451 * Called after processing other sources of option data, this fills those 2452 * options for which no value has been specified with their default values. 2453 */ 2454 int 2455 fill_default_options(Options * options) 2456 { 2457 char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig; 2458 char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig; 2459 int ret = 0, r; 2460 2461 if (options->forward_agent == -1) 2462 options->forward_agent = 0; 2463 if (options->forward_x11 == -1) 2464 options->forward_x11 = 0; 2465 if (options->forward_x11_trusted == -1) 2466 options->forward_x11_trusted = 0; 2467 if (options->forward_x11_timeout == -1) 2468 options->forward_x11_timeout = 1200; 2469 /* 2470 * stdio forwarding (-W) changes the default for these but we defer 2471 * setting the values so they can be overridden. 2472 */ 2473 if (options->exit_on_forward_failure == -1) 2474 options->exit_on_forward_failure = 2475 options->stdio_forward_host != NULL ? 1 : 0; 2476 if (options->clear_forwardings == -1) 2477 options->clear_forwardings = 2478 options->stdio_forward_host != NULL ? 1 : 0; 2479 if (options->clear_forwardings == 1) 2480 clear_forwardings(options); 2481 2482 if (options->xauth_location == NULL) 2483 options->xauth_location = xstrdup(_PATH_XAUTH); 2484 if (options->fwd_opts.gateway_ports == -1) 2485 options->fwd_opts.gateway_ports = 0; 2486 if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1) 2487 options->fwd_opts.streamlocal_bind_mask = 0177; 2488 if (options->fwd_opts.streamlocal_bind_unlink == -1) 2489 options->fwd_opts.streamlocal_bind_unlink = 0; 2490 if (options->pubkey_authentication == -1) 2491 options->pubkey_authentication = 1; 2492 if (options->gss_authentication == -1) 2493 options->gss_authentication = 0; 2494 if (options->gss_deleg_creds == -1) 2495 options->gss_deleg_creds = 0; 2496 if (options->password_authentication == -1) 2497 options->password_authentication = 1; 2498 if (options->kbd_interactive_authentication == -1) 2499 options->kbd_interactive_authentication = 1; 2500 if (options->hostbased_authentication == -1) 2501 options->hostbased_authentication = 0; 2502 if (options->batch_mode == -1) 2503 options->batch_mode = 0; 2504 if (options->check_host_ip == -1) 2505 options->check_host_ip = 0; 2506 if (options->strict_host_key_checking == -1) 2507 options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK; 2508 if (options->compression == -1) 2509 options->compression = 0; 2510 if (options->tcp_keep_alive == -1) 2511 options->tcp_keep_alive = 1; 2512 if (options->port == -1) 2513 options->port = 0; /* Filled in ssh_connect. */ 2514 if (options->address_family == -1) 2515 options->address_family = AF_UNSPEC; 2516 if (options->connection_attempts == -1) 2517 options->connection_attempts = 1; 2518 if (options->number_of_password_prompts == -1) 2519 options->number_of_password_prompts = 3; 2520 /* options->hostkeyalgorithms, default set in myproposals.h */ 2521 if (options->add_keys_to_agent == -1) { 2522 options->add_keys_to_agent = 0; 2523 options->add_keys_to_agent_lifespan = 0; 2524 } 2525 if (options->num_identity_files == 0) { 2526 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0); 2527 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0); 2528 #ifdef OPENSSL_HAS_ECC 2529 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0); 2530 add_identity_file(options, "~/", 2531 _PATH_SSH_CLIENT_ID_ECDSA_SK, 0); 2532 #endif 2533 add_identity_file(options, "~/", 2534 _PATH_SSH_CLIENT_ID_ED25519, 0); 2535 add_identity_file(options, "~/", 2536 _PATH_SSH_CLIENT_ID_ED25519_SK, 0); 2537 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0); 2538 } 2539 if (options->escape_char == -1) 2540 options->escape_char = '~'; 2541 if (options->num_system_hostfiles == 0) { 2542 options->system_hostfiles[options->num_system_hostfiles++] = 2543 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE); 2544 options->system_hostfiles[options->num_system_hostfiles++] = 2545 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2); 2546 } 2547 if (options->update_hostkeys == -1) { 2548 if (options->verify_host_key_dns <= 0 && 2549 (options->num_user_hostfiles == 0 || 2550 (options->num_user_hostfiles == 1 && strcmp(options-> 2551 user_hostfiles[0], _PATH_SSH_USER_HOSTFILE) == 0))) 2552 options->update_hostkeys = SSH_UPDATE_HOSTKEYS_YES; 2553 else 2554 options->update_hostkeys = SSH_UPDATE_HOSTKEYS_NO; 2555 } 2556 if (options->num_user_hostfiles == 0) { 2557 options->user_hostfiles[options->num_user_hostfiles++] = 2558 xstrdup(_PATH_SSH_USER_HOSTFILE); 2559 options->user_hostfiles[options->num_user_hostfiles++] = 2560 xstrdup(_PATH_SSH_USER_HOSTFILE2); 2561 } 2562 if (options->log_level == SYSLOG_LEVEL_NOT_SET) 2563 options->log_level = SYSLOG_LEVEL_INFO; 2564 if (options->log_facility == SYSLOG_FACILITY_NOT_SET) 2565 options->log_facility = SYSLOG_FACILITY_USER; 2566 if (options->no_host_authentication_for_localhost == - 1) 2567 options->no_host_authentication_for_localhost = 0; 2568 if (options->identities_only == -1) 2569 options->identities_only = 0; 2570 if (options->enable_ssh_keysign == -1) 2571 options->enable_ssh_keysign = 0; 2572 if (options->rekey_limit == -1) 2573 options->rekey_limit = 0; 2574 if (options->rekey_interval == -1) 2575 options->rekey_interval = 0; 2576 #if HAVE_LDNS 2577 if (options->verify_host_key_dns == -1) 2578 /* automatically trust a verified SSHFP record */ 2579 options->verify_host_key_dns = 1; 2580 #else 2581 if (options->verify_host_key_dns == -1) 2582 options->verify_host_key_dns = 0; 2583 #endif 2584 if (options->server_alive_interval == -1) 2585 options->server_alive_interval = 0; 2586 if (options->server_alive_count_max == -1) 2587 options->server_alive_count_max = 3; 2588 if (options->control_master == -1) 2589 options->control_master = 0; 2590 if (options->control_persist == -1) { 2591 options->control_persist = 0; 2592 options->control_persist_timeout = 0; 2593 } 2594 if (options->hash_known_hosts == -1) 2595 options->hash_known_hosts = 0; 2596 if (options->tun_open == -1) 2597 options->tun_open = SSH_TUNMODE_NO; 2598 if (options->tun_local == -1) 2599 options->tun_local = SSH_TUNID_ANY; 2600 if (options->tun_remote == -1) 2601 options->tun_remote = SSH_TUNID_ANY; 2602 if (options->permit_local_command == -1) 2603 options->permit_local_command = 0; 2604 if (options->visual_host_key == -1) 2605 options->visual_host_key = 0; 2606 if (options->ip_qos_interactive == -1) 2607 options->ip_qos_interactive = IPTOS_DSCP_AF21; 2608 if (options->ip_qos_bulk == -1) 2609 options->ip_qos_bulk = IPTOS_DSCP_CS1; 2610 if (options->request_tty == -1) 2611 options->request_tty = REQUEST_TTY_AUTO; 2612 if (options->session_type == -1) 2613 options->session_type = SESSION_TYPE_DEFAULT; 2614 if (options->stdin_null == -1) 2615 options->stdin_null = 0; 2616 if (options->fork_after_authentication == -1) 2617 options->fork_after_authentication = 0; 2618 if (options->proxy_use_fdpass == -1) 2619 options->proxy_use_fdpass = 0; 2620 if (options->canonicalize_max_dots == -1) 2621 options->canonicalize_max_dots = 1; 2622 if (options->canonicalize_fallback_local == -1) 2623 options->canonicalize_fallback_local = 1; 2624 if (options->canonicalize_hostname == -1) 2625 options->canonicalize_hostname = SSH_CANONICALISE_NO; 2626 if (options->fingerprint_hash == -1) 2627 options->fingerprint_hash = SSH_FP_HASH_DEFAULT; 2628 #ifdef ENABLE_SK_INTERNAL 2629 if (options->sk_provider == NULL) 2630 options->sk_provider = xstrdup("internal"); 2631 #else 2632 if (options->sk_provider == NULL) 2633 options->sk_provider = xstrdup("$SSH_SK_PROVIDER"); 2634 #endif 2635 2636 /* Expand KEX name lists */ 2637 all_cipher = cipher_alg_list(',', 0); 2638 all_mac = mac_alg_list(','); 2639 all_kex = kex_alg_list(','); 2640 all_key = sshkey_alg_list(0, 0, 1, ','); 2641 all_sig = sshkey_alg_list(0, 1, 1, ','); 2642 /* remove unsupported algos from default lists */ 2643 def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher); 2644 def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac); 2645 def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex); 2646 def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key); 2647 def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig); 2648 #define ASSEMBLE(what, defaults, all) \ 2649 do { \ 2650 if ((r = kex_assemble_names(&options->what, \ 2651 defaults, all)) != 0) { \ 2652 error_fr(r, "%s", #what); \ 2653 goto fail; \ 2654 } \ 2655 } while (0) 2656 ASSEMBLE(ciphers, def_cipher, all_cipher); 2657 ASSEMBLE(macs, def_mac, all_mac); 2658 ASSEMBLE(kex_algorithms, def_kex, all_kex); 2659 ASSEMBLE(hostbased_accepted_algos, def_key, all_key); 2660 ASSEMBLE(pubkey_accepted_algos, def_key, all_key); 2661 ASSEMBLE(ca_sign_algorithms, def_sig, all_sig); 2662 #undef ASSEMBLE 2663 2664 #define CLEAR_ON_NONE(v) \ 2665 do { \ 2666 if (option_clear_or_none(v)) { \ 2667 free(v); \ 2668 v = NULL; \ 2669 } \ 2670 } while(0) 2671 CLEAR_ON_NONE(options->local_command); 2672 CLEAR_ON_NONE(options->remote_command); 2673 CLEAR_ON_NONE(options->proxy_command); 2674 CLEAR_ON_NONE(options->control_path); 2675 CLEAR_ON_NONE(options->revoked_host_keys); 2676 CLEAR_ON_NONE(options->pkcs11_provider); 2677 CLEAR_ON_NONE(options->sk_provider); 2678 CLEAR_ON_NONE(options->known_hosts_command); 2679 if (options->jump_host != NULL && 2680 strcmp(options->jump_host, "none") == 0 && 2681 options->jump_port == 0 && options->jump_user == NULL) { 2682 free(options->jump_host); 2683 options->jump_host = NULL; 2684 } 2685 /* options->identity_agent distinguishes NULL from 'none' */ 2686 /* options->user will be set in the main program if appropriate */ 2687 /* options->hostname will be set in the main program if appropriate */ 2688 /* options->host_key_alias should not be set by default */ 2689 /* options->preferred_authentications will be set in ssh */ 2690 if (options->version_addendum == NULL) 2691 options->version_addendum = xstrdup(SSH_VERSION_FREEBSD); 2692 2693 /* success */ 2694 ret = 0; 2695 fail: 2696 free(all_cipher); 2697 free(all_mac); 2698 free(all_kex); 2699 free(all_key); 2700 free(all_sig); 2701 free(def_cipher); 2702 free(def_mac); 2703 free(def_kex); 2704 free(def_key); 2705 free(def_sig); 2706 return ret; 2707 } 2708 2709 void 2710 free_options(Options *o) 2711 { 2712 int i; 2713 2714 if (o == NULL) 2715 return; 2716 2717 #define FREE_ARRAY(type, n, a) \ 2718 do { \ 2719 type _i; \ 2720 for (_i = 0; _i < (n); _i++) \ 2721 free((a)[_i]); \ 2722 } while (0) 2723 2724 free(o->forward_agent_sock_path); 2725 free(o->xauth_location); 2726 FREE_ARRAY(u_int, o->num_log_verbose, o->log_verbose); 2727 free(o->log_verbose); 2728 free(o->ciphers); 2729 free(o->macs); 2730 free(o->hostkeyalgorithms); 2731 free(o->kex_algorithms); 2732 free(o->ca_sign_algorithms); 2733 free(o->hostname); 2734 free(o->host_key_alias); 2735 free(o->proxy_command); 2736 free(o->user); 2737 FREE_ARRAY(u_int, o->num_system_hostfiles, o->system_hostfiles); 2738 FREE_ARRAY(u_int, o->num_user_hostfiles, o->user_hostfiles); 2739 free(o->preferred_authentications); 2740 free(o->bind_address); 2741 free(o->bind_interface); 2742 free(o->pkcs11_provider); 2743 free(o->sk_provider); 2744 for (i = 0; i < o->num_identity_files; i++) { 2745 free(o->identity_files[i]); 2746 sshkey_free(o->identity_keys[i]); 2747 } 2748 for (i = 0; i < o->num_certificate_files; i++) { 2749 free(o->certificate_files[i]); 2750 sshkey_free(o->certificates[i]); 2751 } 2752 free(o->identity_agent); 2753 for (i = 0; i < o->num_local_forwards; i++) { 2754 free(o->local_forwards[i].listen_host); 2755 free(o->local_forwards[i].listen_path); 2756 free(o->local_forwards[i].connect_host); 2757 free(o->local_forwards[i].connect_path); 2758 } 2759 free(o->local_forwards); 2760 for (i = 0; i < o->num_remote_forwards; i++) { 2761 free(o->remote_forwards[i].listen_host); 2762 free(o->remote_forwards[i].listen_path); 2763 free(o->remote_forwards[i].connect_host); 2764 free(o->remote_forwards[i].connect_path); 2765 } 2766 free(o->remote_forwards); 2767 free(o->stdio_forward_host); 2768 FREE_ARRAY(int, o->num_send_env, o->send_env); 2769 free(o->send_env); 2770 FREE_ARRAY(int, o->num_setenv, o->setenv); 2771 free(o->setenv); 2772 free(o->control_path); 2773 free(o->local_command); 2774 free(o->remote_command); 2775 FREE_ARRAY(int, o->num_canonical_domains, o->canonical_domains); 2776 for (i = 0; i < o->num_permitted_cnames; i++) { 2777 free(o->permitted_cnames[i].source_list); 2778 free(o->permitted_cnames[i].target_list); 2779 } 2780 free(o->revoked_host_keys); 2781 free(o->hostbased_accepted_algos); 2782 free(o->pubkey_accepted_algos); 2783 free(o->jump_user); 2784 free(o->jump_host); 2785 free(o->jump_extra); 2786 free(o->ignored_unknown); 2787 explicit_bzero(o, sizeof(*o)); 2788 #undef FREE_ARRAY 2789 } 2790 2791 struct fwdarg { 2792 char *arg; 2793 int ispath; 2794 }; 2795 2796 /* 2797 * parse_fwd_field 2798 * parses the next field in a port forwarding specification. 2799 * sets fwd to the parsed field and advances p past the colon 2800 * or sets it to NULL at end of string. 2801 * returns 0 on success, else non-zero. 2802 */ 2803 static int 2804 parse_fwd_field(char **p, struct fwdarg *fwd) 2805 { 2806 char *ep, *cp = *p; 2807 int ispath = 0; 2808 2809 if (*cp == '\0') { 2810 *p = NULL; 2811 return -1; /* end of string */ 2812 } 2813 2814 /* 2815 * A field escaped with square brackets is used literally. 2816 * XXX - allow ']' to be escaped via backslash? 2817 */ 2818 if (*cp == '[') { 2819 /* find matching ']' */ 2820 for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) { 2821 if (*ep == '/') 2822 ispath = 1; 2823 } 2824 /* no matching ']' or not at end of field. */ 2825 if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0')) 2826 return -1; 2827 /* NUL terminate the field and advance p past the colon */ 2828 *ep++ = '\0'; 2829 if (*ep != '\0') 2830 *ep++ = '\0'; 2831 fwd->arg = cp + 1; 2832 fwd->ispath = ispath; 2833 *p = ep; 2834 return 0; 2835 } 2836 2837 for (cp = *p; *cp != '\0'; cp++) { 2838 switch (*cp) { 2839 case '\\': 2840 memmove(cp, cp + 1, strlen(cp + 1) + 1); 2841 if (*cp == '\0') 2842 return -1; 2843 break; 2844 case '/': 2845 ispath = 1; 2846 break; 2847 case ':': 2848 *cp++ = '\0'; 2849 goto done; 2850 } 2851 } 2852 done: 2853 fwd->arg = *p; 2854 fwd->ispath = ispath; 2855 *p = cp; 2856 return 0; 2857 } 2858 2859 /* 2860 * parse_forward 2861 * parses a string containing a port forwarding specification of the form: 2862 * dynamicfwd == 0 2863 * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath 2864 * listenpath:connectpath 2865 * dynamicfwd == 1 2866 * [listenhost:]listenport 2867 * returns number of arguments parsed or zero on error 2868 */ 2869 int 2870 parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) 2871 { 2872 struct fwdarg fwdargs[4]; 2873 char *p, *cp; 2874 int i, err; 2875 2876 memset(fwd, 0, sizeof(*fwd)); 2877 memset(fwdargs, 0, sizeof(fwdargs)); 2878 2879 /* 2880 * We expand environment variables before checking if we think they're 2881 * paths so that if ${VAR} expands to a fully qualified path it is 2882 * treated as a path. 2883 */ 2884 cp = p = dollar_expand(&err, fwdspec); 2885 if (p == NULL || err) 2886 return 0; 2887 2888 /* skip leading spaces */ 2889 while (isspace((u_char)*cp)) 2890 cp++; 2891 2892 for (i = 0; i < 4; ++i) { 2893 if (parse_fwd_field(&cp, &fwdargs[i]) != 0) 2894 break; 2895 } 2896 2897 /* Check for trailing garbage */ 2898 if (cp != NULL && *cp != '\0') { 2899 i = 0; /* failure */ 2900 } 2901 2902 switch (i) { 2903 case 1: 2904 if (fwdargs[0].ispath) { 2905 fwd->listen_path = xstrdup(fwdargs[0].arg); 2906 fwd->listen_port = PORT_STREAMLOCAL; 2907 } else { 2908 fwd->listen_host = NULL; 2909 fwd->listen_port = a2port(fwdargs[0].arg); 2910 } 2911 fwd->connect_host = xstrdup("socks"); 2912 break; 2913 2914 case 2: 2915 if (fwdargs[0].ispath && fwdargs[1].ispath) { 2916 fwd->listen_path = xstrdup(fwdargs[0].arg); 2917 fwd->listen_port = PORT_STREAMLOCAL; 2918 fwd->connect_path = xstrdup(fwdargs[1].arg); 2919 fwd->connect_port = PORT_STREAMLOCAL; 2920 } else if (fwdargs[1].ispath) { 2921 fwd->listen_host = NULL; 2922 fwd->listen_port = a2port(fwdargs[0].arg); 2923 fwd->connect_path = xstrdup(fwdargs[1].arg); 2924 fwd->connect_port = PORT_STREAMLOCAL; 2925 } else { 2926 fwd->listen_host = xstrdup(fwdargs[0].arg); 2927 fwd->listen_port = a2port(fwdargs[1].arg); 2928 fwd->connect_host = xstrdup("socks"); 2929 } 2930 break; 2931 2932 case 3: 2933 if (fwdargs[0].ispath) { 2934 fwd->listen_path = xstrdup(fwdargs[0].arg); 2935 fwd->listen_port = PORT_STREAMLOCAL; 2936 fwd->connect_host = xstrdup(fwdargs[1].arg); 2937 fwd->connect_port = a2port(fwdargs[2].arg); 2938 } else if (fwdargs[2].ispath) { 2939 fwd->listen_host = xstrdup(fwdargs[0].arg); 2940 fwd->listen_port = a2port(fwdargs[1].arg); 2941 fwd->connect_path = xstrdup(fwdargs[2].arg); 2942 fwd->connect_port = PORT_STREAMLOCAL; 2943 } else { 2944 fwd->listen_host = NULL; 2945 fwd->listen_port = a2port(fwdargs[0].arg); 2946 fwd->connect_host = xstrdup(fwdargs[1].arg); 2947 fwd->connect_port = a2port(fwdargs[2].arg); 2948 } 2949 break; 2950 2951 case 4: 2952 fwd->listen_host = xstrdup(fwdargs[0].arg); 2953 fwd->listen_port = a2port(fwdargs[1].arg); 2954 fwd->connect_host = xstrdup(fwdargs[2].arg); 2955 fwd->connect_port = a2port(fwdargs[3].arg); 2956 break; 2957 default: 2958 i = 0; /* failure */ 2959 } 2960 2961 free(p); 2962 2963 if (dynamicfwd) { 2964 if (!(i == 1 || i == 2)) 2965 goto fail_free; 2966 } else { 2967 if (!(i == 3 || i == 4)) { 2968 if (fwd->connect_path == NULL && 2969 fwd->listen_path == NULL) 2970 goto fail_free; 2971 } 2972 if (fwd->connect_port <= 0 && fwd->connect_path == NULL) 2973 goto fail_free; 2974 } 2975 2976 if ((fwd->listen_port < 0 && fwd->listen_path == NULL) || 2977 (!remotefwd && fwd->listen_port == 0)) 2978 goto fail_free; 2979 if (fwd->connect_host != NULL && 2980 strlen(fwd->connect_host) >= NI_MAXHOST) 2981 goto fail_free; 2982 /* 2983 * XXX - if connecting to a remote socket, max sun len may not 2984 * match this host 2985 */ 2986 if (fwd->connect_path != NULL && 2987 strlen(fwd->connect_path) >= PATH_MAX_SUN) 2988 goto fail_free; 2989 if (fwd->listen_host != NULL && 2990 strlen(fwd->listen_host) >= NI_MAXHOST) 2991 goto fail_free; 2992 if (fwd->listen_path != NULL && 2993 strlen(fwd->listen_path) >= PATH_MAX_SUN) 2994 goto fail_free; 2995 2996 return (i); 2997 2998 fail_free: 2999 free(fwd->connect_host); 3000 fwd->connect_host = NULL; 3001 free(fwd->connect_path); 3002 fwd->connect_path = NULL; 3003 free(fwd->listen_host); 3004 fwd->listen_host = NULL; 3005 free(fwd->listen_path); 3006 fwd->listen_path = NULL; 3007 return (0); 3008 } 3009 3010 int 3011 parse_jump(const char *s, Options *o, int active) 3012 { 3013 char *orig, *sdup, *cp; 3014 char *host = NULL, *user = NULL; 3015 int r, ret = -1, port = -1, first; 3016 3017 active &= o->proxy_command == NULL && o->jump_host == NULL; 3018 3019 orig = sdup = xstrdup(s); 3020 3021 /* Remove comment and trailing whitespace */ 3022 if ((cp = strchr(orig, '#')) != NULL) 3023 *cp = '\0'; 3024 rtrim(orig); 3025 3026 first = active; 3027 do { 3028 if (strcasecmp(s, "none") == 0) 3029 break; 3030 if ((cp = strrchr(sdup, ',')) == NULL) 3031 cp = sdup; /* last */ 3032 else 3033 *cp++ = '\0'; 3034 3035 if (first) { 3036 /* First argument and configuration is active */ 3037 r = parse_ssh_uri(cp, &user, &host, &port); 3038 if (r == -1 || (r == 1 && 3039 parse_user_host_port(cp, &user, &host, &port) != 0)) 3040 goto out; 3041 } else { 3042 /* Subsequent argument or inactive configuration */ 3043 r = parse_ssh_uri(cp, NULL, NULL, NULL); 3044 if (r == -1 || (r == 1 && 3045 parse_user_host_port(cp, NULL, NULL, NULL) != 0)) 3046 goto out; 3047 } 3048 first = 0; /* only check syntax for subsequent hosts */ 3049 } while (cp != sdup); 3050 /* success */ 3051 if (active) { 3052 if (strcasecmp(s, "none") == 0) { 3053 o->jump_host = xstrdup("none"); 3054 o->jump_port = 0; 3055 } else { 3056 o->jump_user = user; 3057 o->jump_host = host; 3058 o->jump_port = port; 3059 o->proxy_command = xstrdup("none"); 3060 user = host = NULL; 3061 if ((cp = strrchr(s, ',')) != NULL && cp != s) { 3062 o->jump_extra = xstrdup(s); 3063 o->jump_extra[cp - s] = '\0'; 3064 } 3065 } 3066 } 3067 ret = 0; 3068 out: 3069 free(orig); 3070 free(user); 3071 free(host); 3072 return ret; 3073 } 3074 3075 int 3076 parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp) 3077 { 3078 char *user = NULL, *host = NULL, *path = NULL; 3079 int r, port; 3080 3081 r = parse_uri("ssh", uri, &user, &host, &port, &path); 3082 if (r == 0 && path != NULL) 3083 r = -1; /* path not allowed */ 3084 if (r == 0) { 3085 if (userp != NULL) { 3086 *userp = user; 3087 user = NULL; 3088 } 3089 if (hostp != NULL) { 3090 *hostp = host; 3091 host = NULL; 3092 } 3093 if (portp != NULL) 3094 *portp = port; 3095 } 3096 free(user); 3097 free(host); 3098 free(path); 3099 return r; 3100 } 3101 3102 /* XXX the following is a near-vebatim copy from servconf.c; refactor */ 3103 static const char * 3104 fmt_multistate_int(int val, const struct multistate *m) 3105 { 3106 u_int i; 3107 3108 for (i = 0; m[i].key != NULL; i++) { 3109 if (m[i].value == val) 3110 return m[i].key; 3111 } 3112 return "UNKNOWN"; 3113 } 3114 3115 static const char * 3116 fmt_intarg(OpCodes code, int val) 3117 { 3118 if (val == -1) 3119 return "unset"; 3120 switch (code) { 3121 case oAddressFamily: 3122 return fmt_multistate_int(val, multistate_addressfamily); 3123 case oVerifyHostKeyDNS: 3124 case oUpdateHostkeys: 3125 return fmt_multistate_int(val, multistate_yesnoask); 3126 case oStrictHostKeyChecking: 3127 return fmt_multistate_int(val, multistate_strict_hostkey); 3128 case oControlMaster: 3129 return fmt_multistate_int(val, multistate_controlmaster); 3130 case oTunnel: 3131 return fmt_multistate_int(val, multistate_tunnel); 3132 case oRequestTTY: 3133 return fmt_multistate_int(val, multistate_requesttty); 3134 case oSessionType: 3135 return fmt_multistate_int(val, multistate_sessiontype); 3136 case oCanonicalizeHostname: 3137 return fmt_multistate_int(val, multistate_canonicalizehostname); 3138 case oAddKeysToAgent: 3139 return fmt_multistate_int(val, multistate_yesnoaskconfirm); 3140 case oFingerprintHash: 3141 return ssh_digest_alg_name(val); 3142 default: 3143 switch (val) { 3144 case 0: 3145 return "no"; 3146 case 1: 3147 return "yes"; 3148 default: 3149 return "UNKNOWN"; 3150 } 3151 } 3152 } 3153 3154 static const char * 3155 lookup_opcode_name(OpCodes code) 3156 { 3157 u_int i; 3158 3159 for (i = 0; keywords[i].name != NULL; i++) 3160 if (keywords[i].opcode == code) 3161 return(keywords[i].name); 3162 return "UNKNOWN"; 3163 } 3164 3165 static void 3166 dump_cfg_int(OpCodes code, int val) 3167 { 3168 printf("%s %d\n", lookup_opcode_name(code), val); 3169 } 3170 3171 static void 3172 dump_cfg_fmtint(OpCodes code, int val) 3173 { 3174 printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val)); 3175 } 3176 3177 static void 3178 dump_cfg_string(OpCodes code, const char *val) 3179 { 3180 if (val == NULL) 3181 return; 3182 printf("%s %s\n", lookup_opcode_name(code), val); 3183 } 3184 3185 static void 3186 dump_cfg_strarray(OpCodes code, u_int count, char **vals) 3187 { 3188 u_int i; 3189 3190 for (i = 0; i < count; i++) 3191 printf("%s %s\n", lookup_opcode_name(code), vals[i]); 3192 } 3193 3194 static void 3195 dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals) 3196 { 3197 u_int i; 3198 3199 printf("%s", lookup_opcode_name(code)); 3200 if (count == 0) 3201 printf(" none"); 3202 for (i = 0; i < count; i++) 3203 printf(" %s", vals[i]); 3204 printf("\n"); 3205 } 3206 3207 static void 3208 dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds) 3209 { 3210 const struct Forward *fwd; 3211 u_int i; 3212 3213 /* oDynamicForward */ 3214 for (i = 0; i < count; i++) { 3215 fwd = &fwds[i]; 3216 if (code == oDynamicForward && fwd->connect_host != NULL && 3217 strcmp(fwd->connect_host, "socks") != 0) 3218 continue; 3219 if (code == oLocalForward && fwd->connect_host != NULL && 3220 strcmp(fwd->connect_host, "socks") == 0) 3221 continue; 3222 printf("%s", lookup_opcode_name(code)); 3223 if (fwd->listen_port == PORT_STREAMLOCAL) 3224 printf(" %s", fwd->listen_path); 3225 else if (fwd->listen_host == NULL) 3226 printf(" %d", fwd->listen_port); 3227 else { 3228 printf(" [%s]:%d", 3229 fwd->listen_host, fwd->listen_port); 3230 } 3231 if (code != oDynamicForward) { 3232 if (fwd->connect_port == PORT_STREAMLOCAL) 3233 printf(" %s", fwd->connect_path); 3234 else if (fwd->connect_host == NULL) 3235 printf(" %d", fwd->connect_port); 3236 else { 3237 printf(" [%s]:%d", 3238 fwd->connect_host, fwd->connect_port); 3239 } 3240 } 3241 printf("\n"); 3242 } 3243 } 3244 3245 void 3246 dump_client_config(Options *o, const char *host) 3247 { 3248 int i, r; 3249 char buf[8], *all_key; 3250 3251 /* 3252 * Expand HostKeyAlgorithms name lists. This isn't handled in 3253 * fill_default_options() like the other algorithm lists because 3254 * the host key algorithms are by default dynamically chosen based 3255 * on the host's keys found in known_hosts. 3256 */ 3257 all_key = sshkey_alg_list(0, 0, 1, ','); 3258 if ((r = kex_assemble_names(&o->hostkeyalgorithms, kex_default_pk_alg(), 3259 all_key)) != 0) 3260 fatal_fr(r, "expand HostKeyAlgorithms"); 3261 free(all_key); 3262 3263 /* Most interesting options first: user, host, port */ 3264 dump_cfg_string(oUser, o->user); 3265 dump_cfg_string(oHostname, host); 3266 dump_cfg_int(oPort, o->port); 3267 3268 /* Flag options */ 3269 dump_cfg_fmtint(oAddressFamily, o->address_family); 3270 dump_cfg_fmtint(oBatchMode, o->batch_mode); 3271 dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local); 3272 dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname); 3273 dump_cfg_fmtint(oCheckHostIP, o->check_host_ip); 3274 dump_cfg_fmtint(oCompression, o->compression); 3275 dump_cfg_fmtint(oControlMaster, o->control_master); 3276 dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign); 3277 dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings); 3278 dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure); 3279 dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash); 3280 dump_cfg_fmtint(oForwardX11, o->forward_x11); 3281 dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted); 3282 dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports); 3283 #ifdef GSSAPI 3284 dump_cfg_fmtint(oGssAuthentication, o->gss_authentication); 3285 dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds); 3286 #endif /* GSSAPI */ 3287 dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts); 3288 dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication); 3289 dump_cfg_fmtint(oIdentitiesOnly, o->identities_only); 3290 dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication); 3291 dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost); 3292 dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication); 3293 dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command); 3294 dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass); 3295 dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication); 3296 dump_cfg_fmtint(oRequestTTY, o->request_tty); 3297 dump_cfg_fmtint(oSessionType, o->session_type); 3298 dump_cfg_fmtint(oStdinNull, o->stdin_null); 3299 dump_cfg_fmtint(oForkAfterAuthentication, o->fork_after_authentication); 3300 dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink); 3301 dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking); 3302 dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive); 3303 dump_cfg_fmtint(oTunnel, o->tun_open); 3304 dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns); 3305 dump_cfg_fmtint(oVisualHostKey, o->visual_host_key); 3306 dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys); 3307 3308 /* Integer options */ 3309 dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots); 3310 dump_cfg_int(oConnectionAttempts, o->connection_attempts); 3311 dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout); 3312 dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts); 3313 dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max); 3314 dump_cfg_int(oServerAliveInterval, o->server_alive_interval); 3315 3316 /* String options */ 3317 dump_cfg_string(oBindAddress, o->bind_address); 3318 dump_cfg_string(oBindInterface, o->bind_interface); 3319 dump_cfg_string(oCiphers, o->ciphers); 3320 dump_cfg_string(oControlPath, o->control_path); 3321 dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms); 3322 dump_cfg_string(oHostKeyAlias, o->host_key_alias); 3323 dump_cfg_string(oHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos); 3324 dump_cfg_string(oIdentityAgent, o->identity_agent); 3325 dump_cfg_string(oIgnoreUnknown, o->ignored_unknown); 3326 dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices); 3327 dump_cfg_string(oKexAlgorithms, o->kex_algorithms); 3328 dump_cfg_string(oCASignatureAlgorithms, o->ca_sign_algorithms); 3329 dump_cfg_string(oLocalCommand, o->local_command); 3330 dump_cfg_string(oRemoteCommand, o->remote_command); 3331 dump_cfg_string(oLogLevel, log_level_name(o->log_level)); 3332 dump_cfg_string(oMacs, o->macs); 3333 #ifdef ENABLE_PKCS11 3334 dump_cfg_string(oPKCS11Provider, o->pkcs11_provider); 3335 #endif 3336 dump_cfg_string(oSecurityKeyProvider, o->sk_provider); 3337 dump_cfg_string(oPreferredAuthentications, o->preferred_authentications); 3338 dump_cfg_string(oPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos); 3339 dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys); 3340 dump_cfg_string(oXAuthLocation, o->xauth_location); 3341 dump_cfg_string(oKnownHostsCommand, o->known_hosts_command); 3342 3343 /* Forwards */ 3344 dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards); 3345 dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards); 3346 dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards); 3347 3348 /* String array options */ 3349 dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files); 3350 dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains); 3351 dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files); 3352 dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles); 3353 dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles); 3354 dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env); 3355 dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv); 3356 dump_cfg_strarray_oneline(oLogVerbose, 3357 o->num_log_verbose, o->log_verbose); 3358 3359 /* Special cases */ 3360 3361 /* PermitRemoteOpen */ 3362 if (o->num_permitted_remote_opens == 0) 3363 printf("%s any\n", lookup_opcode_name(oPermitRemoteOpen)); 3364 else 3365 dump_cfg_strarray_oneline(oPermitRemoteOpen, 3366 o->num_permitted_remote_opens, o->permitted_remote_opens); 3367 3368 /* AddKeysToAgent */ 3369 if (o->add_keys_to_agent_lifespan <= 0) 3370 dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent); 3371 else { 3372 printf("addkeystoagent%s %d\n", 3373 o->add_keys_to_agent == 3 ? " confirm" : "", 3374 o->add_keys_to_agent_lifespan); 3375 } 3376 3377 /* oForwardAgent */ 3378 if (o->forward_agent_sock_path == NULL) 3379 dump_cfg_fmtint(oForwardAgent, o->forward_agent); 3380 else 3381 dump_cfg_string(oForwardAgent, o->forward_agent_sock_path); 3382 3383 /* oConnectTimeout */ 3384 if (o->connection_timeout == -1) 3385 printf("connecttimeout none\n"); 3386 else 3387 dump_cfg_int(oConnectTimeout, o->connection_timeout); 3388 3389 /* oTunnelDevice */ 3390 printf("tunneldevice"); 3391 if (o->tun_local == SSH_TUNID_ANY) 3392 printf(" any"); 3393 else 3394 printf(" %d", o->tun_local); 3395 if (o->tun_remote == SSH_TUNID_ANY) 3396 printf(":any"); 3397 else 3398 printf(":%d", o->tun_remote); 3399 printf("\n"); 3400 3401 /* oCanonicalizePermittedCNAMEs */ 3402 if ( o->num_permitted_cnames > 0) { 3403 printf("canonicalizePermittedcnames"); 3404 for (i = 0; i < o->num_permitted_cnames; i++) { 3405 printf(" %s:%s", o->permitted_cnames[i].source_list, 3406 o->permitted_cnames[i].target_list); 3407 } 3408 printf("\n"); 3409 } 3410 3411 /* oControlPersist */ 3412 if (o->control_persist == 0 || o->control_persist_timeout == 0) 3413 dump_cfg_fmtint(oControlPersist, o->control_persist); 3414 else 3415 dump_cfg_int(oControlPersist, o->control_persist_timeout); 3416 3417 /* oEscapeChar */ 3418 if (o->escape_char == SSH_ESCAPECHAR_NONE) 3419 printf("escapechar none\n"); 3420 else { 3421 vis(buf, o->escape_char, VIS_WHITE, 0); 3422 printf("escapechar %s\n", buf); 3423 } 3424 3425 /* oIPQoS */ 3426 printf("ipqos %s ", iptos2str(o->ip_qos_interactive)); 3427 printf("%s\n", iptos2str(o->ip_qos_bulk)); 3428 3429 /* oRekeyLimit */ 3430 printf("rekeylimit %llu %d\n", 3431 (unsigned long long)o->rekey_limit, o->rekey_interval); 3432 3433 /* oStreamLocalBindMask */ 3434 printf("streamlocalbindmask 0%o\n", 3435 o->fwd_opts.streamlocal_bind_mask); 3436 3437 /* oLogFacility */ 3438 printf("syslogfacility %s\n", log_facility_name(o->log_facility)); 3439 3440 /* oProxyCommand / oProxyJump */ 3441 if (o->jump_host == NULL) 3442 dump_cfg_string(oProxyCommand, o->proxy_command); 3443 else { 3444 /* Check for numeric addresses */ 3445 i = strchr(o->jump_host, ':') != NULL || 3446 strspn(o->jump_host, "1234567890.") == strlen(o->jump_host); 3447 snprintf(buf, sizeof(buf), "%d", o->jump_port); 3448 printf("proxyjump %s%s%s%s%s%s%s%s%s\n", 3449 /* optional additional jump spec */ 3450 o->jump_extra == NULL ? "" : o->jump_extra, 3451 o->jump_extra == NULL ? "" : ",", 3452 /* optional user */ 3453 o->jump_user == NULL ? "" : o->jump_user, 3454 o->jump_user == NULL ? "" : "@", 3455 /* opening [ if hostname is numeric */ 3456 i ? "[" : "", 3457 /* mandatory hostname */ 3458 o->jump_host, 3459 /* closing ] if hostname is numeric */ 3460 i ? "]" : "", 3461 /* optional port number */ 3462 o->jump_port <= 0 ? "" : ":", 3463 o->jump_port <= 0 ? "" : buf); 3464 } 3465 } 3466