1 /* $OpenBSD: readconf.c,v 1.283 2018/02/23 15:58:37 markus 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, oBindInterface, 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 { "bindinterface", oBindInterface }, 255 { "clearallforwardings", oClearAllForwardings }, 256 { "enablesshkeysign", oEnableSSHKeysign }, 257 { "verifyhostkeydns", oVerifyHostKeyDNS }, 258 { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost }, 259 { "rekeylimit", oRekeyLimit }, 260 { "connecttimeout", oConnectTimeout }, 261 { "addressfamily", oAddressFamily }, 262 { "serveraliveinterval", oServerAliveInterval }, 263 { "serveralivecountmax", oServerAliveCountMax }, 264 { "sendenv", oSendEnv }, 265 { "controlpath", oControlPath }, 266 { "controlmaster", oControlMaster }, 267 { "controlpersist", oControlPersist }, 268 { "hashknownhosts", oHashKnownHosts }, 269 { "include", oInclude }, 270 { "tunnel", oTunnel }, 271 { "tunneldevice", oTunnelDevice }, 272 { "localcommand", oLocalCommand }, 273 { "permitlocalcommand", oPermitLocalCommand }, 274 { "remotecommand", oRemoteCommand }, 275 { "visualhostkey", oVisualHostKey }, 276 { "kexalgorithms", oKexAlgorithms }, 277 { "ipqos", oIPQoS }, 278 { "requesttty", oRequestTTY }, 279 { "proxyusefdpass", oProxyUseFdpass }, 280 { "canonicaldomains", oCanonicalDomains }, 281 { "canonicalizefallbacklocal", oCanonicalizeFallbackLocal }, 282 { "canonicalizehostname", oCanonicalizeHostname }, 283 { "canonicalizemaxdots", oCanonicalizeMaxDots }, 284 { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs }, 285 { "streamlocalbindmask", oStreamLocalBindMask }, 286 { "streamlocalbindunlink", oStreamLocalBindUnlink }, 287 { "revokedhostkeys", oRevokedHostKeys }, 288 { "fingerprinthash", oFingerprintHash }, 289 { "updatehostkeys", oUpdateHostkeys }, 290 { "hostbasedkeytypes", oHostbasedKeyTypes }, 291 { "pubkeyacceptedkeytypes", oPubkeyAcceptedKeyTypes }, 292 { "ignoreunknown", oIgnoreUnknown }, 293 { "proxyjump", oProxyJump }, 294 295 { NULL, oBadOption } 296 }; 297 298 /* 299 * Adds a local TCP/IP port forward to options. Never returns if there is an 300 * error. 301 */ 302 303 void 304 add_local_forward(Options *options, const struct Forward *newfwd) 305 { 306 struct Forward *fwd; 307 extern uid_t original_real_uid; 308 int i; 309 310 if (!bind_permitted(newfwd->listen_port, original_real_uid) && 311 newfwd->listen_path == NULL) 312 fatal("Privileged ports can only be forwarded by root."); 313 /* Don't add duplicates */ 314 for (i = 0; i < options->num_local_forwards; i++) { 315 if (forward_equals(newfwd, options->local_forwards + i)) 316 return; 317 } 318 options->local_forwards = xreallocarray(options->local_forwards, 319 options->num_local_forwards + 1, 320 sizeof(*options->local_forwards)); 321 fwd = &options->local_forwards[options->num_local_forwards++]; 322 323 fwd->listen_host = newfwd->listen_host; 324 fwd->listen_port = newfwd->listen_port; 325 fwd->listen_path = newfwd->listen_path; 326 fwd->connect_host = newfwd->connect_host; 327 fwd->connect_port = newfwd->connect_port; 328 fwd->connect_path = newfwd->connect_path; 329 } 330 331 /* 332 * Adds a remote TCP/IP port forward to options. Never returns if there is 333 * an error. 334 */ 335 336 void 337 add_remote_forward(Options *options, const struct Forward *newfwd) 338 { 339 struct Forward *fwd; 340 int i; 341 342 /* Don't add duplicates */ 343 for (i = 0; i < options->num_remote_forwards; i++) { 344 if (forward_equals(newfwd, options->remote_forwards + i)) 345 return; 346 } 347 options->remote_forwards = xreallocarray(options->remote_forwards, 348 options->num_remote_forwards + 1, 349 sizeof(*options->remote_forwards)); 350 fwd = &options->remote_forwards[options->num_remote_forwards++]; 351 352 fwd->listen_host = newfwd->listen_host; 353 fwd->listen_port = newfwd->listen_port; 354 fwd->listen_path = newfwd->listen_path; 355 fwd->connect_host = newfwd->connect_host; 356 fwd->connect_port = newfwd->connect_port; 357 fwd->connect_path = newfwd->connect_path; 358 fwd->handle = newfwd->handle; 359 fwd->allocated_port = 0; 360 } 361 362 static void 363 clear_forwardings(Options *options) 364 { 365 int i; 366 367 for (i = 0; i < options->num_local_forwards; i++) { 368 free(options->local_forwards[i].listen_host); 369 free(options->local_forwards[i].listen_path); 370 free(options->local_forwards[i].connect_host); 371 free(options->local_forwards[i].connect_path); 372 } 373 if (options->num_local_forwards > 0) { 374 free(options->local_forwards); 375 options->local_forwards = NULL; 376 } 377 options->num_local_forwards = 0; 378 for (i = 0; i < options->num_remote_forwards; i++) { 379 free(options->remote_forwards[i].listen_host); 380 free(options->remote_forwards[i].listen_path); 381 free(options->remote_forwards[i].connect_host); 382 free(options->remote_forwards[i].connect_path); 383 } 384 if (options->num_remote_forwards > 0) { 385 free(options->remote_forwards); 386 options->remote_forwards = NULL; 387 } 388 options->num_remote_forwards = 0; 389 options->tun_open = SSH_TUNMODE_NO; 390 } 391 392 void 393 add_certificate_file(Options *options, const char *path, int userprovided) 394 { 395 int i; 396 397 if (options->num_certificate_files >= SSH_MAX_CERTIFICATE_FILES) 398 fatal("Too many certificate files specified (max %d)", 399 SSH_MAX_CERTIFICATE_FILES); 400 401 /* Avoid registering duplicates */ 402 for (i = 0; i < options->num_certificate_files; i++) { 403 if (options->certificate_file_userprovided[i] == userprovided && 404 strcmp(options->certificate_files[i], path) == 0) { 405 debug2("%s: ignoring duplicate key %s", __func__, path); 406 return; 407 } 408 } 409 410 options->certificate_file_userprovided[options->num_certificate_files] = 411 userprovided; 412 options->certificate_files[options->num_certificate_files++] = 413 xstrdup(path); 414 } 415 416 void 417 add_identity_file(Options *options, const char *dir, const char *filename, 418 int userprovided) 419 { 420 char *path; 421 int i; 422 423 if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES) 424 fatal("Too many identity files specified (max %d)", 425 SSH_MAX_IDENTITY_FILES); 426 427 if (dir == NULL) /* no dir, filename is absolute */ 428 path = xstrdup(filename); 429 else if (xasprintf(&path, "%s%s", dir, filename) >= PATH_MAX) 430 fatal("Identity file path %s too long", path); 431 432 /* Avoid registering duplicates */ 433 for (i = 0; i < options->num_identity_files; i++) { 434 if (options->identity_file_userprovided[i] == userprovided && 435 strcmp(options->identity_files[i], path) == 0) { 436 debug2("%s: ignoring duplicate key %s", __func__, path); 437 free(path); 438 return; 439 } 440 } 441 442 options->identity_file_userprovided[options->num_identity_files] = 443 userprovided; 444 options->identity_files[options->num_identity_files++] = path; 445 } 446 447 int 448 default_ssh_port(void) 449 { 450 static int port; 451 struct servent *sp; 452 453 if (port == 0) { 454 sp = getservbyname(SSH_SERVICE_NAME, "tcp"); 455 port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT; 456 } 457 return port; 458 } 459 460 /* 461 * Execute a command in a shell. 462 * Return its exit status or -1 on abnormal exit. 463 */ 464 static int 465 execute_in_shell(const char *cmd) 466 { 467 char *shell; 468 pid_t pid; 469 int devnull, status; 470 extern uid_t original_real_uid; 471 472 if ((shell = getenv("SHELL")) == NULL) 473 shell = _PATH_BSHELL; 474 475 /* Need this to redirect subprocess stdin/out */ 476 if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) 477 fatal("open(/dev/null): %s", strerror(errno)); 478 479 debug("Executing command: '%.500s'", cmd); 480 481 /* Fork and execute the command. */ 482 if ((pid = fork()) == 0) { 483 char *argv[4]; 484 485 /* Child. Permanently give up superuser privileges. */ 486 permanently_drop_suid(original_real_uid); 487 488 /* Redirect child stdin and stdout. Leave stderr */ 489 if (dup2(devnull, STDIN_FILENO) == -1) 490 fatal("dup2: %s", strerror(errno)); 491 if (dup2(devnull, STDOUT_FILENO) == -1) 492 fatal("dup2: %s", strerror(errno)); 493 if (devnull > STDERR_FILENO) 494 close(devnull); 495 closefrom(STDERR_FILENO + 1); 496 497 argv[0] = shell; 498 argv[1] = "-c"; 499 argv[2] = xstrdup(cmd); 500 argv[3] = NULL; 501 502 execv(argv[0], argv); 503 error("Unable to execute '%.100s': %s", cmd, strerror(errno)); 504 /* Die with signal to make this error apparent to parent. */ 505 signal(SIGTERM, SIG_DFL); 506 kill(getpid(), SIGTERM); 507 _exit(1); 508 } 509 /* Parent. */ 510 if (pid < 0) 511 fatal("%s: fork: %.100s", __func__, strerror(errno)); 512 513 close(devnull); 514 515 while (waitpid(pid, &status, 0) == -1) { 516 if (errno != EINTR && errno != EAGAIN) 517 fatal("%s: waitpid: %s", __func__, strerror(errno)); 518 } 519 if (!WIFEXITED(status)) { 520 error("command '%.100s' exited abnormally", cmd); 521 return -1; 522 } 523 debug3("command returned status %d", WEXITSTATUS(status)); 524 return WEXITSTATUS(status); 525 } 526 527 /* 528 * Parse and execute a Match directive. 529 */ 530 static int 531 match_cfg_line(Options *options, char **condition, struct passwd *pw, 532 const char *host_arg, const char *original_host, int post_canon, 533 const char *filename, int linenum) 534 { 535 char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria; 536 const char *ruser; 537 int r, port, this_result, result = 1, attributes = 0, negate; 538 char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; 539 540 /* 541 * Configuration is likely to be incomplete at this point so we 542 * must be prepared to use default values. 543 */ 544 port = options->port <= 0 ? default_ssh_port() : options->port; 545 ruser = options->user == NULL ? pw->pw_name : options->user; 546 if (post_canon) { 547 host = xstrdup(options->hostname); 548 } else if (options->hostname != NULL) { 549 /* NB. Please keep in sync with ssh.c:main() */ 550 host = percent_expand(options->hostname, 551 "h", host_arg, (char *)NULL); 552 } else { 553 host = xstrdup(host_arg); 554 } 555 556 debug2("checking match for '%s' host %s originally %s", 557 cp, host, original_host); 558 while ((oattrib = attrib = strdelim(&cp)) && *attrib != '\0') { 559 criteria = NULL; 560 this_result = 1; 561 if ((negate = attrib[0] == '!')) 562 attrib++; 563 /* criteria "all" and "canonical" have no argument */ 564 if (strcasecmp(attrib, "all") == 0) { 565 if (attributes > 1 || 566 ((arg = strdelim(&cp)) != NULL && *arg != '\0')) { 567 error("%.200s line %d: '%s' cannot be combined " 568 "with other Match attributes", 569 filename, linenum, oattrib); 570 result = -1; 571 goto out; 572 } 573 if (result) 574 result = negate ? 0 : 1; 575 goto out; 576 } 577 attributes++; 578 if (strcasecmp(attrib, "canonical") == 0) { 579 r = !!post_canon; /* force bitmask member to boolean */ 580 if (r == (negate ? 1 : 0)) 581 this_result = result = 0; 582 debug3("%.200s line %d: %smatched '%s'", 583 filename, linenum, 584 this_result ? "" : "not ", oattrib); 585 continue; 586 } 587 /* All other criteria require an argument */ 588 if ((arg = strdelim(&cp)) == NULL || *arg == '\0') { 589 error("Missing Match criteria for %s", attrib); 590 result = -1; 591 goto out; 592 } 593 if (strcasecmp(attrib, "host") == 0) { 594 criteria = xstrdup(host); 595 r = match_hostname(host, arg) == 1; 596 if (r == (negate ? 1 : 0)) 597 this_result = result = 0; 598 } else if (strcasecmp(attrib, "originalhost") == 0) { 599 criteria = xstrdup(original_host); 600 r = match_hostname(original_host, arg) == 1; 601 if (r == (negate ? 1 : 0)) 602 this_result = result = 0; 603 } else if (strcasecmp(attrib, "user") == 0) { 604 criteria = xstrdup(ruser); 605 r = match_pattern_list(ruser, arg, 0) == 1; 606 if (r == (negate ? 1 : 0)) 607 this_result = result = 0; 608 } else if (strcasecmp(attrib, "localuser") == 0) { 609 criteria = xstrdup(pw->pw_name); 610 r = match_pattern_list(pw->pw_name, arg, 0) == 1; 611 if (r == (negate ? 1 : 0)) 612 this_result = result = 0; 613 } else if (strcasecmp(attrib, "exec") == 0) { 614 if (gethostname(thishost, sizeof(thishost)) == -1) 615 fatal("gethostname: %s", strerror(errno)); 616 strlcpy(shorthost, thishost, sizeof(shorthost)); 617 shorthost[strcspn(thishost, ".")] = '\0'; 618 snprintf(portstr, sizeof(portstr), "%d", port); 619 620 cmd = percent_expand(arg, 621 "L", shorthost, 622 "d", pw->pw_dir, 623 "h", host, 624 "l", thishost, 625 "n", original_host, 626 "p", portstr, 627 "r", ruser, 628 "u", pw->pw_name, 629 (char *)NULL); 630 if (result != 1) { 631 /* skip execution if prior predicate failed */ 632 debug3("%.200s line %d: skipped exec " 633 "\"%.100s\"", filename, linenum, cmd); 634 free(cmd); 635 continue; 636 } 637 r = execute_in_shell(cmd); 638 if (r == -1) { 639 fatal("%.200s line %d: match exec " 640 "'%.100s' error", filename, 641 linenum, cmd); 642 } 643 criteria = xstrdup(cmd); 644 free(cmd); 645 /* Force exit status to boolean */ 646 r = r == 0; 647 if (r == (negate ? 1 : 0)) 648 this_result = result = 0; 649 } else { 650 error("Unsupported Match attribute %s", attrib); 651 result = -1; 652 goto out; 653 } 654 debug3("%.200s line %d: %smatched '%s \"%.100s\"' ", 655 filename, linenum, this_result ? "": "not ", 656 oattrib, criteria); 657 free(criteria); 658 } 659 if (attributes == 0) { 660 error("One or more attributes required for Match"); 661 result = -1; 662 goto out; 663 } 664 out: 665 if (result != -1) 666 debug2("match %sfound", result ? "" : "not "); 667 *condition = cp; 668 free(host); 669 return result; 670 } 671 672 /* 673 * Returns the number of the token pointed to by cp or oBadOption. 674 */ 675 static OpCodes 676 parse_token(const char *cp, const char *filename, int linenum, 677 const char *ignored_unknown) 678 { 679 int i; 680 681 for (i = 0; keywords[i].name; i++) 682 if (strcmp(cp, keywords[i].name) == 0) 683 return keywords[i].opcode; 684 if (ignored_unknown != NULL && 685 match_pattern_list(cp, ignored_unknown, 1) == 1) 686 return oIgnoredUnknownOption; 687 error("%s: line %d: Bad configuration option: %s", 688 filename, linenum, cp); 689 return oBadOption; 690 } 691 692 /* Multistate option parsing */ 693 struct multistate { 694 char *key; 695 int value; 696 }; 697 static const struct multistate multistate_flag[] = { 698 { "true", 1 }, 699 { "false", 0 }, 700 { "yes", 1 }, 701 { "no", 0 }, 702 { NULL, -1 } 703 }; 704 static const struct multistate multistate_yesnoask[] = { 705 { "true", 1 }, 706 { "false", 0 }, 707 { "yes", 1 }, 708 { "no", 0 }, 709 { "ask", 2 }, 710 { NULL, -1 } 711 }; 712 static const struct multistate multistate_strict_hostkey[] = { 713 { "true", SSH_STRICT_HOSTKEY_YES }, 714 { "false", SSH_STRICT_HOSTKEY_OFF }, 715 { "yes", SSH_STRICT_HOSTKEY_YES }, 716 { "no", SSH_STRICT_HOSTKEY_OFF }, 717 { "ask", SSH_STRICT_HOSTKEY_ASK }, 718 { "off", SSH_STRICT_HOSTKEY_OFF }, 719 { "accept-new", SSH_STRICT_HOSTKEY_NEW }, 720 { NULL, -1 } 721 }; 722 static const struct multistate multistate_yesnoaskconfirm[] = { 723 { "true", 1 }, 724 { "false", 0 }, 725 { "yes", 1 }, 726 { "no", 0 }, 727 { "ask", 2 }, 728 { "confirm", 3 }, 729 { NULL, -1 } 730 }; 731 static const struct multistate multistate_addressfamily[] = { 732 { "inet", AF_INET }, 733 { "inet6", AF_INET6 }, 734 { "any", AF_UNSPEC }, 735 { NULL, -1 } 736 }; 737 static const struct multistate multistate_controlmaster[] = { 738 { "true", SSHCTL_MASTER_YES }, 739 { "yes", SSHCTL_MASTER_YES }, 740 { "false", SSHCTL_MASTER_NO }, 741 { "no", SSHCTL_MASTER_NO }, 742 { "auto", SSHCTL_MASTER_AUTO }, 743 { "ask", SSHCTL_MASTER_ASK }, 744 { "autoask", SSHCTL_MASTER_AUTO_ASK }, 745 { NULL, -1 } 746 }; 747 static const struct multistate multistate_tunnel[] = { 748 { "ethernet", SSH_TUNMODE_ETHERNET }, 749 { "point-to-point", SSH_TUNMODE_POINTOPOINT }, 750 { "true", SSH_TUNMODE_DEFAULT }, 751 { "yes", SSH_TUNMODE_DEFAULT }, 752 { "false", SSH_TUNMODE_NO }, 753 { "no", SSH_TUNMODE_NO }, 754 { NULL, -1 } 755 }; 756 static const struct multistate multistate_requesttty[] = { 757 { "true", REQUEST_TTY_YES }, 758 { "yes", REQUEST_TTY_YES }, 759 { "false", REQUEST_TTY_NO }, 760 { "no", REQUEST_TTY_NO }, 761 { "force", REQUEST_TTY_FORCE }, 762 { "auto", REQUEST_TTY_AUTO }, 763 { NULL, -1 } 764 }; 765 static const struct multistate multistate_canonicalizehostname[] = { 766 { "true", SSH_CANONICALISE_YES }, 767 { "false", SSH_CANONICALISE_NO }, 768 { "yes", SSH_CANONICALISE_YES }, 769 { "no", SSH_CANONICALISE_NO }, 770 { "always", SSH_CANONICALISE_ALWAYS }, 771 { NULL, -1 } 772 }; 773 774 /* 775 * Processes a single option line as used in the configuration files. This 776 * only sets those values that have not already been set. 777 */ 778 int 779 process_config_line(Options *options, struct passwd *pw, const char *host, 780 const char *original_host, char *line, const char *filename, 781 int linenum, int *activep, int flags) 782 { 783 return process_config_line_depth(options, pw, host, original_host, 784 line, filename, linenum, activep, flags, 0); 785 } 786 787 #define WHITESPACE " \t\r\n" 788 static int 789 process_config_line_depth(Options *options, struct passwd *pw, const char *host, 790 const char *original_host, char *line, const char *filename, 791 int linenum, int *activep, int flags, int depth) 792 { 793 char *s, **charptr, *endofnumber, *keyword, *arg, *arg2; 794 char **cpptr, fwdarg[256]; 795 u_int i, *uintptr, max_entries = 0; 796 int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0; 797 int remotefwd, dynamicfwd; 798 LogLevel *log_level_ptr; 799 SyslogFacility *log_facility_ptr; 800 long long val64; 801 size_t len; 802 struct Forward fwd; 803 const struct multistate *multistate_ptr; 804 struct allowed_cname *cname; 805 glob_t gl; 806 const char *errstr; 807 808 if (activep == NULL) { /* We are processing a command line directive */ 809 cmdline = 1; 810 activep = &cmdline; 811 } 812 813 /* Strip trailing whitespace. Allow \f (form feed) at EOL only */ 814 if ((len = strlen(line)) == 0) 815 return 0; 816 for (len--; len > 0; len--) { 817 if (strchr(WHITESPACE "\f", line[len]) == NULL) 818 break; 819 line[len] = '\0'; 820 } 821 822 s = line; 823 /* Get the keyword. (Each line is supposed to begin with a keyword). */ 824 if ((keyword = strdelim(&s)) == NULL) 825 return 0; 826 /* Ignore leading whitespace. */ 827 if (*keyword == '\0') 828 keyword = strdelim(&s); 829 if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#') 830 return 0; 831 /* Match lowercase keyword */ 832 lowercase(keyword); 833 834 opcode = parse_token(keyword, filename, linenum, 835 options->ignored_unknown); 836 837 switch (opcode) { 838 case oBadOption: 839 /* don't panic, but count bad options */ 840 return -1; 841 case oIgnore: 842 return 0; 843 case oIgnoredUnknownOption: 844 debug("%s line %d: Ignored unknown option \"%s\"", 845 filename, linenum, keyword); 846 return 0; 847 case oConnectTimeout: 848 intptr = &options->connection_timeout; 849 parse_time: 850 arg = strdelim(&s); 851 if (!arg || *arg == '\0') 852 fatal("%s line %d: missing time value.", 853 filename, linenum); 854 if (strcmp(arg, "none") == 0) 855 value = -1; 856 else if ((value = convtime(arg)) == -1) 857 fatal("%s line %d: invalid time value.", 858 filename, linenum); 859 if (*activep && *intptr == -1) 860 *intptr = value; 861 break; 862 863 case oForwardAgent: 864 intptr = &options->forward_agent; 865 parse_flag: 866 multistate_ptr = multistate_flag; 867 parse_multistate: 868 arg = strdelim(&s); 869 if (!arg || *arg == '\0') 870 fatal("%s line %d: missing argument.", 871 filename, linenum); 872 value = -1; 873 for (i = 0; multistate_ptr[i].key != NULL; i++) { 874 if (strcasecmp(arg, multistate_ptr[i].key) == 0) { 875 value = multistate_ptr[i].value; 876 break; 877 } 878 } 879 if (value == -1) 880 fatal("%s line %d: unsupported option \"%s\".", 881 filename, linenum, arg); 882 if (*activep && *intptr == -1) 883 *intptr = value; 884 break; 885 886 case oForwardX11: 887 intptr = &options->forward_x11; 888 goto parse_flag; 889 890 case oForwardX11Trusted: 891 intptr = &options->forward_x11_trusted; 892 goto parse_flag; 893 894 case oForwardX11Timeout: 895 intptr = &options->forward_x11_timeout; 896 goto parse_time; 897 898 case oGatewayPorts: 899 intptr = &options->fwd_opts.gateway_ports; 900 goto parse_flag; 901 902 case oExitOnForwardFailure: 903 intptr = &options->exit_on_forward_failure; 904 goto parse_flag; 905 906 case oUsePrivilegedPort: 907 intptr = &options->use_privileged_port; 908 goto parse_flag; 909 910 case oPasswordAuthentication: 911 intptr = &options->password_authentication; 912 goto parse_flag; 913 914 case oKbdInteractiveAuthentication: 915 intptr = &options->kbd_interactive_authentication; 916 goto parse_flag; 917 918 case oKbdInteractiveDevices: 919 charptr = &options->kbd_interactive_devices; 920 goto parse_string; 921 922 case oPubkeyAuthentication: 923 intptr = &options->pubkey_authentication; 924 goto parse_flag; 925 926 case oHostbasedAuthentication: 927 intptr = &options->hostbased_authentication; 928 goto parse_flag; 929 930 case oChallengeResponseAuthentication: 931 intptr = &options->challenge_response_authentication; 932 goto parse_flag; 933 934 case oGssAuthentication: 935 intptr = &options->gss_authentication; 936 goto parse_flag; 937 938 case oGssDelegateCreds: 939 intptr = &options->gss_deleg_creds; 940 goto parse_flag; 941 942 case oBatchMode: 943 intptr = &options->batch_mode; 944 goto parse_flag; 945 946 case oCheckHostIP: 947 intptr = &options->check_host_ip; 948 goto parse_flag; 949 950 case oVerifyHostKeyDNS: 951 intptr = &options->verify_host_key_dns; 952 multistate_ptr = multistate_yesnoask; 953 goto parse_multistate; 954 955 case oStrictHostKeyChecking: 956 intptr = &options->strict_host_key_checking; 957 multistate_ptr = multistate_strict_hostkey; 958 goto parse_multistate; 959 960 case oCompression: 961 intptr = &options->compression; 962 goto parse_flag; 963 964 case oTCPKeepAlive: 965 intptr = &options->tcp_keep_alive; 966 goto parse_flag; 967 968 case oNoHostAuthenticationForLocalhost: 969 intptr = &options->no_host_authentication_for_localhost; 970 goto parse_flag; 971 972 case oNumberOfPasswordPrompts: 973 intptr = &options->number_of_password_prompts; 974 goto parse_int; 975 976 case oRekeyLimit: 977 arg = strdelim(&s); 978 if (!arg || *arg == '\0') 979 fatal("%.200s line %d: Missing argument.", filename, 980 linenum); 981 if (strcmp(arg, "default") == 0) { 982 val64 = 0; 983 } else { 984 if (scan_scaled(arg, &val64) == -1) 985 fatal("%.200s line %d: Bad number '%s': %s", 986 filename, linenum, arg, strerror(errno)); 987 if (val64 != 0 && val64 < 16) 988 fatal("%.200s line %d: RekeyLimit too small", 989 filename, linenum); 990 } 991 if (*activep && options->rekey_limit == -1) 992 options->rekey_limit = val64; 993 if (s != NULL) { /* optional rekey interval present */ 994 if (strcmp(s, "none") == 0) { 995 (void)strdelim(&s); /* discard */ 996 break; 997 } 998 intptr = &options->rekey_interval; 999 goto parse_time; 1000 } 1001 break; 1002 1003 case oIdentityFile: 1004 arg = strdelim(&s); 1005 if (!arg || *arg == '\0') 1006 fatal("%.200s line %d: Missing argument.", filename, linenum); 1007 if (*activep) { 1008 intptr = &options->num_identity_files; 1009 if (*intptr >= SSH_MAX_IDENTITY_FILES) 1010 fatal("%.200s line %d: Too many identity files specified (max %d).", 1011 filename, linenum, SSH_MAX_IDENTITY_FILES); 1012 add_identity_file(options, NULL, 1013 arg, flags & SSHCONF_USERCONF); 1014 } 1015 break; 1016 1017 case oCertificateFile: 1018 arg = strdelim(&s); 1019 if (!arg || *arg == '\0') 1020 fatal("%.200s line %d: Missing argument.", 1021 filename, linenum); 1022 if (*activep) { 1023 intptr = &options->num_certificate_files; 1024 if (*intptr >= SSH_MAX_CERTIFICATE_FILES) { 1025 fatal("%.200s line %d: Too many certificate " 1026 "files specified (max %d).", 1027 filename, linenum, 1028 SSH_MAX_CERTIFICATE_FILES); 1029 } 1030 add_certificate_file(options, arg, 1031 flags & SSHCONF_USERCONF); 1032 } 1033 break; 1034 1035 case oXAuthLocation: 1036 charptr=&options->xauth_location; 1037 goto parse_string; 1038 1039 case oUser: 1040 charptr = &options->user; 1041 parse_string: 1042 arg = strdelim(&s); 1043 if (!arg || *arg == '\0') 1044 fatal("%.200s line %d: Missing argument.", 1045 filename, linenum); 1046 if (*activep && *charptr == NULL) 1047 *charptr = xstrdup(arg); 1048 break; 1049 1050 case oGlobalKnownHostsFile: 1051 cpptr = (char **)&options->system_hostfiles; 1052 uintptr = &options->num_system_hostfiles; 1053 max_entries = SSH_MAX_HOSTS_FILES; 1054 parse_char_array: 1055 if (*activep && *uintptr == 0) { 1056 while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1057 if ((*uintptr) >= max_entries) 1058 fatal("%s line %d: " 1059 "too many authorized keys files.", 1060 filename, linenum); 1061 cpptr[(*uintptr)++] = xstrdup(arg); 1062 } 1063 } 1064 return 0; 1065 1066 case oUserKnownHostsFile: 1067 cpptr = (char **)&options->user_hostfiles; 1068 uintptr = &options->num_user_hostfiles; 1069 max_entries = SSH_MAX_HOSTS_FILES; 1070 goto parse_char_array; 1071 1072 case oHostName: 1073 charptr = &options->hostname; 1074 goto parse_string; 1075 1076 case oHostKeyAlias: 1077 charptr = &options->host_key_alias; 1078 goto parse_string; 1079 1080 case oPreferredAuthentications: 1081 charptr = &options->preferred_authentications; 1082 goto parse_string; 1083 1084 case oBindAddress: 1085 charptr = &options->bind_address; 1086 goto parse_string; 1087 1088 case oBindInterface: 1089 charptr = &options->bind_interface; 1090 goto parse_string; 1091 1092 case oPKCS11Provider: 1093 charptr = &options->pkcs11_provider; 1094 goto parse_string; 1095 1096 case oProxyCommand: 1097 charptr = &options->proxy_command; 1098 /* Ignore ProxyCommand if ProxyJump already specified */ 1099 if (options->jump_host != NULL) 1100 charptr = &options->jump_host; /* Skip below */ 1101 parse_command: 1102 if (s == NULL) 1103 fatal("%.200s line %d: Missing argument.", filename, linenum); 1104 len = strspn(s, WHITESPACE "="); 1105 if (*activep && *charptr == NULL) 1106 *charptr = xstrdup(s + len); 1107 return 0; 1108 1109 case oProxyJump: 1110 if (s == NULL) { 1111 fatal("%.200s line %d: Missing argument.", 1112 filename, linenum); 1113 } 1114 len = strspn(s, WHITESPACE "="); 1115 if (parse_jump(s + len, options, *activep) == -1) { 1116 fatal("%.200s line %d: Invalid ProxyJump \"%s\"", 1117 filename, linenum, s + len); 1118 } 1119 return 0; 1120 1121 case oPort: 1122 intptr = &options->port; 1123 parse_int: 1124 arg = strdelim(&s); 1125 if ((errstr = atoi_err(arg, &value)) != NULL) 1126 fatal("%s line %d: integer value %s.", 1127 filename, linenum, errstr); 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 if (!valid_domain(arg, 1, &errstr)) { 1523 fatal("%s line %d: %s", filename, linenum, 1524 errstr); 1525 } 1526 if (!*activep || value) 1527 continue; 1528 if (options->num_canonical_domains >= MAX_CANON_DOMAINS) 1529 fatal("%s line %d: too many hostname suffixes.", 1530 filename, linenum); 1531 options->canonical_domains[ 1532 options->num_canonical_domains++] = xstrdup(arg); 1533 } 1534 break; 1535 1536 case oCanonicalizePermittedCNAMEs: 1537 value = options->num_permitted_cnames != 0; 1538 while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1539 /* Either '*' for everything or 'list:list' */ 1540 if (strcmp(arg, "*") == 0) 1541 arg2 = arg; 1542 else { 1543 lowercase(arg); 1544 if ((arg2 = strchr(arg, ':')) == NULL || 1545 arg2[1] == '\0') { 1546 fatal("%s line %d: " 1547 "Invalid permitted CNAME \"%s\"", 1548 filename, linenum, arg); 1549 } 1550 *arg2 = '\0'; 1551 arg2++; 1552 } 1553 if (!*activep || value) 1554 continue; 1555 if (options->num_permitted_cnames >= MAX_CANON_DOMAINS) 1556 fatal("%s line %d: too many permitted CNAMEs.", 1557 filename, linenum); 1558 cname = options->permitted_cnames + 1559 options->num_permitted_cnames++; 1560 cname->source_list = xstrdup(arg); 1561 cname->target_list = xstrdup(arg2); 1562 } 1563 break; 1564 1565 case oCanonicalizeHostname: 1566 intptr = &options->canonicalize_hostname; 1567 multistate_ptr = multistate_canonicalizehostname; 1568 goto parse_multistate; 1569 1570 case oCanonicalizeMaxDots: 1571 intptr = &options->canonicalize_max_dots; 1572 goto parse_int; 1573 1574 case oCanonicalizeFallbackLocal: 1575 intptr = &options->canonicalize_fallback_local; 1576 goto parse_flag; 1577 1578 case oStreamLocalBindMask: 1579 arg = strdelim(&s); 1580 if (!arg || *arg == '\0') 1581 fatal("%.200s line %d: Missing StreamLocalBindMask argument.", filename, linenum); 1582 /* Parse mode in octal format */ 1583 value = strtol(arg, &endofnumber, 8); 1584 if (arg == endofnumber || value < 0 || value > 0777) 1585 fatal("%.200s line %d: Bad mask.", filename, linenum); 1586 options->fwd_opts.streamlocal_bind_mask = (mode_t)value; 1587 break; 1588 1589 case oStreamLocalBindUnlink: 1590 intptr = &options->fwd_opts.streamlocal_bind_unlink; 1591 goto parse_flag; 1592 1593 case oRevokedHostKeys: 1594 charptr = &options->revoked_host_keys; 1595 goto parse_string; 1596 1597 case oFingerprintHash: 1598 intptr = &options->fingerprint_hash; 1599 arg = strdelim(&s); 1600 if (!arg || *arg == '\0') 1601 fatal("%.200s line %d: Missing argument.", 1602 filename, linenum); 1603 if ((value = ssh_digest_alg_by_name(arg)) == -1) 1604 fatal("%.200s line %d: Invalid hash algorithm \"%s\".", 1605 filename, linenum, arg); 1606 if (*activep && *intptr == -1) 1607 *intptr = value; 1608 break; 1609 1610 case oUpdateHostkeys: 1611 intptr = &options->update_hostkeys; 1612 multistate_ptr = multistate_yesnoask; 1613 goto parse_multistate; 1614 1615 case oHostbasedKeyTypes: 1616 charptr = &options->hostbased_key_types; 1617 goto parse_keytypes; 1618 1619 case oPubkeyAcceptedKeyTypes: 1620 charptr = &options->pubkey_key_types; 1621 goto parse_keytypes; 1622 1623 case oAddKeysToAgent: 1624 intptr = &options->add_keys_to_agent; 1625 multistate_ptr = multistate_yesnoaskconfirm; 1626 goto parse_multistate; 1627 1628 case oIdentityAgent: 1629 charptr = &options->identity_agent; 1630 goto parse_string; 1631 1632 case oDeprecated: 1633 debug("%s line %d: Deprecated option \"%s\"", 1634 filename, linenum, keyword); 1635 return 0; 1636 1637 case oUnsupported: 1638 error("%s line %d: Unsupported option \"%s\"", 1639 filename, linenum, keyword); 1640 return 0; 1641 1642 default: 1643 fatal("%s: Unimplemented opcode %d", __func__, opcode); 1644 } 1645 1646 /* Check that there is no garbage at end of line. */ 1647 if ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1648 fatal("%.200s line %d: garbage at end of line; \"%.200s\".", 1649 filename, linenum, arg); 1650 } 1651 return 0; 1652 } 1653 1654 /* 1655 * Reads the config file and modifies the options accordingly. Options 1656 * should already be initialized before this call. This never returns if 1657 * there is an error. If the file does not exist, this returns 0. 1658 */ 1659 int 1660 read_config_file(const char *filename, struct passwd *pw, const char *host, 1661 const char *original_host, Options *options, int flags) 1662 { 1663 int active = 1; 1664 1665 return read_config_file_depth(filename, pw, host, original_host, 1666 options, flags, &active, 0); 1667 } 1668 1669 #define READCONF_MAX_DEPTH 16 1670 static int 1671 read_config_file_depth(const char *filename, struct passwd *pw, 1672 const char *host, const char *original_host, Options *options, 1673 int flags, int *activep, int depth) 1674 { 1675 FILE *f; 1676 char line[4096]; 1677 int linenum; 1678 int bad_options = 0; 1679 1680 if (depth < 0 || depth > READCONF_MAX_DEPTH) 1681 fatal("Too many recursive configuration includes"); 1682 1683 if ((f = fopen(filename, "r")) == NULL) 1684 return 0; 1685 1686 if (flags & SSHCONF_CHECKPERM) { 1687 struct stat sb; 1688 1689 if (fstat(fileno(f), &sb) == -1) 1690 fatal("fstat %s: %s", filename, strerror(errno)); 1691 if (((sb.st_uid != 0 && sb.st_uid != getuid()) || 1692 (sb.st_mode & 022) != 0)) 1693 fatal("Bad owner or permissions on %s", filename); 1694 } 1695 1696 debug("Reading configuration data %.200s", filename); 1697 1698 /* 1699 * Mark that we are now processing the options. This flag is turned 1700 * on/off by Host specifications. 1701 */ 1702 linenum = 0; 1703 while (fgets(line, sizeof(line), f)) { 1704 /* Update line number counter. */ 1705 linenum++; 1706 if (strlen(line) == sizeof(line) - 1) 1707 fatal("%s line %d too long", filename, linenum); 1708 if (process_config_line_depth(options, pw, host, original_host, 1709 line, filename, linenum, activep, flags, depth) != 0) 1710 bad_options++; 1711 } 1712 fclose(f); 1713 if (bad_options > 0) 1714 fatal("%s: terminating, %d bad configuration options", 1715 filename, bad_options); 1716 return 1; 1717 } 1718 1719 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ 1720 int 1721 option_clear_or_none(const char *o) 1722 { 1723 return o == NULL || strcasecmp(o, "none") == 0; 1724 } 1725 1726 /* 1727 * Initializes options to special values that indicate that they have not yet 1728 * been set. Read_config_file will only set options with this value. Options 1729 * are processed in the following order: command line, user config file, 1730 * system config file. Last, fill_default_options is called. 1731 */ 1732 1733 void 1734 initialize_options(Options * options) 1735 { 1736 memset(options, 'X', sizeof(*options)); 1737 options->forward_agent = -1; 1738 options->forward_x11 = -1; 1739 options->forward_x11_trusted = -1; 1740 options->forward_x11_timeout = -1; 1741 options->stdio_forward_host = NULL; 1742 options->stdio_forward_port = 0; 1743 options->clear_forwardings = -1; 1744 options->exit_on_forward_failure = -1; 1745 options->xauth_location = NULL; 1746 options->fwd_opts.gateway_ports = -1; 1747 options->fwd_opts.streamlocal_bind_mask = (mode_t)-1; 1748 options->fwd_opts.streamlocal_bind_unlink = -1; 1749 options->use_privileged_port = -1; 1750 options->pubkey_authentication = -1; 1751 options->challenge_response_authentication = -1; 1752 options->gss_authentication = -1; 1753 options->gss_deleg_creds = -1; 1754 options->password_authentication = -1; 1755 options->kbd_interactive_authentication = -1; 1756 options->kbd_interactive_devices = NULL; 1757 options->hostbased_authentication = -1; 1758 options->batch_mode = -1; 1759 options->check_host_ip = -1; 1760 options->strict_host_key_checking = -1; 1761 options->compression = -1; 1762 options->tcp_keep_alive = -1; 1763 options->port = -1; 1764 options->address_family = -1; 1765 options->connection_attempts = -1; 1766 options->connection_timeout = -1; 1767 options->number_of_password_prompts = -1; 1768 options->ciphers = NULL; 1769 options->macs = NULL; 1770 options->kex_algorithms = NULL; 1771 options->hostkeyalgorithms = NULL; 1772 options->num_identity_files = 0; 1773 options->num_certificate_files = 0; 1774 options->hostname = NULL; 1775 options->host_key_alias = NULL; 1776 options->proxy_command = NULL; 1777 options->jump_user = NULL; 1778 options->jump_host = NULL; 1779 options->jump_port = -1; 1780 options->jump_extra = NULL; 1781 options->user = NULL; 1782 options->escape_char = -1; 1783 options->num_system_hostfiles = 0; 1784 options->num_user_hostfiles = 0; 1785 options->local_forwards = NULL; 1786 options->num_local_forwards = 0; 1787 options->remote_forwards = NULL; 1788 options->num_remote_forwards = 0; 1789 options->log_facility = SYSLOG_FACILITY_NOT_SET; 1790 options->log_level = SYSLOG_LEVEL_NOT_SET; 1791 options->preferred_authentications = NULL; 1792 options->bind_address = NULL; 1793 options->bind_interface = 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 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0); 1930 } 1931 if (options->escape_char == -1) 1932 options->escape_char = '~'; 1933 if (options->num_system_hostfiles == 0) { 1934 options->system_hostfiles[options->num_system_hostfiles++] = 1935 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE); 1936 options->system_hostfiles[options->num_system_hostfiles++] = 1937 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2); 1938 } 1939 if (options->num_user_hostfiles == 0) { 1940 options->user_hostfiles[options->num_user_hostfiles++] = 1941 xstrdup(_PATH_SSH_USER_HOSTFILE); 1942 options->user_hostfiles[options->num_user_hostfiles++] = 1943 xstrdup(_PATH_SSH_USER_HOSTFILE2); 1944 } 1945 if (options->log_level == SYSLOG_LEVEL_NOT_SET) 1946 options->log_level = SYSLOG_LEVEL_INFO; 1947 if (options->log_facility == SYSLOG_FACILITY_NOT_SET) 1948 options->log_facility = SYSLOG_FACILITY_USER; 1949 if (options->no_host_authentication_for_localhost == - 1) 1950 options->no_host_authentication_for_localhost = 0; 1951 if (options->identities_only == -1) 1952 options->identities_only = 0; 1953 if (options->enable_ssh_keysign == -1) 1954 options->enable_ssh_keysign = 0; 1955 if (options->rekey_limit == -1) 1956 options->rekey_limit = 0; 1957 if (options->rekey_interval == -1) 1958 options->rekey_interval = 0; 1959 if (options->verify_host_key_dns == -1) 1960 options->verify_host_key_dns = 0; 1961 if (options->server_alive_interval == -1) 1962 options->server_alive_interval = 0; 1963 if (options->server_alive_count_max == -1) 1964 options->server_alive_count_max = 3; 1965 if (options->control_master == -1) 1966 options->control_master = 0; 1967 if (options->control_persist == -1) { 1968 options->control_persist = 0; 1969 options->control_persist_timeout = 0; 1970 } 1971 if (options->hash_known_hosts == -1) 1972 options->hash_known_hosts = 0; 1973 if (options->tun_open == -1) 1974 options->tun_open = SSH_TUNMODE_NO; 1975 if (options->tun_local == -1) 1976 options->tun_local = SSH_TUNID_ANY; 1977 if (options->tun_remote == -1) 1978 options->tun_remote = SSH_TUNID_ANY; 1979 if (options->permit_local_command == -1) 1980 options->permit_local_command = 0; 1981 if (options->visual_host_key == -1) 1982 options->visual_host_key = 0; 1983 if (options->ip_qos_interactive == -1) 1984 options->ip_qos_interactive = IPTOS_LOWDELAY; 1985 if (options->ip_qos_bulk == -1) 1986 options->ip_qos_bulk = IPTOS_THROUGHPUT; 1987 if (options->request_tty == -1) 1988 options->request_tty = REQUEST_TTY_AUTO; 1989 if (options->proxy_use_fdpass == -1) 1990 options->proxy_use_fdpass = 0; 1991 if (options->canonicalize_max_dots == -1) 1992 options->canonicalize_max_dots = 1; 1993 if (options->canonicalize_fallback_local == -1) 1994 options->canonicalize_fallback_local = 1; 1995 if (options->canonicalize_hostname == -1) 1996 options->canonicalize_hostname = SSH_CANONICALISE_NO; 1997 if (options->fingerprint_hash == -1) 1998 options->fingerprint_hash = SSH_FP_HASH_DEFAULT; 1999 if (options->update_hostkeys == -1) 2000 options->update_hostkeys = 0; 2001 if (kex_assemble_names(KEX_CLIENT_ENCRYPT, &options->ciphers) != 0 || 2002 kex_assemble_names(KEX_CLIENT_MAC, &options->macs) != 0 || 2003 kex_assemble_names(KEX_CLIENT_KEX, &options->kex_algorithms) != 0 || 2004 kex_assemble_names(KEX_DEFAULT_PK_ALG, 2005 &options->hostbased_key_types) != 0 || 2006 kex_assemble_names(KEX_DEFAULT_PK_ALG, 2007 &options->pubkey_key_types) != 0) 2008 fatal("%s: kex_assemble_names failed", __func__); 2009 2010 #define CLEAR_ON_NONE(v) \ 2011 do { \ 2012 if (option_clear_or_none(v)) { \ 2013 free(v); \ 2014 v = NULL; \ 2015 } \ 2016 } while(0) 2017 CLEAR_ON_NONE(options->local_command); 2018 CLEAR_ON_NONE(options->remote_command); 2019 CLEAR_ON_NONE(options->proxy_command); 2020 CLEAR_ON_NONE(options->control_path); 2021 CLEAR_ON_NONE(options->revoked_host_keys); 2022 /* options->identity_agent distinguishes NULL from 'none' */ 2023 /* options->user will be set in the main program if appropriate */ 2024 /* options->hostname will be set in the main program if appropriate */ 2025 /* options->host_key_alias should not be set by default */ 2026 /* options->preferred_authentications will be set in ssh */ 2027 } 2028 2029 struct fwdarg { 2030 char *arg; 2031 int ispath; 2032 }; 2033 2034 /* 2035 * parse_fwd_field 2036 * parses the next field in a port forwarding specification. 2037 * sets fwd to the parsed field and advances p past the colon 2038 * or sets it to NULL at end of string. 2039 * returns 0 on success, else non-zero. 2040 */ 2041 static int 2042 parse_fwd_field(char **p, struct fwdarg *fwd) 2043 { 2044 char *ep, *cp = *p; 2045 int ispath = 0; 2046 2047 if (*cp == '\0') { 2048 *p = NULL; 2049 return -1; /* end of string */ 2050 } 2051 2052 /* 2053 * A field escaped with square brackets is used literally. 2054 * XXX - allow ']' to be escaped via backslash? 2055 */ 2056 if (*cp == '[') { 2057 /* find matching ']' */ 2058 for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) { 2059 if (*ep == '/') 2060 ispath = 1; 2061 } 2062 /* no matching ']' or not at end of field. */ 2063 if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0')) 2064 return -1; 2065 /* NUL terminate the field and advance p past the colon */ 2066 *ep++ = '\0'; 2067 if (*ep != '\0') 2068 *ep++ = '\0'; 2069 fwd->arg = cp + 1; 2070 fwd->ispath = ispath; 2071 *p = ep; 2072 return 0; 2073 } 2074 2075 for (cp = *p; *cp != '\0'; cp++) { 2076 switch (*cp) { 2077 case '\\': 2078 memmove(cp, cp + 1, strlen(cp + 1) + 1); 2079 if (*cp == '\0') 2080 return -1; 2081 break; 2082 case '/': 2083 ispath = 1; 2084 break; 2085 case ':': 2086 *cp++ = '\0'; 2087 goto done; 2088 } 2089 } 2090 done: 2091 fwd->arg = *p; 2092 fwd->ispath = ispath; 2093 *p = cp; 2094 return 0; 2095 } 2096 2097 /* 2098 * parse_forward 2099 * parses a string containing a port forwarding specification of the form: 2100 * dynamicfwd == 0 2101 * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath 2102 * listenpath:connectpath 2103 * dynamicfwd == 1 2104 * [listenhost:]listenport 2105 * returns number of arguments parsed or zero on error 2106 */ 2107 int 2108 parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) 2109 { 2110 struct fwdarg fwdargs[4]; 2111 char *p, *cp; 2112 int i; 2113 2114 memset(fwd, 0, sizeof(*fwd)); 2115 memset(fwdargs, 0, sizeof(fwdargs)); 2116 2117 cp = p = xstrdup(fwdspec); 2118 2119 /* skip leading spaces */ 2120 while (isspace((u_char)*cp)) 2121 cp++; 2122 2123 for (i = 0; i < 4; ++i) { 2124 if (parse_fwd_field(&cp, &fwdargs[i]) != 0) 2125 break; 2126 } 2127 2128 /* Check for trailing garbage */ 2129 if (cp != NULL && *cp != '\0') { 2130 i = 0; /* failure */ 2131 } 2132 2133 switch (i) { 2134 case 1: 2135 if (fwdargs[0].ispath) { 2136 fwd->listen_path = xstrdup(fwdargs[0].arg); 2137 fwd->listen_port = PORT_STREAMLOCAL; 2138 } else { 2139 fwd->listen_host = NULL; 2140 fwd->listen_port = a2port(fwdargs[0].arg); 2141 } 2142 fwd->connect_host = xstrdup("socks"); 2143 break; 2144 2145 case 2: 2146 if (fwdargs[0].ispath && fwdargs[1].ispath) { 2147 fwd->listen_path = xstrdup(fwdargs[0].arg); 2148 fwd->listen_port = PORT_STREAMLOCAL; 2149 fwd->connect_path = xstrdup(fwdargs[1].arg); 2150 fwd->connect_port = PORT_STREAMLOCAL; 2151 } else if (fwdargs[1].ispath) { 2152 fwd->listen_host = NULL; 2153 fwd->listen_port = a2port(fwdargs[0].arg); 2154 fwd->connect_path = xstrdup(fwdargs[1].arg); 2155 fwd->connect_port = PORT_STREAMLOCAL; 2156 } else { 2157 fwd->listen_host = xstrdup(fwdargs[0].arg); 2158 fwd->listen_port = a2port(fwdargs[1].arg); 2159 fwd->connect_host = xstrdup("socks"); 2160 } 2161 break; 2162 2163 case 3: 2164 if (fwdargs[0].ispath) { 2165 fwd->listen_path = xstrdup(fwdargs[0].arg); 2166 fwd->listen_port = PORT_STREAMLOCAL; 2167 fwd->connect_host = xstrdup(fwdargs[1].arg); 2168 fwd->connect_port = a2port(fwdargs[2].arg); 2169 } else if (fwdargs[2].ispath) { 2170 fwd->listen_host = xstrdup(fwdargs[0].arg); 2171 fwd->listen_port = a2port(fwdargs[1].arg); 2172 fwd->connect_path = xstrdup(fwdargs[2].arg); 2173 fwd->connect_port = PORT_STREAMLOCAL; 2174 } else { 2175 fwd->listen_host = NULL; 2176 fwd->listen_port = a2port(fwdargs[0].arg); 2177 fwd->connect_host = xstrdup(fwdargs[1].arg); 2178 fwd->connect_port = a2port(fwdargs[2].arg); 2179 } 2180 break; 2181 2182 case 4: 2183 fwd->listen_host = xstrdup(fwdargs[0].arg); 2184 fwd->listen_port = a2port(fwdargs[1].arg); 2185 fwd->connect_host = xstrdup(fwdargs[2].arg); 2186 fwd->connect_port = a2port(fwdargs[3].arg); 2187 break; 2188 default: 2189 i = 0; /* failure */ 2190 } 2191 2192 free(p); 2193 2194 if (dynamicfwd) { 2195 if (!(i == 1 || i == 2)) 2196 goto fail_free; 2197 } else { 2198 if (!(i == 3 || i == 4)) { 2199 if (fwd->connect_path == NULL && 2200 fwd->listen_path == NULL) 2201 goto fail_free; 2202 } 2203 if (fwd->connect_port <= 0 && fwd->connect_path == NULL) 2204 goto fail_free; 2205 } 2206 2207 if ((fwd->listen_port < 0 && fwd->listen_path == NULL) || 2208 (!remotefwd && fwd->listen_port == 0)) 2209 goto fail_free; 2210 if (fwd->connect_host != NULL && 2211 strlen(fwd->connect_host) >= NI_MAXHOST) 2212 goto fail_free; 2213 /* XXX - if connecting to a remote socket, max sun len may not match this host */ 2214 if (fwd->connect_path != NULL && 2215 strlen(fwd->connect_path) >= PATH_MAX_SUN) 2216 goto fail_free; 2217 if (fwd->listen_host != NULL && 2218 strlen(fwd->listen_host) >= NI_MAXHOST) 2219 goto fail_free; 2220 if (fwd->listen_path != NULL && 2221 strlen(fwd->listen_path) >= PATH_MAX_SUN) 2222 goto fail_free; 2223 2224 return (i); 2225 2226 fail_free: 2227 free(fwd->connect_host); 2228 fwd->connect_host = NULL; 2229 free(fwd->connect_path); 2230 fwd->connect_path = NULL; 2231 free(fwd->listen_host); 2232 fwd->listen_host = NULL; 2233 free(fwd->listen_path); 2234 fwd->listen_path = NULL; 2235 return (0); 2236 } 2237 2238 int 2239 parse_jump(const char *s, Options *o, int active) 2240 { 2241 char *orig, *sdup, *cp; 2242 char *host = NULL, *user = NULL; 2243 int ret = -1, port = -1, first; 2244 2245 active &= o->proxy_command == NULL && o->jump_host == NULL; 2246 2247 orig = sdup = xstrdup(s); 2248 first = active; 2249 do { 2250 if ((cp = strrchr(sdup, ',')) == NULL) 2251 cp = sdup; /* last */ 2252 else 2253 *cp++ = '\0'; 2254 2255 if (first) { 2256 /* First argument and configuration is active */ 2257 if (parse_ssh_uri(cp, &user, &host, &port) == -1 || 2258 parse_user_host_port(cp, &user, &host, &port) != 0) 2259 goto out; 2260 } else { 2261 /* Subsequent argument or inactive configuration */ 2262 if (parse_ssh_uri(cp, NULL, NULL, NULL) == -1 || 2263 parse_user_host_port(cp, NULL, NULL, NULL) != 0) 2264 goto out; 2265 } 2266 first = 0; /* only check syntax for subsequent hosts */ 2267 } while (cp != sdup); 2268 /* success */ 2269 if (active) { 2270 o->jump_user = user; 2271 o->jump_host = host; 2272 o->jump_port = port; 2273 o->proxy_command = xstrdup("none"); 2274 user = host = NULL; 2275 if ((cp = strrchr(s, ',')) != NULL && cp != s) { 2276 o->jump_extra = xstrdup(s); 2277 o->jump_extra[cp - s] = '\0'; 2278 } 2279 } 2280 ret = 0; 2281 out: 2282 free(orig); 2283 free(user); 2284 free(host); 2285 return ret; 2286 } 2287 2288 int 2289 parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp) 2290 { 2291 char *path; 2292 int r; 2293 2294 r = parse_uri("ssh", uri, userp, hostp, portp, &path); 2295 if (r == 0 && path != NULL) 2296 r = -1; /* path not allowed */ 2297 return r; 2298 } 2299 2300 /* XXX the following is a near-vebatim copy from servconf.c; refactor */ 2301 static const char * 2302 fmt_multistate_int(int val, const struct multistate *m) 2303 { 2304 u_int i; 2305 2306 for (i = 0; m[i].key != NULL; i++) { 2307 if (m[i].value == val) 2308 return m[i].key; 2309 } 2310 return "UNKNOWN"; 2311 } 2312 2313 static const char * 2314 fmt_intarg(OpCodes code, int val) 2315 { 2316 if (val == -1) 2317 return "unset"; 2318 switch (code) { 2319 case oAddressFamily: 2320 return fmt_multistate_int(val, multistate_addressfamily); 2321 case oVerifyHostKeyDNS: 2322 case oUpdateHostkeys: 2323 return fmt_multistate_int(val, multistate_yesnoask); 2324 case oStrictHostKeyChecking: 2325 return fmt_multistate_int(val, multistate_strict_hostkey); 2326 case oControlMaster: 2327 return fmt_multistate_int(val, multistate_controlmaster); 2328 case oTunnel: 2329 return fmt_multistate_int(val, multistate_tunnel); 2330 case oRequestTTY: 2331 return fmt_multistate_int(val, multistate_requesttty); 2332 case oCanonicalizeHostname: 2333 return fmt_multistate_int(val, multistate_canonicalizehostname); 2334 case oFingerprintHash: 2335 return ssh_digest_alg_name(val); 2336 default: 2337 switch (val) { 2338 case 0: 2339 return "no"; 2340 case 1: 2341 return "yes"; 2342 default: 2343 return "UNKNOWN"; 2344 } 2345 } 2346 } 2347 2348 static const char * 2349 lookup_opcode_name(OpCodes code) 2350 { 2351 u_int i; 2352 2353 for (i = 0; keywords[i].name != NULL; i++) 2354 if (keywords[i].opcode == code) 2355 return(keywords[i].name); 2356 return "UNKNOWN"; 2357 } 2358 2359 static void 2360 dump_cfg_int(OpCodes code, int val) 2361 { 2362 printf("%s %d\n", lookup_opcode_name(code), val); 2363 } 2364 2365 static void 2366 dump_cfg_fmtint(OpCodes code, int val) 2367 { 2368 printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val)); 2369 } 2370 2371 static void 2372 dump_cfg_string(OpCodes code, const char *val) 2373 { 2374 if (val == NULL) 2375 return; 2376 printf("%s %s\n", lookup_opcode_name(code), val); 2377 } 2378 2379 static void 2380 dump_cfg_strarray(OpCodes code, u_int count, char **vals) 2381 { 2382 u_int i; 2383 2384 for (i = 0; i < count; i++) 2385 printf("%s %s\n", lookup_opcode_name(code), vals[i]); 2386 } 2387 2388 static void 2389 dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals) 2390 { 2391 u_int i; 2392 2393 printf("%s", lookup_opcode_name(code)); 2394 for (i = 0; i < count; i++) 2395 printf(" %s", vals[i]); 2396 printf("\n"); 2397 } 2398 2399 static void 2400 dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds) 2401 { 2402 const struct Forward *fwd; 2403 u_int i; 2404 2405 /* oDynamicForward */ 2406 for (i = 0; i < count; i++) { 2407 fwd = &fwds[i]; 2408 if (code == oDynamicForward && fwd->connect_host != NULL && 2409 strcmp(fwd->connect_host, "socks") != 0) 2410 continue; 2411 if (code == oLocalForward && fwd->connect_host != NULL && 2412 strcmp(fwd->connect_host, "socks") == 0) 2413 continue; 2414 printf("%s", lookup_opcode_name(code)); 2415 if (fwd->listen_port == PORT_STREAMLOCAL) 2416 printf(" %s", fwd->listen_path); 2417 else if (fwd->listen_host == NULL) 2418 printf(" %d", fwd->listen_port); 2419 else { 2420 printf(" [%s]:%d", 2421 fwd->listen_host, fwd->listen_port); 2422 } 2423 if (code != oDynamicForward) { 2424 if (fwd->connect_port == PORT_STREAMLOCAL) 2425 printf(" %s", fwd->connect_path); 2426 else if (fwd->connect_host == NULL) 2427 printf(" %d", fwd->connect_port); 2428 else { 2429 printf(" [%s]:%d", 2430 fwd->connect_host, fwd->connect_port); 2431 } 2432 } 2433 printf("\n"); 2434 } 2435 } 2436 2437 void 2438 dump_client_config(Options *o, const char *host) 2439 { 2440 int i; 2441 char buf[8]; 2442 2443 /* This is normally prepared in ssh_kex2 */ 2444 if (kex_assemble_names(KEX_DEFAULT_PK_ALG, &o->hostkeyalgorithms) != 0) 2445 fatal("%s: kex_assemble_names failed", __func__); 2446 2447 /* Most interesting options first: user, host, port */ 2448 dump_cfg_string(oUser, o->user); 2449 dump_cfg_string(oHostName, host); 2450 dump_cfg_int(oPort, o->port); 2451 2452 /* Flag options */ 2453 dump_cfg_fmtint(oAddressFamily, o->address_family); 2454 dump_cfg_fmtint(oBatchMode, o->batch_mode); 2455 dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local); 2456 dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname); 2457 dump_cfg_fmtint(oChallengeResponseAuthentication, o->challenge_response_authentication); 2458 dump_cfg_fmtint(oCheckHostIP, o->check_host_ip); 2459 dump_cfg_fmtint(oCompression, o->compression); 2460 dump_cfg_fmtint(oControlMaster, o->control_master); 2461 dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign); 2462 dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings); 2463 dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure); 2464 dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash); 2465 dump_cfg_fmtint(oForwardAgent, o->forward_agent); 2466 dump_cfg_fmtint(oForwardX11, o->forward_x11); 2467 dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted); 2468 dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports); 2469 #ifdef GSSAPI 2470 dump_cfg_fmtint(oGssAuthentication, o->gss_authentication); 2471 dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds); 2472 #endif /* GSSAPI */ 2473 dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts); 2474 dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication); 2475 dump_cfg_fmtint(oIdentitiesOnly, o->identities_only); 2476 dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication); 2477 dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost); 2478 dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication); 2479 dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command); 2480 dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass); 2481 dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication); 2482 dump_cfg_fmtint(oRequestTTY, o->request_tty); 2483 dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink); 2484 dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking); 2485 dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive); 2486 dump_cfg_fmtint(oTunnel, o->tun_open); 2487 dump_cfg_fmtint(oUsePrivilegedPort, o->use_privileged_port); 2488 dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns); 2489 dump_cfg_fmtint(oVisualHostKey, o->visual_host_key); 2490 dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys); 2491 2492 /* Integer options */ 2493 dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots); 2494 dump_cfg_int(oConnectionAttempts, o->connection_attempts); 2495 dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout); 2496 dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts); 2497 dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max); 2498 dump_cfg_int(oServerAliveInterval, o->server_alive_interval); 2499 2500 /* String options */ 2501 dump_cfg_string(oBindAddress, o->bind_address); 2502 dump_cfg_string(oBindInterface, o->bind_interface); 2503 dump_cfg_string(oCiphers, o->ciphers ? o->ciphers : KEX_CLIENT_ENCRYPT); 2504 dump_cfg_string(oControlPath, o->control_path); 2505 dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms); 2506 dump_cfg_string(oHostKeyAlias, o->host_key_alias); 2507 dump_cfg_string(oHostbasedKeyTypes, o->hostbased_key_types); 2508 dump_cfg_string(oIdentityAgent, o->identity_agent); 2509 dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices); 2510 dump_cfg_string(oKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : KEX_CLIENT_KEX); 2511 dump_cfg_string(oLocalCommand, o->local_command); 2512 dump_cfg_string(oRemoteCommand, o->remote_command); 2513 dump_cfg_string(oLogLevel, log_level_name(o->log_level)); 2514 dump_cfg_string(oMacs, o->macs ? o->macs : KEX_CLIENT_MAC); 2515 #ifdef ENABLE_PKCS11 2516 dump_cfg_string(oPKCS11Provider, o->pkcs11_provider); 2517 #endif 2518 dump_cfg_string(oPreferredAuthentications, o->preferred_authentications); 2519 dump_cfg_string(oPubkeyAcceptedKeyTypes, o->pubkey_key_types); 2520 dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys); 2521 dump_cfg_string(oXAuthLocation, o->xauth_location); 2522 2523 /* Forwards */ 2524 dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards); 2525 dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards); 2526 dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards); 2527 2528 /* String array options */ 2529 dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files); 2530 dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains); 2531 dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles); 2532 dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles); 2533 dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env); 2534 2535 /* Special cases */ 2536 2537 /* oConnectTimeout */ 2538 if (o->connection_timeout == -1) 2539 printf("connecttimeout none\n"); 2540 else 2541 dump_cfg_int(oConnectTimeout, o->connection_timeout); 2542 2543 /* oTunnelDevice */ 2544 printf("tunneldevice"); 2545 if (o->tun_local == SSH_TUNID_ANY) 2546 printf(" any"); 2547 else 2548 printf(" %d", o->tun_local); 2549 if (o->tun_remote == SSH_TUNID_ANY) 2550 printf(":any"); 2551 else 2552 printf(":%d", o->tun_remote); 2553 printf("\n"); 2554 2555 /* oCanonicalizePermittedCNAMEs */ 2556 if ( o->num_permitted_cnames > 0) { 2557 printf("canonicalizePermittedcnames"); 2558 for (i = 0; i < o->num_permitted_cnames; i++) { 2559 printf(" %s:%s", o->permitted_cnames[i].source_list, 2560 o->permitted_cnames[i].target_list); 2561 } 2562 printf("\n"); 2563 } 2564 2565 /* oControlPersist */ 2566 if (o->control_persist == 0 || o->control_persist_timeout == 0) 2567 dump_cfg_fmtint(oControlPersist, o->control_persist); 2568 else 2569 dump_cfg_int(oControlPersist, o->control_persist_timeout); 2570 2571 /* oEscapeChar */ 2572 if (o->escape_char == SSH_ESCAPECHAR_NONE) 2573 printf("escapechar none\n"); 2574 else { 2575 vis(buf, o->escape_char, VIS_WHITE, 0); 2576 printf("escapechar %s\n", buf); 2577 } 2578 2579 /* oIPQoS */ 2580 printf("ipqos %s ", iptos2str(o->ip_qos_interactive)); 2581 printf("%s\n", iptos2str(o->ip_qos_bulk)); 2582 2583 /* oRekeyLimit */ 2584 printf("rekeylimit %llu %d\n", 2585 (unsigned long long)o->rekey_limit, o->rekey_interval); 2586 2587 /* oStreamLocalBindMask */ 2588 printf("streamlocalbindmask 0%o\n", 2589 o->fwd_opts.streamlocal_bind_mask); 2590 2591 /* oProxyCommand / oProxyJump */ 2592 if (o->jump_host == NULL) 2593 dump_cfg_string(oProxyCommand, o->proxy_command); 2594 else { 2595 /* Check for numeric addresses */ 2596 i = strchr(o->jump_host, ':') != NULL || 2597 strspn(o->jump_host, "1234567890.") == strlen(o->jump_host); 2598 snprintf(buf, sizeof(buf), "%d", o->jump_port); 2599 printf("proxyjump %s%s%s%s%s%s%s%s%s\n", 2600 /* optional additional jump spec */ 2601 o->jump_extra == NULL ? "" : o->jump_extra, 2602 o->jump_extra == NULL ? "" : ",", 2603 /* optional user */ 2604 o->jump_user == NULL ? "" : o->jump_user, 2605 o->jump_user == NULL ? "" : "@", 2606 /* opening [ if hostname is numeric */ 2607 i ? "[" : "", 2608 /* mandatory hostname */ 2609 o->jump_host, 2610 /* closing ] if hostname is numeric */ 2611 i ? "]" : "", 2612 /* optional port number */ 2613 o->jump_port <= 0 ? "" : ":", 2614 o->jump_port <= 0 ? "" : buf); 2615 } 2616 } 2617