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