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