1/* $NetBSD: readconf.c,v 1.44 2023/12/20 17:15:21 christos Exp $ */ 2/* $OpenBSD: readconf.c,v 1.383 2023/10/12 02:18:18 djm Exp $ */ 3 4/* 5 * Author: Tatu Ylonen <ylo@cs.hut.fi> 6 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 7 * All rights reserved 8 * Functions for reading the configuration files. 9 * 10 * As far as I am concerned, the code I have written for this software 11 * can be used freely for any purpose. Any derived versions of this 12 * software must be clearly marked as such, and if the derived work is 13 * incompatible with the protocol description in the RFC file, it must be 14 * called by a name other than "ssh" or "Secure Shell". 15 */ 16 17#include "includes.h" 18__RCSID("$NetBSD: readconf.c,v 1.44 2023/12/20 17:15:21 christos Exp $"); 19#include <sys/types.h> 20#include <sys/stat.h> 21#include <sys/socket.h> 22#include <sys/wait.h> 23#include <sys/un.h> 24 25#include <net/if.h> 26#include <netinet/in.h> 27#include <netinet/ip.h> 28 29#include <ctype.h> 30#include <errno.h> 31#include <fcntl.h> 32#include <glob.h> 33#include <ifaddrs.h> 34#include <netdb.h> 35#include <paths.h> 36#include <pwd.h> 37#include <signal.h> 38#include <stdio.h> 39#include <string.h> 40#include <stdarg.h> 41#include <unistd.h> 42#include <limits.h> 43#include <util.h> 44#include <vis.h> 45 46#include "xmalloc.h" 47#include "ssh.h" 48#include "sshbuf.h" 49#include "ssherr.h" 50#include "cipher.h" 51#include "pathnames.h" 52#include "log.h" 53#include "sshkey.h" 54#include "misc.h" 55#include "readconf.h" 56#include "match.h" 57#include "kex.h" 58#include "mac.h" 59#include "fmt_scaled.h" 60#include "uidswap.h" 61#include "myproposal.h" 62#include "digest.h" 63 64/* Format of the configuration file: 65 66 # Configuration data is parsed as follows: 67 # 1. command line options 68 # 2. user-specific file 69 # 3. system-wide file 70 # Any configuration value is only changed the first time it is set. 71 # Thus, host-specific definitions should be at the beginning of the 72 # configuration file, and defaults at the end. 73 74 # Host-specific declarations. These may override anything above. A single 75 # host may match multiple declarations; these are processed in the order 76 # that they are given in. 77 78 Host *.ngs.fi ngs.fi 79 User foo 80 81 Host fake.com 82 Hostname another.host.name.real.org 83 User blaah 84 Port 34289 85 ForwardX11 no 86 ForwardAgent no 87 88 Host books.com 89 RemoteForward 9999 shadows.cs.hut.fi:9999 90 Ciphers 3des-cbc 91 92 Host fascist.blob.com 93 Port 23123 94 User tylonen 95 PasswordAuthentication no 96 97 Host puukko.hut.fi 98 User t35124p 99 ProxyCommand ssh-proxy %h %p 100 101 Host *.fr 102 PublicKeyAuthentication no 103 104 Host *.su 105 Ciphers aes128-ctr 106 PasswordAuthentication no 107 108 Host vpn.fake.com 109 Tunnel yes 110 TunnelDevice 3 111 112 # Defaults for various options 113 Host * 114 ForwardAgent no 115 ForwardX11 no 116 PasswordAuthentication yes 117 StrictHostKeyChecking yes 118 TcpKeepAlive no 119 IdentityFile ~/.ssh/identity 120 Port 22 121 EscapeChar ~ 122 123*/ 124 125static int read_config_file_depth(const char *filename, struct passwd *pw, 126 const char *host, const char *original_host, Options *options, 127 int flags, int *activep, int *want_final_pass, int depth); 128static int process_config_line_depth(Options *options, struct passwd *pw, 129 const char *host, const char *original_host, char *line, 130 const char *filename, int linenum, int *activep, int flags, 131 int *want_final_pass, int depth); 132 133/* Keyword tokens. */ 134 135typedef enum { 136 oBadOption, 137 oHost, oMatch, oInclude, oTag, 138 oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout, 139 oGatewayPorts, oExitOnForwardFailure, 140 oPasswordAuthentication, 141 oXAuthLocation, 142#if defined(KRB4) || defined(KRB5) 143 oKerberosAuthentication, 144#endif 145#if defined(AFS) || defined(KRB5) 146 oKerberosTgtPassing, 147#endif 148#ifdef AFS 149 oAFSTokenPassing, 150#endif 151 oIdentityFile, oHostname, oPort, oRemoteForward, oLocalForward, 152 oPermitRemoteOpen, 153 oCertificateFile, oAddKeysToAgent, oIdentityAgent, 154 oUser, oEscapeChar, oProxyCommand, 155 oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, 156 oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, 157 oTCPKeepAlive, oNumberOfPasswordPrompts, 158 oLogFacility, oLogLevel, oLogVerbose, oCiphers, oMacs, 159 oPubkeyAuthentication, 160 oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, 161 oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, 162 oHostKeyAlgorithms, oBindAddress, oBindInterface, oPKCS11Provider, 163 oIPv6PreferTemporary, 164 oClearAllForwardings, oNoHostAuthenticationForLocalhost, 165 oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, 166 oAddressFamily, oGssAuthentication, oGssDelegateCreds, 167 oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, 168 oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist, 169 oHashKnownHosts, 170 oTunnel, oTunnelDevice, 171 oLocalCommand, oPermitLocalCommand, oRemoteCommand, 172 oVisualHostKey, 173 oKexAlgorithms, oIPQoS, oRequestTTY, oSessionType, oStdinNull, 174 oForkAfterAuthentication, oIgnoreUnknown, oProxyUseFdpass, 175 oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, 176 oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, 177 oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys, 178 oFingerprintHash, oUpdateHostkeys, oHostbasedAcceptedAlgorithms, 179 oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump, 180 oSecurityKeyProvider, oKnownHostsCommand, oRequiredRSASize, 181 oEnableEscapeCommandline, oObscureKeystrokeTiming, oChannelTimeout, 182 oNoneEnabled, oTcpRcvBufPoll, oTcpRcvBuf, oNoneSwitch, oHPNDisabled, 183 oHPNBufferSize, 184 oSendVersionFirst, 185 oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported 186} OpCodes; 187 188/* Textual representations of the tokens. */ 189 190static struct { 191 const char *name; 192 OpCodes opcode; 193} keywords[] = { 194 /* Deprecated options */ 195 { "protocol", oIgnore }, /* NB. silently ignored */ 196 { "cipher", oDeprecated }, 197 { "fallbacktorsh", oDeprecated }, 198 { "globalknownhostsfile2", oDeprecated }, 199 { "rhostsauthentication", oDeprecated }, 200 { "userknownhostsfile2", oDeprecated }, 201 { "useroaming", oDeprecated }, 202 { "usersh", oDeprecated }, 203 { "useprivilegedport", oDeprecated }, 204 205 /* Unsupported options */ 206#ifdef AFS 207 { "afstokenpassing", oAFSTokenPassing }, 208#else 209 { "afstokenpassing", oUnsupported }, 210#endif 211#if defined(KRB4) || defined(KRB5) 212 { "kerberosauthentication", oKerberosAuthentication }, 213#else 214 { "kerberosauthentication", oUnsupported }, 215#endif 216#if defined(AFS) || defined(KRB5) 217 { "kerberostgtpassing", oKerberosTgtPassing }, 218 { "kerberos5tgtpassing", oKerberosTgtPassing }, /* alias */ 219 { "kerberos4tgtpassing", oKerberosTgtPassing }, /* alias */ 220#else 221 { "kerberostgtpassing", oUnsupported }, 222 { "kerberos5tgtpassing", oUnsupported }, 223 { "kerberos4tgtpassing", oUnsupported }, 224#endif 225 { "rsaauthentication", oUnsupported }, 226 { "rhostsrsaauthentication", oUnsupported }, 227 { "compressionlevel", oUnsupported }, 228 229 /* Sometimes-unsupported options */ 230#if defined(GSSAPI) 231 { "gssapiauthentication", oGssAuthentication }, 232 { "gssapidelegatecredentials", oGssDelegateCreds }, 233# else 234 { "gssapiauthentication", oUnsupported }, 235 { "gssapidelegatecredentials", oUnsupported }, 236#endif 237#ifdef ENABLE_PKCS11 238 { "pkcs11provider", oPKCS11Provider }, 239 { "smartcarddevice", oPKCS11Provider }, 240# else 241 { "smartcarddevice", oUnsupported }, 242 { "pkcs11provider", oUnsupported }, 243#endif 244 245 { "forwardagent", oForwardAgent }, 246 { "forwardx11", oForwardX11 }, 247 { "forwardx11trusted", oForwardX11Trusted }, 248 { "forwardx11timeout", oForwardX11Timeout }, 249 { "exitonforwardfailure", oExitOnForwardFailure }, 250 { "xauthlocation", oXAuthLocation }, 251 { "gatewayports", oGatewayPorts }, 252 { "passwordauthentication", oPasswordAuthentication }, 253 { "kbdinteractiveauthentication", oKbdInteractiveAuthentication }, 254 { "kbdinteractivedevices", oKbdInteractiveDevices }, 255 { "challengeresponseauthentication", oKbdInteractiveAuthentication }, /* alias */ 256 { "skeyauthentication", oKbdInteractiveAuthentication }, /* alias */ 257 { "tisauthentication", oKbdInteractiveAuthentication }, /* alias */ 258 { "pubkeyauthentication", oPubkeyAuthentication }, 259 { "dsaauthentication", oPubkeyAuthentication }, /* alias */ 260 { "hostbasedauthentication", oHostbasedAuthentication }, 261#if defined(GSSAPI) 262 { "gssapiauthentication", oGssAuthentication }, 263 { "gssapidelegatecredentials", oGssDelegateCreds }, 264#else 265 { "gssapiauthentication", oUnsupported }, 266 { "gssapidelegatecredentials", oUnsupported }, 267#endif 268 { "identityfile", oIdentityFile }, 269 { "identityfile2", oIdentityFile }, /* obsolete */ 270 { "identitiesonly", oIdentitiesOnly }, 271 { "certificatefile", oCertificateFile }, 272 { "addkeystoagent", oAddKeysToAgent }, 273 { "identityagent", oIdentityAgent }, 274 { "hostname", oHostname }, 275 { "hostkeyalias", oHostKeyAlias }, 276 { "proxycommand", oProxyCommand }, 277 { "port", oPort }, 278 { "ciphers", oCiphers }, 279 { "macs", oMacs }, 280 { "remoteforward", oRemoteForward }, 281 { "localforward", oLocalForward }, 282 { "permitremoteopen", oPermitRemoteOpen }, 283 { "user", oUser }, 284 { "host", oHost }, 285 { "match", oMatch }, 286 { "tag", oTag }, 287 { "escapechar", oEscapeChar }, 288 { "globalknownhostsfile", oGlobalKnownHostsFile }, 289 { "userknownhostsfile", oUserKnownHostsFile }, 290 { "connectionattempts", oConnectionAttempts }, 291 { "batchmode", oBatchMode }, 292 { "checkhostip", oCheckHostIP }, 293 { "stricthostkeychecking", oStrictHostKeyChecking }, 294 { "compression", oCompression }, 295 { "tcpkeepalive", oTCPKeepAlive }, 296 { "keepalive", oTCPKeepAlive }, /* obsolete */ 297 { "numberofpasswordprompts", oNumberOfPasswordPrompts }, 298 { "syslogfacility", oLogFacility }, 299 { "loglevel", oLogLevel }, 300 { "logverbose", oLogVerbose }, 301 { "dynamicforward", oDynamicForward }, 302 { "preferredauthentications", oPreferredAuthentications }, 303 { "hostkeyalgorithms", oHostKeyAlgorithms }, 304 { "casignaturealgorithms", oCASignatureAlgorithms }, 305 { "bindaddress", oBindAddress }, 306 { "bindinterface", oBindInterface }, 307 { "ipv6prefertemporary", oIPv6PreferTemporary }, 308 { "clearallforwardings", oClearAllForwardings }, 309 { "enablesshkeysign", oEnableSSHKeysign }, 310 { "verifyhostkeydns", oVerifyHostKeyDNS }, 311 { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost }, 312 { "rekeylimit", oRekeyLimit }, 313 { "connecttimeout", oConnectTimeout }, 314 { "addressfamily", oAddressFamily }, 315 { "serveraliveinterval", oServerAliveInterval }, 316 { "serveralivecountmax", oServerAliveCountMax }, 317 { "sendenv", oSendEnv }, 318 { "setenv", oSetEnv }, 319 { "controlpath", oControlPath }, 320 { "controlmaster", oControlMaster }, 321 { "controlpersist", oControlPersist }, 322 { "hashknownhosts", oHashKnownHosts }, 323 { "include", oInclude }, 324 { "tunnel", oTunnel }, 325 { "tunneldevice", oTunnelDevice }, 326 { "localcommand", oLocalCommand }, 327 { "permitlocalcommand", oPermitLocalCommand }, 328 { "remotecommand", oRemoteCommand }, 329 { "visualhostkey", oVisualHostKey }, 330 { "kexalgorithms", oKexAlgorithms }, 331 { "ipqos", oIPQoS }, 332 { "requesttty", oRequestTTY }, 333 { "sessiontype", oSessionType }, 334 { "stdinnull", oStdinNull }, 335 { "forkafterauthentication", oForkAfterAuthentication }, 336 { "proxyusefdpass", oProxyUseFdpass }, 337 { "canonicaldomains", oCanonicalDomains }, 338 { "canonicalizefallbacklocal", oCanonicalizeFallbackLocal }, 339 { "canonicalizehostname", oCanonicalizeHostname }, 340 { "canonicalizemaxdots", oCanonicalizeMaxDots }, 341 { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs }, 342 { "streamlocalbindmask", oStreamLocalBindMask }, 343 { "streamlocalbindunlink", oStreamLocalBindUnlink }, 344 { "revokedhostkeys", oRevokedHostKeys }, 345 { "fingerprinthash", oFingerprintHash }, 346 { "updatehostkeys", oUpdateHostkeys }, 347 { "hostbasedacceptedalgorithms", oHostbasedAcceptedAlgorithms }, 348 { "hostbasedkeytypes", oHostbasedAcceptedAlgorithms }, /* obsolete */ 349 { "pubkeyacceptedalgorithms", oPubkeyAcceptedAlgorithms }, 350 { "pubkeyacceptedkeytypes", oPubkeyAcceptedAlgorithms }, /* obsolete */ 351 { "proxyjump", oProxyJump }, 352 { "noneenabled", oNoneEnabled }, 353 { "tcprcvbufpoll", oTcpRcvBufPoll }, 354 { "tcprcvbuf", oTcpRcvBuf }, 355 { "noneswitch", oNoneSwitch }, 356 { "hpndisabled", oHPNDisabled }, 357 { "hpnbuffersize", oHPNBufferSize }, 358 { "sendversionfirst", oSendVersionFirst }, 359 { "ignoreunknown", oIgnoreUnknown }, 360 { "proxyjump", oProxyJump }, 361 { "securitykeyprovider", oSecurityKeyProvider }, 362 { "knownhostscommand", oKnownHostsCommand }, 363 { "requiredrsasize", oRequiredRSASize }, 364 { "enableescapecommandline", oEnableEscapeCommandline }, 365 { "obscurekeystroketiming", oObscureKeystrokeTiming }, 366 { "channeltimeout", oChannelTimeout }, 367 368 { NULL, oBadOption } 369}; 370 371static const char *lookup_opcode_name(OpCodes code); 372 373const char * 374kex_default_pk_alg(void) 375{ 376 static char *pkalgs; 377 378 if (pkalgs == NULL) { 379 char *all_key; 380 381 all_key = sshkey_alg_list(0, 0, 1, ','); 382 pkalgs = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key); 383 free(all_key); 384 } 385 return pkalgs; 386} 387 388char * 389ssh_connection_hash(const char *thishost, const char *host, const char *portstr, 390 const char *user, const char *jumphost) 391{ 392 struct ssh_digest_ctx *md; 393 u_char conn_hash[SSH_DIGEST_MAX_LENGTH]; 394 395 if ((md = ssh_digest_start(SSH_DIGEST_SHA1)) == NULL || 396 ssh_digest_update(md, thishost, strlen(thishost)) < 0 || 397 ssh_digest_update(md, host, strlen(host)) < 0 || 398 ssh_digest_update(md, portstr, strlen(portstr)) < 0 || 399 ssh_digest_update(md, user, strlen(user)) < 0 || 400 ssh_digest_update(md, jumphost, strlen(jumphost)) < 0 || 401 ssh_digest_final(md, conn_hash, sizeof(conn_hash)) < 0) 402 fatal_f("mux digest failed"); 403 ssh_digest_free(md); 404 return tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1)); 405} 406 407/* 408 * Adds a local TCP/IP port forward to options. Never returns if there is an 409 * error. 410 */ 411 412void 413add_local_forward(Options *options, const struct Forward *newfwd) 414{ 415 struct Forward *fwd; 416 int i; 417 418 /* Don't add duplicates */ 419 for (i = 0; i < options->num_local_forwards; i++) { 420 if (forward_equals(newfwd, options->local_forwards + i)) 421 return; 422 } 423 options->local_forwards = xreallocarray(options->local_forwards, 424 options->num_local_forwards + 1, 425 sizeof(*options->local_forwards)); 426 fwd = &options->local_forwards[options->num_local_forwards++]; 427 428 fwd->listen_host = newfwd->listen_host; 429 fwd->listen_port = newfwd->listen_port; 430 fwd->listen_path = newfwd->listen_path; 431 fwd->connect_host = newfwd->connect_host; 432 fwd->connect_port = newfwd->connect_port; 433 fwd->connect_path = newfwd->connect_path; 434} 435 436/* 437 * Adds a remote TCP/IP port forward to options. Never returns if there is 438 * an error. 439 */ 440 441void 442add_remote_forward(Options *options, const struct Forward *newfwd) 443{ 444 struct Forward *fwd; 445 int i; 446 447 /* Don't add duplicates */ 448 for (i = 0; i < options->num_remote_forwards; i++) { 449 if (forward_equals(newfwd, options->remote_forwards + i)) 450 return; 451 } 452 options->remote_forwards = xreallocarray(options->remote_forwards, 453 options->num_remote_forwards + 1, 454 sizeof(*options->remote_forwards)); 455 fwd = &options->remote_forwards[options->num_remote_forwards++]; 456 457 fwd->listen_host = newfwd->listen_host; 458 fwd->listen_port = newfwd->listen_port; 459 fwd->listen_path = newfwd->listen_path; 460 fwd->connect_host = newfwd->connect_host; 461 fwd->connect_port = newfwd->connect_port; 462 fwd->connect_path = newfwd->connect_path; 463 fwd->handle = newfwd->handle; 464 fwd->allocated_port = 0; 465} 466 467static void 468clear_forwardings(Options *options) 469{ 470 int i; 471 472 for (i = 0; i < options->num_local_forwards; i++) { 473 free(options->local_forwards[i].listen_host); 474 free(options->local_forwards[i].listen_path); 475 free(options->local_forwards[i].connect_host); 476 free(options->local_forwards[i].connect_path); 477 } 478 if (options->num_local_forwards > 0) { 479 free(options->local_forwards); 480 options->local_forwards = NULL; 481 } 482 options->num_local_forwards = 0; 483 for (i = 0; i < options->num_remote_forwards; i++) { 484 free(options->remote_forwards[i].listen_host); 485 free(options->remote_forwards[i].listen_path); 486 free(options->remote_forwards[i].connect_host); 487 free(options->remote_forwards[i].connect_path); 488 } 489 if (options->num_remote_forwards > 0) { 490 free(options->remote_forwards); 491 options->remote_forwards = NULL; 492 } 493 options->num_remote_forwards = 0; 494 options->tun_open = SSH_TUNMODE_NO; 495} 496 497void 498add_certificate_file(Options *options, const char *path, int userprovided) 499{ 500 int i; 501 502 if (options->num_certificate_files >= SSH_MAX_CERTIFICATE_FILES) 503 fatal("Too many certificate files specified (max %d)", 504 SSH_MAX_CERTIFICATE_FILES); 505 506 /* Avoid registering duplicates */ 507 for (i = 0; i < options->num_certificate_files; i++) { 508 if (options->certificate_file_userprovided[i] == userprovided && 509 strcmp(options->certificate_files[i], path) == 0) { 510 debug2_f("ignoring duplicate key %s", path); 511 return; 512 } 513 } 514 515 options->certificate_file_userprovided[options->num_certificate_files] = 516 userprovided; 517 options->certificate_files[options->num_certificate_files++] = 518 xstrdup(path); 519} 520 521void 522add_identity_file(Options *options, const char *dir, const char *filename, 523 int userprovided) 524{ 525 char *path; 526 int i; 527 528 if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES) 529 fatal("Too many identity files specified (max %d)", 530 SSH_MAX_IDENTITY_FILES); 531 532 if (dir == NULL) /* no dir, filename is absolute */ 533 path = xstrdup(filename); 534 else if (xasprintf(&path, "%s%s", dir, filename) >= PATH_MAX) 535 fatal("Identity file path %s too long", path); 536 537 /* Avoid registering duplicates */ 538 for (i = 0; i < options->num_identity_files; i++) { 539 if (options->identity_file_userprovided[i] == userprovided && 540 strcmp(options->identity_files[i], path) == 0) { 541 debug2_f("ignoring duplicate key %s", path); 542 free(path); 543 return; 544 } 545 } 546 547 options->identity_file_userprovided[options->num_identity_files] = 548 userprovided; 549 options->identity_files[options->num_identity_files++] = path; 550} 551 552int 553default_ssh_port(void) 554{ 555 static int port; 556 struct servent *sp; 557 558 if (port == 0) { 559 sp = getservbyname(SSH_SERVICE_NAME, "tcp"); 560 port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT; 561 } 562 return port; 563} 564 565/* 566 * Execute a command in a shell. 567 * Return its exit status or -1 on abnormal exit. 568 */ 569static int 570execute_in_shell(const char *cmd) 571{ 572 const char *shell; 573 pid_t pid; 574 int status; 575 576 if ((shell = getenv("SHELL")) == NULL) 577 shell = _PATH_BSHELL; 578 579 if (access(shell, X_OK) == -1) { 580 fatal("Shell \"%s\" is not executable: %s", 581 shell, strerror(errno)); 582 } 583 584 debug("Executing command: '%.500s'", cmd); 585 586 /* Fork and execute the command. */ 587 if ((pid = fork()) == 0) { 588 char *argv[4]; 589 590 if (stdfd_devnull(1, 1, 0) == -1) 591 fatal_f("stdfd_devnull failed"); 592 closefrom(STDERR_FILENO + 1); 593 594 argv[0] = __UNCONST(shell); 595 argv[1] = __UNCONST("-c"); 596 argv[2] = xstrdup(cmd); 597 argv[3] = NULL; 598 599 execv(argv[0], argv); 600 error("Unable to execute '%.100s': %s", cmd, strerror(errno)); 601 /* Die with signal to make this error apparent to parent. */ 602 ssh_signal(SIGTERM, SIG_DFL); 603 kill(getpid(), SIGTERM); 604 _exit(1); 605 } 606 /* Parent. */ 607 if (pid == -1) 608 fatal_f("fork: %.100s", strerror(errno)); 609 610 while (waitpid(pid, &status, 0) == -1) { 611 if (errno != EINTR && errno != EAGAIN) 612 fatal_f("waitpid: %s", strerror(errno)); 613 } 614 if (!WIFEXITED(status)) { 615 error("command '%.100s' exited abnormally", cmd); 616 return -1; 617 } 618 debug3("command returned status %d", WEXITSTATUS(status)); 619 return WEXITSTATUS(status); 620} 621 622/* 623 * Check whether a local network interface address appears in CIDR pattern- 624 * list 'addrlist'. Returns 1 if matched or 0 otherwise. 625 */ 626static int 627check_match_ifaddrs(const char *addrlist) 628{ 629 struct ifaddrs *ifa, *ifaddrs = NULL; 630 int r, found = 0; 631 char addr[NI_MAXHOST]; 632 socklen_t salen; 633 634 if (getifaddrs(&ifaddrs) != 0) { 635 error("match localnetwork: getifaddrs failed: %s", 636 strerror(errno)); 637 return 0; 638 } 639 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) { 640 if (ifa->ifa_addr == NULL || ifa->ifa_name == NULL || 641 (ifa->ifa_flags & IFF_UP) == 0) 642 continue; 643 switch (ifa->ifa_addr->sa_family) { 644 case AF_INET: 645 salen = sizeof(struct sockaddr_in); 646 break; 647 case AF_INET6: 648 salen = sizeof(struct sockaddr_in6); 649 break; 650 case AF_LINK: 651 /* ignore */ 652 continue; 653 default: 654 debug2_f("interface %s: unsupported address family %d", 655 ifa->ifa_name, ifa->ifa_addr->sa_family); 656 continue; 657 } 658 if ((r = getnameinfo(ifa->ifa_addr, salen, addr, sizeof(addr), 659 NULL, 0, NI_NUMERICHOST)) != 0) { 660 debug2_f("interface %s getnameinfo failed: %s", 661 ifa->ifa_name, gai_strerror(r)); 662 continue; 663 } 664 debug3_f("interface %s addr %s", ifa->ifa_name, addr); 665 if (addr_match_cidr_list(addr, addrlist) == 1) { 666 debug3_f("matched interface %s: address %s in %s", 667 ifa->ifa_name, addr, addrlist); 668 found = 1; 669 break; 670 } 671 } 672 freeifaddrs(ifaddrs); 673 return found; 674} 675 676/* 677 * Parse and execute a Match directive. 678 */ 679static int 680match_cfg_line(Options *options, char **condition, struct passwd *pw, 681 const char *host_arg, const char *original_host, int final_pass, 682 int *want_final_pass, const char *filename, int linenum) 683{ 684 char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria; 685 const char *ruser; 686 int r, port, this_result, result = 1, attributes = 0, negate; 687 char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; 688 char uidstr[32]; 689 690 /* 691 * Configuration is likely to be incomplete at this point so we 692 * must be prepared to use default values. 693 */ 694 port = options->port <= 0 ? default_ssh_port() : options->port; 695 ruser = options->user == NULL ? pw->pw_name : options->user; 696 if (final_pass) { 697 host = xstrdup(options->hostname); 698 } else if (options->hostname != NULL) { 699 /* NB. Please keep in sync with ssh.c:main() */ 700 host = percent_expand(options->hostname, 701 "h", host_arg, (char *)NULL); 702 } else { 703 host = xstrdup(host_arg); 704 } 705 706 debug2("checking match for '%s' host %s originally %s", 707 cp, host, original_host); 708 while ((oattrib = attrib = strdelim(&cp)) && *attrib != '\0') { 709 /* Terminate on comment */ 710 if (*attrib == '#') { 711 cp = NULL; /* mark all arguments consumed */ 712 break; 713 } 714 arg = criteria = NULL; 715 this_result = 1; 716 if ((negate = (attrib[0] == '!'))) 717 attrib++; 718 /* Criterion "all" has no argument and must appear alone */ 719 if (strcasecmp(attrib, "all") == 0) { 720 if (attributes > 1 || ((arg = strdelim(&cp)) != NULL && 721 *arg != '\0' && *arg != '#')) { 722 error("%.200s line %d: '%s' cannot be combined " 723 "with other Match attributes", 724 filename, linenum, oattrib); 725 result = -1; 726 goto out; 727 } 728 if (arg != NULL && *arg == '#') 729 cp = NULL; /* mark all arguments consumed */ 730 if (result) 731 result = negate ? 0 : 1; 732 goto out; 733 } 734 attributes++; 735 /* criteria "final" and "canonical" have no argument */ 736 if (strcasecmp(attrib, "canonical") == 0 || 737 strcasecmp(attrib, "final") == 0) { 738 /* 739 * If the config requests "Match final" then remember 740 * this so we can perform a second pass later. 741 */ 742 if (strcasecmp(attrib, "final") == 0 && 743 want_final_pass != NULL) 744 *want_final_pass = 1; 745 r = !!final_pass; /* force bitmask member to boolean */ 746 if (r == (negate ? 1 : 0)) 747 this_result = result = 0; 748 debug3("%.200s line %d: %smatched '%s'", 749 filename, linenum, 750 this_result ? "" : "not ", oattrib); 751 continue; 752 } 753 /* All other criteria require an argument */ 754 if ((arg = strdelim(&cp)) == NULL || 755 *arg == '\0' || *arg == '#') { 756 error("Missing Match criteria for %s", attrib); 757 result = -1; 758 goto out; 759 } 760 if (strcasecmp(attrib, "host") == 0) { 761 criteria = xstrdup(host); 762 r = match_hostname(host, arg) == 1; 763 if (r == (negate ? 1 : 0)) 764 this_result = result = 0; 765 } else if (strcasecmp(attrib, "originalhost") == 0) { 766 criteria = xstrdup(original_host); 767 r = match_hostname(original_host, arg) == 1; 768 if (r == (negate ? 1 : 0)) 769 this_result = result = 0; 770 } else if (strcasecmp(attrib, "user") == 0) { 771 criteria = xstrdup(ruser); 772 r = match_pattern_list(ruser, arg, 0) == 1; 773 if (r == (negate ? 1 : 0)) 774 this_result = result = 0; 775 } else if (strcasecmp(attrib, "localuser") == 0) { 776 criteria = xstrdup(pw->pw_name); 777 r = match_pattern_list(pw->pw_name, arg, 0) == 1; 778 if (r == (negate ? 1 : 0)) 779 this_result = result = 0; 780 } else if (strcasecmp(attrib, "localnetwork") == 0) { 781 if (addr_match_cidr_list(NULL, arg) == -1) { 782 /* Error already printed */ 783 result = -1; 784 goto out; 785 } 786 r = check_match_ifaddrs(arg) == 1; 787 if (r == (negate ? 1 : 0)) 788 this_result = result = 0; 789 } else if (strcasecmp(attrib, "tagged") == 0) { 790 criteria = xstrdup(options->tag == NULL ? "" : 791 options->tag); 792 r = match_pattern_list(criteria, arg, 0) == 1; 793 if (r == (negate ? 1 : 0)) 794 this_result = result = 0; 795 } else if (strcasecmp(attrib, "exec") == 0) { 796 char *conn_hash_hex, *keyalias; 797 const char *jmphost; 798 799 if (gethostname(thishost, sizeof(thishost)) == -1) 800 fatal("gethostname: %s", strerror(errno)); 801 jmphost = option_clear_or_none(options->jump_host) ? 802 "" : options->jump_host; 803 strlcpy(shorthost, thishost, sizeof(shorthost)); 804 shorthost[strcspn(thishost, ".")] = '\0'; 805 snprintf(portstr, sizeof(portstr), "%d", port); 806 snprintf(uidstr, sizeof(uidstr), "%llu", 807 (unsigned long long)pw->pw_uid); 808 conn_hash_hex = ssh_connection_hash(thishost, host, 809 portstr, ruser, jmphost); 810 keyalias = options->host_key_alias ? 811 options->host_key_alias : host; 812 813 cmd = percent_expand(arg, 814 "C", conn_hash_hex, 815 "L", shorthost, 816 "d", pw->pw_dir, 817 "h", host, 818 "k", keyalias, 819 "l", thishost, 820 "n", original_host, 821 "p", portstr, 822 "r", ruser, 823 "u", pw->pw_name, 824 "i", uidstr, 825 "j", jmphost, 826 (char *)NULL); 827 free(conn_hash_hex); 828 if (result != 1) { 829 /* skip execution if prior predicate failed */ 830 debug3("%.200s line %d: skipped exec " 831 "\"%.100s\"", filename, linenum, cmd); 832 free(cmd); 833 continue; 834 } 835 r = execute_in_shell(cmd); 836 if (r == -1) { 837 fatal("%.200s line %d: match exec " 838 "'%.100s' error", filename, 839 linenum, cmd); 840 } 841 criteria = xstrdup(cmd); 842 free(cmd); 843 /* Force exit status to boolean */ 844 r = r == 0; 845 if (r == (negate ? 1 : 0)) 846 this_result = result = 0; 847 } else { 848 error("Unsupported Match attribute %s", attrib); 849 result = -1; 850 goto out; 851 } 852 debug3("%.200s line %d: %smatched '%s%s%.100s%s' ", 853 filename, linenum, this_result ? "": "not ", oattrib, 854 criteria == NULL ? "" : " \"", 855 criteria == NULL ? "" : criteria, 856 criteria == NULL ? "" : "\""); 857 free(criteria); 858 } 859 if (attributes == 0) { 860 error("One or more attributes required for Match"); 861 result = -1; 862 goto out; 863 } 864 out: 865 if (result != -1) 866 debug2("match %sfound", result ? "" : "not "); 867 *condition = cp; 868 free(host); 869 return result; 870} 871 872/* Remove environment variable by pattern */ 873static void 874rm_env(Options *options, const char *arg, const char *filename, int linenum) 875{ 876 u_int i, j, onum_send_env = options->num_send_env; 877 878 /* Remove an environment variable */ 879 for (i = 0; i < options->num_send_env; ) { 880 if (!match_pattern(options->send_env[i], arg + 1)) { 881 i++; 882 continue; 883 } 884 debug3("%s line %d: removing environment %s", 885 filename, linenum, options->send_env[i]); 886 free(options->send_env[i]); 887 options->send_env[i] = NULL; 888 for (j = i; j < options->num_send_env - 1; j++) { 889 options->send_env[j] = options->send_env[j + 1]; 890 options->send_env[j + 1] = NULL; 891 } 892 options->num_send_env--; 893 /* NB. don't increment i */ 894 } 895 if (onum_send_env != options->num_send_env) { 896 options->send_env = xrecallocarray(options->send_env, 897 onum_send_env, options->num_send_env, 898 sizeof(*options->send_env)); 899 } 900} 901 902/* 903 * Returns the number of the token pointed to by cp or oBadOption. 904 */ 905static OpCodes 906parse_token(const char *cp, const char *filename, int linenum, 907 const char *ignored_unknown) 908{ 909 int i; 910 911 for (i = 0; keywords[i].name; i++) 912 if (strcmp(cp, keywords[i].name) == 0) 913 return keywords[i].opcode; 914 if (ignored_unknown != NULL && 915 match_pattern_list(cp, ignored_unknown, 1) == 1) 916 return oIgnoredUnknownOption; 917 error("%s: line %d: Bad configuration option: %s", 918 filename, linenum, cp); 919 return oBadOption; 920} 921 922/* Multistate option parsing */ 923struct multistate { 924 const char *key; 925 int value; 926}; 927static const struct multistate multistate_flag[] = { 928 { "true", 1 }, 929 { "false", 0 }, 930 { "yes", 1 }, 931 { "no", 0 }, 932 { NULL, -1 } 933}; 934static const struct multistate multistate_yesnoask[] = { 935 { "true", 1 }, 936 { "false", 0 }, 937 { "yes", 1 }, 938 { "no", 0 }, 939 { "ask", 2 }, 940 { NULL, -1 } 941}; 942static const struct multistate multistate_strict_hostkey[] = { 943 { "true", SSH_STRICT_HOSTKEY_YES }, 944 { "false", SSH_STRICT_HOSTKEY_OFF }, 945 { "yes", SSH_STRICT_HOSTKEY_YES }, 946 { "no", SSH_STRICT_HOSTKEY_OFF }, 947 { "ask", SSH_STRICT_HOSTKEY_ASK }, 948 { "off", SSH_STRICT_HOSTKEY_OFF }, 949 { "accept-new", SSH_STRICT_HOSTKEY_NEW }, 950 { NULL, -1 } 951}; 952static const struct multistate multistate_yesnoaskconfirm[] = { 953 { "true", 1 }, 954 { "false", 0 }, 955 { "yes", 1 }, 956 { "no", 0 }, 957 { "ask", 2 }, 958 { "confirm", 3 }, 959 { NULL, -1 } 960}; 961static const struct multistate multistate_addressfamily[] = { 962 { "inet", AF_INET }, 963 { "inet6", AF_INET6 }, 964 { "any", AF_UNSPEC }, 965 { NULL, -1 } 966}; 967static const struct multistate multistate_controlmaster[] = { 968 { "true", SSHCTL_MASTER_YES }, 969 { "yes", SSHCTL_MASTER_YES }, 970 { "false", SSHCTL_MASTER_NO }, 971 { "no", SSHCTL_MASTER_NO }, 972 { "auto", SSHCTL_MASTER_AUTO }, 973 { "ask", SSHCTL_MASTER_ASK }, 974 { "autoask", SSHCTL_MASTER_AUTO_ASK }, 975 { NULL, -1 } 976}; 977static const struct multistate multistate_tunnel[] = { 978 { "ethernet", SSH_TUNMODE_ETHERNET }, 979 { "point-to-point", SSH_TUNMODE_POINTOPOINT }, 980 { "true", SSH_TUNMODE_DEFAULT }, 981 { "yes", SSH_TUNMODE_DEFAULT }, 982 { "false", SSH_TUNMODE_NO }, 983 { "no", SSH_TUNMODE_NO }, 984 { NULL, -1 } 985}; 986static const struct multistate multistate_requesttty[] = { 987 { "true", REQUEST_TTY_YES }, 988 { "yes", REQUEST_TTY_YES }, 989 { "false", REQUEST_TTY_NO }, 990 { "no", REQUEST_TTY_NO }, 991 { "force", REQUEST_TTY_FORCE }, 992 { "auto", REQUEST_TTY_AUTO }, 993 { NULL, -1 } 994}; 995static const struct multistate multistate_sessiontype[] = { 996 { "none", SESSION_TYPE_NONE }, 997 { "subsystem", SESSION_TYPE_SUBSYSTEM }, 998 { "default", SESSION_TYPE_DEFAULT }, 999 { NULL, -1 } 1000}; 1001static const struct multistate multistate_canonicalizehostname[] = { 1002 { "true", SSH_CANONICALISE_YES }, 1003 { "false", SSH_CANONICALISE_NO }, 1004 { "yes", SSH_CANONICALISE_YES }, 1005 { "no", SSH_CANONICALISE_NO }, 1006 { "always", SSH_CANONICALISE_ALWAYS }, 1007 { NULL, -1 } 1008}; 1009static const struct multistate multistate_pubkey_auth[] = { 1010 { "true", SSH_PUBKEY_AUTH_ALL }, 1011 { "false", SSH_PUBKEY_AUTH_NO }, 1012 { "yes", SSH_PUBKEY_AUTH_ALL }, 1013 { "no", SSH_PUBKEY_AUTH_NO }, 1014 { "unbound", SSH_PUBKEY_AUTH_UNBOUND }, 1015 { "host-bound", SSH_PUBKEY_AUTH_HBOUND }, 1016 { NULL, -1 } 1017}; 1018static const struct multistate multistate_compression[] = { 1019#ifdef WITH_ZLIB 1020 { "yes", COMP_ZLIB }, 1021#endif 1022 { "no", COMP_NONE }, 1023 { NULL, -1 } 1024}; 1025 1026static int 1027parse_multistate_value(const char *arg, const char *filename, int linenum, 1028 const struct multistate *multistate_ptr) 1029{ 1030 int i; 1031 1032 if (!arg || *arg == '\0') { 1033 error("%s line %d: missing argument.", filename, linenum); 1034 return -1; 1035 } 1036 for (i = 0; multistate_ptr[i].key != NULL; i++) { 1037 if (strcasecmp(arg, multistate_ptr[i].key) == 0) 1038 return multistate_ptr[i].value; 1039 } 1040 return -1; 1041} 1042 1043/* 1044 * Processes a single option line as used in the configuration files. This 1045 * only sets those values that have not already been set. 1046 */ 1047int 1048process_config_line(Options *options, struct passwd *pw, const char *host, 1049 const char *original_host, char *line, const char *filename, 1050 int linenum, int *activep, int flags) 1051{ 1052 return process_config_line_depth(options, pw, host, original_host, 1053 line, filename, linenum, activep, flags, NULL, 0); 1054} 1055 1056#define WHITESPACE " \t\r\n" 1057static int 1058process_config_line_depth(Options *options, struct passwd *pw, const char *host, 1059 const char *original_host, char *line, const char *filename, 1060 int linenum, int *activep, int flags, int *want_final_pass, int depth) 1061{ 1062 char *str, **charptr, *endofnumber, *keyword, *arg, *arg2, *p; 1063 char **cpptr, ***cppptr, fwdarg[256]; 1064 u_int i, *uintptr, uvalue, max_entries = 0; 1065 int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0; 1066 int remotefwd, dynamicfwd, ca_only = 0; 1067 LogLevel *log_level_ptr; 1068 SyslogFacility *log_facility_ptr; 1069 long long val64; 1070 size_t len; 1071 struct Forward fwd; 1072 const struct multistate *multistate_ptr; 1073 struct allowed_cname *cname; 1074 glob_t gl; 1075 const char *errstr; 1076 char **oav = NULL, **av; 1077 int oac = 0, ac; 1078 int ret = -1; 1079 1080 if (activep == NULL) { /* We are processing a command line directive */ 1081 cmdline = 1; 1082 activep = &cmdline; 1083 } 1084 1085 /* Strip trailing whitespace. Allow \f (form feed) at EOL only */ 1086 if ((len = strlen(line)) == 0) 1087 return 0; 1088 for (len--; len > 0; len--) { 1089 if (strchr(WHITESPACE "\f", line[len]) == NULL) 1090 break; 1091 line[len] = '\0'; 1092 } 1093 1094 str = line; 1095 /* Get the keyword. (Each line is supposed to begin with a keyword). */ 1096 if ((keyword = strdelim(&str)) == NULL) 1097 return 0; 1098 /* Ignore leading whitespace. */ 1099 if (*keyword == '\0') 1100 keyword = strdelim(&str); 1101 if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#') 1102 return 0; 1103 /* Match lowercase keyword */ 1104 lowercase(keyword); 1105 1106 /* Prepare to parse remainder of line */ 1107 if (str != NULL) 1108 str += strspn(str, WHITESPACE); 1109 if (str == NULL || *str == '\0') { 1110 error("%s line %d: no argument after keyword \"%s\"", 1111 filename, linenum, keyword); 1112 return -1; 1113 } 1114 opcode = parse_token(keyword, filename, linenum, 1115 options->ignored_unknown); 1116 if (argv_split(str, &oac, &oav, 1) != 0) { 1117 error("%s line %d: invalid quotes", filename, linenum); 1118 return -1; 1119 } 1120 ac = oac; 1121 av = oav; 1122 1123 switch (opcode) { 1124 case oBadOption: 1125 /* don't panic, but count bad options */ 1126 goto out; 1127 case oIgnore: 1128 argv_consume(&ac); 1129 break; 1130 case oIgnoredUnknownOption: 1131 debug("%s line %d: Ignored unknown option \"%s\"", 1132 filename, linenum, keyword); 1133 argv_consume(&ac); 1134 break; 1135 case oConnectTimeout: 1136 intptr = &options->connection_timeout; 1137parse_time: 1138 arg = argv_next(&ac, &av); 1139 if (!arg || *arg == '\0') { 1140 error("%s line %d: missing time value.", 1141 filename, linenum); 1142 goto out; 1143 } 1144 if (strcmp(arg, "none") == 0) 1145 value = -1; 1146 else if ((value = convtime(arg)) == -1) { 1147 error("%s line %d: invalid time value.", 1148 filename, linenum); 1149 goto out; 1150 } 1151 if (*activep && *intptr == -1) 1152 *intptr = value; 1153 break; 1154 1155 case oForwardAgent: 1156 intptr = &options->forward_agent; 1157 1158 arg = argv_next(&ac, &av); 1159 if (!arg || *arg == '\0') { 1160 error("%s line %d: missing argument.", 1161 filename, linenum); 1162 goto out; 1163 } 1164 1165 value = -1; 1166 multistate_ptr = multistate_flag; 1167 for (i = 0; multistate_ptr[i].key != NULL; i++) { 1168 if (strcasecmp(arg, multistate_ptr[i].key) == 0) { 1169 value = multistate_ptr[i].value; 1170 break; 1171 } 1172 } 1173 if (value != -1) { 1174 if (*activep && *intptr == -1) 1175 *intptr = value; 1176 break; 1177 } 1178 /* ForwardAgent wasn't 'yes' or 'no', assume a path */ 1179 if (*activep && *intptr == -1) 1180 *intptr = 1; 1181 1182 charptr = &options->forward_agent_sock_path; 1183 goto parse_agent_path; 1184 1185 case oForwardX11: 1186 intptr = &options->forward_x11; 1187 parse_flag: 1188 multistate_ptr = multistate_flag; 1189 parse_multistate: 1190 arg = argv_next(&ac, &av); 1191 if ((value = parse_multistate_value(arg, filename, linenum, 1192 multistate_ptr)) == -1) { 1193 error("%s line %d: unsupported option \"%s\".", 1194 filename, linenum, arg); 1195 goto out; 1196 } 1197 if (*activep && *intptr == -1) 1198 *intptr = value; 1199 break; 1200 1201 case oForwardX11Trusted: 1202 intptr = &options->forward_x11_trusted; 1203 goto parse_flag; 1204 1205 case oForwardX11Timeout: 1206 intptr = &options->forward_x11_timeout; 1207 goto parse_time; 1208 1209 case oGatewayPorts: 1210 intptr = &options->fwd_opts.gateway_ports; 1211 goto parse_flag; 1212 1213 case oExitOnForwardFailure: 1214 intptr = &options->exit_on_forward_failure; 1215 goto parse_flag; 1216 1217 case oPasswordAuthentication: 1218 intptr = &options->password_authentication; 1219 goto parse_flag; 1220 1221 case oKbdInteractiveAuthentication: 1222 intptr = &options->kbd_interactive_authentication; 1223 goto parse_flag; 1224 1225 case oKbdInteractiveDevices: 1226 charptr = &options->kbd_interactive_devices; 1227 goto parse_string; 1228 1229 case oPubkeyAuthentication: 1230 multistate_ptr = multistate_pubkey_auth; 1231 intptr = &options->pubkey_authentication; 1232 goto parse_multistate; 1233 1234 case oHostbasedAuthentication: 1235 intptr = &options->hostbased_authentication; 1236 goto parse_flag; 1237 1238#if defined(KRB4) || defined(KRB5) 1239 case oKerberosAuthentication: 1240 intptr = &options->kerberos_authentication; 1241 goto parse_flag; 1242#endif 1243#if defined(AFS) || defined(KRB5) 1244 case oKerberosTgtPassing: 1245 intptr = &options->kerberos_tgt_passing; 1246 goto parse_flag; 1247#endif 1248 1249 case oGssAuthentication: 1250 intptr = &options->gss_authentication; 1251 goto parse_flag; 1252 1253#ifdef AFS 1254 case oAFSTokenPassing: 1255 intptr = &options->afs_token_passing; 1256 goto parse_flag; 1257#endif 1258 1259 case oGssDelegateCreds: 1260 intptr = &options->gss_deleg_creds; 1261 goto parse_flag; 1262 1263 case oBatchMode: 1264 intptr = &options->batch_mode; 1265 goto parse_flag; 1266 1267 case oCheckHostIP: 1268 intptr = &options->check_host_ip; 1269 goto parse_flag; 1270 1271 case oNoneEnabled: 1272 intptr = &options->none_enabled; 1273 goto parse_flag; 1274 1275 /* we check to see if the command comes from the */ 1276 /* command line or not. If it does then enable it */ 1277 /* otherwise fail. NONE should never be a default configuration */ 1278 case oNoneSwitch: 1279 if(strcmp(filename,"command-line")==0) 1280 { 1281 intptr = &options->none_switch; 1282 goto parse_flag; 1283 } else { 1284 error("NoneSwitch is found in %.200s.\nYou may only use this configuration option from the command line", filename); 1285 error("Continuing..."); 1286 debug("NoneSwitch directive found in %.200s.", filename); 1287 return 0; 1288 } 1289 1290 case oHPNDisabled: 1291 intptr = &options->hpn_disabled; 1292 goto parse_flag; 1293 1294 case oHPNBufferSize: 1295 intptr = &options->hpn_buffer_size; 1296 goto parse_int; 1297 1298 case oTcpRcvBufPoll: 1299 intptr = &options->tcp_rcv_buf_poll; 1300 goto parse_flag; 1301 1302 case oVerifyHostKeyDNS: 1303 intptr = &options->verify_host_key_dns; 1304 multistate_ptr = multistate_yesnoask; 1305 goto parse_multistate; 1306 1307 case oStrictHostKeyChecking: 1308 intptr = &options->strict_host_key_checking; 1309 multistate_ptr = multistate_strict_hostkey; 1310 goto parse_multistate; 1311 1312 case oCompression: 1313 intptr = &options->compression; 1314 multistate_ptr = multistate_compression; 1315 goto parse_multistate; 1316 1317 case oTCPKeepAlive: 1318 intptr = &options->tcp_keep_alive; 1319 goto parse_flag; 1320 1321 case oNoHostAuthenticationForLocalhost: 1322 intptr = &options->no_host_authentication_for_localhost; 1323 goto parse_flag; 1324 1325 case oNumberOfPasswordPrompts: 1326 intptr = &options->number_of_password_prompts; 1327 goto parse_int; 1328 1329 case oRekeyLimit: 1330 arg = argv_next(&ac, &av); 1331 if (!arg || *arg == '\0') { 1332 error("%.200s line %d: Missing argument.", filename, 1333 linenum); 1334 goto out; 1335 } 1336 if (strcmp(arg, "default") == 0) { 1337 val64 = 0; 1338 } else { 1339 if (scan_scaled(arg, &val64) == -1) { 1340 error("%.200s line %d: Bad number '%s': %s", 1341 filename, linenum, arg, strerror(errno)); 1342 goto out; 1343 } 1344 if (val64 != 0 && val64 < 16) { 1345 error("%.200s line %d: RekeyLimit too small", 1346 filename, linenum); 1347 goto out; 1348 } 1349 } 1350 if (*activep && options->rekey_limit == -1) 1351 options->rekey_limit = val64; 1352 if (ac != 0) { /* optional rekey interval present */ 1353 if (strcmp(av[0], "none") == 0) { 1354 (void)argv_next(&ac, &av); /* discard */ 1355 break; 1356 } 1357 intptr = &options->rekey_interval; 1358 goto parse_time; 1359 } 1360 break; 1361 1362 case oIdentityFile: 1363 arg = argv_next(&ac, &av); 1364 if (!arg || *arg == '\0') { 1365 error("%.200s line %d: Missing argument.", 1366 filename, linenum); 1367 goto out; 1368 } 1369 if (*activep) { 1370 intptr = &options->num_identity_files; 1371 if (*intptr >= SSH_MAX_IDENTITY_FILES) { 1372 error("%.200s line %d: Too many identity files " 1373 "specified (max %d).", filename, linenum, 1374 SSH_MAX_IDENTITY_FILES); 1375 goto out; 1376 } 1377 add_identity_file(options, NULL, 1378 arg, flags & SSHCONF_USERCONF); 1379 } 1380 break; 1381 1382 case oCertificateFile: 1383 arg = argv_next(&ac, &av); 1384 if (!arg || *arg == '\0') { 1385 error("%.200s line %d: Missing argument.", 1386 filename, linenum); 1387 goto out; 1388 } 1389 if (*activep) { 1390 intptr = &options->num_certificate_files; 1391 if (*intptr >= SSH_MAX_CERTIFICATE_FILES) { 1392 error("%.200s line %d: Too many certificate " 1393 "files specified (max %d).", 1394 filename, linenum, 1395 SSH_MAX_CERTIFICATE_FILES); 1396 goto out; 1397 } 1398 add_certificate_file(options, arg, 1399 flags & SSHCONF_USERCONF); 1400 } 1401 break; 1402 1403 case oXAuthLocation: 1404 charptr=&options->xauth_location; 1405 goto parse_string; 1406 1407 case oUser: 1408 charptr = &options->user; 1409parse_string: 1410 arg = argv_next(&ac, &av); 1411 if (!arg || *arg == '\0') { 1412 error("%.200s line %d: Missing argument.", 1413 filename, linenum); 1414 goto out; 1415 } 1416 if (*activep && *charptr == NULL) 1417 *charptr = xstrdup(arg); 1418 break; 1419 1420 case oGlobalKnownHostsFile: 1421 cpptr = (char **)&options->system_hostfiles; 1422 uintptr = &options->num_system_hostfiles; 1423 max_entries = SSH_MAX_HOSTS_FILES; 1424parse_char_array: 1425 i = 0; 1426 value = *uintptr == 0; /* was array empty when we started? */ 1427 while ((arg = argv_next(&ac, &av)) != NULL) { 1428 if (*arg == '\0') { 1429 error("%s line %d: keyword %s empty argument", 1430 filename, linenum, keyword); 1431 goto out; 1432 } 1433 /* Allow "none" only in first position */ 1434 if (strcasecmp(arg, "none") == 0) { 1435 if (i > 0 || ac > 0) { 1436 error("%s line %d: keyword %s \"none\" " 1437 "argument must appear alone.", 1438 filename, linenum, keyword); 1439 goto out; 1440 } 1441 } 1442 i++; 1443 if (*activep && value) { 1444 if ((*uintptr) >= max_entries) { 1445 error("%s line %d: too many %s " 1446 "entries.", filename, linenum, 1447 keyword); 1448 goto out; 1449 } 1450 cpptr[(*uintptr)++] = xstrdup(arg); 1451 } 1452 } 1453 break; 1454 1455 case oUserKnownHostsFile: 1456 cpptr = (char **)&options->user_hostfiles; 1457 uintptr = &options->num_user_hostfiles; 1458 max_entries = SSH_MAX_HOSTS_FILES; 1459 goto parse_char_array; 1460 1461 case oHostname: 1462 charptr = &options->hostname; 1463 goto parse_string; 1464 1465 case oTag: 1466 charptr = &options->tag; 1467 goto parse_string; 1468 1469 case oHostKeyAlias: 1470 charptr = &options->host_key_alias; 1471 goto parse_string; 1472 1473 case oPreferredAuthentications: 1474 charptr = &options->preferred_authentications; 1475 goto parse_string; 1476 1477 case oBindAddress: 1478 charptr = &options->bind_address; 1479 goto parse_string; 1480 1481 case oBindInterface: 1482 charptr = &options->bind_interface; 1483 goto parse_string; 1484 1485 case oIPv6PreferTemporary: 1486 intptr = &options->ipv6_prefer_temporary; 1487 goto parse_flag; 1488 1489 case oPKCS11Provider: 1490 charptr = &options->pkcs11_provider; 1491 goto parse_string; 1492 1493 case oSecurityKeyProvider: 1494 charptr = &options->sk_provider; 1495 goto parse_string; 1496 1497 case oKnownHostsCommand: 1498 charptr = &options->known_hosts_command; 1499 goto parse_command; 1500 1501 case oProxyCommand: 1502 charptr = &options->proxy_command; 1503 /* Ignore ProxyCommand if ProxyJump already specified */ 1504 if (options->jump_host != NULL) 1505 charptr = &options->jump_host; /* Skip below */ 1506parse_command: 1507 if (str == NULL) { 1508 error("%.200s line %d: Missing argument.", 1509 filename, linenum); 1510 goto out; 1511 } 1512 len = strspn(str, WHITESPACE "="); 1513 if (*activep && *charptr == NULL) 1514 *charptr = xstrdup(str + len); 1515 argv_consume(&ac); 1516 break; 1517 1518 case oProxyJump: 1519 if (str == NULL) { 1520 error("%.200s line %d: Missing argument.", 1521 filename, linenum); 1522 goto out; 1523 } 1524 len = strspn(str, WHITESPACE "="); 1525 /* XXX use argv? */ 1526 if (parse_jump(str + len, options, *activep) == -1) { 1527 error("%.200s line %d: Invalid ProxyJump \"%s\"", 1528 filename, linenum, str + len); 1529 goto out; 1530 } 1531 argv_consume(&ac); 1532 break; 1533 1534 case oPort: 1535 arg = argv_next(&ac, &av); 1536 if (!arg || *arg == '\0') { 1537 error("%.200s line %d: Missing argument.", 1538 filename, linenum); 1539 goto out; 1540 } 1541 value = a2port(arg); 1542 if (value <= 0) { 1543 error("%.200s line %d: Bad port '%s'.", 1544 filename, linenum, arg); 1545 goto out; 1546 } 1547 if (*activep && options->port == -1) 1548 options->port = value; 1549 break; 1550 1551 case oConnectionAttempts: 1552 intptr = &options->connection_attempts; 1553parse_int: 1554 arg = argv_next(&ac, &av); 1555 if ((errstr = atoi_err(arg, &value)) != NULL) { 1556 error("%s line %d: integer value %s.", 1557 filename, linenum, errstr); 1558 goto out; 1559 } 1560 if (*activep && *intptr == -1) 1561 *intptr = value; 1562 break; 1563 1564 case oTcpRcvBuf: 1565 intptr = &options->tcp_rcv_buf; 1566 goto parse_int; 1567 1568 case oCiphers: 1569 arg = argv_next(&ac, &av); 1570 if (!arg || *arg == '\0') { 1571 error("%.200s line %d: Missing argument.", 1572 filename, linenum); 1573 goto out; 1574 } 1575 if (*arg != '-' && 1576 !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)){ 1577 error("%.200s line %d: Bad SSH2 cipher spec '%s'.", 1578 filename, linenum, arg ? arg : "<NONE>"); 1579 goto out; 1580 } 1581 if (*activep && options->ciphers == NULL) 1582 options->ciphers = xstrdup(arg); 1583 break; 1584 1585 case oMacs: 1586 arg = argv_next(&ac, &av); 1587 if (!arg || *arg == '\0') { 1588 error("%.200s line %d: Missing argument.", 1589 filename, linenum); 1590 goto out; 1591 } 1592 if (*arg != '-' && 1593 !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) { 1594 error("%.200s line %d: Bad SSH2 MAC spec '%s'.", 1595 filename, linenum, arg ? arg : "<NONE>"); 1596 goto out; 1597 } 1598 if (*activep && options->macs == NULL) 1599 options->macs = xstrdup(arg); 1600 break; 1601 1602 case oKexAlgorithms: 1603 arg = argv_next(&ac, &av); 1604 if (!arg || *arg == '\0') { 1605 error("%.200s line %d: Missing argument.", 1606 filename, linenum); 1607 goto out; 1608 } 1609 if (*arg != '-' && 1610 !kex_names_valid(*arg == '+' || *arg == '^' ? 1611 arg + 1 : arg)) { 1612 error("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.", 1613 filename, linenum, arg ? arg : "<NONE>"); 1614 goto out; 1615 } 1616 if (*activep && options->kex_algorithms == NULL) 1617 options->kex_algorithms = xstrdup(arg); 1618 break; 1619 1620 case oHostKeyAlgorithms: 1621 charptr = &options->hostkeyalgorithms; 1622 ca_only = 0; 1623parse_pubkey_algos: 1624 arg = argv_next(&ac, &av); 1625 if (!arg || *arg == '\0') { 1626 error("%.200s line %d: Missing argument.", 1627 filename, linenum); 1628 goto out; 1629 } 1630 if (*arg != '-' && 1631 !sshkey_names_valid2(*arg == '+' || *arg == '^' ? 1632 arg + 1 : arg, 1, ca_only)) { 1633 error("%s line %d: Bad key types '%s'.", 1634 filename, linenum, arg ? arg : "<NONE>"); 1635 goto out; 1636 } 1637 if (*activep && *charptr == NULL) 1638 *charptr = xstrdup(arg); 1639 break; 1640 1641 case oCASignatureAlgorithms: 1642 charptr = &options->ca_sign_algorithms; 1643 ca_only = 1; 1644 goto parse_pubkey_algos; 1645 1646 case oLogLevel: 1647 log_level_ptr = &options->log_level; 1648 arg = argv_next(&ac, &av); 1649 value = log_level_number(arg); 1650 if (value == SYSLOG_LEVEL_NOT_SET) { 1651 error("%.200s line %d: unsupported log level '%s'", 1652 filename, linenum, arg ? arg : "<NONE>"); 1653 goto out; 1654 } 1655 if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET) 1656 *log_level_ptr = (LogLevel) value; 1657 break; 1658 1659 case oLogFacility: 1660 log_facility_ptr = &options->log_facility; 1661 arg = argv_next(&ac, &av); 1662 value = log_facility_number(arg); 1663 if (value == SYSLOG_FACILITY_NOT_SET) { 1664 error("%.200s line %d: unsupported log facility '%s'", 1665 filename, linenum, arg ? arg : "<NONE>"); 1666 goto out; 1667 } 1668 if (*log_facility_ptr == -1) 1669 *log_facility_ptr = (SyslogFacility) value; 1670 break; 1671 1672 case oLogVerbose: 1673 cppptr = &options->log_verbose; 1674 uintptr = &options->num_log_verbose; 1675 i = 0; 1676 while ((arg = argv_next(&ac, &av)) != NULL) { 1677 if (*arg == '\0') { 1678 error("%s line %d: keyword %s empty argument", 1679 filename, linenum, keyword); 1680 goto out; 1681 } 1682 /* Allow "none" only in first position */ 1683 if (strcasecmp(arg, "none") == 0) { 1684 if (i > 0 || ac > 0) { 1685 error("%s line %d: keyword %s \"none\" " 1686 "argument must appear alone.", 1687 filename, linenum, keyword); 1688 goto out; 1689 } 1690 } 1691 i++; 1692 if (*activep && *uintptr == 0) { 1693 *cppptr = xrecallocarray(*cppptr, *uintptr, 1694 *uintptr + 1, sizeof(**cppptr)); 1695 (*cppptr)[(*uintptr)++] = xstrdup(arg); 1696 } 1697 } 1698 break; 1699 1700 case oLocalForward: 1701 case oRemoteForward: 1702 case oDynamicForward: 1703 arg = argv_next(&ac, &av); 1704 if (!arg || *arg == '\0') { 1705 error("%.200s line %d: Missing argument.", 1706 filename, linenum); 1707 goto out; 1708 } 1709 1710 remotefwd = (opcode == oRemoteForward); 1711 dynamicfwd = (opcode == oDynamicForward); 1712 1713 if (!dynamicfwd) { 1714 arg2 = argv_next(&ac, &av); 1715 if (arg2 == NULL || *arg2 == '\0') { 1716 if (remotefwd) 1717 dynamicfwd = 1; 1718 else { 1719 error("%.200s line %d: Missing target " 1720 "argument.", filename, linenum); 1721 goto out; 1722 } 1723 } else { 1724 /* construct a string for parse_forward */ 1725 snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, 1726 arg2); 1727 } 1728 } 1729 if (dynamicfwd) 1730 strlcpy(fwdarg, arg, sizeof(fwdarg)); 1731 1732 if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0) { 1733 error("%.200s line %d: Bad forwarding specification.", 1734 filename, linenum); 1735 goto out; 1736 } 1737 1738 if (*activep) { 1739 if (remotefwd) { 1740 add_remote_forward(options, &fwd); 1741 } else { 1742 add_local_forward(options, &fwd); 1743 } 1744 } 1745 break; 1746 1747 case oPermitRemoteOpen: 1748 uintptr = &options->num_permitted_remote_opens; 1749 cppptr = &options->permitted_remote_opens; 1750 uvalue = *uintptr; /* modified later */ 1751 i = 0; 1752 while ((arg = argv_next(&ac, &av)) != NULL) { 1753 arg2 = xstrdup(arg); 1754 /* Allow any/none only in first position */ 1755 if (strcasecmp(arg, "none") == 0 || 1756 strcasecmp(arg, "any") == 0) { 1757 if (i > 0 || ac > 0) { 1758 error("%s line %d: keyword %s \"%s\" " 1759 "argument must appear alone.", 1760 filename, linenum, keyword, arg); 1761 free(arg2); 1762 goto out; 1763 } 1764 } else { 1765 p = hpdelim(&arg); 1766 if (p == NULL) { 1767 fatal("%s line %d: missing host in %s", 1768 filename, linenum, 1769 lookup_opcode_name(opcode)); 1770 } 1771 p = cleanhostname(p); 1772 /* 1773 * don't want to use permitopen_port to avoid 1774 * dependency on channels.[ch] here. 1775 */ 1776 if (arg == NULL || (strcmp(arg, "*") != 0 && 1777 a2port(arg) <= 0)) { 1778 fatal("%s line %d: bad port number " 1779 "in %s", filename, linenum, 1780 lookup_opcode_name(opcode)); 1781 } 1782 } 1783 if (*activep && uvalue == 0) { 1784 opt_array_append(filename, linenum, 1785 lookup_opcode_name(opcode), 1786 cppptr, uintptr, arg2); 1787 } 1788 free(arg2); 1789 i++; 1790 } 1791 if (i == 0) 1792 fatal("%s line %d: missing %s specification", 1793 filename, linenum, lookup_opcode_name(opcode)); 1794 break; 1795 1796 case oClearAllForwardings: 1797 intptr = &options->clear_forwardings; 1798 goto parse_flag; 1799 1800 case oHost: 1801 if (cmdline) { 1802 error("Host directive not supported as a command-line " 1803 "option"); 1804 goto out; 1805 } 1806 *activep = 0; 1807 arg2 = NULL; 1808 while ((arg = argv_next(&ac, &av)) != NULL) { 1809 if (*arg == '\0') { 1810 error("%s line %d: keyword %s empty argument", 1811 filename, linenum, keyword); 1812 goto out; 1813 } 1814 if ((flags & SSHCONF_NEVERMATCH) != 0) { 1815 argv_consume(&ac); 1816 break; 1817 } 1818 negated = *arg == '!'; 1819 if (negated) 1820 arg++; 1821 if (match_pattern(host, arg)) { 1822 if (negated) { 1823 debug("%.200s line %d: Skipping Host " 1824 "block because of negated match " 1825 "for %.100s", filename, linenum, 1826 arg); 1827 *activep = 0; 1828 argv_consume(&ac); 1829 break; 1830 } 1831 if (!*activep) 1832 arg2 = arg; /* logged below */ 1833 *activep = 1; 1834 } 1835 } 1836 if (*activep) 1837 debug("%.200s line %d: Applying options for %.100s", 1838 filename, linenum, arg2); 1839 break; 1840 1841 case oMatch: 1842 if (cmdline) { 1843 error("Host directive not supported as a command-line " 1844 "option"); 1845 goto out; 1846 } 1847 value = match_cfg_line(options, &str, pw, host, original_host, 1848 flags & SSHCONF_FINAL, want_final_pass, 1849 filename, linenum); 1850 if (value < 0) { 1851 error("%.200s line %d: Bad Match condition", filename, 1852 linenum); 1853 goto out; 1854 } 1855 *activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value; 1856 /* 1857 * If match_cfg_line() didn't consume all its arguments then 1858 * arrange for the extra arguments check below to fail. 1859 */ 1860 1861 if (str == NULL || *str == '\0') 1862 argv_consume(&ac); 1863 break; 1864 1865 case oEscapeChar: 1866 intptr = &options->escape_char; 1867 arg = argv_next(&ac, &av); 1868 if (!arg || *arg == '\0') { 1869 error("%.200s line %d: Missing argument.", 1870 filename, linenum); 1871 goto out; 1872 } 1873 if (strcmp(arg, "none") == 0) 1874 value = SSH_ESCAPECHAR_NONE; 1875 else if (arg[1] == '\0') 1876 value = (u_char) arg[0]; 1877 else if (arg[0] == '^' && arg[2] == 0 && 1878 (u_char) arg[1] >= 64 && (u_char) arg[1] < 128) 1879 value = (u_char) arg[1] & 31; 1880 else { 1881 error("%.200s line %d: Bad escape character.", 1882 filename, linenum); 1883 goto out; 1884 } 1885 if (*activep && *intptr == -1) 1886 *intptr = value; 1887 break; 1888 1889 case oAddressFamily: 1890 intptr = &options->address_family; 1891 multistate_ptr = multistate_addressfamily; 1892 goto parse_multistate; 1893 1894 case oEnableSSHKeysign: 1895 intptr = &options->enable_ssh_keysign; 1896 goto parse_flag; 1897 1898 case oIdentitiesOnly: 1899 intptr = &options->identities_only; 1900 goto parse_flag; 1901 1902 case oServerAliveInterval: 1903 intptr = &options->server_alive_interval; 1904 goto parse_time; 1905 1906 case oServerAliveCountMax: 1907 intptr = &options->server_alive_count_max; 1908 goto parse_int; 1909 1910 case oSendEnv: 1911 while ((arg = argv_next(&ac, &av)) != NULL) { 1912 if (*arg == '\0' || strchr(arg, '=') != NULL) { 1913 error("%s line %d: Invalid environment name.", 1914 filename, linenum); 1915 goto out; 1916 } 1917 if (!*activep) 1918 continue; 1919 if (*arg == '-') { 1920 /* Removing an env var */ 1921 rm_env(options, arg, filename, linenum); 1922 continue; 1923 } 1924 opt_array_append(filename, linenum, 1925 lookup_opcode_name(opcode), 1926 &options->send_env, &options->num_send_env, arg); 1927 } 1928 break; 1929 1930 case oSetEnv: 1931 value = options->num_setenv; 1932 while ((arg = argv_next(&ac, &av)) != NULL) { 1933 if (strchr(arg, '=') == NULL) { 1934 error("%s line %d: Invalid SetEnv.", 1935 filename, linenum); 1936 goto out; 1937 } 1938 if (!*activep || value != 0) 1939 continue; 1940 if (lookup_setenv_in_list(arg, options->setenv, 1941 options->num_setenv) != NULL) { 1942 debug2("%s line %d: ignoring duplicate env " 1943 "name \"%.64s\"", filename, linenum, arg); 1944 continue; 1945 } 1946 opt_array_append(filename, linenum, 1947 lookup_opcode_name(opcode), 1948 &options->setenv, &options->num_setenv, arg); 1949 } 1950 break; 1951 1952 case oControlPath: 1953 charptr = &options->control_path; 1954 goto parse_string; 1955 1956 case oControlMaster: 1957 intptr = &options->control_master; 1958 multistate_ptr = multistate_controlmaster; 1959 goto parse_multistate; 1960 1961 case oControlPersist: 1962 /* no/false/yes/true, or a time spec */ 1963 intptr = &options->control_persist; 1964 arg = argv_next(&ac, &av); 1965 if (!arg || *arg == '\0') { 1966 error("%.200s line %d: Missing ControlPersist" 1967 " argument.", filename, linenum); 1968 goto out; 1969 } 1970 value = 0; 1971 value2 = 0; /* timeout */ 1972 if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 1973 value = 0; 1974 else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 1975 value = 1; 1976 else if ((value2 = convtime(arg)) >= 0) 1977 value = 1; 1978 else { 1979 error("%.200s line %d: Bad ControlPersist argument.", 1980 filename, linenum); 1981 goto out; 1982 } 1983 if (*activep && *intptr == -1) { 1984 *intptr = value; 1985 options->control_persist_timeout = value2; 1986 } 1987 break; 1988 1989 case oHashKnownHosts: 1990 intptr = &options->hash_known_hosts; 1991 goto parse_flag; 1992 1993 case oTunnel: 1994 intptr = &options->tun_open; 1995 multistate_ptr = multistate_tunnel; 1996 goto parse_multistate; 1997 1998 case oTunnelDevice: 1999 arg = argv_next(&ac, &av); 2000 if (!arg || *arg == '\0') { 2001 error("%.200s line %d: Missing argument.", 2002 filename, linenum); 2003 goto out; 2004 } 2005 value = a2tun(arg, &value2); 2006 if (value == SSH_TUNID_ERR) { 2007 error("%.200s line %d: Bad tun device.", 2008 filename, linenum); 2009 goto out; 2010 } 2011 if (*activep && options->tun_local == -1) { 2012 options->tun_local = value; 2013 options->tun_remote = value2; 2014 } 2015 break; 2016 2017 case oLocalCommand: 2018 charptr = &options->local_command; 2019 goto parse_command; 2020 2021 case oPermitLocalCommand: 2022 intptr = &options->permit_local_command; 2023 goto parse_flag; 2024 2025 case oRemoteCommand: 2026 charptr = &options->remote_command; 2027 goto parse_command; 2028 2029 case oVisualHostKey: 2030 intptr = &options->visual_host_key; 2031 goto parse_flag; 2032 2033 case oInclude: 2034 if (cmdline) { 2035 error("Include directive not supported as a " 2036 "command-line option"); 2037 goto out; 2038 } 2039 value = 0; 2040 while ((arg = argv_next(&ac, &av)) != NULL) { 2041 if (*arg == '\0') { 2042 error("%s line %d: keyword %s empty argument", 2043 filename, linenum, keyword); 2044 goto out; 2045 } 2046 /* 2047 * Ensure all paths are anchored. User configuration 2048 * files may begin with '~/' but system configurations 2049 * must not. If the path is relative, then treat it 2050 * as living in ~/.ssh for user configurations or 2051 * /etc/ssh for system ones. 2052 */ 2053 if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0) { 2054 error("%.200s line %d: bad include path %s.", 2055 filename, linenum, arg); 2056 goto out; 2057 } 2058 if (!path_absolute(arg) && *arg != '~') { 2059 xasprintf(&arg2, "%s/%s", 2060 (flags & SSHCONF_USERCONF) ? 2061 "~/" _PATH_SSH_USER_DIR : SSHDIR, arg); 2062 } else 2063 arg2 = xstrdup(arg); 2064 memset(&gl, 0, sizeof(gl)); 2065 r = glob(arg2, GLOB_TILDE | GLOB_LIMIT, NULL, &gl); 2066 if (r == GLOB_NOMATCH) { 2067 debug("%.200s line %d: include %s matched no " 2068 "files",filename, linenum, arg2); 2069 free(arg2); 2070 continue; 2071 } else if (r != 0) { 2072 error("%.200s line %d: glob failed for %s.", 2073 filename, linenum, arg2); 2074 goto out; 2075 } 2076 free(arg2); 2077 oactive = *activep; 2078 for (i = 0; i < gl.gl_pathc; i++) { 2079 debug3("%.200s line %d: Including file %s " 2080 "depth %d%s", filename, linenum, 2081 gl.gl_pathv[i], depth, 2082 oactive ? "" : " (parse only)"); 2083 r = read_config_file_depth(gl.gl_pathv[i], 2084 pw, host, original_host, options, 2085 flags | SSHCONF_CHECKPERM | 2086 (oactive ? 0 : SSHCONF_NEVERMATCH), 2087 activep, want_final_pass, depth + 1); 2088 if (r != 1 && errno != ENOENT) { 2089 error("Can't open user config file " 2090 "%.100s: %.100s", gl.gl_pathv[i], 2091 strerror(errno)); 2092 globfree(&gl); 2093 goto out; 2094 } 2095 /* 2096 * don't let Match in includes clobber the 2097 * containing file's Match state. 2098 */ 2099 *activep = oactive; 2100 if (r != 1) 2101 value = -1; 2102 } 2103 globfree(&gl); 2104 } 2105 if (value != 0) 2106 ret = value; 2107 break; 2108 2109 case oIPQoS: 2110 arg = argv_next(&ac, &av); 2111 if ((value = parse_ipqos(arg)) == -1) { 2112 error("%s line %d: Bad IPQoS value: %s", 2113 filename, linenum, arg); 2114 goto out; 2115 } 2116 arg = argv_next(&ac, &av); 2117 if (arg == NULL) 2118 value2 = value; 2119 else if ((value2 = parse_ipqos(arg)) == -1) { 2120 error("%s line %d: Bad IPQoS value: %s", 2121 filename, linenum, arg); 2122 goto out; 2123 } 2124 if (*activep && options->ip_qos_interactive == -1) { 2125 options->ip_qos_interactive = value; 2126 options->ip_qos_bulk = value2; 2127 } 2128 break; 2129 2130 case oRequestTTY: 2131 intptr = &options->request_tty; 2132 multistate_ptr = multistate_requesttty; 2133 goto parse_multistate; 2134 2135 case oSendVersionFirst: 2136 intptr = &options->send_version_first; 2137 goto parse_flag; 2138 2139 case oSessionType: 2140 intptr = &options->session_type; 2141 multistate_ptr = multistate_sessiontype; 2142 goto parse_multistate; 2143 2144 case oStdinNull: 2145 intptr = &options->stdin_null; 2146 goto parse_flag; 2147 2148 case oForkAfterAuthentication: 2149 intptr = &options->fork_after_authentication; 2150 goto parse_flag; 2151 2152 case oIgnoreUnknown: 2153 charptr = &options->ignored_unknown; 2154 goto parse_string; 2155 2156 case oProxyUseFdpass: 2157 intptr = &options->proxy_use_fdpass; 2158 goto parse_flag; 2159 2160 case oCanonicalDomains: 2161 value = options->num_canonical_domains != 0; 2162 i = 0; 2163 while ((arg = argv_next(&ac, &av)) != NULL) { 2164 if (*arg == '\0') { 2165 error("%s line %d: keyword %s empty argument", 2166 filename, linenum, keyword); 2167 goto out; 2168 } 2169 /* Allow "none" only in first position */ 2170 if (strcasecmp(arg, "none") == 0) { 2171 if (i > 0 || ac > 0) { 2172 error("%s line %d: keyword %s \"none\" " 2173 "argument must appear alone.", 2174 filename, linenum, keyword); 2175 goto out; 2176 } 2177 } 2178 i++; 2179 if (!valid_domain(arg, 1, &errstr)) { 2180 error("%s line %d: %s", filename, linenum, 2181 errstr); 2182 goto out; 2183 } 2184 if (!*activep || value) 2185 continue; 2186 if (options->num_canonical_domains >= 2187 MAX_CANON_DOMAINS) { 2188 error("%s line %d: too many hostname suffixes.", 2189 filename, linenum); 2190 goto out; 2191 } 2192 options->canonical_domains[ 2193 options->num_canonical_domains++] = xstrdup(arg); 2194 } 2195 break; 2196 2197 case oCanonicalizePermittedCNAMEs: 2198 value = options->num_permitted_cnames != 0; 2199 i = 0; 2200 while ((arg = argv_next(&ac, &av)) != NULL) { 2201 char empty[] = ""; 2202 /* 2203 * Either 'none' (only in first position), '*' for 2204 * everything or 'list:list' 2205 */ 2206 if (strcasecmp(arg, "none") == 0) { 2207 if (i > 0 || ac > 0) { 2208 error("%s line %d: keyword %s \"none\" " 2209 "argument must appear alone.", 2210 filename, linenum, keyword); 2211 goto out; 2212 } 2213 arg2 = empty; 2214 } else if (strcmp(arg, "*") == 0) { 2215 arg2 = arg; 2216 } else { 2217 lowercase(arg); 2218 if ((arg2 = strchr(arg, ':')) == NULL || 2219 arg2[1] == '\0') { 2220 error("%s line %d: " 2221 "Invalid permitted CNAME \"%s\"", 2222 filename, linenum, arg); 2223 goto out; 2224 } 2225 *arg2 = '\0'; 2226 arg2++; 2227 } 2228 i++; 2229 if (!*activep || value) 2230 continue; 2231 if (options->num_permitted_cnames >= 2232 MAX_CANON_DOMAINS) { 2233 error("%s line %d: too many permitted CNAMEs.", 2234 filename, linenum); 2235 goto out; 2236 } 2237 cname = options->permitted_cnames + 2238 options->num_permitted_cnames++; 2239 cname->source_list = xstrdup(arg); 2240 cname->target_list = xstrdup(arg2); 2241 } 2242 break; 2243 2244 case oCanonicalizeHostname: 2245 intptr = &options->canonicalize_hostname; 2246 multistate_ptr = multistate_canonicalizehostname; 2247 goto parse_multistate; 2248 2249 case oCanonicalizeMaxDots: 2250 intptr = &options->canonicalize_max_dots; 2251 goto parse_int; 2252 2253 case oCanonicalizeFallbackLocal: 2254 intptr = &options->canonicalize_fallback_local; 2255 goto parse_flag; 2256 2257 case oStreamLocalBindMask: 2258 arg = argv_next(&ac, &av); 2259 if (!arg || *arg == '\0') { 2260 error("%.200s line %d: Missing StreamLocalBindMask " 2261 "argument.", filename, linenum); 2262 goto out; 2263 } 2264 /* Parse mode in octal format */ 2265 value = strtol(arg, &endofnumber, 8); 2266 if (arg == endofnumber || value < 0 || value > 0777) { 2267 error("%.200s line %d: Bad mask.", filename, linenum); 2268 goto out; 2269 } 2270 options->fwd_opts.streamlocal_bind_mask = (mode_t)value; 2271 break; 2272 2273 case oStreamLocalBindUnlink: 2274 intptr = &options->fwd_opts.streamlocal_bind_unlink; 2275 goto parse_flag; 2276 2277 case oRevokedHostKeys: 2278 charptr = &options->revoked_host_keys; 2279 goto parse_string; 2280 2281 case oFingerprintHash: 2282 intptr = &options->fingerprint_hash; 2283 arg = argv_next(&ac, &av); 2284 if (!arg || *arg == '\0') { 2285 error("%.200s line %d: Missing argument.", 2286 filename, linenum); 2287 goto out; 2288 } 2289 if ((value = ssh_digest_alg_by_name(arg)) == -1) { 2290 error("%.200s line %d: Invalid hash algorithm \"%s\".", 2291 filename, linenum, arg); 2292 goto out; 2293 } 2294 if (*activep && *intptr == -1) 2295 *intptr = value; 2296 break; 2297 2298 case oUpdateHostkeys: 2299 intptr = &options->update_hostkeys; 2300 multistate_ptr = multistate_yesnoask; 2301 goto parse_multistate; 2302 2303 case oHostbasedAcceptedAlgorithms: 2304 charptr = &options->hostbased_accepted_algos; 2305 ca_only = 0; 2306 goto parse_pubkey_algos; 2307 2308 case oPubkeyAcceptedAlgorithms: 2309 charptr = &options->pubkey_accepted_algos; 2310 ca_only = 0; 2311 goto parse_pubkey_algos; 2312 2313 case oAddKeysToAgent: 2314 arg = argv_next(&ac, &av); 2315 arg2 = argv_next(&ac, &av); 2316 value = parse_multistate_value(arg, filename, linenum, 2317 multistate_yesnoaskconfirm); 2318 value2 = 0; /* unlimited lifespan by default */ 2319 if (value == 3 && arg2 != NULL) { 2320 /* allow "AddKeysToAgent confirm 5m" */ 2321 if ((value2 = convtime(arg2)) == -1) { 2322 error("%s line %d: invalid time value.", 2323 filename, linenum); 2324 goto out; 2325 } 2326 } else if (value == -1 && arg2 == NULL) { 2327 if ((value2 = convtime(arg)) == -1) { 2328 error("%s line %d: unsupported option", 2329 filename, linenum); 2330 goto out; 2331 } 2332 value = 1; /* yes */ 2333 } else if (value == -1 || arg2 != NULL) { 2334 error("%s line %d: unsupported option", 2335 filename, linenum); 2336 goto out; 2337 } 2338 if (*activep && options->add_keys_to_agent == -1) { 2339 options->add_keys_to_agent = value; 2340 options->add_keys_to_agent_lifespan = value2; 2341 } 2342 break; 2343 2344 case oIdentityAgent: 2345 charptr = &options->identity_agent; 2346 arg = argv_next(&ac, &av); 2347 if (!arg || *arg == '\0') { 2348 error("%.200s line %d: Missing argument.", 2349 filename, linenum); 2350 goto out; 2351 } 2352 parse_agent_path: 2353 /* Extra validation if the string represents an env var. */ 2354 if ((arg2 = dollar_expand(&r, arg)) == NULL || r) { 2355 error("%.200s line %d: Invalid environment expansion " 2356 "%s.", filename, linenum, arg); 2357 goto out; 2358 } 2359 free(arg2); 2360 /* check for legacy environment format */ 2361 if (arg[0] == '$' && arg[1] != '{' && 2362 !valid_env_name(arg + 1)) { 2363 error("%.200s line %d: Invalid environment name %s.", 2364 filename, linenum, arg); 2365 goto out; 2366 } 2367 if (*activep && *charptr == NULL) 2368 *charptr = xstrdup(arg); 2369 break; 2370 2371 case oEnableEscapeCommandline: 2372 intptr = &options->enable_escape_commandline; 2373 goto parse_flag; 2374 2375 case oRequiredRSASize: 2376 intptr = &options->required_rsa_size; 2377 goto parse_int; 2378 2379 case oObscureKeystrokeTiming: 2380 value = -1; 2381 while ((arg = argv_next(&ac, &av)) != NULL) { 2382 if (value != -1) { 2383 error("%s line %d: invalid arguments", 2384 filename, linenum); 2385 goto out; 2386 } 2387 if (strcmp(arg, "yes") == 0 || 2388 strcmp(arg, "true") == 0) 2389 value = SSH_KEYSTROKE_DEFAULT_INTERVAL_MS; 2390 else if (strcmp(arg, "no") == 0 || 2391 strcmp(arg, "false") == 0) 2392 value = 0; 2393 else if (strncmp(arg, "interval:", 9) == 0) { 2394 if ((errstr = atoi_err(arg + 9, 2395 &value)) != NULL) { 2396 error("%s line %d: integer value %s.", 2397 filename, linenum, errstr); 2398 goto out; 2399 } 2400 if (value <= 0 || value > 1000) { 2401 error("%s line %d: value out of range.", 2402 filename, linenum); 2403 goto out; 2404 } 2405 } else { 2406 error("%s line %d: unsupported argument \"%s\"", 2407 filename, linenum, arg); 2408 goto out; 2409 } 2410 } 2411 if (value == -1) { 2412 error("%s line %d: missing argument", 2413 filename, linenum); 2414 goto out; 2415 } 2416 intptr = &options->obscure_keystroke_timing_interval; 2417 if (*activep && *intptr == -1) 2418 *intptr = value; 2419 break; 2420 2421 case oChannelTimeout: 2422 uvalue = options->num_channel_timeouts; 2423 i = 0; 2424 while ((arg = argv_next(&ac, &av)) != NULL) { 2425 /* Allow "none" only in first position */ 2426 if (strcasecmp(arg, "none") == 0) { 2427 if (i > 0 || ac > 0) { 2428 error("%s line %d: keyword %s \"none\" " 2429 "argument must appear alone.", 2430 filename, linenum, keyword); 2431 goto out; 2432 } 2433 } else if (parse_pattern_interval(arg, 2434 NULL, NULL) != 0) { 2435 fatal("%s line %d: invalid channel timeout %s", 2436 filename, linenum, arg); 2437 } 2438 if (!*activep || uvalue != 0) 2439 continue; 2440 opt_array_append(filename, linenum, keyword, 2441 &options->channel_timeouts, 2442 &options->num_channel_timeouts, arg); 2443 } 2444 break; 2445 2446 case oDeprecated: 2447 debug("%s line %d: Deprecated option \"%s\"", 2448 filename, linenum, keyword); 2449 argv_consume(&ac); 2450 break; 2451 2452 case oUnsupported: 2453 error("%s line %d: Unsupported option \"%s\"", 2454 filename, linenum, keyword); 2455 argv_consume(&ac); 2456 break; 2457 2458 default: 2459 error("%s line %d: Unimplemented opcode %d", 2460 filename, linenum, opcode); 2461 goto out; 2462 } 2463 2464 /* Check that there is no garbage at end of line. */ 2465 if (ac > 0) { 2466 error("%.200s line %d: keyword %s extra arguments " 2467 "at end of line", filename, linenum, keyword); 2468 goto out; 2469 } 2470 2471 /* success */ 2472 ret = 0; 2473 out: 2474 argv_free(oav, oac); 2475 return ret; 2476} 2477 2478/* 2479 * Reads the config file and modifies the options accordingly. Options 2480 * should already be initialized before this call. This never returns if 2481 * there is an error. If the file does not exist, this returns 0. 2482 */ 2483int 2484read_config_file(const char *filename, struct passwd *pw, const char *host, 2485 const char *original_host, Options *options, int flags, 2486 int *want_final_pass) 2487{ 2488 int active = 1; 2489 2490 return read_config_file_depth(filename, pw, host, original_host, 2491 options, flags, &active, want_final_pass, 0); 2492} 2493 2494#define READCONF_MAX_DEPTH 16 2495static int 2496read_config_file_depth(const char *filename, struct passwd *pw, 2497 const char *host, const char *original_host, Options *options, 2498 int flags, int *activep, int *want_final_pass, int depth) 2499{ 2500 FILE *f; 2501 char *line = NULL; 2502 size_t linesize = 0; 2503 int linenum; 2504 int bad_options = 0; 2505 2506 if (depth < 0 || depth > READCONF_MAX_DEPTH) 2507 fatal("Too many recursive configuration includes"); 2508 2509 if ((f = fopen(filename, "r")) == NULL) 2510 return 0; 2511 2512 if (flags & SSHCONF_CHECKPERM) { 2513 struct stat sb; 2514 2515 if (fstat(fileno(f), &sb) == -1) 2516 fatal("fstat %s: %s", filename, strerror(errno)); 2517 if (((sb.st_uid != 0 && sb.st_uid != getuid()) || 2518 (sb.st_mode & 022) != 0)) 2519 fatal("Bad owner or permissions on %s", filename); 2520 } 2521 2522 debug("Reading configuration data %.200s", filename); 2523 2524 /* 2525 * Mark that we are now processing the options. This flag is turned 2526 * on/off by Host specifications. 2527 */ 2528 linenum = 0; 2529 while (getline(&line, &linesize, f) != -1) { 2530 /* Update line number counter. */ 2531 linenum++; 2532 /* 2533 * Trim out comments and strip whitespace. 2534 * NB - preserve newlines, they are needed to reproduce 2535 * line numbers later for error messages. 2536 */ 2537 if (process_config_line_depth(options, pw, host, original_host, 2538 line, filename, linenum, activep, flags, want_final_pass, 2539 depth) != 0) 2540 bad_options++; 2541 } 2542 free(line); 2543 fclose(f); 2544 if (bad_options > 0) 2545 fatal("%s: terminating, %d bad configuration options", 2546 filename, bad_options); 2547 return 1; 2548} 2549 2550/* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ 2551int 2552option_clear_or_none(const char *o) 2553{ 2554 return o == NULL || strcasecmp(o, "none") == 0; 2555} 2556 2557/* 2558 * Returns 1 if CanonicalizePermittedCNAMEs have been specified, 0 otherwise. 2559 * Allowed to be called on non-final configuration. 2560 */ 2561int 2562config_has_permitted_cnames(Options *options) 2563{ 2564 if (options->num_permitted_cnames == 1 && 2565 strcasecmp(options->permitted_cnames[0].source_list, "none") == 0 && 2566 strcmp(options->permitted_cnames[0].target_list, "") == 0) 2567 return 0; 2568 return options->num_permitted_cnames > 0; 2569} 2570 2571/* 2572 * Initializes options to special values that indicate that they have not yet 2573 * been set. Read_config_file will only set options with this value. Options 2574 * are processed in the following order: command line, user config file, 2575 * system config file. Last, fill_default_options is called. 2576 */ 2577 2578void 2579initialize_options(Options * options) 2580{ 2581 memset(options, 'X', sizeof(*options)); 2582 options->host_arg = NULL; 2583 options->forward_agent = -1; 2584 options->forward_agent_sock_path = NULL; 2585 options->forward_x11 = -1; 2586 options->forward_x11_trusted = -1; 2587 options->forward_x11_timeout = -1; 2588 options->stdio_forward_host = NULL; 2589 options->stdio_forward_port = 0; 2590 options->clear_forwardings = -1; 2591 options->exit_on_forward_failure = -1; 2592 options->xauth_location = NULL; 2593 options->fwd_opts.gateway_ports = -1; 2594 options->fwd_opts.streamlocal_bind_mask = (mode_t)-1; 2595 options->fwd_opts.streamlocal_bind_unlink = -1; 2596 options->pubkey_authentication = -1; 2597#if defined(KRB4) || defined(KRB5) 2598 options->kerberos_authentication = -1; 2599#endif 2600#if defined(AFS) || defined(KRB5) 2601 options->kerberos_tgt_passing = -1; 2602#endif 2603#ifdef AFS 2604 options->afs_token_passing = -1; 2605#endif 2606 options->gss_authentication = -1; 2607 options->gss_deleg_creds = -1; 2608 options->password_authentication = -1; 2609 options->kbd_interactive_authentication = -1; 2610 options->kbd_interactive_devices = NULL; 2611 options->hostbased_authentication = -1; 2612 options->batch_mode = -1; 2613 options->check_host_ip = -1; 2614 options->strict_host_key_checking = -1; 2615 options->compression = -1; 2616 options->tcp_keep_alive = -1; 2617 options->port = -1; 2618 options->address_family = -1; 2619 options->connection_attempts = -1; 2620 options->connection_timeout = -1; 2621 options->number_of_password_prompts = -1; 2622 options->ciphers = NULL; 2623 options->macs = NULL; 2624 options->kex_algorithms = NULL; 2625 options->hostkeyalgorithms = NULL; 2626 options->ca_sign_algorithms = NULL; 2627 options->num_identity_files = 0; 2628 memset(options->identity_keys, 0, sizeof(options->identity_keys)); 2629 options->num_certificate_files = 0; 2630 memset(options->certificates, 0, sizeof(options->certificates)); 2631 options->hostname = NULL; 2632 options->host_key_alias = NULL; 2633 options->proxy_command = NULL; 2634 options->jump_user = NULL; 2635 options->jump_host = NULL; 2636 options->jump_port = -1; 2637 options->jump_extra = NULL; 2638 options->user = NULL; 2639 options->escape_char = -1; 2640 options->num_system_hostfiles = 0; 2641 options->num_user_hostfiles = 0; 2642 options->local_forwards = NULL; 2643 options->num_local_forwards = 0; 2644 options->remote_forwards = NULL; 2645 options->num_remote_forwards = 0; 2646 options->permitted_remote_opens = NULL; 2647 options->num_permitted_remote_opens = 0; 2648 options->log_facility = SYSLOG_FACILITY_NOT_SET; 2649 options->log_level = SYSLOG_LEVEL_NOT_SET; 2650 options->num_log_verbose = 0; 2651 options->log_verbose = NULL; 2652 options->preferred_authentications = NULL; 2653 options->bind_address = NULL; 2654 options->bind_interface = NULL; 2655 options->ipv6_prefer_temporary = -1; 2656 options->pkcs11_provider = NULL; 2657 options->sk_provider = NULL; 2658 options->enable_ssh_keysign = - 1; 2659 options->no_host_authentication_for_localhost = - 1; 2660 options->identities_only = - 1; 2661 options->rekey_limit = - 1; 2662 options->rekey_interval = -1; 2663 options->verify_host_key_dns = -1; 2664 options->server_alive_interval = -1; 2665 options->server_alive_count_max = -1; 2666 options->send_env = NULL; 2667 options->num_send_env = 0; 2668 options->setenv = NULL; 2669 options->num_setenv = 0; 2670 options->control_path = NULL; 2671 options->control_master = -1; 2672 options->control_persist = -1; 2673 options->control_persist_timeout = 0; 2674 options->hash_known_hosts = -1; 2675 options->tun_open = -1; 2676 options->tun_local = -1; 2677 options->tun_remote = -1; 2678 options->local_command = NULL; 2679 options->permit_local_command = -1; 2680 options->remote_command = NULL; 2681 options->add_keys_to_agent = -1; 2682 options->add_keys_to_agent_lifespan = -1; 2683 options->identity_agent = NULL; 2684 options->visual_host_key = -1; 2685 options->ip_qos_interactive = -1; 2686 options->ip_qos_bulk = -1; 2687 options->request_tty = -1; 2688 options->session_type = -1; 2689 options->stdin_null = -1; 2690 options->fork_after_authentication = -1; 2691 options->proxy_use_fdpass = -1; 2692 options->ignored_unknown = NULL; 2693 options->num_canonical_domains = 0; 2694 options->num_permitted_cnames = 0; 2695 options->canonicalize_max_dots = -1; 2696 options->canonicalize_fallback_local = -1; 2697 options->canonicalize_hostname = -1; 2698 options->revoked_host_keys = NULL; 2699 options->fingerprint_hash = -1; 2700 options->update_hostkeys = -1; 2701 options->hostbased_accepted_algos = NULL; 2702 options->pubkey_accepted_algos = NULL; 2703 options->known_hosts_command = NULL; 2704 options->required_rsa_size = -1; 2705 options->enable_escape_commandline = -1; 2706 options->obscure_keystroke_timing_interval = -1; 2707 options->tag = NULL; 2708 options->channel_timeouts = NULL; 2709 options->num_channel_timeouts = 0; 2710 options->none_switch = -1; 2711 options->none_enabled = -1; 2712 options->hpn_disabled = -1; 2713 options->hpn_buffer_size = -1; 2714 options->tcp_rcv_buf_poll = -1; 2715 options->tcp_rcv_buf = -1; 2716 options->send_version_first = -1; 2717} 2718 2719/* 2720 * A petite version of fill_default_options() that just fills the options 2721 * needed for hostname canonicalization to proceed. 2722 */ 2723void 2724fill_default_options_for_canonicalization(Options *options) 2725{ 2726 if (options->canonicalize_max_dots == -1) 2727 options->canonicalize_max_dots = 1; 2728 if (options->canonicalize_fallback_local == -1) 2729 options->canonicalize_fallback_local = 1; 2730 if (options->canonicalize_hostname == -1) 2731 options->canonicalize_hostname = SSH_CANONICALISE_NO; 2732} 2733 2734/* 2735 * Called after processing other sources of option data, this fills those 2736 * options for which no value has been specified with their default values. 2737 */ 2738int 2739fill_default_options(Options * options) 2740{ 2741 char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig; 2742 char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig; 2743 int ret = 0, r; 2744 2745 if (options->forward_agent == -1) 2746 options->forward_agent = 0; 2747 if (options->forward_x11 == -1) 2748 options->forward_x11 = 0; 2749 if (options->forward_x11_trusted == -1) 2750 options->forward_x11_trusted = 0; 2751 if (options->forward_x11_timeout == -1) 2752 options->forward_x11_timeout = 1200; 2753 /* 2754 * stdio forwarding (-W) changes the default for these but we defer 2755 * setting the values so they can be overridden. 2756 */ 2757 if (options->exit_on_forward_failure == -1) 2758 options->exit_on_forward_failure = 2759 options->stdio_forward_host != NULL ? 1 : 0; 2760 if (options->clear_forwardings == -1) 2761 options->clear_forwardings = 2762 options->stdio_forward_host != NULL ? 1 : 0; 2763 if (options->clear_forwardings == 1) 2764 clear_forwardings(options); 2765 2766 if (options->xauth_location == NULL) 2767 options->xauth_location = xstrdup(_PATH_XAUTH); 2768 if (options->fwd_opts.gateway_ports == -1) 2769 options->fwd_opts.gateway_ports = 0; 2770 if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1) 2771 options->fwd_opts.streamlocal_bind_mask = 0177; 2772 if (options->fwd_opts.streamlocal_bind_unlink == -1) 2773 options->fwd_opts.streamlocal_bind_unlink = 0; 2774 if (options->pubkey_authentication == -1) 2775 options->pubkey_authentication = SSH_PUBKEY_AUTH_ALL; 2776#if defined(KRB4) || defined(KRB5) 2777 if (options->kerberos_authentication == -1) 2778 options->kerberos_authentication = 1; 2779#endif 2780#if defined(AFS) || defined(KRB5) 2781 if (options->kerberos_tgt_passing == -1) 2782 options->kerberos_tgt_passing = 1; 2783#endif 2784#ifdef AFS 2785 if (options->afs_token_passing == -1) 2786 options->afs_token_passing = 1; 2787#endif 2788 if (options->gss_authentication == -1) 2789 options->gss_authentication = 0; 2790 if (options->gss_deleg_creds == -1) 2791 options->gss_deleg_creds = 0; 2792 if (options->password_authentication == -1) 2793 options->password_authentication = 1; 2794 if (options->kbd_interactive_authentication == -1) 2795 options->kbd_interactive_authentication = 1; 2796 if (options->hostbased_authentication == -1) 2797 options->hostbased_authentication = 0; 2798 if (options->batch_mode == -1) 2799 options->batch_mode = 0; 2800 if (options->check_host_ip == -1) 2801 options->check_host_ip = 0; 2802 if (options->strict_host_key_checking == -1) 2803 options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK; 2804 if (options->compression == -1) 2805 options->compression = 0; 2806 if (options->tcp_keep_alive == -1) 2807 options->tcp_keep_alive = 1; 2808 if (options->port == -1) 2809 options->port = 0; /* Filled in ssh_connect. */ 2810 if (options->address_family == -1) 2811 options->address_family = AF_UNSPEC; 2812 if (options->connection_attempts == -1) 2813 options->connection_attempts = 1; 2814 if (options->number_of_password_prompts == -1) 2815 options->number_of_password_prompts = 3; 2816 /* options->hostkeyalgorithms, default set in myproposals.h */ 2817 if (options->add_keys_to_agent == -1) { 2818 options->add_keys_to_agent = 0; 2819 options->add_keys_to_agent_lifespan = 0; 2820 } 2821 if (options->num_identity_files == 0) { 2822 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0); 2823 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0); 2824 add_identity_file(options, "~/", 2825 _PATH_SSH_CLIENT_ID_ECDSA_SK, 0); 2826 add_identity_file(options, "~/", 2827 _PATH_SSH_CLIENT_ID_ED25519, 0); 2828 add_identity_file(options, "~/", 2829 _PATH_SSH_CLIENT_ID_ED25519_SK, 0); 2830 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0); 2831 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0); 2832 } 2833 if (options->escape_char == -1) 2834 options->escape_char = '~'; 2835 if (options->num_system_hostfiles == 0) { 2836 options->system_hostfiles[options->num_system_hostfiles++] = 2837 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE); 2838 options->system_hostfiles[options->num_system_hostfiles++] = 2839 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2); 2840 } 2841 if (options->update_hostkeys == -1) { 2842 if (options->verify_host_key_dns <= 0 && 2843 (options->num_user_hostfiles == 0 || 2844 (options->num_user_hostfiles == 1 && strcmp(options-> 2845 user_hostfiles[0], _PATH_SSH_USER_HOSTFILE) == 0))) 2846 options->update_hostkeys = SSH_UPDATE_HOSTKEYS_YES; 2847 else 2848 options->update_hostkeys = SSH_UPDATE_HOSTKEYS_NO; 2849 } 2850 if (options->num_user_hostfiles == 0) { 2851 options->user_hostfiles[options->num_user_hostfiles++] = 2852 xstrdup(_PATH_SSH_USER_HOSTFILE); 2853 options->user_hostfiles[options->num_user_hostfiles++] = 2854 xstrdup(_PATH_SSH_USER_HOSTFILE2); 2855 } 2856 if (options->log_level == SYSLOG_LEVEL_NOT_SET) 2857 options->log_level = SYSLOG_LEVEL_INFO; 2858 if (options->log_facility == SYSLOG_FACILITY_NOT_SET) 2859 options->log_facility = SYSLOG_FACILITY_USER; 2860 if (options->no_host_authentication_for_localhost == - 1) 2861 options->no_host_authentication_for_localhost = 0; 2862 if (options->identities_only == -1) 2863 options->identities_only = 0; 2864 if (options->enable_ssh_keysign == -1) 2865 options->enable_ssh_keysign = 0; 2866 if (options->rekey_limit == -1) 2867 options->rekey_limit = 0; 2868 if (options->rekey_interval == -1) 2869 options->rekey_interval = 0; 2870 if (options->verify_host_key_dns == -1) 2871 options->verify_host_key_dns = 0; 2872 if (options->server_alive_interval == -1) 2873 options->server_alive_interval = 0; 2874 if (options->server_alive_count_max == -1) 2875 options->server_alive_count_max = 3; 2876 if (options->none_switch == -1) 2877 options->none_switch = 0; 2878 if (options->hpn_disabled == -1) 2879 options->hpn_disabled = 0; 2880 if (options->hpn_buffer_size > -1) 2881 { 2882 /* if a user tries to set the size to 0 set it to 1KB */ 2883 if (options->hpn_buffer_size == 0) 2884 options->hpn_buffer_size = 1; 2885 /*limit the buffer to 64MB*/ 2886 if (options->hpn_buffer_size > (SSHBUF_SIZE_MAX / 1024)) 2887 { 2888 options->hpn_buffer_size = SSHBUF_SIZE_MAX; 2889 debug("User requested buffer larger than 256MB. Request reverted to 256MB"); 2890 } else 2891 options->hpn_buffer_size *= 1024; 2892 debug("hpn_buffer_size set to %d", options->hpn_buffer_size); 2893 } 2894 if (options->tcp_rcv_buf == 0) 2895 options->tcp_rcv_buf = 1; 2896 if (options->tcp_rcv_buf > -1) 2897 options->tcp_rcv_buf *=1024; 2898 if (options->tcp_rcv_buf_poll == -1) 2899 options->tcp_rcv_buf_poll = 1; 2900 if (options->control_master == -1) 2901 options->control_master = 0; 2902 if (options->control_persist == -1) { 2903 options->control_persist = 0; 2904 options->control_persist_timeout = 0; 2905 } 2906 if (options->hash_known_hosts == -1) 2907 options->hash_known_hosts = 0; 2908 if (options->tun_open == -1) 2909 options->tun_open = SSH_TUNMODE_NO; 2910 if (options->tun_local == -1) 2911 options->tun_local = SSH_TUNID_ANY; 2912 if (options->tun_remote == -1) 2913 options->tun_remote = SSH_TUNID_ANY; 2914 if (options->permit_local_command == -1) 2915 options->permit_local_command = 0; 2916 if (options->visual_host_key == -1) 2917 options->visual_host_key = 0; 2918 if (options->ip_qos_interactive == -1) 2919 options->ip_qos_interactive = IPTOS_DSCP_AF21; 2920 if (options->ip_qos_bulk == -1) 2921 options->ip_qos_bulk = IPTOS_DSCP_CS1; 2922 if (options->request_tty == -1) 2923 options->request_tty = REQUEST_TTY_AUTO; 2924 if (options->session_type == -1) 2925 options->session_type = SESSION_TYPE_DEFAULT; 2926 if (options->stdin_null == -1) 2927 options->stdin_null = 0; 2928 if (options->fork_after_authentication == -1) 2929 options->fork_after_authentication = 0; 2930 if (options->proxy_use_fdpass == -1) 2931 options->proxy_use_fdpass = 0; 2932 if (options->canonicalize_max_dots == -1) 2933 options->canonicalize_max_dots = 1; 2934 if (options->canonicalize_fallback_local == -1) 2935 options->canonicalize_fallback_local = 1; 2936 if (options->canonicalize_hostname == -1) 2937 options->canonicalize_hostname = SSH_CANONICALISE_NO; 2938 if (options->fingerprint_hash == -1) 2939 options->fingerprint_hash = SSH_FP_HASH_DEFAULT; 2940 if (options->sk_provider == NULL) 2941 options->sk_provider = xstrdup("internal"); 2942 if (options->required_rsa_size == -1) 2943 options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE; 2944 if (options->enable_escape_commandline == -1) 2945 options->enable_escape_commandline = 0; 2946 if (options->obscure_keystroke_timing_interval == -1) { 2947 options->obscure_keystroke_timing_interval = 2948 SSH_KEYSTROKE_DEFAULT_INTERVAL_MS; 2949 } 2950 2951 /* Expand KEX name lists */ 2952 all_cipher = cipher_alg_list(',', 0); 2953 all_mac = mac_alg_list(','); 2954 all_kex = kex_alg_list(','); 2955 all_key = sshkey_alg_list(0, 0, 1, ','); 2956 all_sig = sshkey_alg_list(0, 1, 1, ','); 2957 /* remove unsupported algos from default lists */ 2958 def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher); 2959 def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac); 2960 def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex); 2961 def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key); 2962 def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig); 2963#define ASSEMBLE(what, defaults, all) \ 2964 do { \ 2965 if ((r = kex_assemble_names(&options->what, \ 2966 defaults, all)) != 0) { \ 2967 error_fr(r, "%s", #what); \ 2968 goto fail; \ 2969 } \ 2970 } while (0) 2971 ASSEMBLE(ciphers, def_cipher, all_cipher); 2972 ASSEMBLE(macs, def_mac, all_mac); 2973 ASSEMBLE(kex_algorithms, def_kex, all_kex); 2974 ASSEMBLE(hostbased_accepted_algos, def_key, all_key); 2975 ASSEMBLE(pubkey_accepted_algos, def_key, all_key); 2976 ASSEMBLE(ca_sign_algorithms, def_sig, all_sig); 2977#undef ASSEMBLE 2978 2979 if (options->send_version_first == -1) 2980 options->send_version_first = 1; 2981#define CLEAR_ON_NONE(v) \ 2982 do { \ 2983 if (option_clear_or_none(v)) { \ 2984 free(v); \ 2985 v = NULL; \ 2986 } \ 2987 } while(0) 2988#define CLEAR_ON_NONE_ARRAY(v, nv, none) \ 2989 do { \ 2990 if (options->nv == 1 && \ 2991 strcasecmp(options->v[0], none) == 0) { \ 2992 free(options->v[0]); \ 2993 free(options->v); \ 2994 options->v = NULL; \ 2995 options->nv = 0; \ 2996 } \ 2997 } while (0) 2998 CLEAR_ON_NONE(options->local_command); 2999 CLEAR_ON_NONE(options->remote_command); 3000 CLEAR_ON_NONE(options->proxy_command); 3001 CLEAR_ON_NONE(options->control_path); 3002 CLEAR_ON_NONE(options->revoked_host_keys); 3003 CLEAR_ON_NONE(options->pkcs11_provider); 3004 CLEAR_ON_NONE(options->sk_provider); 3005 CLEAR_ON_NONE(options->known_hosts_command); 3006 CLEAR_ON_NONE_ARRAY(channel_timeouts, num_channel_timeouts, "none"); 3007#undef CLEAR_ON_NONE 3008#undef CLEAR_ON_NONE_ARRAY 3009 if (options->jump_host != NULL && 3010 strcmp(options->jump_host, "none") == 0 && 3011 options->jump_port == 0 && options->jump_user == NULL) { 3012 free(options->jump_host); 3013 options->jump_host = NULL; 3014 } 3015 if (options->num_permitted_cnames == 1 && 3016 !config_has_permitted_cnames(options)) { 3017 /* clean up CanonicalizePermittedCNAMEs=none */ 3018 free(options->permitted_cnames[0].source_list); 3019 free(options->permitted_cnames[0].target_list); 3020 memset(options->permitted_cnames, '\0', 3021 sizeof(*options->permitted_cnames)); 3022 options->num_permitted_cnames = 0; 3023 } 3024 /* options->identity_agent distinguishes NULL from 'none' */ 3025 /* options->user will be set in the main program if appropriate */ 3026 /* options->hostname will be set in the main program if appropriate */ 3027 /* options->host_key_alias should not be set by default */ 3028 /* options->preferred_authentications will be set in ssh */ 3029 3030 /* success */ 3031 ret = 0; 3032 fail: 3033 free(all_cipher); 3034 free(all_mac); 3035 free(all_kex); 3036 free(all_key); 3037 free(all_sig); 3038 free(def_cipher); 3039 free(def_mac); 3040 free(def_kex); 3041 free(def_key); 3042 free(def_sig); 3043 return ret; 3044} 3045 3046void 3047free_options(Options *o) 3048{ 3049 int i; 3050 3051 if (o == NULL) 3052 return; 3053 3054#define FREE_ARRAY(type, n, a) \ 3055 do { \ 3056 type _i; \ 3057 for (_i = 0; _i < (n); _i++) \ 3058 free((a)[_i]); \ 3059 } while (0) 3060 3061 free(o->forward_agent_sock_path); 3062 free(o->xauth_location); 3063 FREE_ARRAY(u_int, o->num_log_verbose, o->log_verbose); 3064 free(o->log_verbose); 3065 free(o->ciphers); 3066 free(o->macs); 3067 free(o->hostkeyalgorithms); 3068 free(o->kex_algorithms); 3069 free(o->ca_sign_algorithms); 3070 free(o->hostname); 3071 free(o->host_key_alias); 3072 free(o->proxy_command); 3073 free(o->user); 3074 FREE_ARRAY(u_int, o->num_system_hostfiles, o->system_hostfiles); 3075 FREE_ARRAY(u_int, o->num_user_hostfiles, o->user_hostfiles); 3076 free(o->preferred_authentications); 3077 free(o->bind_address); 3078 free(o->bind_interface); 3079 free(o->pkcs11_provider); 3080 free(o->sk_provider); 3081 for (i = 0; i < o->num_identity_files; i++) { 3082 free(o->identity_files[i]); 3083 sshkey_free(o->identity_keys[i]); 3084 } 3085 for (i = 0; i < o->num_certificate_files; i++) { 3086 free(o->certificate_files[i]); 3087 sshkey_free(o->certificates[i]); 3088 } 3089 free(o->identity_agent); 3090 for (i = 0; i < o->num_local_forwards; i++) { 3091 free(o->local_forwards[i].listen_host); 3092 free(o->local_forwards[i].listen_path); 3093 free(o->local_forwards[i].connect_host); 3094 free(o->local_forwards[i].connect_path); 3095 } 3096 free(o->local_forwards); 3097 for (i = 0; i < o->num_remote_forwards; i++) { 3098 free(o->remote_forwards[i].listen_host); 3099 free(o->remote_forwards[i].listen_path); 3100 free(o->remote_forwards[i].connect_host); 3101 free(o->remote_forwards[i].connect_path); 3102 } 3103 free(o->remote_forwards); 3104 free(o->stdio_forward_host); 3105 FREE_ARRAY(u_int, o->num_send_env, o->send_env); 3106 free(o->send_env); 3107 FREE_ARRAY(u_int, o->num_setenv, o->setenv); 3108 free(o->setenv); 3109 free(o->control_path); 3110 free(o->local_command); 3111 free(o->remote_command); 3112 FREE_ARRAY(int, o->num_canonical_domains, o->canonical_domains); 3113 for (i = 0; i < o->num_permitted_cnames; i++) { 3114 free(o->permitted_cnames[i].source_list); 3115 free(o->permitted_cnames[i].target_list); 3116 } 3117 free(o->revoked_host_keys); 3118 free(o->hostbased_accepted_algos); 3119 free(o->pubkey_accepted_algos); 3120 free(o->jump_user); 3121 free(o->jump_host); 3122 free(o->jump_extra); 3123 free(o->ignored_unknown); 3124 explicit_bzero(o, sizeof(*o)); 3125#undef FREE_ARRAY 3126} 3127 3128struct fwdarg { 3129 char *arg; 3130 int ispath; 3131}; 3132 3133/* 3134 * parse_fwd_field 3135 * parses the next field in a port forwarding specification. 3136 * sets fwd to the parsed field and advances p past the colon 3137 * or sets it to NULL at end of string. 3138 * returns 0 on success, else non-zero. 3139 */ 3140static int 3141parse_fwd_field(char **p, struct fwdarg *fwd) 3142{ 3143 char *ep, *cp = *p; 3144 int ispath = 0; 3145 3146 if (*cp == '\0') { 3147 *p = NULL; 3148 return -1; /* end of string */ 3149 } 3150 3151 /* 3152 * A field escaped with square brackets is used literally. 3153 * XXX - allow ']' to be escaped via backslash? 3154 */ 3155 if (*cp == '[') { 3156 /* find matching ']' */ 3157 for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) { 3158 if (*ep == '/') 3159 ispath = 1; 3160 } 3161 /* no matching ']' or not at end of field. */ 3162 if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0')) 3163 return -1; 3164 /* NUL terminate the field and advance p past the colon */ 3165 *ep++ = '\0'; 3166 if (*ep != '\0') 3167 *ep++ = '\0'; 3168 fwd->arg = cp + 1; 3169 fwd->ispath = ispath; 3170 *p = ep; 3171 return 0; 3172 } 3173 3174 for (cp = *p; *cp != '\0'; cp++) { 3175 switch (*cp) { 3176 case '\\': 3177 memmove(cp, cp + 1, strlen(cp + 1) + 1); 3178 if (*cp == '\0') 3179 return -1; 3180 break; 3181 case '/': 3182 ispath = 1; 3183 break; 3184 case ':': 3185 *cp++ = '\0'; 3186 goto done; 3187 } 3188 } 3189done: 3190 fwd->arg = *p; 3191 fwd->ispath = ispath; 3192 *p = cp; 3193 return 0; 3194} 3195 3196/* 3197 * parse_forward 3198 * parses a string containing a port forwarding specification of the form: 3199 * dynamicfwd == 0 3200 * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath 3201 * listenpath:connectpath 3202 * dynamicfwd == 1 3203 * [listenhost:]listenport 3204 * returns number of arguments parsed or zero on error 3205 */ 3206int 3207parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) 3208{ 3209 struct fwdarg fwdargs[4]; 3210 char *p, *cp; 3211 int i, err; 3212 3213 memset(fwd, 0, sizeof(*fwd)); 3214 memset(fwdargs, 0, sizeof(fwdargs)); 3215 3216 /* 3217 * We expand environment variables before checking if we think they're 3218 * paths so that if ${VAR} expands to a fully qualified path it is 3219 * treated as a path. 3220 */ 3221 cp = p = dollar_expand(&err, fwdspec); 3222 if (p == NULL || err) 3223 return 0; 3224 3225 /* skip leading spaces */ 3226 while (isspace((u_char)*cp)) 3227 cp++; 3228 3229 for (i = 0; i < 4; ++i) { 3230 if (parse_fwd_field(&cp, &fwdargs[i]) != 0) 3231 break; 3232 } 3233 3234 /* Check for trailing garbage */ 3235 if (cp != NULL && *cp != '\0') { 3236 i = 0; /* failure */ 3237 } 3238 3239 switch (i) { 3240 case 1: 3241 if (fwdargs[0].ispath) { 3242 fwd->listen_path = xstrdup(fwdargs[0].arg); 3243 fwd->listen_port = PORT_STREAMLOCAL; 3244 } else { 3245 fwd->listen_host = NULL; 3246 fwd->listen_port = a2port(fwdargs[0].arg); 3247 } 3248 fwd->connect_host = xstrdup("socks"); 3249 break; 3250 3251 case 2: 3252 if (fwdargs[0].ispath && fwdargs[1].ispath) { 3253 fwd->listen_path = xstrdup(fwdargs[0].arg); 3254 fwd->listen_port = PORT_STREAMLOCAL; 3255 fwd->connect_path = xstrdup(fwdargs[1].arg); 3256 fwd->connect_port = PORT_STREAMLOCAL; 3257 } else if (fwdargs[1].ispath) { 3258 fwd->listen_host = NULL; 3259 fwd->listen_port = a2port(fwdargs[0].arg); 3260 fwd->connect_path = xstrdup(fwdargs[1].arg); 3261 fwd->connect_port = PORT_STREAMLOCAL; 3262 } else { 3263 fwd->listen_host = xstrdup(fwdargs[0].arg); 3264 fwd->listen_port = a2port(fwdargs[1].arg); 3265 fwd->connect_host = xstrdup("socks"); 3266 } 3267 break; 3268 3269 case 3: 3270 if (fwdargs[0].ispath) { 3271 fwd->listen_path = xstrdup(fwdargs[0].arg); 3272 fwd->listen_port = PORT_STREAMLOCAL; 3273 fwd->connect_host = xstrdup(fwdargs[1].arg); 3274 fwd->connect_port = a2port(fwdargs[2].arg); 3275 } else if (fwdargs[2].ispath) { 3276 fwd->listen_host = xstrdup(fwdargs[0].arg); 3277 fwd->listen_port = a2port(fwdargs[1].arg); 3278 fwd->connect_path = xstrdup(fwdargs[2].arg); 3279 fwd->connect_port = PORT_STREAMLOCAL; 3280 } else { 3281 fwd->listen_host = NULL; 3282 fwd->listen_port = a2port(fwdargs[0].arg); 3283 fwd->connect_host = xstrdup(fwdargs[1].arg); 3284 fwd->connect_port = a2port(fwdargs[2].arg); 3285 } 3286 break; 3287 3288 case 4: 3289 fwd->listen_host = xstrdup(fwdargs[0].arg); 3290 fwd->listen_port = a2port(fwdargs[1].arg); 3291 fwd->connect_host = xstrdup(fwdargs[2].arg); 3292 fwd->connect_port = a2port(fwdargs[3].arg); 3293 break; 3294 default: 3295 i = 0; /* failure */ 3296 } 3297 3298 free(p); 3299 3300 if (dynamicfwd) { 3301 if (!(i == 1 || i == 2)) 3302 goto fail_free; 3303 } else { 3304 if (!(i == 3 || i == 4)) { 3305 if (fwd->connect_path == NULL && 3306 fwd->listen_path == NULL) 3307 goto fail_free; 3308 } 3309 if (fwd->connect_port <= 0 && fwd->connect_path == NULL) 3310 goto fail_free; 3311 } 3312 3313 if ((fwd->listen_port < 0 && fwd->listen_path == NULL) || 3314 (!remotefwd && fwd->listen_port == 0)) 3315 goto fail_free; 3316 if (fwd->connect_host != NULL && 3317 strlen(fwd->connect_host) >= NI_MAXHOST) 3318 goto fail_free; 3319 /* 3320 * XXX - if connecting to a remote socket, max sun len may not 3321 * match this host 3322 */ 3323 if (fwd->connect_path != NULL && 3324 strlen(fwd->connect_path) >= PATH_MAX_SUN) 3325 goto fail_free; 3326 if (fwd->listen_host != NULL && 3327 strlen(fwd->listen_host) >= NI_MAXHOST) 3328 goto fail_free; 3329 if (fwd->listen_path != NULL && 3330 strlen(fwd->listen_path) >= PATH_MAX_SUN) 3331 goto fail_free; 3332 3333 return (i); 3334 3335 fail_free: 3336 free(fwd->connect_host); 3337 fwd->connect_host = NULL; 3338 free(fwd->connect_path); 3339 fwd->connect_path = NULL; 3340 free(fwd->listen_host); 3341 fwd->listen_host = NULL; 3342 free(fwd->listen_path); 3343 fwd->listen_path = NULL; 3344 return (0); 3345} 3346 3347int 3348parse_jump(const char *s, Options *o, int active) 3349{ 3350 char *orig, *sdup, *cp; 3351 char *host = NULL, *user = NULL; 3352 int r, ret = -1, port = -1, first; 3353 3354 active &= o->proxy_command == NULL && o->jump_host == NULL; 3355 3356 orig = sdup = xstrdup(s); 3357 3358 /* Remove comment and trailing whitespace */ 3359 if ((cp = strchr(orig, '#')) != NULL) 3360 *cp = '\0'; 3361 rtrim(orig); 3362 3363 first = active; 3364 do { 3365 if (strcasecmp(s, "none") == 0) 3366 break; 3367 if ((cp = strrchr(sdup, ',')) == NULL) 3368 cp = sdup; /* last */ 3369 else 3370 *cp++ = '\0'; 3371 3372 if (first) { 3373 /* First argument and configuration is active */ 3374 r = parse_ssh_uri(cp, &user, &host, &port); 3375 if (r == -1 || (r == 1 && 3376 parse_user_host_port(cp, &user, &host, &port) != 0)) 3377 goto out; 3378 } else { 3379 /* Subsequent argument or inactive configuration */ 3380 r = parse_ssh_uri(cp, NULL, NULL, NULL); 3381 if (r == -1 || (r == 1 && 3382 parse_user_host_port(cp, NULL, NULL, NULL) != 0)) 3383 goto out; 3384 } 3385 first = 0; /* only check syntax for subsequent hosts */ 3386 } while (cp != sdup); 3387 /* success */ 3388 if (active) { 3389 if (strcasecmp(s, "none") == 0) { 3390 o->jump_host = xstrdup("none"); 3391 o->jump_port = 0; 3392 } else { 3393 o->jump_user = user; 3394 o->jump_host = host; 3395 o->jump_port = port; 3396 o->proxy_command = xstrdup("none"); 3397 user = host = NULL; 3398 if ((cp = strrchr(s, ',')) != NULL && cp != s) { 3399 o->jump_extra = xstrdup(s); 3400 o->jump_extra[cp - s] = '\0'; 3401 } 3402 } 3403 } 3404 ret = 0; 3405 out: 3406 free(orig); 3407 free(user); 3408 free(host); 3409 return ret; 3410} 3411 3412int 3413parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp) 3414{ 3415 char *user = NULL, *host = NULL, *path = NULL; 3416 int r, port; 3417 3418 r = parse_uri("ssh", uri, &user, &host, &port, &path); 3419 if (r == 0 && path != NULL) 3420 r = -1; /* path not allowed */ 3421 if (r == 0) { 3422 if (userp != NULL) { 3423 *userp = user; 3424 user = NULL; 3425 } 3426 if (hostp != NULL) { 3427 *hostp = host; 3428 host = NULL; 3429 } 3430 if (portp != NULL) 3431 *portp = port; 3432 } 3433 free(user); 3434 free(host); 3435 free(path); 3436 return r; 3437} 3438 3439/* XXX the following is a near-vebatim copy from servconf.c; refactor */ 3440static const char * 3441fmt_multistate_int(int val, const struct multistate *m) 3442{ 3443 u_int i; 3444 3445 for (i = 0; m[i].key != NULL; i++) { 3446 if (m[i].value == val) 3447 return m[i].key; 3448 } 3449 return "UNKNOWN"; 3450} 3451 3452static const char * 3453fmt_intarg(OpCodes code, int val) 3454{ 3455 if (val == -1) 3456 return "unset"; 3457 switch (code) { 3458 case oAddressFamily: 3459 return fmt_multistate_int(val, multistate_addressfamily); 3460 case oVerifyHostKeyDNS: 3461 case oUpdateHostkeys: 3462 return fmt_multistate_int(val, multistate_yesnoask); 3463 case oStrictHostKeyChecking: 3464 return fmt_multistate_int(val, multistate_strict_hostkey); 3465 case oControlMaster: 3466 return fmt_multistate_int(val, multistate_controlmaster); 3467 case oTunnel: 3468 return fmt_multistate_int(val, multistate_tunnel); 3469 case oRequestTTY: 3470 return fmt_multistate_int(val, multistate_requesttty); 3471 case oSessionType: 3472 return fmt_multistate_int(val, multistate_sessiontype); 3473 case oCanonicalizeHostname: 3474 return fmt_multistate_int(val, multistate_canonicalizehostname); 3475 case oAddKeysToAgent: 3476 return fmt_multistate_int(val, multistate_yesnoaskconfirm); 3477 case oPubkeyAuthentication: 3478 return fmt_multistate_int(val, multistate_pubkey_auth); 3479 case oFingerprintHash: 3480 return ssh_digest_alg_name(val); 3481 default: 3482 switch (val) { 3483 case 0: 3484 return "no"; 3485 case 1: 3486 return "yes"; 3487 default: 3488 return "UNKNOWN"; 3489 } 3490 } 3491} 3492 3493static const char * 3494lookup_opcode_name(OpCodes code) 3495{ 3496 u_int i; 3497 3498 for (i = 0; keywords[i].name != NULL; i++) 3499 if (keywords[i].opcode == code) 3500 return(keywords[i].name); 3501 return "UNKNOWN"; 3502} 3503 3504static void 3505dump_cfg_int(OpCodes code, int val) 3506{ 3507 if (code == oObscureKeystrokeTiming) { 3508 if (val == 0) { 3509 printf("%s no\n", lookup_opcode_name(code)); 3510 return; 3511 } else if (val == SSH_KEYSTROKE_DEFAULT_INTERVAL_MS) { 3512 printf("%s yes\n", lookup_opcode_name(code)); 3513 return; 3514 } 3515 /* FALLTHROUGH */ 3516 } 3517 printf("%s %d\n", lookup_opcode_name(code), val); 3518} 3519 3520static void 3521dump_cfg_fmtint(OpCodes code, int val) 3522{ 3523 printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val)); 3524} 3525 3526static void 3527dump_cfg_string(OpCodes code, const char *val) 3528{ 3529 if (val == NULL) 3530 return; 3531 printf("%s %s\n", lookup_opcode_name(code), val); 3532} 3533 3534static void 3535dump_cfg_strarray(OpCodes code, u_int count, char **vals) 3536{ 3537 u_int i; 3538 3539 for (i = 0; i < count; i++) 3540 printf("%s %s\n", lookup_opcode_name(code), vals[i]); 3541} 3542 3543static void 3544dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals) 3545{ 3546 u_int i; 3547 3548 printf("%s", lookup_opcode_name(code)); 3549 if (count == 0) 3550 printf(" none"); 3551 for (i = 0; i < count; i++) 3552 printf(" %s", vals[i]); 3553 printf("\n"); 3554} 3555 3556static void 3557dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds) 3558{ 3559 const struct Forward *fwd; 3560 u_int i; 3561 3562 /* oDynamicForward */ 3563 for (i = 0; i < count; i++) { 3564 fwd = &fwds[i]; 3565 if (code == oDynamicForward && fwd->connect_host != NULL && 3566 strcmp(fwd->connect_host, "socks") != 0) 3567 continue; 3568 if (code == oLocalForward && fwd->connect_host != NULL && 3569 strcmp(fwd->connect_host, "socks") == 0) 3570 continue; 3571 printf("%s", lookup_opcode_name(code)); 3572 if (fwd->listen_port == PORT_STREAMLOCAL) 3573 printf(" %s", fwd->listen_path); 3574 else if (fwd->listen_host == NULL) 3575 printf(" %d", fwd->listen_port); 3576 else { 3577 printf(" [%s]:%d", 3578 fwd->listen_host, fwd->listen_port); 3579 } 3580 if (code != oDynamicForward) { 3581 if (fwd->connect_port == PORT_STREAMLOCAL) 3582 printf(" %s", fwd->connect_path); 3583 else if (fwd->connect_host == NULL) 3584 printf(" %d", fwd->connect_port); 3585 else { 3586 printf(" [%s]:%d", 3587 fwd->connect_host, fwd->connect_port); 3588 } 3589 } 3590 printf("\n"); 3591 } 3592} 3593 3594void 3595dump_client_config(Options *o, const char *host) 3596{ 3597 int i, r; 3598 char buf[8], *all_key; 3599 3600 /* 3601 * Expand HostKeyAlgorithms name lists. This isn't handled in 3602 * fill_default_options() like the other algorithm lists because 3603 * the host key algorithms are by default dynamically chosen based 3604 * on the host's keys found in known_hosts. 3605 */ 3606 all_key = sshkey_alg_list(0, 0, 1, ','); 3607 if ((r = kex_assemble_names(&o->hostkeyalgorithms, kex_default_pk_alg(), 3608 all_key)) != 0) 3609 fatal_fr(r, "expand HostKeyAlgorithms"); 3610 free(all_key); 3611 3612 /* Most interesting options first: user, host, port */ 3613 dump_cfg_string(oHost, o->host_arg); 3614 dump_cfg_string(oUser, o->user); 3615 dump_cfg_string(oHostname, host); 3616 dump_cfg_int(oPort, o->port); 3617 3618 /* Flag options */ 3619 dump_cfg_fmtint(oAddressFamily, o->address_family); 3620 dump_cfg_fmtint(oBatchMode, o->batch_mode); 3621 dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local); 3622 dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname); 3623 dump_cfg_fmtint(oCheckHostIP, o->check_host_ip); 3624 dump_cfg_fmtint(oCompression, o->compression); 3625 dump_cfg_fmtint(oControlMaster, o->control_master); 3626 dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign); 3627 dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings); 3628 dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure); 3629 dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash); 3630 dump_cfg_fmtint(oForwardX11, o->forward_x11); 3631 dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted); 3632 dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports); 3633#ifdef GSSAPI 3634 dump_cfg_fmtint(oGssAuthentication, o->gss_authentication); 3635 dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds); 3636#endif /* GSSAPI */ 3637 dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts); 3638 dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication); 3639 dump_cfg_fmtint(oIdentitiesOnly, o->identities_only); 3640 dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication); 3641 dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost); 3642 dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication); 3643 dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command); 3644 dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass); 3645 dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication); 3646 dump_cfg_fmtint(oRequestTTY, o->request_tty); 3647 dump_cfg_fmtint(oSessionType, o->session_type); 3648 dump_cfg_fmtint(oStdinNull, o->stdin_null); 3649 dump_cfg_fmtint(oForkAfterAuthentication, o->fork_after_authentication); 3650 dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink); 3651 dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking); 3652 dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive); 3653 dump_cfg_fmtint(oTunnel, o->tun_open); 3654 dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns); 3655 dump_cfg_fmtint(oVisualHostKey, o->visual_host_key); 3656 dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys); 3657 dump_cfg_fmtint(oEnableEscapeCommandline, o->enable_escape_commandline); 3658 3659 /* Integer options */ 3660 dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots); 3661 dump_cfg_int(oConnectionAttempts, o->connection_attempts); 3662 dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout); 3663 dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts); 3664 dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max); 3665 dump_cfg_int(oServerAliveInterval, o->server_alive_interval); 3666 dump_cfg_int(oRequiredRSASize, o->required_rsa_size); 3667 dump_cfg_int(oObscureKeystrokeTiming, 3668 o->obscure_keystroke_timing_interval); 3669 3670 /* String options */ 3671 dump_cfg_string(oBindAddress, o->bind_address); 3672 dump_cfg_string(oBindInterface, o->bind_interface); 3673 dump_cfg_string(oCiphers, o->ciphers); 3674 dump_cfg_string(oControlPath, o->control_path); 3675 dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms); 3676 dump_cfg_string(oHostKeyAlias, o->host_key_alias); 3677 dump_cfg_string(oHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos); 3678 dump_cfg_string(oIdentityAgent, o->identity_agent); 3679 dump_cfg_string(oIgnoreUnknown, o->ignored_unknown); 3680 dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices); 3681 dump_cfg_string(oKexAlgorithms, o->kex_algorithms); 3682 dump_cfg_string(oCASignatureAlgorithms, o->ca_sign_algorithms); 3683 dump_cfg_string(oLocalCommand, o->local_command); 3684 dump_cfg_string(oRemoteCommand, o->remote_command); 3685 dump_cfg_string(oLogLevel, log_level_name(o->log_level)); 3686 dump_cfg_string(oMacs, o->macs); 3687#ifdef ENABLE_PKCS11 3688 dump_cfg_string(oPKCS11Provider, o->pkcs11_provider); 3689#endif 3690 dump_cfg_string(oSecurityKeyProvider, o->sk_provider); 3691 dump_cfg_string(oPreferredAuthentications, o->preferred_authentications); 3692 dump_cfg_string(oPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos); 3693 dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys); 3694 dump_cfg_string(oXAuthLocation, o->xauth_location); 3695 dump_cfg_string(oKnownHostsCommand, o->known_hosts_command); 3696 dump_cfg_string(oTag, o->tag); 3697 3698 /* Forwards */ 3699 dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards); 3700 dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards); 3701 dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards); 3702 3703 /* String array options */ 3704 dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files); 3705 dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains); 3706 dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files); 3707 dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles); 3708 dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles); 3709 dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env); 3710 dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv); 3711 dump_cfg_strarray_oneline(oLogVerbose, 3712 o->num_log_verbose, o->log_verbose); 3713 dump_cfg_strarray_oneline(oChannelTimeout, 3714 o->num_channel_timeouts, o->channel_timeouts); 3715 3716 /* Special cases */ 3717 3718 /* PermitRemoteOpen */ 3719 if (o->num_permitted_remote_opens == 0) 3720 printf("%s any\n", lookup_opcode_name(oPermitRemoteOpen)); 3721 else 3722 dump_cfg_strarray_oneline(oPermitRemoteOpen, 3723 o->num_permitted_remote_opens, o->permitted_remote_opens); 3724 3725 /* AddKeysToAgent */ 3726 if (o->add_keys_to_agent_lifespan <= 0) 3727 dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent); 3728 else { 3729 printf("addkeystoagent%s %d\n", 3730 o->add_keys_to_agent == 3 ? " confirm" : "", 3731 o->add_keys_to_agent_lifespan); 3732 } 3733 3734 /* oForwardAgent */ 3735 if (o->forward_agent_sock_path == NULL) 3736 dump_cfg_fmtint(oForwardAgent, o->forward_agent); 3737 else 3738 dump_cfg_string(oForwardAgent, o->forward_agent_sock_path); 3739 3740 /* oConnectTimeout */ 3741 if (o->connection_timeout == -1) 3742 printf("connecttimeout none\n"); 3743 else 3744 dump_cfg_int(oConnectTimeout, o->connection_timeout); 3745 3746 /* oTunnelDevice */ 3747 printf("tunneldevice"); 3748 if (o->tun_local == SSH_TUNID_ANY) 3749 printf(" any"); 3750 else 3751 printf(" %d", o->tun_local); 3752 if (o->tun_remote == SSH_TUNID_ANY) 3753 printf(":any"); 3754 else 3755 printf(":%d", o->tun_remote); 3756 printf("\n"); 3757 3758 /* oCanonicalizePermittedCNAMEs */ 3759 printf("canonicalizePermittedcnames"); 3760 if (o->num_permitted_cnames == 0) 3761 printf(" none"); 3762 for (i = 0; i < o->num_permitted_cnames; i++) { 3763 printf(" %s:%s", o->permitted_cnames[i].source_list, 3764 o->permitted_cnames[i].target_list); 3765 } 3766 printf("\n"); 3767 3768 /* oControlPersist */ 3769 if (o->control_persist == 0 || o->control_persist_timeout == 0) 3770 dump_cfg_fmtint(oControlPersist, o->control_persist); 3771 else 3772 dump_cfg_int(oControlPersist, o->control_persist_timeout); 3773 3774 /* oEscapeChar */ 3775 if (o->escape_char == SSH_ESCAPECHAR_NONE) 3776 printf("escapechar none\n"); 3777 else { 3778 vis(buf, o->escape_char, VIS_WHITE, 0); 3779 printf("escapechar %s\n", buf); 3780 } 3781 3782 /* oIPQoS */ 3783 printf("ipqos %s ", iptos2str(o->ip_qos_interactive)); 3784 printf("%s\n", iptos2str(o->ip_qos_bulk)); 3785 3786 /* oRekeyLimit */ 3787 printf("rekeylimit %llu %d\n", 3788 (unsigned long long)o->rekey_limit, o->rekey_interval); 3789 3790 /* oStreamLocalBindMask */ 3791 printf("streamlocalbindmask 0%o\n", 3792 o->fwd_opts.streamlocal_bind_mask); 3793 3794 /* oLogFacility */ 3795 printf("syslogfacility %s\n", log_facility_name(o->log_facility)); 3796 3797 /* oProxyCommand / oProxyJump */ 3798 if (o->jump_host == NULL) 3799 dump_cfg_string(oProxyCommand, o->proxy_command); 3800 else { 3801 /* Check for numeric addresses */ 3802 i = strchr(o->jump_host, ':') != NULL || 3803 strspn(o->jump_host, "1234567890.") == strlen(o->jump_host); 3804 snprintf(buf, sizeof(buf), "%d", o->jump_port); 3805 printf("proxyjump %s%s%s%s%s%s%s%s%s\n", 3806 /* optional additional jump spec */ 3807 o->jump_extra == NULL ? "" : o->jump_extra, 3808 o->jump_extra == NULL ? "" : ",", 3809 /* optional user */ 3810 o->jump_user == NULL ? "" : o->jump_user, 3811 o->jump_user == NULL ? "" : "@", 3812 /* opening [ if hostname is numeric */ 3813 i ? "[" : "", 3814 /* mandatory hostname */ 3815 o->jump_host, 3816 /* closing ] if hostname is numeric */ 3817 i ? "]" : "", 3818 /* optional port number */ 3819 o->jump_port <= 0 ? "" : ":", 3820 o->jump_port <= 0 ? "" : buf); 3821 } 3822} 3823