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