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