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