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