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