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