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