1 /* $OpenBSD: readconf.c,v 1.280 2017/10/21 23:06:24 millert 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 /* 672 * Returns the number of the token pointed to by cp or oBadOption. 673 */ 674 static OpCodes 675 parse_token(const char *cp, const char *filename, int linenum, 676 const char *ignored_unknown) 677 { 678 int i; 679 680 for (i = 0; keywords[i].name; i++) 681 if (strcmp(cp, keywords[i].name) == 0) 682 return keywords[i].opcode; 683 if (ignored_unknown != NULL && 684 match_pattern_list(cp, ignored_unknown, 1) == 1) 685 return oIgnoredUnknownOption; 686 error("%s: line %d: Bad configuration option: %s", 687 filename, linenum, cp); 688 return oBadOption; 689 } 690 691 /* Multistate option parsing */ 692 struct multistate { 693 char *key; 694 int value; 695 }; 696 static const struct multistate multistate_flag[] = { 697 { "true", 1 }, 698 { "false", 0 }, 699 { "yes", 1 }, 700 { "no", 0 }, 701 { NULL, -1 } 702 }; 703 static const struct multistate multistate_yesnoask[] = { 704 { "true", 1 }, 705 { "false", 0 }, 706 { "yes", 1 }, 707 { "no", 0 }, 708 { "ask", 2 }, 709 { NULL, -1 } 710 }; 711 static const struct multistate multistate_strict_hostkey[] = { 712 { "true", SSH_STRICT_HOSTKEY_YES }, 713 { "false", SSH_STRICT_HOSTKEY_OFF }, 714 { "yes", SSH_STRICT_HOSTKEY_YES }, 715 { "no", SSH_STRICT_HOSTKEY_OFF }, 716 { "ask", SSH_STRICT_HOSTKEY_ASK }, 717 { "off", SSH_STRICT_HOSTKEY_OFF }, 718 { "accept-new", SSH_STRICT_HOSTKEY_NEW }, 719 { NULL, -1 } 720 }; 721 static const struct multistate multistate_yesnoaskconfirm[] = { 722 { "true", 1 }, 723 { "false", 0 }, 724 { "yes", 1 }, 725 { "no", 0 }, 726 { "ask", 2 }, 727 { "confirm", 3 }, 728 { NULL, -1 } 729 }; 730 static const struct multistate multistate_addressfamily[] = { 731 { "inet", AF_INET }, 732 { "inet6", AF_INET6 }, 733 { "any", AF_UNSPEC }, 734 { NULL, -1 } 735 }; 736 static const struct multistate multistate_controlmaster[] = { 737 { "true", SSHCTL_MASTER_YES }, 738 { "yes", SSHCTL_MASTER_YES }, 739 { "false", SSHCTL_MASTER_NO }, 740 { "no", SSHCTL_MASTER_NO }, 741 { "auto", SSHCTL_MASTER_AUTO }, 742 { "ask", SSHCTL_MASTER_ASK }, 743 { "autoask", SSHCTL_MASTER_AUTO_ASK }, 744 { NULL, -1 } 745 }; 746 static const struct multistate multistate_tunnel[] = { 747 { "ethernet", SSH_TUNMODE_ETHERNET }, 748 { "point-to-point", SSH_TUNMODE_POINTOPOINT }, 749 { "true", SSH_TUNMODE_DEFAULT }, 750 { "yes", SSH_TUNMODE_DEFAULT }, 751 { "false", SSH_TUNMODE_NO }, 752 { "no", SSH_TUNMODE_NO }, 753 { NULL, -1 } 754 }; 755 static const struct multistate multistate_requesttty[] = { 756 { "true", REQUEST_TTY_YES }, 757 { "yes", REQUEST_TTY_YES }, 758 { "false", REQUEST_TTY_NO }, 759 { "no", REQUEST_TTY_NO }, 760 { "force", REQUEST_TTY_FORCE }, 761 { "auto", REQUEST_TTY_AUTO }, 762 { NULL, -1 } 763 }; 764 static const struct multistate multistate_canonicalizehostname[] = { 765 { "true", SSH_CANONICALISE_YES }, 766 { "false", SSH_CANONICALISE_NO }, 767 { "yes", SSH_CANONICALISE_YES }, 768 { "no", SSH_CANONICALISE_NO }, 769 { "always", SSH_CANONICALISE_ALWAYS }, 770 { NULL, -1 } 771 }; 772 773 /* 774 * Processes a single option line as used in the configuration files. This 775 * only sets those values that have not already been set. 776 */ 777 int 778 process_config_line(Options *options, struct passwd *pw, const char *host, 779 const char *original_host, char *line, const char *filename, 780 int linenum, int *activep, int flags) 781 { 782 return process_config_line_depth(options, pw, host, original_host, 783 line, filename, linenum, activep, flags, 0); 784 } 785 786 #define WHITESPACE " \t\r\n" 787 static int 788 process_config_line_depth(Options *options, struct passwd *pw, const char *host, 789 const char *original_host, char *line, const char *filename, 790 int linenum, int *activep, int flags, int depth) 791 { 792 char *s, **charptr, *endofnumber, *keyword, *arg, *arg2; 793 char **cpptr, fwdarg[256]; 794 u_int i, *uintptr, max_entries = 0; 795 int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0; 796 int remotefwd, dynamicfwd; 797 LogLevel *log_level_ptr; 798 SyslogFacility *log_facility_ptr; 799 long long val64; 800 size_t len; 801 struct Forward fwd; 802 const struct multistate *multistate_ptr; 803 struct allowed_cname *cname; 804 glob_t gl; 805 806 if (activep == NULL) { /* We are processing a command line directive */ 807 cmdline = 1; 808 activep = &cmdline; 809 } 810 811 /* Strip trailing whitespace. Allow \f (form feed) at EOL only */ 812 if ((len = strlen(line)) == 0) 813 return 0; 814 for (len--; len > 0; len--) { 815 if (strchr(WHITESPACE "\f", line[len]) == NULL) 816 break; 817 line[len] = '\0'; 818 } 819 820 s = line; 821 /* Get the keyword. (Each line is supposed to begin with a keyword). */ 822 if ((keyword = strdelim(&s)) == NULL) 823 return 0; 824 /* Ignore leading whitespace. */ 825 if (*keyword == '\0') 826 keyword = strdelim(&s); 827 if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#') 828 return 0; 829 /* Match lowercase keyword */ 830 lowercase(keyword); 831 832 opcode = parse_token(keyword, filename, linenum, 833 options->ignored_unknown); 834 835 switch (opcode) { 836 case oBadOption: 837 /* don't panic, but count bad options */ 838 return -1; 839 case oIgnore: 840 return 0; 841 case oIgnoredUnknownOption: 842 debug("%s line %d: Ignored unknown option \"%s\"", 843 filename, linenum, keyword); 844 return 0; 845 case oConnectTimeout: 846 intptr = &options->connection_timeout; 847 parse_time: 848 arg = strdelim(&s); 849 if (!arg || *arg == '\0') 850 fatal("%s line %d: missing time value.", 851 filename, linenum); 852 if (strcmp(arg, "none") == 0) 853 value = -1; 854 else if ((value = convtime(arg)) == -1) 855 fatal("%s line %d: invalid time value.", 856 filename, linenum); 857 if (*activep && *intptr == -1) 858 *intptr = value; 859 break; 860 861 case oForwardAgent: 862 intptr = &options->forward_agent; 863 parse_flag: 864 multistate_ptr = multistate_flag; 865 parse_multistate: 866 arg = strdelim(&s); 867 if (!arg || *arg == '\0') 868 fatal("%s line %d: missing argument.", 869 filename, linenum); 870 value = -1; 871 for (i = 0; multistate_ptr[i].key != NULL; i++) { 872 if (strcasecmp(arg, multistate_ptr[i].key) == 0) { 873 value = multistate_ptr[i].value; 874 break; 875 } 876 } 877 if (value == -1) 878 fatal("%s line %d: unsupported option \"%s\".", 879 filename, linenum, arg); 880 if (*activep && *intptr == -1) 881 *intptr = value; 882 break; 883 884 case oForwardX11: 885 intptr = &options->forward_x11; 886 goto parse_flag; 887 888 case oForwardX11Trusted: 889 intptr = &options->forward_x11_trusted; 890 goto parse_flag; 891 892 case oForwardX11Timeout: 893 intptr = &options->forward_x11_timeout; 894 goto parse_time; 895 896 case oGatewayPorts: 897 intptr = &options->fwd_opts.gateway_ports; 898 goto parse_flag; 899 900 case oExitOnForwardFailure: 901 intptr = &options->exit_on_forward_failure; 902 goto parse_flag; 903 904 case oUsePrivilegedPort: 905 intptr = &options->use_privileged_port; 906 goto parse_flag; 907 908 case oPasswordAuthentication: 909 intptr = &options->password_authentication; 910 goto parse_flag; 911 912 case oKbdInteractiveAuthentication: 913 intptr = &options->kbd_interactive_authentication; 914 goto parse_flag; 915 916 case oKbdInteractiveDevices: 917 charptr = &options->kbd_interactive_devices; 918 goto parse_string; 919 920 case oPubkeyAuthentication: 921 intptr = &options->pubkey_authentication; 922 goto parse_flag; 923 924 case oHostbasedAuthentication: 925 intptr = &options->hostbased_authentication; 926 goto parse_flag; 927 928 case oChallengeResponseAuthentication: 929 intptr = &options->challenge_response_authentication; 930 goto parse_flag; 931 932 case oGssAuthentication: 933 intptr = &options->gss_authentication; 934 goto parse_flag; 935 936 case oGssDelegateCreds: 937 intptr = &options->gss_deleg_creds; 938 goto parse_flag; 939 940 case oBatchMode: 941 intptr = &options->batch_mode; 942 goto parse_flag; 943 944 case oCheckHostIP: 945 intptr = &options->check_host_ip; 946 goto parse_flag; 947 948 case oVerifyHostKeyDNS: 949 intptr = &options->verify_host_key_dns; 950 multistate_ptr = multistate_yesnoask; 951 goto parse_multistate; 952 953 case oStrictHostKeyChecking: 954 intptr = &options->strict_host_key_checking; 955 multistate_ptr = multistate_strict_hostkey; 956 goto parse_multistate; 957 958 case oCompression: 959 intptr = &options->compression; 960 goto parse_flag; 961 962 case oTCPKeepAlive: 963 intptr = &options->tcp_keep_alive; 964 goto parse_flag; 965 966 case oNoHostAuthenticationForLocalhost: 967 intptr = &options->no_host_authentication_for_localhost; 968 goto parse_flag; 969 970 case oNumberOfPasswordPrompts: 971 intptr = &options->number_of_password_prompts; 972 goto parse_int; 973 974 case oRekeyLimit: 975 arg = strdelim(&s); 976 if (!arg || *arg == '\0') 977 fatal("%.200s line %d: Missing argument.", filename, 978 linenum); 979 if (strcmp(arg, "default") == 0) { 980 val64 = 0; 981 } else { 982 if (scan_scaled(arg, &val64) == -1) 983 fatal("%.200s line %d: Bad number '%s': %s", 984 filename, linenum, arg, strerror(errno)); 985 if (val64 != 0 && val64 < 16) 986 fatal("%.200s line %d: RekeyLimit too small", 987 filename, linenum); 988 } 989 if (*activep && options->rekey_limit == -1) 990 options->rekey_limit = val64; 991 if (s != NULL) { /* optional rekey interval present */ 992 if (strcmp(s, "none") == 0) { 993 (void)strdelim(&s); /* discard */ 994 break; 995 } 996 intptr = &options->rekey_interval; 997 goto parse_time; 998 } 999 break; 1000 1001 case oIdentityFile: 1002 arg = strdelim(&s); 1003 if (!arg || *arg == '\0') 1004 fatal("%.200s line %d: Missing argument.", filename, linenum); 1005 if (*activep) { 1006 intptr = &options->num_identity_files; 1007 if (*intptr >= SSH_MAX_IDENTITY_FILES) 1008 fatal("%.200s line %d: Too many identity files specified (max %d).", 1009 filename, linenum, SSH_MAX_IDENTITY_FILES); 1010 add_identity_file(options, NULL, 1011 arg, flags & SSHCONF_USERCONF); 1012 } 1013 break; 1014 1015 case oCertificateFile: 1016 arg = strdelim(&s); 1017 if (!arg || *arg == '\0') 1018 fatal("%.200s line %d: Missing argument.", 1019 filename, linenum); 1020 if (*activep) { 1021 intptr = &options->num_certificate_files; 1022 if (*intptr >= SSH_MAX_CERTIFICATE_FILES) { 1023 fatal("%.200s line %d: Too many certificate " 1024 "files specified (max %d).", 1025 filename, linenum, 1026 SSH_MAX_CERTIFICATE_FILES); 1027 } 1028 add_certificate_file(options, arg, 1029 flags & SSHCONF_USERCONF); 1030 } 1031 break; 1032 1033 case oXAuthLocation: 1034 charptr=&options->xauth_location; 1035 goto parse_string; 1036 1037 case oUser: 1038 charptr = &options->user; 1039 parse_string: 1040 arg = strdelim(&s); 1041 if (!arg || *arg == '\0') 1042 fatal("%.200s line %d: Missing argument.", 1043 filename, linenum); 1044 if (*activep && *charptr == NULL) 1045 *charptr = xstrdup(arg); 1046 break; 1047 1048 case oGlobalKnownHostsFile: 1049 cpptr = (char **)&options->system_hostfiles; 1050 uintptr = &options->num_system_hostfiles; 1051 max_entries = SSH_MAX_HOSTS_FILES; 1052 parse_char_array: 1053 if (*activep && *uintptr == 0) { 1054 while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1055 if ((*uintptr) >= max_entries) 1056 fatal("%s line %d: " 1057 "too many authorized keys files.", 1058 filename, linenum); 1059 cpptr[(*uintptr)++] = xstrdup(arg); 1060 } 1061 } 1062 return 0; 1063 1064 case oUserKnownHostsFile: 1065 cpptr = (char **)&options->user_hostfiles; 1066 uintptr = &options->num_user_hostfiles; 1067 max_entries = SSH_MAX_HOSTS_FILES; 1068 goto parse_char_array; 1069 1070 case oHostName: 1071 charptr = &options->hostname; 1072 goto parse_string; 1073 1074 case oHostKeyAlias: 1075 charptr = &options->host_key_alias; 1076 goto parse_string; 1077 1078 case oPreferredAuthentications: 1079 charptr = &options->preferred_authentications; 1080 goto parse_string; 1081 1082 case oBindAddress: 1083 charptr = &options->bind_address; 1084 goto parse_string; 1085 1086 case oPKCS11Provider: 1087 charptr = &options->pkcs11_provider; 1088 goto parse_string; 1089 1090 case oProxyCommand: 1091 charptr = &options->proxy_command; 1092 /* Ignore ProxyCommand if ProxyJump already specified */ 1093 if (options->jump_host != NULL) 1094 charptr = &options->jump_host; /* Skip below */ 1095 parse_command: 1096 if (s == NULL) 1097 fatal("%.200s line %d: Missing argument.", filename, linenum); 1098 len = strspn(s, WHITESPACE "="); 1099 if (*activep && *charptr == NULL) 1100 *charptr = xstrdup(s + len); 1101 return 0; 1102 1103 case oProxyJump: 1104 if (s == NULL) { 1105 fatal("%.200s line %d: Missing argument.", 1106 filename, linenum); 1107 } 1108 len = strspn(s, WHITESPACE "="); 1109 if (parse_jump(s + len, options, *activep) == -1) { 1110 fatal("%.200s line %d: Invalid ProxyJump \"%s\"", 1111 filename, linenum, s + len); 1112 } 1113 return 0; 1114 1115 case oPort: 1116 intptr = &options->port; 1117 parse_int: 1118 arg = strdelim(&s); 1119 if (!arg || *arg == '\0') 1120 fatal("%.200s line %d: Missing argument.", filename, linenum); 1121 if (arg[0] < '0' || arg[0] > '9') 1122 fatal("%.200s line %d: Bad number.", filename, linenum); 1123 1124 /* Octal, decimal, or hex format? */ 1125 value = strtol(arg, &endofnumber, 0); 1126 if (arg == endofnumber) 1127 fatal("%.200s line %d: Bad number.", filename, linenum); 1128 if (*activep && *intptr == -1) 1129 *intptr = value; 1130 break; 1131 1132 case oConnectionAttempts: 1133 intptr = &options->connection_attempts; 1134 goto parse_int; 1135 1136 case oCiphers: 1137 arg = strdelim(&s); 1138 if (!arg || *arg == '\0') 1139 fatal("%.200s line %d: Missing argument.", filename, linenum); 1140 if (*arg != '-' && !ciphers_valid(*arg == '+' ? arg + 1 : arg)) 1141 fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.", 1142 filename, linenum, arg ? arg : "<NONE>"); 1143 if (*activep && options->ciphers == NULL) 1144 options->ciphers = xstrdup(arg); 1145 break; 1146 1147 case oMacs: 1148 arg = strdelim(&s); 1149 if (!arg || *arg == '\0') 1150 fatal("%.200s line %d: Missing argument.", filename, linenum); 1151 if (*arg != '-' && !mac_valid(*arg == '+' ? arg + 1 : arg)) 1152 fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.", 1153 filename, linenum, arg ? arg : "<NONE>"); 1154 if (*activep && options->macs == NULL) 1155 options->macs = xstrdup(arg); 1156 break; 1157 1158 case oKexAlgorithms: 1159 arg = strdelim(&s); 1160 if (!arg || *arg == '\0') 1161 fatal("%.200s line %d: Missing argument.", 1162 filename, linenum); 1163 if (*arg != '-' && 1164 !kex_names_valid(*arg == '+' ? arg + 1 : arg)) 1165 fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.", 1166 filename, linenum, arg ? arg : "<NONE>"); 1167 if (*activep && options->kex_algorithms == NULL) 1168 options->kex_algorithms = xstrdup(arg); 1169 break; 1170 1171 case oHostKeyAlgorithms: 1172 charptr = &options->hostkeyalgorithms; 1173 parse_keytypes: 1174 arg = strdelim(&s); 1175 if (!arg || *arg == '\0') 1176 fatal("%.200s line %d: Missing argument.", 1177 filename, linenum); 1178 if (*arg != '-' && 1179 !sshkey_names_valid2(*arg == '+' ? arg + 1 : arg, 1)) 1180 fatal("%s line %d: Bad key types '%s'.", 1181 filename, linenum, arg ? arg : "<NONE>"); 1182 if (*activep && *charptr == NULL) 1183 *charptr = xstrdup(arg); 1184 break; 1185 1186 case oLogLevel: 1187 log_level_ptr = &options->log_level; 1188 arg = strdelim(&s); 1189 value = log_level_number(arg); 1190 if (value == SYSLOG_LEVEL_NOT_SET) 1191 fatal("%.200s line %d: unsupported log level '%s'", 1192 filename, linenum, arg ? arg : "<NONE>"); 1193 if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET) 1194 *log_level_ptr = (LogLevel) value; 1195 break; 1196 1197 case oLogFacility: 1198 log_facility_ptr = &options->log_facility; 1199 arg = strdelim(&s); 1200 value = log_facility_number(arg); 1201 if (value == SYSLOG_FACILITY_NOT_SET) 1202 fatal("%.200s line %d: unsupported log facility '%s'", 1203 filename, linenum, arg ? arg : "<NONE>"); 1204 if (*log_facility_ptr == -1) 1205 *log_facility_ptr = (SyslogFacility) value; 1206 break; 1207 1208 case oLocalForward: 1209 case oRemoteForward: 1210 case oDynamicForward: 1211 arg = strdelim(&s); 1212 if (arg == NULL || *arg == '\0') 1213 fatal("%.200s line %d: Missing port argument.", 1214 filename, linenum); 1215 1216 remotefwd = (opcode == oRemoteForward); 1217 dynamicfwd = (opcode == oDynamicForward); 1218 1219 if (!dynamicfwd) { 1220 arg2 = strdelim(&s); 1221 if (arg2 == NULL || *arg2 == '\0') { 1222 if (remotefwd) 1223 dynamicfwd = 1; 1224 else 1225 fatal("%.200s line %d: Missing target " 1226 "argument.", filename, linenum); 1227 } else { 1228 /* construct a string for parse_forward */ 1229 snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, 1230 arg2); 1231 } 1232 } 1233 if (dynamicfwd) 1234 strlcpy(fwdarg, arg, sizeof(fwdarg)); 1235 1236 if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0) 1237 fatal("%.200s line %d: Bad forwarding specification.", 1238 filename, linenum); 1239 1240 if (*activep) { 1241 if (remotefwd) { 1242 add_remote_forward(options, &fwd); 1243 } else { 1244 add_local_forward(options, &fwd); 1245 } 1246 } 1247 break; 1248 1249 case oClearAllForwardings: 1250 intptr = &options->clear_forwardings; 1251 goto parse_flag; 1252 1253 case oHost: 1254 if (cmdline) 1255 fatal("Host directive not supported as a command-line " 1256 "option"); 1257 *activep = 0; 1258 arg2 = NULL; 1259 while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1260 if ((flags & SSHCONF_NEVERMATCH) != 0) 1261 break; 1262 negated = *arg == '!'; 1263 if (negated) 1264 arg++; 1265 if (match_pattern(host, arg)) { 1266 if (negated) { 1267 debug("%.200s line %d: Skipping Host " 1268 "block because of negated match " 1269 "for %.100s", filename, linenum, 1270 arg); 1271 *activep = 0; 1272 break; 1273 } 1274 if (!*activep) 1275 arg2 = arg; /* logged below */ 1276 *activep = 1; 1277 } 1278 } 1279 if (*activep) 1280 debug("%.200s line %d: Applying options for %.100s", 1281 filename, linenum, arg2); 1282 /* Avoid garbage check below, as strdelim is done. */ 1283 return 0; 1284 1285 case oMatch: 1286 if (cmdline) 1287 fatal("Host directive not supported as a command-line " 1288 "option"); 1289 value = match_cfg_line(options, &s, pw, host, original_host, 1290 flags & SSHCONF_POSTCANON, filename, linenum); 1291 if (value < 0) 1292 fatal("%.200s line %d: Bad Match condition", filename, 1293 linenum); 1294 *activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value; 1295 break; 1296 1297 case oEscapeChar: 1298 intptr = &options->escape_char; 1299 arg = strdelim(&s); 1300 if (!arg || *arg == '\0') 1301 fatal("%.200s line %d: Missing argument.", filename, linenum); 1302 if (strcmp(arg, "none") == 0) 1303 value = SSH_ESCAPECHAR_NONE; 1304 else if (arg[1] == '\0') 1305 value = (u_char) arg[0]; 1306 else if (arg[0] == '^' && arg[2] == 0 && 1307 (u_char) arg[1] >= 64 && (u_char) arg[1] < 128) 1308 value = (u_char) arg[1] & 31; 1309 else { 1310 fatal("%.200s line %d: Bad escape character.", 1311 filename, linenum); 1312 /* NOTREACHED */ 1313 value = 0; /* Avoid compiler warning. */ 1314 } 1315 if (*activep && *intptr == -1) 1316 *intptr = value; 1317 break; 1318 1319 case oAddressFamily: 1320 intptr = &options->address_family; 1321 multistate_ptr = multistate_addressfamily; 1322 goto parse_multistate; 1323 1324 case oEnableSSHKeysign: 1325 intptr = &options->enable_ssh_keysign; 1326 goto parse_flag; 1327 1328 case oIdentitiesOnly: 1329 intptr = &options->identities_only; 1330 goto parse_flag; 1331 1332 case oServerAliveInterval: 1333 intptr = &options->server_alive_interval; 1334 goto parse_time; 1335 1336 case oServerAliveCountMax: 1337 intptr = &options->server_alive_count_max; 1338 goto parse_int; 1339 1340 case oSendEnv: 1341 while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1342 if (strchr(arg, '=') != NULL) 1343 fatal("%s line %d: Invalid environment name.", 1344 filename, linenum); 1345 if (!*activep) 1346 continue; 1347 if (options->num_send_env >= MAX_SEND_ENV) 1348 fatal("%s line %d: too many send env.", 1349 filename, linenum); 1350 options->send_env[options->num_send_env++] = 1351 xstrdup(arg); 1352 } 1353 break; 1354 1355 case oControlPath: 1356 charptr = &options->control_path; 1357 goto parse_string; 1358 1359 case oControlMaster: 1360 intptr = &options->control_master; 1361 multistate_ptr = multistate_controlmaster; 1362 goto parse_multistate; 1363 1364 case oControlPersist: 1365 /* no/false/yes/true, or a time spec */ 1366 intptr = &options->control_persist; 1367 arg = strdelim(&s); 1368 if (!arg || *arg == '\0') 1369 fatal("%.200s line %d: Missing ControlPersist" 1370 " argument.", filename, linenum); 1371 value = 0; 1372 value2 = 0; /* timeout */ 1373 if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 1374 value = 0; 1375 else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 1376 value = 1; 1377 else if ((value2 = convtime(arg)) >= 0) 1378 value = 1; 1379 else 1380 fatal("%.200s line %d: Bad ControlPersist argument.", 1381 filename, linenum); 1382 if (*activep && *intptr == -1) { 1383 *intptr = value; 1384 options->control_persist_timeout = value2; 1385 } 1386 break; 1387 1388 case oHashKnownHosts: 1389 intptr = &options->hash_known_hosts; 1390 goto parse_flag; 1391 1392 case oTunnel: 1393 intptr = &options->tun_open; 1394 multistate_ptr = multistate_tunnel; 1395 goto parse_multistate; 1396 1397 case oTunnelDevice: 1398 arg = strdelim(&s); 1399 if (!arg || *arg == '\0') 1400 fatal("%.200s line %d: Missing argument.", filename, linenum); 1401 value = a2tun(arg, &value2); 1402 if (value == SSH_TUNID_ERR) 1403 fatal("%.200s line %d: Bad tun device.", filename, linenum); 1404 if (*activep) { 1405 options->tun_local = value; 1406 options->tun_remote = value2; 1407 } 1408 break; 1409 1410 case oLocalCommand: 1411 charptr = &options->local_command; 1412 goto parse_command; 1413 1414 case oPermitLocalCommand: 1415 intptr = &options->permit_local_command; 1416 goto parse_flag; 1417 1418 case oRemoteCommand: 1419 charptr = &options->remote_command; 1420 goto parse_command; 1421 1422 case oVisualHostKey: 1423 intptr = &options->visual_host_key; 1424 goto parse_flag; 1425 1426 case oInclude: 1427 if (cmdline) 1428 fatal("Include directive not supported as a " 1429 "command-line option"); 1430 value = 0; 1431 while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1432 /* 1433 * Ensure all paths are anchored. User configuration 1434 * files may begin with '~/' but system configurations 1435 * must not. If the path is relative, then treat it 1436 * as living in ~/.ssh for user configurations or 1437 * /etc/ssh for system ones. 1438 */ 1439 if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0) 1440 fatal("%.200s line %d: bad include path %s.", 1441 filename, linenum, arg); 1442 if (*arg != '/' && *arg != '~') { 1443 xasprintf(&arg2, "%s/%s", 1444 (flags & SSHCONF_USERCONF) ? 1445 "~/" _PATH_SSH_USER_DIR : SSHDIR, arg); 1446 } else 1447 arg2 = xstrdup(arg); 1448 memset(&gl, 0, sizeof(gl)); 1449 r = glob(arg2, GLOB_TILDE, NULL, &gl); 1450 if (r == GLOB_NOMATCH) { 1451 debug("%.200s line %d: include %s matched no " 1452 "files",filename, linenum, arg2); 1453 free(arg2); 1454 continue; 1455 } else if (r != 0 || gl.gl_pathc < 0) 1456 fatal("%.200s line %d: glob failed for %s.", 1457 filename, linenum, arg2); 1458 free(arg2); 1459 oactive = *activep; 1460 for (i = 0; i < (u_int)gl.gl_pathc; i++) { 1461 debug3("%.200s line %d: Including file %s " 1462 "depth %d%s", filename, linenum, 1463 gl.gl_pathv[i], depth, 1464 oactive ? "" : " (parse only)"); 1465 r = read_config_file_depth(gl.gl_pathv[i], 1466 pw, host, original_host, options, 1467 flags | SSHCONF_CHECKPERM | 1468 (oactive ? 0 : SSHCONF_NEVERMATCH), 1469 activep, depth + 1); 1470 if (r != 1 && errno != ENOENT) { 1471 fatal("Can't open user config file " 1472 "%.100s: %.100s", gl.gl_pathv[i], 1473 strerror(errno)); 1474 } 1475 /* 1476 * don't let Match in includes clobber the 1477 * containing file's Match state. 1478 */ 1479 *activep = oactive; 1480 if (r != 1) 1481 value = -1; 1482 } 1483 globfree(&gl); 1484 } 1485 if (value != 0) 1486 return value; 1487 break; 1488 1489 case oIPQoS: 1490 arg = strdelim(&s); 1491 if ((value = parse_ipqos(arg)) == -1) 1492 fatal("%s line %d: Bad IPQoS value: %s", 1493 filename, linenum, arg); 1494 arg = strdelim(&s); 1495 if (arg == NULL) 1496 value2 = value; 1497 else if ((value2 = parse_ipqos(arg)) == -1) 1498 fatal("%s line %d: Bad IPQoS value: %s", 1499 filename, linenum, arg); 1500 if (*activep) { 1501 options->ip_qos_interactive = value; 1502 options->ip_qos_bulk = value2; 1503 } 1504 break; 1505 1506 case oRequestTTY: 1507 intptr = &options->request_tty; 1508 multistate_ptr = multistate_requesttty; 1509 goto parse_multistate; 1510 1511 case oIgnoreUnknown: 1512 charptr = &options->ignored_unknown; 1513 goto parse_string; 1514 1515 case oProxyUseFdpass: 1516 intptr = &options->proxy_use_fdpass; 1517 goto parse_flag; 1518 1519 case oCanonicalDomains: 1520 value = options->num_canonical_domains != 0; 1521 while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1522 const char *errstr; 1523 if (!valid_domain(arg, 1, &errstr)) { 1524 fatal("%s line %d: %s", filename, linenum, 1525 errstr); 1526 } 1527 if (!*activep || value) 1528 continue; 1529 if (options->num_canonical_domains >= MAX_CANON_DOMAINS) 1530 fatal("%s line %d: too many hostname suffixes.", 1531 filename, linenum); 1532 options->canonical_domains[ 1533 options->num_canonical_domains++] = xstrdup(arg); 1534 } 1535 break; 1536 1537 case oCanonicalizePermittedCNAMEs: 1538 value = options->num_permitted_cnames != 0; 1539 while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1540 /* Either '*' for everything or 'list:list' */ 1541 if (strcmp(arg, "*") == 0) 1542 arg2 = arg; 1543 else { 1544 lowercase(arg); 1545 if ((arg2 = strchr(arg, ':')) == NULL || 1546 arg2[1] == '\0') { 1547 fatal("%s line %d: " 1548 "Invalid permitted CNAME \"%s\"", 1549 filename, linenum, arg); 1550 } 1551 *arg2 = '\0'; 1552 arg2++; 1553 } 1554 if (!*activep || value) 1555 continue; 1556 if (options->num_permitted_cnames >= MAX_CANON_DOMAINS) 1557 fatal("%s line %d: too many permitted CNAMEs.", 1558 filename, linenum); 1559 cname = options->permitted_cnames + 1560 options->num_permitted_cnames++; 1561 cname->source_list = xstrdup(arg); 1562 cname->target_list = xstrdup(arg2); 1563 } 1564 break; 1565 1566 case oCanonicalizeHostname: 1567 intptr = &options->canonicalize_hostname; 1568 multistate_ptr = multistate_canonicalizehostname; 1569 goto parse_multistate; 1570 1571 case oCanonicalizeMaxDots: 1572 intptr = &options->canonicalize_max_dots; 1573 goto parse_int; 1574 1575 case oCanonicalizeFallbackLocal: 1576 intptr = &options->canonicalize_fallback_local; 1577 goto parse_flag; 1578 1579 case oStreamLocalBindMask: 1580 arg = strdelim(&s); 1581 if (!arg || *arg == '\0') 1582 fatal("%.200s line %d: Missing StreamLocalBindMask argument.", filename, linenum); 1583 /* Parse mode in octal format */ 1584 value = strtol(arg, &endofnumber, 8); 1585 if (arg == endofnumber || value < 0 || value > 0777) 1586 fatal("%.200s line %d: Bad mask.", filename, linenum); 1587 options->fwd_opts.streamlocal_bind_mask = (mode_t)value; 1588 break; 1589 1590 case oStreamLocalBindUnlink: 1591 intptr = &options->fwd_opts.streamlocal_bind_unlink; 1592 goto parse_flag; 1593 1594 case oRevokedHostKeys: 1595 charptr = &options->revoked_host_keys; 1596 goto parse_string; 1597 1598 case oFingerprintHash: 1599 intptr = &options->fingerprint_hash; 1600 arg = strdelim(&s); 1601 if (!arg || *arg == '\0') 1602 fatal("%.200s line %d: Missing argument.", 1603 filename, linenum); 1604 if ((value = ssh_digest_alg_by_name(arg)) == -1) 1605 fatal("%.200s line %d: Invalid hash algorithm \"%s\".", 1606 filename, linenum, arg); 1607 if (*activep && *intptr == -1) 1608 *intptr = value; 1609 break; 1610 1611 case oUpdateHostkeys: 1612 intptr = &options->update_hostkeys; 1613 multistate_ptr = multistate_yesnoask; 1614 goto parse_multistate; 1615 1616 case oHostbasedKeyTypes: 1617 charptr = &options->hostbased_key_types; 1618 goto parse_keytypes; 1619 1620 case oPubkeyAcceptedKeyTypes: 1621 charptr = &options->pubkey_key_types; 1622 goto parse_keytypes; 1623 1624 case oAddKeysToAgent: 1625 intptr = &options->add_keys_to_agent; 1626 multistate_ptr = multistate_yesnoaskconfirm; 1627 goto parse_multistate; 1628 1629 case oIdentityAgent: 1630 charptr = &options->identity_agent; 1631 goto parse_string; 1632 1633 case oDeprecated: 1634 debug("%s line %d: Deprecated option \"%s\"", 1635 filename, linenum, keyword); 1636 return 0; 1637 1638 case oUnsupported: 1639 error("%s line %d: Unsupported option \"%s\"", 1640 filename, linenum, keyword); 1641 return 0; 1642 1643 default: 1644 fatal("%s: Unimplemented opcode %d", __func__, opcode); 1645 } 1646 1647 /* Check that there is no garbage at end of line. */ 1648 if ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1649 fatal("%.200s line %d: garbage at end of line; \"%.200s\".", 1650 filename, linenum, arg); 1651 } 1652 return 0; 1653 } 1654 1655 /* 1656 * Reads the config file and modifies the options accordingly. Options 1657 * should already be initialized before this call. This never returns if 1658 * there is an error. If the file does not exist, this returns 0. 1659 */ 1660 int 1661 read_config_file(const char *filename, struct passwd *pw, const char *host, 1662 const char *original_host, Options *options, int flags) 1663 { 1664 int active = 1; 1665 1666 return read_config_file_depth(filename, pw, host, original_host, 1667 options, flags, &active, 0); 1668 } 1669 1670 #define READCONF_MAX_DEPTH 16 1671 static int 1672 read_config_file_depth(const char *filename, struct passwd *pw, 1673 const char *host, const char *original_host, Options *options, 1674 int flags, int *activep, int depth) 1675 { 1676 FILE *f; 1677 char line[4096]; 1678 int linenum; 1679 int bad_options = 0; 1680 1681 if (depth < 0 || depth > READCONF_MAX_DEPTH) 1682 fatal("Too many recursive configuration includes"); 1683 1684 if ((f = fopen(filename, "r")) == NULL) 1685 return 0; 1686 1687 if (flags & SSHCONF_CHECKPERM) { 1688 struct stat sb; 1689 1690 if (fstat(fileno(f), &sb) == -1) 1691 fatal("fstat %s: %s", filename, strerror(errno)); 1692 if (((sb.st_uid != 0 && sb.st_uid != getuid()) || 1693 (sb.st_mode & 022) != 0)) 1694 fatal("Bad owner or permissions on %s", filename); 1695 } 1696 1697 debug("Reading configuration data %.200s", filename); 1698 1699 /* 1700 * Mark that we are now processing the options. This flag is turned 1701 * on/off by Host specifications. 1702 */ 1703 linenum = 0; 1704 while (fgets(line, sizeof(line), f)) { 1705 /* Update line number counter. */ 1706 linenum++; 1707 if (strlen(line) == sizeof(line) - 1) 1708 fatal("%s line %d too long", filename, linenum); 1709 if (process_config_line_depth(options, pw, host, original_host, 1710 line, filename, linenum, activep, flags, depth) != 0) 1711 bad_options++; 1712 } 1713 fclose(f); 1714 if (bad_options > 0) 1715 fatal("%s: terminating, %d bad configuration options", 1716 filename, bad_options); 1717 return 1; 1718 } 1719 1720 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ 1721 int 1722 option_clear_or_none(const char *o) 1723 { 1724 return o == NULL || strcasecmp(o, "none") == 0; 1725 } 1726 1727 /* 1728 * Initializes options to special values that indicate that they have not yet 1729 * been set. Read_config_file will only set options with this value. Options 1730 * are processed in the following order: command line, user config file, 1731 * system config file. Last, fill_default_options is called. 1732 */ 1733 1734 void 1735 initialize_options(Options * options) 1736 { 1737 memset(options, 'X', sizeof(*options)); 1738 options->forward_agent = -1; 1739 options->forward_x11 = -1; 1740 options->forward_x11_trusted = -1; 1741 options->forward_x11_timeout = -1; 1742 options->stdio_forward_host = NULL; 1743 options->stdio_forward_port = 0; 1744 options->clear_forwardings = -1; 1745 options->exit_on_forward_failure = -1; 1746 options->xauth_location = NULL; 1747 options->fwd_opts.gateway_ports = -1; 1748 options->fwd_opts.streamlocal_bind_mask = (mode_t)-1; 1749 options->fwd_opts.streamlocal_bind_unlink = -1; 1750 options->use_privileged_port = -1; 1751 options->pubkey_authentication = -1; 1752 options->challenge_response_authentication = -1; 1753 options->gss_authentication = -1; 1754 options->gss_deleg_creds = -1; 1755 options->password_authentication = -1; 1756 options->kbd_interactive_authentication = -1; 1757 options->kbd_interactive_devices = NULL; 1758 options->hostbased_authentication = -1; 1759 options->batch_mode = -1; 1760 options->check_host_ip = -1; 1761 options->strict_host_key_checking = -1; 1762 options->compression = -1; 1763 options->tcp_keep_alive = -1; 1764 options->port = -1; 1765 options->address_family = -1; 1766 options->connection_attempts = -1; 1767 options->connection_timeout = -1; 1768 options->number_of_password_prompts = -1; 1769 options->ciphers = NULL; 1770 options->macs = NULL; 1771 options->kex_algorithms = NULL; 1772 options->hostkeyalgorithms = NULL; 1773 options->num_identity_files = 0; 1774 options->num_certificate_files = 0; 1775 options->hostname = NULL; 1776 options->host_key_alias = NULL; 1777 options->proxy_command = NULL; 1778 options->jump_user = NULL; 1779 options->jump_host = NULL; 1780 options->jump_port = -1; 1781 options->jump_extra = NULL; 1782 options->user = NULL; 1783 options->escape_char = -1; 1784 options->num_system_hostfiles = 0; 1785 options->num_user_hostfiles = 0; 1786 options->local_forwards = NULL; 1787 options->num_local_forwards = 0; 1788 options->remote_forwards = NULL; 1789 options->num_remote_forwards = 0; 1790 options->log_facility = SYSLOG_FACILITY_NOT_SET; 1791 options->log_level = SYSLOG_LEVEL_NOT_SET; 1792 options->preferred_authentications = NULL; 1793 options->bind_address = NULL; 1794 options->pkcs11_provider = NULL; 1795 options->enable_ssh_keysign = - 1; 1796 options->no_host_authentication_for_localhost = - 1; 1797 options->identities_only = - 1; 1798 options->rekey_limit = - 1; 1799 options->rekey_interval = -1; 1800 options->verify_host_key_dns = -1; 1801 options->server_alive_interval = -1; 1802 options->server_alive_count_max = -1; 1803 options->num_send_env = 0; 1804 options->control_path = NULL; 1805 options->control_master = -1; 1806 options->control_persist = -1; 1807 options->control_persist_timeout = 0; 1808 options->hash_known_hosts = -1; 1809 options->tun_open = -1; 1810 options->tun_local = -1; 1811 options->tun_remote = -1; 1812 options->local_command = NULL; 1813 options->permit_local_command = -1; 1814 options->remote_command = NULL; 1815 options->add_keys_to_agent = -1; 1816 options->identity_agent = NULL; 1817 options->visual_host_key = -1; 1818 options->ip_qos_interactive = -1; 1819 options->ip_qos_bulk = -1; 1820 options->request_tty = -1; 1821 options->proxy_use_fdpass = -1; 1822 options->ignored_unknown = NULL; 1823 options->num_canonical_domains = 0; 1824 options->num_permitted_cnames = 0; 1825 options->canonicalize_max_dots = -1; 1826 options->canonicalize_fallback_local = -1; 1827 options->canonicalize_hostname = -1; 1828 options->revoked_host_keys = NULL; 1829 options->fingerprint_hash = -1; 1830 options->update_hostkeys = -1; 1831 options->hostbased_key_types = NULL; 1832 options->pubkey_key_types = NULL; 1833 } 1834 1835 /* 1836 * A petite version of fill_default_options() that just fills the options 1837 * needed for hostname canonicalization to proceed. 1838 */ 1839 void 1840 fill_default_options_for_canonicalization(Options *options) 1841 { 1842 if (options->canonicalize_max_dots == -1) 1843 options->canonicalize_max_dots = 1; 1844 if (options->canonicalize_fallback_local == -1) 1845 options->canonicalize_fallback_local = 1; 1846 if (options->canonicalize_hostname == -1) 1847 options->canonicalize_hostname = SSH_CANONICALISE_NO; 1848 } 1849 1850 /* 1851 * Called after processing other sources of option data, this fills those 1852 * options for which no value has been specified with their default values. 1853 */ 1854 void 1855 fill_default_options(Options * options) 1856 { 1857 if (options->forward_agent == -1) 1858 options->forward_agent = 0; 1859 if (options->forward_x11 == -1) 1860 options->forward_x11 = 0; 1861 if (options->forward_x11_trusted == -1) 1862 options->forward_x11_trusted = 0; 1863 if (options->forward_x11_timeout == -1) 1864 options->forward_x11_timeout = 1200; 1865 /* 1866 * stdio forwarding (-W) changes the default for these but we defer 1867 * setting the values so they can be overridden. 1868 */ 1869 if (options->exit_on_forward_failure == -1) 1870 options->exit_on_forward_failure = 1871 options->stdio_forward_host != NULL ? 1 : 0; 1872 if (options->clear_forwardings == -1) 1873 options->clear_forwardings = 1874 options->stdio_forward_host != NULL ? 1 : 0; 1875 if (options->clear_forwardings == 1) 1876 clear_forwardings(options); 1877 1878 if (options->xauth_location == NULL) 1879 options->xauth_location = _PATH_XAUTH; 1880 if (options->fwd_opts.gateway_ports == -1) 1881 options->fwd_opts.gateway_ports = 0; 1882 if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1) 1883 options->fwd_opts.streamlocal_bind_mask = 0177; 1884 if (options->fwd_opts.streamlocal_bind_unlink == -1) 1885 options->fwd_opts.streamlocal_bind_unlink = 0; 1886 if (options->use_privileged_port == -1) 1887 options->use_privileged_port = 0; 1888 if (options->pubkey_authentication == -1) 1889 options->pubkey_authentication = 1; 1890 if (options->challenge_response_authentication == -1) 1891 options->challenge_response_authentication = 1; 1892 if (options->gss_authentication == -1) 1893 options->gss_authentication = 0; 1894 if (options->gss_deleg_creds == -1) 1895 options->gss_deleg_creds = 0; 1896 if (options->password_authentication == -1) 1897 options->password_authentication = 1; 1898 if (options->kbd_interactive_authentication == -1) 1899 options->kbd_interactive_authentication = 1; 1900 if (options->hostbased_authentication == -1) 1901 options->hostbased_authentication = 0; 1902 if (options->batch_mode == -1) 1903 options->batch_mode = 0; 1904 if (options->check_host_ip == -1) 1905 options->check_host_ip = 1; 1906 if (options->strict_host_key_checking == -1) 1907 options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK; 1908 if (options->compression == -1) 1909 options->compression = 0; 1910 if (options->tcp_keep_alive == -1) 1911 options->tcp_keep_alive = 1; 1912 if (options->port == -1) 1913 options->port = 0; /* Filled in ssh_connect. */ 1914 if (options->address_family == -1) 1915 options->address_family = AF_UNSPEC; 1916 if (options->connection_attempts == -1) 1917 options->connection_attempts = 1; 1918 if (options->number_of_password_prompts == -1) 1919 options->number_of_password_prompts = 3; 1920 /* options->hostkeyalgorithms, default set in myproposals.h */ 1921 if (options->add_keys_to_agent == -1) 1922 options->add_keys_to_agent = 0; 1923 if (options->num_identity_files == 0) { 1924 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0); 1925 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0); 1926 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0); 1927 add_identity_file(options, "~/", 1928 _PATH_SSH_CLIENT_ID_ED25519, 0); 1929 } 1930 if (options->escape_char == -1) 1931 options->escape_char = '~'; 1932 if (options->num_system_hostfiles == 0) { 1933 options->system_hostfiles[options->num_system_hostfiles++] = 1934 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE); 1935 options->system_hostfiles[options->num_system_hostfiles++] = 1936 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2); 1937 } 1938 if (options->num_user_hostfiles == 0) { 1939 options->user_hostfiles[options->num_user_hostfiles++] = 1940 xstrdup(_PATH_SSH_USER_HOSTFILE); 1941 options->user_hostfiles[options->num_user_hostfiles++] = 1942 xstrdup(_PATH_SSH_USER_HOSTFILE2); 1943 } 1944 if (options->log_level == SYSLOG_LEVEL_NOT_SET) 1945 options->log_level = SYSLOG_LEVEL_INFO; 1946 if (options->log_facility == SYSLOG_FACILITY_NOT_SET) 1947 options->log_facility = SYSLOG_FACILITY_USER; 1948 if (options->no_host_authentication_for_localhost == - 1) 1949 options->no_host_authentication_for_localhost = 0; 1950 if (options->identities_only == -1) 1951 options->identities_only = 0; 1952 if (options->enable_ssh_keysign == -1) 1953 options->enable_ssh_keysign = 0; 1954 if (options->rekey_limit == -1) 1955 options->rekey_limit = 0; 1956 if (options->rekey_interval == -1) 1957 options->rekey_interval = 0; 1958 if (options->verify_host_key_dns == -1) 1959 options->verify_host_key_dns = 0; 1960 if (options->server_alive_interval == -1) 1961 options->server_alive_interval = 0; 1962 if (options->server_alive_count_max == -1) 1963 options->server_alive_count_max = 3; 1964 if (options->control_master == -1) 1965 options->control_master = 0; 1966 if (options->control_persist == -1) { 1967 options->control_persist = 0; 1968 options->control_persist_timeout = 0; 1969 } 1970 if (options->hash_known_hosts == -1) 1971 options->hash_known_hosts = 0; 1972 if (options->tun_open == -1) 1973 options->tun_open = SSH_TUNMODE_NO; 1974 if (options->tun_local == -1) 1975 options->tun_local = SSH_TUNID_ANY; 1976 if (options->tun_remote == -1) 1977 options->tun_remote = SSH_TUNID_ANY; 1978 if (options->permit_local_command == -1) 1979 options->permit_local_command = 0; 1980 if (options->visual_host_key == -1) 1981 options->visual_host_key = 0; 1982 if (options->ip_qos_interactive == -1) 1983 options->ip_qos_interactive = IPTOS_LOWDELAY; 1984 if (options->ip_qos_bulk == -1) 1985 options->ip_qos_bulk = IPTOS_THROUGHPUT; 1986 if (options->request_tty == -1) 1987 options->request_tty = REQUEST_TTY_AUTO; 1988 if (options->proxy_use_fdpass == -1) 1989 options->proxy_use_fdpass = 0; 1990 if (options->canonicalize_max_dots == -1) 1991 options->canonicalize_max_dots = 1; 1992 if (options->canonicalize_fallback_local == -1) 1993 options->canonicalize_fallback_local = 1; 1994 if (options->canonicalize_hostname == -1) 1995 options->canonicalize_hostname = SSH_CANONICALISE_NO; 1996 if (options->fingerprint_hash == -1) 1997 options->fingerprint_hash = SSH_FP_HASH_DEFAULT; 1998 if (options->update_hostkeys == -1) 1999 options->update_hostkeys = 0; 2000 if (kex_assemble_names(KEX_CLIENT_ENCRYPT, &options->ciphers) != 0 || 2001 kex_assemble_names(KEX_CLIENT_MAC, &options->macs) != 0 || 2002 kex_assemble_names(KEX_CLIENT_KEX, &options->kex_algorithms) != 0 || 2003 kex_assemble_names(KEX_DEFAULT_PK_ALG, 2004 &options->hostbased_key_types) != 0 || 2005 kex_assemble_names(KEX_DEFAULT_PK_ALG, 2006 &options->pubkey_key_types) != 0) 2007 fatal("%s: kex_assemble_names failed", __func__); 2008 2009 #define CLEAR_ON_NONE(v) \ 2010 do { \ 2011 if (option_clear_or_none(v)) { \ 2012 free(v); \ 2013 v = NULL; \ 2014 } \ 2015 } while(0) 2016 CLEAR_ON_NONE(options->local_command); 2017 CLEAR_ON_NONE(options->remote_command); 2018 CLEAR_ON_NONE(options->proxy_command); 2019 CLEAR_ON_NONE(options->control_path); 2020 CLEAR_ON_NONE(options->revoked_host_keys); 2021 /* options->identity_agent distinguishes NULL from 'none' */ 2022 /* options->user will be set in the main program if appropriate */ 2023 /* options->hostname will be set in the main program if appropriate */ 2024 /* options->host_key_alias should not be set by default */ 2025 /* options->preferred_authentications will be set in ssh */ 2026 } 2027 2028 struct fwdarg { 2029 char *arg; 2030 int ispath; 2031 }; 2032 2033 /* 2034 * parse_fwd_field 2035 * parses the next field in a port forwarding specification. 2036 * sets fwd to the parsed field and advances p past the colon 2037 * or sets it to NULL at end of string. 2038 * returns 0 on success, else non-zero. 2039 */ 2040 static int 2041 parse_fwd_field(char **p, struct fwdarg *fwd) 2042 { 2043 char *ep, *cp = *p; 2044 int ispath = 0; 2045 2046 if (*cp == '\0') { 2047 *p = NULL; 2048 return -1; /* end of string */ 2049 } 2050 2051 /* 2052 * A field escaped with square brackets is used literally. 2053 * XXX - allow ']' to be escaped via backslash? 2054 */ 2055 if (*cp == '[') { 2056 /* find matching ']' */ 2057 for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) { 2058 if (*ep == '/') 2059 ispath = 1; 2060 } 2061 /* no matching ']' or not at end of field. */ 2062 if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0')) 2063 return -1; 2064 /* NUL terminate the field and advance p past the colon */ 2065 *ep++ = '\0'; 2066 if (*ep != '\0') 2067 *ep++ = '\0'; 2068 fwd->arg = cp + 1; 2069 fwd->ispath = ispath; 2070 *p = ep; 2071 return 0; 2072 } 2073 2074 for (cp = *p; *cp != '\0'; cp++) { 2075 switch (*cp) { 2076 case '\\': 2077 memmove(cp, cp + 1, strlen(cp + 1) + 1); 2078 if (*cp == '\0') 2079 return -1; 2080 break; 2081 case '/': 2082 ispath = 1; 2083 break; 2084 case ':': 2085 *cp++ = '\0'; 2086 goto done; 2087 } 2088 } 2089 done: 2090 fwd->arg = *p; 2091 fwd->ispath = ispath; 2092 *p = cp; 2093 return 0; 2094 } 2095 2096 /* 2097 * parse_forward 2098 * parses a string containing a port forwarding specification of the form: 2099 * dynamicfwd == 0 2100 * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath 2101 * listenpath:connectpath 2102 * dynamicfwd == 1 2103 * [listenhost:]listenport 2104 * returns number of arguments parsed or zero on error 2105 */ 2106 int 2107 parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) 2108 { 2109 struct fwdarg fwdargs[4]; 2110 char *p, *cp; 2111 int i; 2112 2113 memset(fwd, 0, sizeof(*fwd)); 2114 memset(fwdargs, 0, sizeof(fwdargs)); 2115 2116 cp = p = xstrdup(fwdspec); 2117 2118 /* skip leading spaces */ 2119 while (isspace((u_char)*cp)) 2120 cp++; 2121 2122 for (i = 0; i < 4; ++i) { 2123 if (parse_fwd_field(&cp, &fwdargs[i]) != 0) 2124 break; 2125 } 2126 2127 /* Check for trailing garbage */ 2128 if (cp != NULL && *cp != '\0') { 2129 i = 0; /* failure */ 2130 } 2131 2132 switch (i) { 2133 case 1: 2134 if (fwdargs[0].ispath) { 2135 fwd->listen_path = xstrdup(fwdargs[0].arg); 2136 fwd->listen_port = PORT_STREAMLOCAL; 2137 } else { 2138 fwd->listen_host = NULL; 2139 fwd->listen_port = a2port(fwdargs[0].arg); 2140 } 2141 fwd->connect_host = xstrdup("socks"); 2142 break; 2143 2144 case 2: 2145 if (fwdargs[0].ispath && fwdargs[1].ispath) { 2146 fwd->listen_path = xstrdup(fwdargs[0].arg); 2147 fwd->listen_port = PORT_STREAMLOCAL; 2148 fwd->connect_path = xstrdup(fwdargs[1].arg); 2149 fwd->connect_port = PORT_STREAMLOCAL; 2150 } else if (fwdargs[1].ispath) { 2151 fwd->listen_host = NULL; 2152 fwd->listen_port = a2port(fwdargs[0].arg); 2153 fwd->connect_path = xstrdup(fwdargs[1].arg); 2154 fwd->connect_port = PORT_STREAMLOCAL; 2155 } else { 2156 fwd->listen_host = xstrdup(fwdargs[0].arg); 2157 fwd->listen_port = a2port(fwdargs[1].arg); 2158 fwd->connect_host = xstrdup("socks"); 2159 } 2160 break; 2161 2162 case 3: 2163 if (fwdargs[0].ispath) { 2164 fwd->listen_path = xstrdup(fwdargs[0].arg); 2165 fwd->listen_port = PORT_STREAMLOCAL; 2166 fwd->connect_host = xstrdup(fwdargs[1].arg); 2167 fwd->connect_port = a2port(fwdargs[2].arg); 2168 } else if (fwdargs[2].ispath) { 2169 fwd->listen_host = xstrdup(fwdargs[0].arg); 2170 fwd->listen_port = a2port(fwdargs[1].arg); 2171 fwd->connect_path = xstrdup(fwdargs[2].arg); 2172 fwd->connect_port = PORT_STREAMLOCAL; 2173 } else { 2174 fwd->listen_host = NULL; 2175 fwd->listen_port = a2port(fwdargs[0].arg); 2176 fwd->connect_host = xstrdup(fwdargs[1].arg); 2177 fwd->connect_port = a2port(fwdargs[2].arg); 2178 } 2179 break; 2180 2181 case 4: 2182 fwd->listen_host = xstrdup(fwdargs[0].arg); 2183 fwd->listen_port = a2port(fwdargs[1].arg); 2184 fwd->connect_host = xstrdup(fwdargs[2].arg); 2185 fwd->connect_port = a2port(fwdargs[3].arg); 2186 break; 2187 default: 2188 i = 0; /* failure */ 2189 } 2190 2191 free(p); 2192 2193 if (dynamicfwd) { 2194 if (!(i == 1 || i == 2)) 2195 goto fail_free; 2196 } else { 2197 if (!(i == 3 || i == 4)) { 2198 if (fwd->connect_path == NULL && 2199 fwd->listen_path == NULL) 2200 goto fail_free; 2201 } 2202 if (fwd->connect_port <= 0 && fwd->connect_path == NULL) 2203 goto fail_free; 2204 } 2205 2206 if ((fwd->listen_port < 0 && fwd->listen_path == NULL) || 2207 (!remotefwd && fwd->listen_port == 0)) 2208 goto fail_free; 2209 if (fwd->connect_host != NULL && 2210 strlen(fwd->connect_host) >= NI_MAXHOST) 2211 goto fail_free; 2212 /* XXX - if connecting to a remote socket, max sun len may not match this host */ 2213 if (fwd->connect_path != NULL && 2214 strlen(fwd->connect_path) >= PATH_MAX_SUN) 2215 goto fail_free; 2216 if (fwd->listen_host != NULL && 2217 strlen(fwd->listen_host) >= NI_MAXHOST) 2218 goto fail_free; 2219 if (fwd->listen_path != NULL && 2220 strlen(fwd->listen_path) >= PATH_MAX_SUN) 2221 goto fail_free; 2222 2223 return (i); 2224 2225 fail_free: 2226 free(fwd->connect_host); 2227 fwd->connect_host = NULL; 2228 free(fwd->connect_path); 2229 fwd->connect_path = NULL; 2230 free(fwd->listen_host); 2231 fwd->listen_host = NULL; 2232 free(fwd->listen_path); 2233 fwd->listen_path = NULL; 2234 return (0); 2235 } 2236 2237 int 2238 parse_jump(const char *s, Options *o, int active) 2239 { 2240 char *orig, *sdup, *cp; 2241 char *host = NULL, *user = NULL; 2242 int ret = -1, port = -1, first; 2243 2244 active &= o->proxy_command == NULL && o->jump_host == NULL; 2245 2246 orig = sdup = xstrdup(s); 2247 first = active; 2248 do { 2249 if ((cp = strrchr(sdup, ',')) == NULL) 2250 cp = sdup; /* last */ 2251 else 2252 *cp++ = '\0'; 2253 2254 if (first) { 2255 /* First argument and configuration is active */ 2256 if (parse_ssh_uri(cp, &user, &host, &port) == -1 || 2257 parse_user_host_port(cp, &user, &host, &port) != 0) 2258 goto out; 2259 } else { 2260 /* Subsequent argument or inactive configuration */ 2261 if (parse_ssh_uri(cp, NULL, NULL, NULL) == -1 || 2262 parse_user_host_port(cp, NULL, NULL, NULL) != 0) 2263 goto out; 2264 } 2265 first = 0; /* only check syntax for subsequent hosts */ 2266 } while (cp != sdup); 2267 /* success */ 2268 if (active) { 2269 o->jump_user = user; 2270 o->jump_host = host; 2271 o->jump_port = port; 2272 o->proxy_command = xstrdup("none"); 2273 user = host = NULL; 2274 if ((cp = strrchr(s, ',')) != NULL && cp != s) { 2275 o->jump_extra = xstrdup(s); 2276 o->jump_extra[cp - s] = '\0'; 2277 } 2278 } 2279 ret = 0; 2280 out: 2281 free(orig); 2282 free(user); 2283 free(host); 2284 return ret; 2285 } 2286 2287 int 2288 parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp) 2289 { 2290 char *path; 2291 int r; 2292 2293 r = parse_uri("ssh", uri, userp, hostp, portp, &path); 2294 if (r == 0 && path != NULL) 2295 r = -1; /* path not allowed */ 2296 return r; 2297 } 2298 2299 /* XXX the following is a near-vebatim copy from servconf.c; refactor */ 2300 static const char * 2301 fmt_multistate_int(int val, const struct multistate *m) 2302 { 2303 u_int i; 2304 2305 for (i = 0; m[i].key != NULL; i++) { 2306 if (m[i].value == val) 2307 return m[i].key; 2308 } 2309 return "UNKNOWN"; 2310 } 2311 2312 static const char * 2313 fmt_intarg(OpCodes code, int val) 2314 { 2315 if (val == -1) 2316 return "unset"; 2317 switch (code) { 2318 case oAddressFamily: 2319 return fmt_multistate_int(val, multistate_addressfamily); 2320 case oVerifyHostKeyDNS: 2321 case oUpdateHostkeys: 2322 return fmt_multistate_int(val, multistate_yesnoask); 2323 case oStrictHostKeyChecking: 2324 return fmt_multistate_int(val, multistate_strict_hostkey); 2325 case oControlMaster: 2326 return fmt_multistate_int(val, multistate_controlmaster); 2327 case oTunnel: 2328 return fmt_multistate_int(val, multistate_tunnel); 2329 case oRequestTTY: 2330 return fmt_multistate_int(val, multistate_requesttty); 2331 case oCanonicalizeHostname: 2332 return fmt_multistate_int(val, multistate_canonicalizehostname); 2333 case oFingerprintHash: 2334 return ssh_digest_alg_name(val); 2335 default: 2336 switch (val) { 2337 case 0: 2338 return "no"; 2339 case 1: 2340 return "yes"; 2341 default: 2342 return "UNKNOWN"; 2343 } 2344 } 2345 } 2346 2347 static const char * 2348 lookup_opcode_name(OpCodes code) 2349 { 2350 u_int i; 2351 2352 for (i = 0; keywords[i].name != NULL; i++) 2353 if (keywords[i].opcode == code) 2354 return(keywords[i].name); 2355 return "UNKNOWN"; 2356 } 2357 2358 static void 2359 dump_cfg_int(OpCodes code, int val) 2360 { 2361 printf("%s %d\n", lookup_opcode_name(code), val); 2362 } 2363 2364 static void 2365 dump_cfg_fmtint(OpCodes code, int val) 2366 { 2367 printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val)); 2368 } 2369 2370 static void 2371 dump_cfg_string(OpCodes code, const char *val) 2372 { 2373 if (val == NULL) 2374 return; 2375 printf("%s %s\n", lookup_opcode_name(code), val); 2376 } 2377 2378 static void 2379 dump_cfg_strarray(OpCodes code, u_int count, char **vals) 2380 { 2381 u_int i; 2382 2383 for (i = 0; i < count; i++) 2384 printf("%s %s\n", lookup_opcode_name(code), vals[i]); 2385 } 2386 2387 static void 2388 dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals) 2389 { 2390 u_int i; 2391 2392 printf("%s", lookup_opcode_name(code)); 2393 for (i = 0; i < count; i++) 2394 printf(" %s", vals[i]); 2395 printf("\n"); 2396 } 2397 2398 static void 2399 dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds) 2400 { 2401 const struct Forward *fwd; 2402 u_int i; 2403 2404 /* oDynamicForward */ 2405 for (i = 0; i < count; i++) { 2406 fwd = &fwds[i]; 2407 if (code == oDynamicForward && fwd->connect_host != NULL && 2408 strcmp(fwd->connect_host, "socks") != 0) 2409 continue; 2410 if (code == oLocalForward && fwd->connect_host != NULL && 2411 strcmp(fwd->connect_host, "socks") == 0) 2412 continue; 2413 printf("%s", lookup_opcode_name(code)); 2414 if (fwd->listen_port == PORT_STREAMLOCAL) 2415 printf(" %s", fwd->listen_path); 2416 else if (fwd->listen_host == NULL) 2417 printf(" %d", fwd->listen_port); 2418 else { 2419 printf(" [%s]:%d", 2420 fwd->listen_host, fwd->listen_port); 2421 } 2422 if (code != oDynamicForward) { 2423 if (fwd->connect_port == PORT_STREAMLOCAL) 2424 printf(" %s", fwd->connect_path); 2425 else if (fwd->connect_host == NULL) 2426 printf(" %d", fwd->connect_port); 2427 else { 2428 printf(" [%s]:%d", 2429 fwd->connect_host, fwd->connect_port); 2430 } 2431 } 2432 printf("\n"); 2433 } 2434 } 2435 2436 void 2437 dump_client_config(Options *o, const char *host) 2438 { 2439 int i; 2440 char buf[8]; 2441 2442 /* This is normally prepared in ssh_kex2 */ 2443 if (kex_assemble_names(KEX_DEFAULT_PK_ALG, &o->hostkeyalgorithms) != 0) 2444 fatal("%s: kex_assemble_names failed", __func__); 2445 2446 /* Most interesting options first: user, host, port */ 2447 dump_cfg_string(oUser, o->user); 2448 dump_cfg_string(oHostName, host); 2449 dump_cfg_int(oPort, o->port); 2450 2451 /* Flag options */ 2452 dump_cfg_fmtint(oAddressFamily, o->address_family); 2453 dump_cfg_fmtint(oBatchMode, o->batch_mode); 2454 dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local); 2455 dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname); 2456 dump_cfg_fmtint(oChallengeResponseAuthentication, o->challenge_response_authentication); 2457 dump_cfg_fmtint(oCheckHostIP, o->check_host_ip); 2458 dump_cfg_fmtint(oCompression, o->compression); 2459 dump_cfg_fmtint(oControlMaster, o->control_master); 2460 dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign); 2461 dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings); 2462 dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure); 2463 dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash); 2464 dump_cfg_fmtint(oForwardAgent, o->forward_agent); 2465 dump_cfg_fmtint(oForwardX11, o->forward_x11); 2466 dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted); 2467 dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports); 2468 #ifdef GSSAPI 2469 dump_cfg_fmtint(oGssAuthentication, o->gss_authentication); 2470 dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds); 2471 #endif /* GSSAPI */ 2472 dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts); 2473 dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication); 2474 dump_cfg_fmtint(oIdentitiesOnly, o->identities_only); 2475 dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication); 2476 dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost); 2477 dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication); 2478 dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command); 2479 dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass); 2480 dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication); 2481 dump_cfg_fmtint(oRequestTTY, o->request_tty); 2482 dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink); 2483 dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking); 2484 dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive); 2485 dump_cfg_fmtint(oTunnel, o->tun_open); 2486 dump_cfg_fmtint(oUsePrivilegedPort, o->use_privileged_port); 2487 dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns); 2488 dump_cfg_fmtint(oVisualHostKey, o->visual_host_key); 2489 dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys); 2490 2491 /* Integer options */ 2492 dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots); 2493 dump_cfg_int(oConnectionAttempts, o->connection_attempts); 2494 dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout); 2495 dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts); 2496 dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max); 2497 dump_cfg_int(oServerAliveInterval, o->server_alive_interval); 2498 2499 /* String options */ 2500 dump_cfg_string(oBindAddress, o->bind_address); 2501 dump_cfg_string(oCiphers, o->ciphers ? o->ciphers : KEX_CLIENT_ENCRYPT); 2502 dump_cfg_string(oControlPath, o->control_path); 2503 dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms); 2504 dump_cfg_string(oHostKeyAlias, o->host_key_alias); 2505 dump_cfg_string(oHostbasedKeyTypes, o->hostbased_key_types); 2506 dump_cfg_string(oIdentityAgent, o->identity_agent); 2507 dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices); 2508 dump_cfg_string(oKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : KEX_CLIENT_KEX); 2509 dump_cfg_string(oLocalCommand, o->local_command); 2510 dump_cfg_string(oRemoteCommand, o->remote_command); 2511 dump_cfg_string(oLogLevel, log_level_name(o->log_level)); 2512 dump_cfg_string(oMacs, o->macs ? o->macs : KEX_CLIENT_MAC); 2513 #ifdef ENABLE_PKCS11 2514 dump_cfg_string(oPKCS11Provider, o->pkcs11_provider); 2515 #endif 2516 dump_cfg_string(oPreferredAuthentications, o->preferred_authentications); 2517 dump_cfg_string(oPubkeyAcceptedKeyTypes, o->pubkey_key_types); 2518 dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys); 2519 dump_cfg_string(oXAuthLocation, o->xauth_location); 2520 2521 /* Forwards */ 2522 dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards); 2523 dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards); 2524 dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards); 2525 2526 /* String array options */ 2527 dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files); 2528 dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains); 2529 dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles); 2530 dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles); 2531 dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env); 2532 2533 /* Special cases */ 2534 2535 /* oConnectTimeout */ 2536 if (o->connection_timeout == -1) 2537 printf("connecttimeout none\n"); 2538 else 2539 dump_cfg_int(oConnectTimeout, o->connection_timeout); 2540 2541 /* oTunnelDevice */ 2542 printf("tunneldevice"); 2543 if (o->tun_local == SSH_TUNID_ANY) 2544 printf(" any"); 2545 else 2546 printf(" %d", o->tun_local); 2547 if (o->tun_remote == SSH_TUNID_ANY) 2548 printf(":any"); 2549 else 2550 printf(":%d", o->tun_remote); 2551 printf("\n"); 2552 2553 /* oCanonicalizePermittedCNAMEs */ 2554 if ( o->num_permitted_cnames > 0) { 2555 printf("canonicalizePermittedcnames"); 2556 for (i = 0; i < o->num_permitted_cnames; i++) { 2557 printf(" %s:%s", o->permitted_cnames[i].source_list, 2558 o->permitted_cnames[i].target_list); 2559 } 2560 printf("\n"); 2561 } 2562 2563 /* oControlPersist */ 2564 if (o->control_persist == 0 || o->control_persist_timeout == 0) 2565 dump_cfg_fmtint(oControlPersist, o->control_persist); 2566 else 2567 dump_cfg_int(oControlPersist, o->control_persist_timeout); 2568 2569 /* oEscapeChar */ 2570 if (o->escape_char == SSH_ESCAPECHAR_NONE) 2571 printf("escapechar none\n"); 2572 else { 2573 vis(buf, o->escape_char, VIS_WHITE, 0); 2574 printf("escapechar %s\n", buf); 2575 } 2576 2577 /* oIPQoS */ 2578 printf("ipqos %s ", iptos2str(o->ip_qos_interactive)); 2579 printf("%s\n", iptos2str(o->ip_qos_bulk)); 2580 2581 /* oRekeyLimit */ 2582 printf("rekeylimit %llu %d\n", 2583 (unsigned long long)o->rekey_limit, o->rekey_interval); 2584 2585 /* oStreamLocalBindMask */ 2586 printf("streamlocalbindmask 0%o\n", 2587 o->fwd_opts.streamlocal_bind_mask); 2588 2589 /* oProxyCommand / oProxyJump */ 2590 if (o->jump_host == NULL) 2591 dump_cfg_string(oProxyCommand, o->proxy_command); 2592 else { 2593 /* Check for numeric addresses */ 2594 i = strchr(o->jump_host, ':') != NULL || 2595 strspn(o->jump_host, "1234567890.") == strlen(o->jump_host); 2596 snprintf(buf, sizeof(buf), "%d", o->jump_port); 2597 printf("proxyjump %s%s%s%s%s%s%s%s%s\n", 2598 /* optional additional jump spec */ 2599 o->jump_extra == NULL ? "" : o->jump_extra, 2600 o->jump_extra == NULL ? "" : ",", 2601 /* optional user */ 2602 o->jump_user == NULL ? "" : o->jump_user, 2603 o->jump_user == NULL ? "" : "@", 2604 /* opening [ if hostname is numeric */ 2605 i ? "[" : "", 2606 /* mandatory hostname */ 2607 o->jump_host, 2608 /* closing ] if hostname is numeric */ 2609 i ? "]" : "", 2610 /* optional port number */ 2611 o->jump_port <= 0 ? "" : ":", 2612 o->jump_port <= 0 ? "" : buf); 2613 } 2614 } 2615