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