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