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