Home | History | Annotate | Line # | Download | only in dist
readconf.c revision 1.13
      1 /*	$NetBSD: readconf.c,v 1.13 2015/04/03 23:58:19 christos Exp $	*/
      2 /* $OpenBSD: readconf.c,v 1.232 2015/02/16 22:13:32 djm 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.13 2015/04/03 23:58:19 christos 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 <netdb.h>
     31 #include <paths.h>
     32 #include <pwd.h>
     33 #include <signal.h>
     34 #include <stdio.h>
     35 #include <string.h>
     36 #include <unistd.h>
     37 #include <limits.h>
     38 #include <util.h>
     39 #include <vis.h>
     40 
     41 #include "xmalloc.h"
     42 #include "ssh.h"
     43 #include "compat.h"
     44 #include "cipher.h"
     45 #include "pathnames.h"
     46 #include "log.h"
     47 #include "sshkey.h"
     48 #include "misc.h"
     49 #include "readconf.h"
     50 #include "match.h"
     51 #include "kex.h"
     52 #include "mac.h"
     53 #include "fmt_scaled.h"
     54 #include "uidswap.h"
     55 #include "myproposal.h"
     56 #include "digest.h"
     57 
     58 /* Format of the configuration file:
     59 
     60    # Configuration data is parsed as follows:
     61    #  1. command line options
     62    #  2. user-specific file
     63    #  3. system-wide file
     64    # Any configuration value is only changed the first time it is set.
     65    # Thus, host-specific definitions should be at the beginning of the
     66    # configuration file, and defaults at the end.
     67 
     68    # Host-specific declarations.  These may override anything above.  A single
     69    # host may match multiple declarations; these are processed in the order
     70    # that they are given in.
     71 
     72    Host *.ngs.fi ngs.fi
     73      User foo
     74 
     75    Host fake.com
     76      HostName another.host.name.real.org
     77      User blaah
     78      Port 34289
     79      ForwardX11 no
     80      ForwardAgent no
     81 
     82    Host books.com
     83      RemoteForward 9999 shadows.cs.hut.fi:9999
     84      Cipher 3des
     85 
     86    Host fascist.blob.com
     87      Port 23123
     88      User tylonen
     89      PasswordAuthentication no
     90 
     91    Host puukko.hut.fi
     92      User t35124p
     93      ProxyCommand ssh-proxy %h %p
     94 
     95    Host *.fr
     96      PublicKeyAuthentication no
     97 
     98    Host *.su
     99      Cipher none
    100      PasswordAuthentication no
    101 
    102    Host vpn.fake.com
    103      Tunnel yes
    104      TunnelDevice 3
    105 
    106    # Defaults for various options
    107    Host *
    108      ForwardAgent no
    109      ForwardX11 no
    110      PasswordAuthentication yes
    111      RSAAuthentication yes
    112      RhostsRSAAuthentication yes
    113      StrictHostKeyChecking yes
    114      TcpKeepAlive no
    115      IdentityFile ~/.ssh/identity
    116      Port 22
    117      EscapeChar ~
    118 
    119 */
    120 
    121 /* Keyword tokens. */
    122 
    123 typedef enum {
    124 	oBadOption,
    125 	oHost, oMatch,
    126 	oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
    127 	oGatewayPorts, oExitOnForwardFailure,
    128 	oPasswordAuthentication, oRSAAuthentication,
    129 	oChallengeResponseAuthentication, oXAuthLocation,
    130 #if defined(KRB4) || defined(KRB5)
    131 	oKerberosAuthentication,
    132 #endif
    133 #if defined(AFS) || defined(KRB5)
    134 	oKerberosTgtPassing,
    135 #endif
    136 #ifdef AFS
    137 	oAFSTokenPassing,
    138 #endif
    139 	oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
    140 	oUser, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
    141 	oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
    142 	oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
    143 	oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
    144 	oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
    145 	oPubkeyAuthentication,
    146 	oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
    147 	oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
    148 	oHostKeyAlgorithms, oBindAddress, oPKCS11Provider,
    149 	oClearAllForwardings, oNoHostAuthenticationForLocalhost,
    150 	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
    151 	oAddressFamily, oGssAuthentication, oGssDelegateCreds,
    152 	oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
    153 	oSendEnv, oControlPath, oControlMaster, oControlPersist,
    154 	oHashKnownHosts,
    155 	oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
    156 	oVisualHostKey, oUseRoaming,
    157 	oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass,
    158 	oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
    159 	oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
    160 	oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
    161 	oFingerprintHash, oUpdateHostkeys, oHostbasedKeyTypes,
    162 	oNoneEnabled, oTcpRcvBufPoll, oTcpRcvBuf, oNoneSwitch, oHPNDisabled,
    163 	oHPNBufferSize,
    164 	oSendVersionFirst,
    165 	oIgnoredUnknownOption, oDeprecated, oUnsupported
    166 } OpCodes;
    167 
    168 /* Textual representations of the tokens. */
    169 
    170 static struct {
    171 	const char *name;
    172 	OpCodes opcode;
    173 } keywords[] = {
    174 	{ "forwardagent", oForwardAgent },
    175 	{ "forwardx11", oForwardX11 },
    176 	{ "forwardx11trusted", oForwardX11Trusted },
    177 	{ "forwardx11timeout", oForwardX11Timeout },
    178 	{ "exitonforwardfailure", oExitOnForwardFailure },
    179 	{ "xauthlocation", oXAuthLocation },
    180 	{ "gatewayports", oGatewayPorts },
    181 	{ "useprivilegedport", oUsePrivilegedPort },
    182 	{ "rhostsauthentication", oDeprecated },
    183 	{ "passwordauthentication", oPasswordAuthentication },
    184 	{ "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
    185 	{ "kbdinteractivedevices", oKbdInteractiveDevices },
    186 	{ "rsaauthentication", oRSAAuthentication },
    187 	{ "pubkeyauthentication", oPubkeyAuthentication },
    188 	{ "dsaauthentication", oPubkeyAuthentication },		    /* alias */
    189 	{ "rhostsrsaauthentication", oRhostsRSAAuthentication },
    190 	{ "hostbasedauthentication", oHostbasedAuthentication },
    191 	{ "challengeresponseauthentication", oChallengeResponseAuthentication },
    192 	{ "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
    193 	{ "tisauthentication", oChallengeResponseAuthentication },  /* alias */
    194 #if defined(KRB4) || defined(KRB5)
    195 	{ "kerberosauthentication", oKerberosAuthentication },
    196 #endif
    197 #if defined(AFS) || defined(KRB5)
    198 	{ "kerberostgtpassing", oKerberosTgtPassing },
    199 	{ "kerberos5tgtpassing", oKerberosTgtPassing },		/* alias */
    200 	{ "kerberos4tgtpassing", oKerberosTgtPassing },		/* alias */
    201 #endif
    202 #ifdef AFS
    203 	{ "afstokenpassing", oAFSTokenPassing },
    204 #endif
    205 #if defined(GSSAPI)
    206 	{ "gssapiauthentication", oGssAuthentication },
    207 	{ "gssapidelegatecredentials", oGssDelegateCreds },
    208 #else
    209 	{ "gssapiauthentication", oUnsupported },
    210 	{ "gssapidelegatecredentials", oUnsupported },
    211 #endif
    212 	{ "fallbacktorsh", oDeprecated },
    213 	{ "usersh", oDeprecated },
    214 	{ "identityfile", oIdentityFile },
    215 	{ "identityfile2", oIdentityFile },			/* obsolete */
    216 	{ "identitiesonly", oIdentitiesOnly },
    217 	{ "hostname", oHostName },
    218 	{ "hostkeyalias", oHostKeyAlias },
    219 	{ "proxycommand", oProxyCommand },
    220 	{ "port", oPort },
    221 	{ "cipher", oCipher },
    222 	{ "ciphers", oCiphers },
    223 	{ "macs", oMacs },
    224 	{ "protocol", oProtocol },
    225 	{ "remoteforward", oRemoteForward },
    226 	{ "localforward", oLocalForward },
    227 	{ "user", oUser },
    228 	{ "host", oHost },
    229 	{ "match", oMatch },
    230 	{ "escapechar", oEscapeChar },
    231 	{ "globalknownhostsfile", oGlobalKnownHostsFile },
    232 	{ "globalknownhostsfile2", oDeprecated },
    233 	{ "userknownhostsfile", oUserKnownHostsFile },
    234 	{ "userknownhostsfile2", oDeprecated },
    235 	{ "connectionattempts", oConnectionAttempts },
    236 	{ "batchmode", oBatchMode },
    237 	{ "checkhostip", oCheckHostIP },
    238 	{ "stricthostkeychecking", oStrictHostKeyChecking },
    239 	{ "compression", oCompression },
    240 	{ "compressionlevel", oCompressionLevel },
    241 	{ "tcpkeepalive", oTCPKeepAlive },
    242 	{ "keepalive", oTCPKeepAlive },				/* obsolete */
    243 	{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
    244 	{ "loglevel", oLogLevel },
    245 	{ "dynamicforward", oDynamicForward },
    246 	{ "preferredauthentications", oPreferredAuthentications },
    247 	{ "hostkeyalgorithms", oHostKeyAlgorithms },
    248 	{ "bindaddress", oBindAddress },
    249 #ifdef ENABLE_PKCS11
    250 	{ "smartcarddevice", oPKCS11Provider },
    251 	{ "pkcs11provider", oPKCS11Provider },
    252 #else
    253 	{ "smartcarddevice", oUnsupported },
    254 	{ "pkcs11provider", oUnsupported },
    255 #endif
    256 	{ "clearallforwardings", oClearAllForwardings },
    257 	{ "enablesshkeysign", oEnableSSHKeysign },
    258 	{ "verifyhostkeydns", oVerifyHostKeyDNS },
    259 	{ "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
    260 	{ "rekeylimit", oRekeyLimit },
    261 	{ "connecttimeout", oConnectTimeout },
    262 	{ "addressfamily", oAddressFamily },
    263 	{ "serveraliveinterval", oServerAliveInterval },
    264 	{ "serveralivecountmax", oServerAliveCountMax },
    265 	{ "sendenv", oSendEnv },
    266 	{ "controlpath", oControlPath },
    267 	{ "controlmaster", oControlMaster },
    268 	{ "controlpersist", oControlPersist },
    269 	{ "hashknownhosts", oHashKnownHosts },
    270 	{ "tunnel", oTunnel },
    271 	{ "tunneldevice", oTunnelDevice },
    272 	{ "localcommand", oLocalCommand },
    273 	{ "permitlocalcommand", oPermitLocalCommand },
    274 	{ "visualhostkey", oVisualHostKey },
    275 	{ "useroaming", oUseRoaming },
    276 	{ "kexalgorithms", oKexAlgorithms },
    277 	{ "ipqos", oIPQoS },
    278 	{ "requesttty", oRequestTTY },
    279 	{ "proxyusefdpass", oProxyUseFdpass },
    280 	{ "canonicaldomains", oCanonicalDomains },
    281 	{ "canonicalizefallbacklocal", oCanonicalizeFallbackLocal },
    282 	{ "canonicalizehostname", oCanonicalizeHostname },
    283 	{ "canonicalizemaxdots", oCanonicalizeMaxDots },
    284 	{ "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs },
    285 	{ "streamlocalbindmask", oStreamLocalBindMask },
    286 	{ "streamlocalbindunlink", oStreamLocalBindUnlink },
    287 	{ "revokedhostkeys", oRevokedHostKeys },
    288 	{ "fingerprinthash", oFingerprintHash },
    289 	{ "updatehostkeys", oUpdateHostkeys },
    290 	{ "hostbasedkeytypes", oHostbasedKeyTypes },
    291 	{ "noneenabled", oNoneEnabled },
    292 	{ "tcprcvbufpoll", oTcpRcvBufPoll },
    293 	{ "tcprcvbuf", oTcpRcvBuf },
    294 	{ "noneswitch", oNoneSwitch },
    295 	{ "hpndisabled", oHPNDisabled },
    296 	{ "hpnbuffersize", oHPNBufferSize },
    297 	{ "sendversionfirst", oSendVersionFirst },
    298 	{ "ignoreunknown", oIgnoreUnknown },
    299 	{ NULL, oBadOption }
    300 };
    301 
    302 /*
    303  * Adds a local TCP/IP port forward to options.  Never returns if there is an
    304  * error.
    305  */
    306 
    307 void
    308 add_local_forward(Options *options, const struct Forward *newfwd)
    309 {
    310 	struct Forward *fwd;
    311 	extern uid_t original_real_uid;
    312 
    313 	if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0 &&
    314 	    newfwd->listen_path == NULL)
    315 		fatal("Privileged ports can only be forwarded by root.");
    316 	options->local_forwards = xrealloc(options->local_forwards,
    317 	    options->num_local_forwards + 1,
    318 	    sizeof(*options->local_forwards));
    319 	fwd = &options->local_forwards[options->num_local_forwards++];
    320 
    321 	fwd->listen_host = newfwd->listen_host;
    322 	fwd->listen_port = newfwd->listen_port;
    323 	fwd->listen_path = newfwd->listen_path;
    324 	fwd->connect_host = newfwd->connect_host;
    325 	fwd->connect_port = newfwd->connect_port;
    326 	fwd->connect_path = newfwd->connect_path;
    327 }
    328 
    329 /*
    330  * Adds a remote TCP/IP port forward to options.  Never returns if there is
    331  * an error.
    332  */
    333 
    334 void
    335 add_remote_forward(Options *options, const struct Forward *newfwd)
    336 {
    337 	struct Forward *fwd;
    338 
    339 	options->remote_forwards = xrealloc(options->remote_forwards,
    340 	    options->num_remote_forwards + 1,
    341 	    sizeof(*options->remote_forwards));
    342 	fwd = &options->remote_forwards[options->num_remote_forwards++];
    343 
    344 	fwd->listen_host = newfwd->listen_host;
    345 	fwd->listen_port = newfwd->listen_port;
    346 	fwd->listen_path = newfwd->listen_path;
    347 	fwd->connect_host = newfwd->connect_host;
    348 	fwd->connect_port = newfwd->connect_port;
    349 	fwd->connect_path = newfwd->connect_path;
    350 	fwd->handle = newfwd->handle;
    351 	fwd->allocated_port = 0;
    352 }
    353 
    354 static void
    355 clear_forwardings(Options *options)
    356 {
    357 	int i;
    358 
    359 	for (i = 0; i < options->num_local_forwards; i++) {
    360 		free(options->local_forwards[i].listen_host);
    361 		free(options->local_forwards[i].listen_path);
    362 		free(options->local_forwards[i].connect_host);
    363 		free(options->local_forwards[i].connect_path);
    364 	}
    365 	if (options->num_local_forwards > 0) {
    366 		free(options->local_forwards);
    367 		options->local_forwards = NULL;
    368 	}
    369 	options->num_local_forwards = 0;
    370 	for (i = 0; i < options->num_remote_forwards; i++) {
    371 		free(options->remote_forwards[i].listen_host);
    372 		free(options->remote_forwards[i].listen_path);
    373 		free(options->remote_forwards[i].connect_host);
    374 		free(options->remote_forwards[i].connect_path);
    375 	}
    376 	if (options->num_remote_forwards > 0) {
    377 		free(options->remote_forwards);
    378 		options->remote_forwards = NULL;
    379 	}
    380 	options->num_remote_forwards = 0;
    381 	options->tun_open = SSH_TUNMODE_NO;
    382 }
    383 
    384 void
    385 add_identity_file(Options *options, const char *dir, const char *filename,
    386     int userprovided)
    387 {
    388 	char *path;
    389 	int i;
    390 
    391 	if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
    392 		fatal("Too many identity files specified (max %d)",
    393 		    SSH_MAX_IDENTITY_FILES);
    394 
    395 	if (dir == NULL) /* no dir, filename is absolute */
    396 		path = xstrdup(filename);
    397 	else
    398 		(void)xasprintf(&path, "%.100s%.100s", dir, filename);
    399 
    400 	/* Avoid registering duplicates */
    401 	for (i = 0; i < options->num_identity_files; i++) {
    402 		if (options->identity_file_userprovided[i] == userprovided &&
    403 		    strcmp(options->identity_files[i], path) == 0) {
    404 			debug2("%s: ignoring duplicate key %s", __func__, path);
    405 			free(path);
    406 			return;
    407 		}
    408 	}
    409 
    410 	options->identity_file_userprovided[options->num_identity_files] =
    411 	    userprovided;
    412 	options->identity_files[options->num_identity_files++] = path;
    413 }
    414 
    415 int
    416 default_ssh_port(void)
    417 {
    418 	static int port;
    419 	struct servent *sp;
    420 
    421 	if (port == 0) {
    422 		sp = getservbyname(SSH_SERVICE_NAME, "tcp");
    423 		port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT;
    424 	}
    425 	return port;
    426 }
    427 
    428 /*
    429  * Execute a command in a shell.
    430  * Return its exit status or -1 on abnormal exit.
    431  */
    432 static int
    433 execute_in_shell(const char *cmd)
    434 {
    435 	const char *shell;
    436 	char *command_string;
    437 	pid_t pid;
    438 	int devnull, status;
    439 	extern uid_t original_real_uid;
    440 
    441 	if ((shell = getenv("SHELL")) == NULL)
    442 		shell = _PATH_BSHELL;
    443 
    444 	/*
    445 	 * Use "exec" to avoid "sh -c" processes on some platforms
    446 	 * (e.g. Solaris)
    447 	 */
    448 	xasprintf(&command_string, "exec %s", cmd);
    449 
    450 	/* Need this to redirect subprocess stdin/out */
    451 	if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1)
    452 		fatal("open(/dev/null): %s", strerror(errno));
    453 
    454 	debug("Executing command: '%.500s'", cmd);
    455 
    456 	/* Fork and execute the command. */
    457 	if ((pid = fork()) == 0) {
    458 		char *argv[4];
    459 
    460 		/* Child.  Permanently give up superuser privileges. */
    461 		permanently_drop_suid(original_real_uid);
    462 
    463 		/* Redirect child stdin and stdout. Leave stderr */
    464 		if (dup2(devnull, STDIN_FILENO) == -1)
    465 			fatal("dup2: %s", strerror(errno));
    466 		if (dup2(devnull, STDOUT_FILENO) == -1)
    467 			fatal("dup2: %s", strerror(errno));
    468 		if (devnull > STDERR_FILENO)
    469 			close(devnull);
    470 		closefrom(STDERR_FILENO + 1);
    471 
    472 		argv[0] = __UNCONST(shell);
    473 		argv[1] = __UNCONST("-c");
    474 		argv[2] = command_string;
    475 		argv[3] = NULL;
    476 
    477 		execv(argv[0], argv);
    478 		error("Unable to execute '%.100s': %s", cmd, strerror(errno));
    479 		/* Die with signal to make this error apparent to parent. */
    480 		signal(SIGTERM, SIG_DFL);
    481 		kill(getpid(), SIGTERM);
    482 		_exit(1);
    483 	}
    484 	/* Parent. */
    485 	if (pid < 0)
    486 		fatal("%s: fork: %.100s", __func__, strerror(errno));
    487 
    488 	close(devnull);
    489 	free(command_string);
    490 
    491 	while (waitpid(pid, &status, 0) == -1) {
    492 		if (errno != EINTR && errno != EAGAIN)
    493 			fatal("%s: waitpid: %s", __func__, strerror(errno));
    494 	}
    495 	if (!WIFEXITED(status)) {
    496 		error("command '%.100s' exited abnormally", cmd);
    497 		return -1;
    498 	}
    499 	debug3("command returned status %d", WEXITSTATUS(status));
    500 	return WEXITSTATUS(status);
    501 }
    502 
    503 /*
    504  * Parse and execute a Match directive.
    505  */
    506 static int
    507 match_cfg_line(Options *options, char **condition, struct passwd *pw,
    508     const char *host_arg, const char *original_host, int post_canon,
    509     const char *filename, int linenum)
    510 {
    511 	char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria;
    512 	const char *ruser;
    513 	int r, port, this_result, result = 1, attributes = 0, negate;
    514 	size_t len;
    515 	char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
    516 
    517 	/*
    518 	 * Configuration is likely to be incomplete at this point so we
    519 	 * must be prepared to use default values.
    520 	 */
    521 	port = options->port <= 0 ? default_ssh_port() : options->port;
    522 	ruser = options->user == NULL ? pw->pw_name : options->user;
    523 	if (options->hostname != NULL) {
    524 		/* NB. Please keep in sync with ssh.c:main() */
    525 		host = percent_expand(options->hostname,
    526 		    "h", host_arg, (char *)NULL);
    527 	} else
    528 		host = xstrdup(host_arg);
    529 
    530 	debug2("checking match for '%s' host %s originally %s",
    531 	    cp, host, original_host);
    532 	while ((oattrib = attrib = strdelim(&cp)) && *attrib != '\0') {
    533 		criteria = NULL;
    534 		this_result = 1;
    535 		if ((negate = attrib[0] == '!'))
    536 			attrib++;
    537 		/* criteria "all" and "canonical" have no argument */
    538 		if (strcasecmp(attrib, "all") == 0) {
    539 			if (attributes > 1 ||
    540 			    ((arg = strdelim(&cp)) != NULL && *arg != '\0')) {
    541 				error("%.200s line %d: '%s' cannot be combined "
    542 				    "with other Match attributes",
    543 				    filename, linenum, oattrib);
    544 				result = -1;
    545 				goto out;
    546 			}
    547 			if (result)
    548 				result = negate ? 0 : 1;
    549 			goto out;
    550 		}
    551 		attributes++;
    552 		if (strcasecmp(attrib, "canonical") == 0) {
    553 			r = !!post_canon;  /* force bitmask member to boolean */
    554 			if (r == (negate ? 1 : 0))
    555 				this_result = result = 0;
    556 			debug3("%.200s line %d: %smatched '%s'",
    557 			    filename, linenum,
    558 			    this_result ? "" : "not ", oattrib);
    559 			continue;
    560 		}
    561 		/* All other criteria require an argument */
    562 		if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
    563 			error("Missing Match criteria for %s", attrib);
    564 			result = -1;
    565 			goto out;
    566 		}
    567 		len = strlen(arg);
    568 		if (strcasecmp(attrib, "host") == 0) {
    569 			criteria = xstrdup(host);
    570 			r = match_hostname(host, arg, len) == 1;
    571 			if (r == (negate ? 1 : 0))
    572 				this_result = result = 0;
    573 		} else if (strcasecmp(attrib, "originalhost") == 0) {
    574 			criteria = xstrdup(original_host);
    575 			r = match_hostname(original_host, arg, len) == 1;
    576 			if (r == (negate ? 1 : 0))
    577 				this_result = result = 0;
    578 		} else if (strcasecmp(attrib, "user") == 0) {
    579 			criteria = xstrdup(ruser);
    580 			r = match_pattern_list(ruser, arg, len, 0) == 1;
    581 			if (r == (negate ? 1 : 0))
    582 				this_result = result = 0;
    583 		} else if (strcasecmp(attrib, "localuser") == 0) {
    584 			criteria = xstrdup(pw->pw_name);
    585 			r = match_pattern_list(pw->pw_name, arg, len, 0) == 1;
    586 			if (r == (negate ? 1 : 0))
    587 				this_result = result = 0;
    588 		} else if (strcasecmp(attrib, "exec") == 0) {
    589 			if (gethostname(thishost, sizeof(thishost)) == -1)
    590 				fatal("gethostname: %s", strerror(errno));
    591 			strlcpy(shorthost, thishost, sizeof(shorthost));
    592 			shorthost[strcspn(thishost, ".")] = '\0';
    593 			snprintf(portstr, sizeof(portstr), "%d", port);
    594 
    595 			cmd = percent_expand(arg,
    596 			    "L", shorthost,
    597 			    "d", pw->pw_dir,
    598 			    "h", host,
    599 			    "l", thishost,
    600 			    "n", original_host,
    601 			    "p", portstr,
    602 			    "r", ruser,
    603 			    "u", pw->pw_name,
    604 			    (char *)NULL);
    605 			if (result != 1) {
    606 				/* skip execution if prior predicate failed */
    607 				debug3("%.200s line %d: skipped exec "
    608 				    "\"%.100s\"", filename, linenum, cmd);
    609 				free(cmd);
    610 				continue;
    611 			}
    612 			r = execute_in_shell(cmd);
    613 			if (r == -1) {
    614 				fatal("%.200s line %d: match exec "
    615 				    "'%.100s' error", filename,
    616 				    linenum, cmd);
    617 			}
    618 			criteria = xstrdup(cmd);
    619 			free(cmd);
    620 			/* Force exit status to boolean */
    621 			r = r == 0;
    622 			if (r == (negate ? 1 : 0))
    623 				this_result = result = 0;
    624 		} else {
    625 			error("Unsupported Match attribute %s", attrib);
    626 			result = -1;
    627 			goto out;
    628 		}
    629 		debug3("%.200s line %d: %smatched '%s \"%.100s\"' ",
    630 		    filename, linenum, this_result ? "": "not ",
    631 		    oattrib, criteria);
    632 		free(criteria);
    633 	}
    634 	if (attributes == 0) {
    635 		error("One or more attributes required for Match");
    636 		result = -1;
    637 		goto out;
    638 	}
    639  out:
    640 	if (result != -1)
    641 		debug2("match %sfound", result ? "" : "not ");
    642 	*condition = cp;
    643 	free(host);
    644 	return result;
    645 }
    646 
    647 /* Check and prepare a domain name: removes trailing '.' and lowercases */
    648 static void
    649 valid_domain(char *name, const char *filename, int linenum)
    650 {
    651 	size_t i, l = strlen(name);
    652 	u_char c, last = '\0';
    653 
    654 	if (l == 0)
    655 		fatal("%s line %d: empty hostname suffix", filename, linenum);
    656 	if (!isalpha((u_char)name[0]) && !isdigit((u_char)name[0]))
    657 		fatal("%s line %d: hostname suffix \"%.100s\" "
    658 		    "starts with invalid character", filename, linenum, name);
    659 	for (i = 0; i < l; i++) {
    660 		c = tolower((u_char)name[i]);
    661 		name[i] = (char)c;
    662 		if (last == '.' && c == '.')
    663 			fatal("%s line %d: hostname suffix \"%.100s\" contains "
    664 			    "consecutive separators", filename, linenum, name);
    665 		if (c != '.' && c != '-' && !isalnum(c) &&
    666 		    c != '_') /* technically invalid, but common */
    667 			fatal("%s line %d: hostname suffix \"%.100s\" contains "
    668 			    "invalid characters", filename, linenum, name);
    669 		last = c;
    670 	}
    671 	if (name[l - 1] == '.')
    672 		name[l - 1] = '\0';
    673 }
    674 
    675 /*
    676  * Returns the number of the token pointed to by cp or oBadOption.
    677  */
    678 static OpCodes
    679 parse_token(const char *cp, const char *filename, int linenum,
    680     const char *ignored_unknown)
    681 {
    682 	int i;
    683 
    684 	for (i = 0; keywords[i].name; i++)
    685 		if (strcmp(cp, keywords[i].name) == 0)
    686 			return keywords[i].opcode;
    687 	if (ignored_unknown != NULL && match_pattern_list(cp, ignored_unknown,
    688 	    strlen(ignored_unknown), 1) == 1)
    689 		return oIgnoredUnknownOption;
    690 	error("%s: line %d: Bad configuration option: %s",
    691 	    filename, linenum, cp);
    692 	return oBadOption;
    693 }
    694 
    695 /* Multistate option parsing */
    696 struct multistate {
    697 	const char *key;
    698 	int value;
    699 };
    700 static const struct multistate multistate_flag[] = {
    701 	{ "true",			1 },
    702 	{ "false",			0 },
    703 	{ "yes",			1 },
    704 	{ "no",				0 },
    705 	{ NULL, -1 }
    706 };
    707 static const struct multistate multistate_yesnoask[] = {
    708 	{ "true",			1 },
    709 	{ "false",			0 },
    710 	{ "yes",			1 },
    711 	{ "no",				0 },
    712 	{ "ask",			2 },
    713 	{ NULL, -1 }
    714 };
    715 static const struct multistate multistate_addressfamily[] = {
    716 	{ "inet",			AF_INET },
    717 	{ "inet6",			AF_INET6 },
    718 	{ "any",			AF_UNSPEC },
    719 	{ NULL, -1 }
    720 };
    721 static const struct multistate multistate_controlmaster[] = {
    722 	{ "true",			SSHCTL_MASTER_YES },
    723 	{ "yes",			SSHCTL_MASTER_YES },
    724 	{ "false",			SSHCTL_MASTER_NO },
    725 	{ "no",				SSHCTL_MASTER_NO },
    726 	{ "auto",			SSHCTL_MASTER_AUTO },
    727 	{ "ask",			SSHCTL_MASTER_ASK },
    728 	{ "autoask",			SSHCTL_MASTER_AUTO_ASK },
    729 	{ NULL, -1 }
    730 };
    731 static const struct multistate multistate_tunnel[] = {
    732 	{ "ethernet",			SSH_TUNMODE_ETHERNET },
    733 	{ "point-to-point",		SSH_TUNMODE_POINTOPOINT },
    734 	{ "true",			SSH_TUNMODE_DEFAULT },
    735 	{ "yes",			SSH_TUNMODE_DEFAULT },
    736 	{ "false",			SSH_TUNMODE_NO },
    737 	{ "no",				SSH_TUNMODE_NO },
    738 	{ NULL, -1 }
    739 };
    740 static const struct multistate multistate_requesttty[] = {
    741 	{ "true",			REQUEST_TTY_YES },
    742 	{ "yes",			REQUEST_TTY_YES },
    743 	{ "false",			REQUEST_TTY_NO },
    744 	{ "no",				REQUEST_TTY_NO },
    745 	{ "force",			REQUEST_TTY_FORCE },
    746 	{ "auto",			REQUEST_TTY_AUTO },
    747 	{ NULL, -1 }
    748 };
    749 static const struct multistate multistate_canonicalizehostname[] = {
    750 	{ "true",			SSH_CANONICALISE_YES },
    751 	{ "false",			SSH_CANONICALISE_NO },
    752 	{ "yes",			SSH_CANONICALISE_YES },
    753 	{ "no",				SSH_CANONICALISE_NO },
    754 	{ "always",			SSH_CANONICALISE_ALWAYS },
    755 	{ NULL, -1 }
    756 };
    757 
    758 /*
    759  * Processes a single option line as used in the configuration files. This
    760  * only sets those values that have not already been set.
    761  */
    762 #define WHITESPACE " \t\r\n"
    763 int
    764 process_config_line(Options *options, struct passwd *pw, const char *host,
    765     const char *original_host, char *line, const char *filename,
    766     int linenum, int *activep, int flags)
    767 {
    768 	char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;
    769 	char **cpptr, fwdarg[256];
    770 	u_int i, *uintptr, max_entries = 0;
    771 	int negated, opcode, *intptr, value, value2, cmdline = 0;
    772 	LogLevel *log_level_ptr;
    773 	long long val64;
    774 	size_t len;
    775 	struct Forward fwd;
    776 	const struct multistate *multistate_ptr;
    777 	struct allowed_cname *cname;
    778 
    779 	if (activep == NULL) { /* We are processing a command line directive */
    780 		cmdline = 1;
    781 		activep = &cmdline;
    782 	}
    783 
    784 	/* Strip trailing whitespace */
    785 	for (len = strlen(line) - 1; len > 0; len--) {
    786 		if (strchr(WHITESPACE, line[len]) == NULL)
    787 			break;
    788 		line[len] = '\0';
    789 	}
    790 
    791 	s = line;
    792 	/* Get the keyword. (Each line is supposed to begin with a keyword). */
    793 	if ((keyword = strdelim(&s)) == NULL)
    794 		return 0;
    795 	/* Ignore leading whitespace. */
    796 	if (*keyword == '\0')
    797 		keyword = strdelim(&s);
    798 	if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
    799 		return 0;
    800 	/* Match lowercase keyword */
    801 	lowercase(keyword);
    802 
    803 	opcode = parse_token(keyword, filename, linenum,
    804 	    options->ignored_unknown);
    805 
    806 	switch (opcode) {
    807 	case oBadOption:
    808 		/* don't panic, but count bad options */
    809 		return -1;
    810 		/* NOTREACHED */
    811 	case oIgnoredUnknownOption:
    812 		debug("%s line %d: Ignored unknown option \"%s\"",
    813 		    filename, linenum, keyword);
    814 		return 0;
    815 	case oConnectTimeout:
    816 		intptr = &options->connection_timeout;
    817 parse_time:
    818 		arg = strdelim(&s);
    819 		if (!arg || *arg == '\0')
    820 			fatal("%s line %d: missing time value.",
    821 			    filename, linenum);
    822 		if (strcmp(arg, "none") == 0)
    823 			value = -1;
    824 		else if ((value = convtime(arg)) == -1)
    825 			fatal("%s line %d: invalid time value.",
    826 			    filename, linenum);
    827 		if (*activep && *intptr == -1)
    828 			*intptr = value;
    829 		break;
    830 
    831 	case oForwardAgent:
    832 		intptr = &options->forward_agent;
    833  parse_flag:
    834 		multistate_ptr = multistate_flag;
    835  parse_multistate:
    836 		arg = strdelim(&s);
    837 		if (!arg || *arg == '\0')
    838 			fatal("%s line %d: missing argument.",
    839 			    filename, linenum);
    840 		value = -1;
    841 		for (i = 0; multistate_ptr[i].key != NULL; i++) {
    842 			if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
    843 				value = multistate_ptr[i].value;
    844 				break;
    845 			}
    846 		}
    847 		if (value == -1)
    848 			fatal("%s line %d: unsupported option \"%s\".",
    849 			    filename, linenum, arg);
    850 		if (*activep && *intptr == -1)
    851 			*intptr = value;
    852 		break;
    853 
    854 	case oForwardX11:
    855 		intptr = &options->forward_x11;
    856 		goto parse_flag;
    857 
    858 	case oForwardX11Trusted:
    859 		intptr = &options->forward_x11_trusted;
    860 		goto parse_flag;
    861 
    862 	case oForwardX11Timeout:
    863 		intptr = &options->forward_x11_timeout;
    864 		goto parse_time;
    865 
    866 	case oGatewayPorts:
    867 		intptr = &options->fwd_opts.gateway_ports;
    868 		goto parse_flag;
    869 
    870 	case oExitOnForwardFailure:
    871 		intptr = &options->exit_on_forward_failure;
    872 		goto parse_flag;
    873 
    874 	case oUsePrivilegedPort:
    875 		intptr = &options->use_privileged_port;
    876 		goto parse_flag;
    877 
    878 	case oPasswordAuthentication:
    879 		intptr = &options->password_authentication;
    880 		goto parse_flag;
    881 
    882 	case oKbdInteractiveAuthentication:
    883 		intptr = &options->kbd_interactive_authentication;
    884 		goto parse_flag;
    885 
    886 	case oKbdInteractiveDevices:
    887 		charptr = &options->kbd_interactive_devices;
    888 		goto parse_string;
    889 
    890 	case oPubkeyAuthentication:
    891 		intptr = &options->pubkey_authentication;
    892 		goto parse_flag;
    893 
    894 	case oRSAAuthentication:
    895 		intptr = &options->rsa_authentication;
    896 		goto parse_flag;
    897 
    898 	case oRhostsRSAAuthentication:
    899 		intptr = &options->rhosts_rsa_authentication;
    900 		goto parse_flag;
    901 
    902 	case oHostbasedAuthentication:
    903 		intptr = &options->hostbased_authentication;
    904 		goto parse_flag;
    905 
    906 	case oChallengeResponseAuthentication:
    907 		intptr = &options->challenge_response_authentication;
    908 		goto parse_flag;
    909 
    910 #if defined(KRB4) || defined(KRB5)
    911 	case oKerberosAuthentication:
    912 		intptr = &options->kerberos_authentication;
    913 		goto parse_flag;
    914 #endif
    915 #if defined(AFS) || defined(KRB5)
    916 	case oKerberosTgtPassing:
    917 		intptr = &options->kerberos_tgt_passing;
    918 		goto parse_flag;
    919 #endif
    920 
    921 	case oGssAuthentication:
    922 		intptr = &options->gss_authentication;
    923 		goto parse_flag;
    924 
    925 #ifdef AFS
    926 	case oAFSTokenPassing:
    927 		intptr = &options->afs_token_passing;
    928  		goto parse_flag;
    929 #endif
    930 
    931 	case oGssDelegateCreds:
    932 		intptr = &options->gss_deleg_creds;
    933 		goto parse_flag;
    934 
    935 	case oBatchMode:
    936 		intptr = &options->batch_mode;
    937 		goto parse_flag;
    938 
    939 	case oCheckHostIP:
    940 		intptr = &options->check_host_ip;
    941 		goto parse_flag;
    942 
    943 	case oNoneEnabled:
    944 		intptr = &options->none_enabled;
    945 		goto parse_flag;
    946 
    947 	/* we check to see if the command comes from the */
    948 	/* command line or not. If it does then enable it */
    949 	/* otherwise fail. NONE should never be a default configuration */
    950 	case oNoneSwitch:
    951 		if(strcmp(filename,"command-line")==0)
    952 		{
    953 		    intptr = &options->none_switch;
    954 		    goto parse_flag;
    955 		} else {
    956 		    error("NoneSwitch is found in %.200s.\nYou may only use this configuration option from the command line", filename);
    957 		    error("Continuing...");
    958 		    debug("NoneSwitch directive found in %.200s.", filename);
    959 		    return 0;
    960 	        }
    961 
    962 	case oHPNDisabled:
    963 		intptr = &options->hpn_disabled;
    964 		goto parse_flag;
    965 
    966 	case oHPNBufferSize:
    967 		intptr = &options->hpn_buffer_size;
    968 		goto parse_int;
    969 
    970 	case oTcpRcvBufPoll:
    971 		intptr = &options->tcp_rcv_buf_poll;
    972 		goto parse_flag;
    973 
    974 	case oVerifyHostKeyDNS:
    975 		intptr = &options->verify_host_key_dns;
    976 		multistate_ptr = multistate_yesnoask;
    977 		goto parse_multistate;
    978 
    979 	case oStrictHostKeyChecking:
    980 		intptr = &options->strict_host_key_checking;
    981 		multistate_ptr = multistate_yesnoask;
    982 		goto parse_multistate;
    983 
    984 	case oCompression:
    985 		intptr = &options->compression;
    986 		goto parse_flag;
    987 
    988 	case oTCPKeepAlive:
    989 		intptr = &options->tcp_keep_alive;
    990 		goto parse_flag;
    991 
    992 	case oNoHostAuthenticationForLocalhost:
    993 		intptr = &options->no_host_authentication_for_localhost;
    994 		goto parse_flag;
    995 
    996 	case oNumberOfPasswordPrompts:
    997 		intptr = &options->number_of_password_prompts;
    998 		goto parse_int;
    999 
   1000 	case oCompressionLevel:
   1001 		intptr = &options->compression_level;
   1002 		goto parse_int;
   1003 
   1004 	case oRekeyLimit:
   1005 		arg = strdelim(&s);
   1006 		if (!arg || *arg == '\0')
   1007 			fatal("%.200s line %d: Missing argument.", filename,
   1008 			    linenum);
   1009 		if (strcmp(arg, "default") == 0) {
   1010 			val64 = 0;
   1011 		} else {
   1012 			if (scan_scaled(arg, &val64) == -1)
   1013 				fatal("%.200s line %d: Bad number '%s': %s",
   1014 				    filename, linenum, arg, strerror(errno));
   1015 			/* check for too-large or too-small limits */
   1016 			if (val64 > UINT_MAX)
   1017 				fatal("%.200s line %d: RekeyLimit too large",
   1018 				    filename, linenum);
   1019 			if (val64 != 0 && val64 < 16)
   1020 				fatal("%.200s line %d: RekeyLimit too small",
   1021 				    filename, linenum);
   1022 		}
   1023 		if (*activep && options->rekey_limit == -1)
   1024 			options->rekey_limit = (u_int32_t)val64;
   1025 		if (s != NULL) { /* optional rekey interval present */
   1026 			if (strcmp(s, "none") == 0) {
   1027 				(void)strdelim(&s);	/* discard */
   1028 				break;
   1029 			}
   1030 			intptr = &options->rekey_interval;
   1031 			goto parse_time;
   1032 		}
   1033 		break;
   1034 
   1035 	case oIdentityFile:
   1036 		arg = strdelim(&s);
   1037 		if (!arg || *arg == '\0')
   1038 			fatal("%.200s line %d: Missing argument.", filename, linenum);
   1039 		if (*activep) {
   1040 			intptr = &options->num_identity_files;
   1041 			if (*intptr >= SSH_MAX_IDENTITY_FILES)
   1042 				fatal("%.200s line %d: Too many identity files specified (max %d).",
   1043 				    filename, linenum, SSH_MAX_IDENTITY_FILES);
   1044 			add_identity_file(options, NULL,
   1045 			    arg, flags & SSHCONF_USERCONF);
   1046 		}
   1047 		break;
   1048 
   1049 	case oXAuthLocation:
   1050 		charptr=&options->xauth_location;
   1051 		goto parse_string;
   1052 
   1053 	case oUser:
   1054 		charptr = &options->user;
   1055 parse_string:
   1056 		arg = strdelim(&s);
   1057 		if (!arg || *arg == '\0')
   1058 			fatal("%.200s line %d: Missing argument.",
   1059 			    filename, linenum);
   1060 		if (*activep && *charptr == NULL)
   1061 			*charptr = xstrdup(arg);
   1062 		break;
   1063 
   1064 	case oGlobalKnownHostsFile:
   1065 		cpptr = (char **)&options->system_hostfiles;
   1066 		uintptr = &options->num_system_hostfiles;
   1067 		max_entries = SSH_MAX_HOSTS_FILES;
   1068 parse_char_array:
   1069 		if (*activep && *uintptr == 0) {
   1070 			while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
   1071 				if ((*uintptr) >= max_entries)
   1072 					fatal("%s line %d: "
   1073 					    "too many authorized keys files.",
   1074 					    filename, linenum);
   1075 				cpptr[(*uintptr)++] = xstrdup(arg);
   1076 			}
   1077 		}
   1078 		return 0;
   1079 
   1080 	case oUserKnownHostsFile:
   1081 		cpptr = (char **)&options->user_hostfiles;
   1082 		uintptr = &options->num_user_hostfiles;
   1083 		max_entries = SSH_MAX_HOSTS_FILES;
   1084 		goto parse_char_array;
   1085 
   1086 	case oHostName:
   1087 		charptr = &options->hostname;
   1088 		goto parse_string;
   1089 
   1090 	case oHostKeyAlias:
   1091 		charptr = &options->host_key_alias;
   1092 		goto parse_string;
   1093 
   1094 	case oPreferredAuthentications:
   1095 		charptr = &options->preferred_authentications;
   1096 		goto parse_string;
   1097 
   1098 	case oBindAddress:
   1099 		charptr = &options->bind_address;
   1100 		goto parse_string;
   1101 
   1102 	case oPKCS11Provider:
   1103 		charptr = &options->pkcs11_provider;
   1104 		goto parse_string;
   1105 
   1106 	case oProxyCommand:
   1107 		charptr = &options->proxy_command;
   1108 parse_command:
   1109 		if (s == NULL)
   1110 			fatal("%.200s line %d: Missing argument.", filename, linenum);
   1111 		len = strspn(s, WHITESPACE "=");
   1112 		if (*activep && *charptr == NULL)
   1113 			*charptr = xstrdup(s + len);
   1114 		return 0;
   1115 
   1116 	case oPort:
   1117 		intptr = &options->port;
   1118 parse_int:
   1119 		arg = strdelim(&s);
   1120 		if (!arg || *arg == '\0')
   1121 			fatal("%.200s line %d: Missing argument.", filename, linenum);
   1122 		if (arg[0] < '0' || arg[0] > '9')
   1123 			fatal("%.200s line %d: Bad number.", filename, linenum);
   1124 
   1125 		/* Octal, decimal, or hex format? */
   1126 		value = strtol(arg, &endofnumber, 0);
   1127 		if (arg == endofnumber)
   1128 			fatal("%.200s line %d: Bad number.", filename, linenum);
   1129 		if (*activep && *intptr == -1)
   1130 			*intptr = value;
   1131 		break;
   1132 
   1133 	case oConnectionAttempts:
   1134 		intptr = &options->connection_attempts;
   1135 		goto parse_int;
   1136 
   1137 	case oTcpRcvBuf:
   1138 		intptr = &options->tcp_rcv_buf;
   1139 		goto parse_int;
   1140 
   1141 	case oCipher:
   1142 		intptr = &options->cipher;
   1143 		arg = strdelim(&s);
   1144 		if (!arg || *arg == '\0')
   1145 			fatal("%.200s line %d: Missing argument.", filename, linenum);
   1146 		value = cipher_number(arg);
   1147 		if (value == -1)
   1148 			fatal("%.200s line %d: Bad cipher '%s'.",
   1149 			    filename, linenum, arg ? arg : "<NONE>");
   1150 		if (*activep && *intptr == -1)
   1151 			*intptr = value;
   1152 		break;
   1153 
   1154 	case oCiphers:
   1155 		arg = strdelim(&s);
   1156 		if (!arg || *arg == '\0')
   1157 			fatal("%.200s line %d: Missing argument.", filename, linenum);
   1158 		if (!ciphers_valid(arg))
   1159 			fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
   1160 			    filename, linenum, arg ? arg : "<NONE>");
   1161 		if (*activep && options->ciphers == NULL)
   1162 			options->ciphers = xstrdup(arg);
   1163 		break;
   1164 
   1165 	case oMacs:
   1166 		arg = strdelim(&s);
   1167 		if (!arg || *arg == '\0')
   1168 			fatal("%.200s line %d: Missing argument.", filename, linenum);
   1169 		if (!mac_valid(arg))
   1170 			fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
   1171 			    filename, linenum, arg ? arg : "<NONE>");
   1172 		if (*activep && options->macs == NULL)
   1173 			options->macs = xstrdup(arg);
   1174 		break;
   1175 
   1176 	case oKexAlgorithms:
   1177 		arg = strdelim(&s);
   1178 		if (!arg || *arg == '\0')
   1179 			fatal("%.200s line %d: Missing argument.",
   1180 			    filename, linenum);
   1181 		if (!kex_names_valid(arg))
   1182 			fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
   1183 			    filename, linenum, arg ? arg : "<NONE>");
   1184 		if (*activep && options->kex_algorithms == NULL)
   1185 			options->kex_algorithms = xstrdup(arg);
   1186 		break;
   1187 
   1188 	case oHostKeyAlgorithms:
   1189 		arg = strdelim(&s);
   1190 		if (!arg || *arg == '\0')
   1191 			fatal("%.200s line %d: Missing argument.", filename, linenum);
   1192 		if (!sshkey_names_valid2(arg, 1))
   1193 			fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
   1194 			    filename, linenum, arg ? arg : "<NONE>");
   1195 		if (*activep && options->hostkeyalgorithms == NULL)
   1196 			options->hostkeyalgorithms = xstrdup(arg);
   1197 		break;
   1198 
   1199 	case oProtocol:
   1200 		intptr = &options->protocol;
   1201 		arg = strdelim(&s);
   1202 		if (!arg || *arg == '\0')
   1203 			fatal("%.200s line %d: Missing argument.", filename, linenum);
   1204 		value = proto_spec(arg);
   1205 		if (value == SSH_PROTO_UNKNOWN)
   1206 			fatal("%.200s line %d: Bad protocol spec '%s'.",
   1207 			    filename, linenum, arg ? arg : "<NONE>");
   1208 		if (*activep && *intptr == SSH_PROTO_UNKNOWN)
   1209 			*intptr = value;
   1210 		break;
   1211 
   1212 	case oLogLevel:
   1213 		log_level_ptr = &options->log_level;
   1214 		arg = strdelim(&s);
   1215 		value = log_level_number(arg);
   1216 		if (value == SYSLOG_LEVEL_NOT_SET)
   1217 			fatal("%.200s line %d: unsupported log level '%s'",
   1218 			    filename, linenum, arg ? arg : "<NONE>");
   1219 		if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
   1220 			*log_level_ptr = (LogLevel) value;
   1221 		break;
   1222 
   1223 	case oLocalForward:
   1224 	case oRemoteForward:
   1225 	case oDynamicForward:
   1226 		arg = strdelim(&s);
   1227 		if (arg == NULL || *arg == '\0')
   1228 			fatal("%.200s line %d: Missing port argument.",
   1229 			    filename, linenum);
   1230 
   1231 		if (opcode == oLocalForward ||
   1232 		    opcode == oRemoteForward) {
   1233 			arg2 = strdelim(&s);
   1234 			if (arg2 == NULL || *arg2 == '\0')
   1235 				fatal("%.200s line %d: Missing target argument.",
   1236 				    filename, linenum);
   1237 
   1238 			/* construct a string for parse_forward */
   1239 			snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
   1240 		} else if (opcode == oDynamicForward) {
   1241 			strlcpy(fwdarg, arg, sizeof(fwdarg));
   1242 		}
   1243 
   1244 		if (parse_forward(&fwd, fwdarg,
   1245 		    opcode == oDynamicForward ? 1 : 0,
   1246 		    opcode == oRemoteForward ? 1 : 0) == 0)
   1247 			fatal("%.200s line %d: Bad forwarding specification.",
   1248 			    filename, linenum);
   1249 
   1250 		if (*activep) {
   1251 			if (opcode == oLocalForward ||
   1252 			    opcode == oDynamicForward)
   1253 				add_local_forward(options, &fwd);
   1254 			else if (opcode == oRemoteForward)
   1255 				add_remote_forward(options, &fwd);
   1256 		}
   1257 		break;
   1258 
   1259 	case oClearAllForwardings:
   1260 		intptr = &options->clear_forwardings;
   1261 		goto parse_flag;
   1262 
   1263 	case oHost:
   1264 		if (cmdline)
   1265 			fatal("Host directive not supported as a command-line "
   1266 			    "option");
   1267 		*activep = 0;
   1268 		arg2 = NULL;
   1269 		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
   1270 			negated = *arg == '!';
   1271 			if (negated)
   1272 				arg++;
   1273 			if (match_pattern(host, arg)) {
   1274 				if (negated) {
   1275 					debug("%.200s line %d: Skipping Host "
   1276 					    "block because of negated match "
   1277 					    "for %.100s", filename, linenum,
   1278 					    arg);
   1279 					*activep = 0;
   1280 					break;
   1281 				}
   1282 				if (!*activep)
   1283 					arg2 = arg; /* logged below */
   1284 				*activep = 1;
   1285 			}
   1286 		}
   1287 		if (*activep)
   1288 			debug("%.200s line %d: Applying options for %.100s",
   1289 			    filename, linenum, arg2);
   1290 		/* Avoid garbage check below, as strdelim is done. */
   1291 		return 0;
   1292 
   1293 	case oMatch:
   1294 		if (cmdline)
   1295 			fatal("Host directive not supported as a command-line "
   1296 			    "option");
   1297 		value = match_cfg_line(options, &s, pw, host, original_host,
   1298 		    flags & SSHCONF_POSTCANON, filename, linenum);
   1299 		if (value < 0)
   1300 			fatal("%.200s line %d: Bad Match condition", filename,
   1301 			    linenum);
   1302 		*activep = value;
   1303 		break;
   1304 
   1305 	case oEscapeChar:
   1306 		intptr = &options->escape_char;
   1307 		arg = strdelim(&s);
   1308 		if (!arg || *arg == '\0')
   1309 			fatal("%.200s line %d: Missing argument.", filename, linenum);
   1310 		value = 0;	/* To avoid compiler warning... */
   1311 		if (arg[0] == '^' && arg[2] == 0 &&
   1312 		    (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
   1313 			value = (u_char) arg[1] & 31;
   1314 		else if (strlen(arg) == 1)
   1315 			value = (u_char) arg[0];
   1316 		else if (strcmp(arg, "none") == 0)
   1317 			value = SSH_ESCAPECHAR_NONE;
   1318 		else {
   1319 			fatal("%.200s line %d: Bad escape character.",
   1320 			    filename, linenum);
   1321 			/* NOTREACHED */
   1322 			value = 0;	/* Avoid compiler warning. */
   1323 		}
   1324 		if (*activep && *intptr == -1)
   1325 			*intptr = value;
   1326 		break;
   1327 
   1328 	case oAddressFamily:
   1329 		intptr = &options->address_family;
   1330 		multistate_ptr = multistate_addressfamily;
   1331 		goto parse_multistate;
   1332 
   1333 	case oEnableSSHKeysign:
   1334 		intptr = &options->enable_ssh_keysign;
   1335 		goto parse_flag;
   1336 
   1337 	case oIdentitiesOnly:
   1338 		intptr = &options->identities_only;
   1339 		goto parse_flag;
   1340 
   1341 	case oServerAliveInterval:
   1342 		intptr = &options->server_alive_interval;
   1343 		goto parse_time;
   1344 
   1345 	case oServerAliveCountMax:
   1346 		intptr = &options->server_alive_count_max;
   1347 		goto parse_int;
   1348 
   1349 	case oSendEnv:
   1350 		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
   1351 			if (strchr(arg, '=') != NULL)
   1352 				fatal("%s line %d: Invalid environment name.",
   1353 				    filename, linenum);
   1354 			if (!*activep)
   1355 				continue;
   1356 			if (options->num_send_env >= MAX_SEND_ENV)
   1357 				fatal("%s line %d: too many send env.",
   1358 				    filename, linenum);
   1359 			options->send_env[options->num_send_env++] =
   1360 			    xstrdup(arg);
   1361 		}
   1362 		break;
   1363 
   1364 	case oControlPath:
   1365 		charptr = &options->control_path;
   1366 		goto parse_string;
   1367 
   1368 	case oControlMaster:
   1369 		intptr = &options->control_master;
   1370 		multistate_ptr = multistate_controlmaster;
   1371 		goto parse_multistate;
   1372 
   1373 	case oControlPersist:
   1374 		/* no/false/yes/true, or a time spec */
   1375 		intptr = &options->control_persist;
   1376 		arg = strdelim(&s);
   1377 		if (!arg || *arg == '\0')
   1378 			fatal("%.200s line %d: Missing ControlPersist"
   1379 			    " argument.", filename, linenum);
   1380 		value = 0;
   1381 		value2 = 0;	/* timeout */
   1382 		if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
   1383 			value = 0;
   1384 		else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
   1385 			value = 1;
   1386 		else if ((value2 = convtime(arg)) >= 0)
   1387 			value = 1;
   1388 		else
   1389 			fatal("%.200s line %d: Bad ControlPersist argument.",
   1390 			    filename, linenum);
   1391 		if (*activep && *intptr == -1) {
   1392 			*intptr = value;
   1393 			options->control_persist_timeout = value2;
   1394 		}
   1395 		break;
   1396 
   1397 	case oHashKnownHosts:
   1398 		intptr = &options->hash_known_hosts;
   1399 		goto parse_flag;
   1400 
   1401 	case oTunnel:
   1402 		intptr = &options->tun_open;
   1403 		multistate_ptr = multistate_tunnel;
   1404 		goto parse_multistate;
   1405 
   1406 	case oTunnelDevice:
   1407 		arg = strdelim(&s);
   1408 		if (!arg || *arg == '\0')
   1409 			fatal("%.200s line %d: Missing argument.", filename, linenum);
   1410 		value = a2tun(arg, &value2);
   1411 		if (value == SSH_TUNID_ERR)
   1412 			fatal("%.200s line %d: Bad tun device.", filename, linenum);
   1413 		if (*activep) {
   1414 			options->tun_local = value;
   1415 			options->tun_remote = value2;
   1416 		}
   1417 		break;
   1418 
   1419 	case oLocalCommand:
   1420 		charptr = &options->local_command;
   1421 		goto parse_command;
   1422 
   1423 	case oPermitLocalCommand:
   1424 		intptr = &options->permit_local_command;
   1425 		goto parse_flag;
   1426 
   1427 	case oVisualHostKey:
   1428 		intptr = &options->visual_host_key;
   1429 		goto parse_flag;
   1430 
   1431 	case oIPQoS:
   1432 		arg = strdelim(&s);
   1433 		if ((value = parse_ipqos(arg)) == -1)
   1434 			fatal("%s line %d: Bad IPQoS value: %s",
   1435 			    filename, linenum, arg);
   1436 		arg = strdelim(&s);
   1437 		if (arg == NULL)
   1438 			value2 = value;
   1439 		else if ((value2 = parse_ipqos(arg)) == -1)
   1440 			fatal("%s line %d: Bad IPQoS value: %s",
   1441 			    filename, linenum, arg);
   1442 		if (*activep) {
   1443 			options->ip_qos_interactive = value;
   1444 			options->ip_qos_bulk = value2;
   1445 		}
   1446 		break;
   1447 
   1448 	case oUseRoaming:
   1449 		intptr = &options->use_roaming;
   1450 		goto parse_flag;
   1451 
   1452 	case oRequestTTY:
   1453 		intptr = &options->request_tty;
   1454 		multistate_ptr = multistate_requesttty;
   1455 		goto parse_multistate;
   1456 
   1457 	case oSendVersionFirst:
   1458 		intptr = &options->send_version_first;
   1459 		goto parse_flag;
   1460 
   1461 	case oIgnoreUnknown:
   1462 		charptr = &options->ignored_unknown;
   1463 		goto parse_string;
   1464 
   1465 	case oProxyUseFdpass:
   1466 		intptr = &options->proxy_use_fdpass;
   1467 		goto parse_flag;
   1468 
   1469 	case oCanonicalDomains:
   1470 		value = options->num_canonical_domains != 0;
   1471 		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
   1472 			valid_domain(arg, filename, linenum);
   1473 			if (!*activep || value)
   1474 				continue;
   1475 			if (options->num_canonical_domains >= MAX_CANON_DOMAINS)
   1476 				fatal("%s line %d: too many hostname suffixes.",
   1477 				    filename, linenum);
   1478 			options->canonical_domains[
   1479 			    options->num_canonical_domains++] = xstrdup(arg);
   1480 		}
   1481 		break;
   1482 
   1483 	case oCanonicalizePermittedCNAMEs:
   1484 		value = options->num_permitted_cnames != 0;
   1485 		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
   1486 			/* Either '*' for everything or 'list:list' */
   1487 			if (strcmp(arg, "*") == 0)
   1488 				arg2 = arg;
   1489 			else {
   1490 				lowercase(arg);
   1491 				if ((arg2 = strchr(arg, ':')) == NULL ||
   1492 				    arg2[1] == '\0') {
   1493 					fatal("%s line %d: "
   1494 					    "Invalid permitted CNAME \"%s\"",
   1495 					    filename, linenum, arg);
   1496 				}
   1497 				*arg2 = '\0';
   1498 				arg2++;
   1499 			}
   1500 			if (!*activep || value)
   1501 				continue;
   1502 			if (options->num_permitted_cnames >= MAX_CANON_DOMAINS)
   1503 				fatal("%s line %d: too many permitted CNAMEs.",
   1504 				    filename, linenum);
   1505 			cname = options->permitted_cnames +
   1506 			    options->num_permitted_cnames++;
   1507 			cname->source_list = xstrdup(arg);
   1508 			cname->target_list = xstrdup(arg2);
   1509 		}
   1510 		break;
   1511 
   1512 	case oCanonicalizeHostname:
   1513 		intptr = &options->canonicalize_hostname;
   1514 		multistate_ptr = multistate_canonicalizehostname;
   1515 		goto parse_multistate;
   1516 
   1517 	case oCanonicalizeMaxDots:
   1518 		intptr = &options->canonicalize_max_dots;
   1519 		goto parse_int;
   1520 
   1521 	case oCanonicalizeFallbackLocal:
   1522 		intptr = &options->canonicalize_fallback_local;
   1523 		goto parse_flag;
   1524 
   1525 	case oStreamLocalBindMask:
   1526 		arg = strdelim(&s);
   1527 		if (!arg || *arg == '\0')
   1528 			fatal("%.200s line %d: Missing StreamLocalBindMask argument.", filename, linenum);
   1529 		/* Parse mode in octal format */
   1530 		value = strtol(arg, &endofnumber, 8);
   1531 		if (arg == endofnumber || value < 0 || value > 0777)
   1532 			fatal("%.200s line %d: Bad mask.", filename, linenum);
   1533 		options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
   1534 		break;
   1535 
   1536 	case oStreamLocalBindUnlink:
   1537 		intptr = &options->fwd_opts.streamlocal_bind_unlink;
   1538 		goto parse_flag;
   1539 
   1540 	case oRevokedHostKeys:
   1541 		charptr = &options->revoked_host_keys;
   1542 		goto parse_string;
   1543 
   1544 	case oFingerprintHash:
   1545 		intptr = &options->fingerprint_hash;
   1546 		arg = strdelim(&s);
   1547 		if (!arg || *arg == '\0')
   1548 			fatal("%.200s line %d: Missing argument.",
   1549 			    filename, linenum);
   1550 		if ((value = ssh_digest_alg_by_name(arg)) == -1)
   1551 			fatal("%.200s line %d: Invalid hash algorithm \"%s\".",
   1552 			    filename, linenum, arg);
   1553 		if (*activep && *intptr == -1)
   1554 			*intptr = value;
   1555 		break;
   1556 
   1557 	case oUpdateHostkeys:
   1558 		intptr = &options->update_hostkeys;
   1559 		multistate_ptr = multistate_yesnoask;
   1560 		goto parse_multistate;
   1561 
   1562 	case oHostbasedKeyTypes:
   1563 		charptr = &options->hostbased_key_types;
   1564 		arg = strdelim(&s);
   1565 		if (!arg || *arg == '\0')
   1566 			fatal("%.200s line %d: Missing argument.",
   1567 			    filename, linenum);
   1568 		if (!sshkey_names_valid2(arg, 1))
   1569 			fatal("%s line %d: Bad key types '%s'.",
   1570 				filename, linenum, arg ? arg : "<NONE>");
   1571 		if (*activep && *charptr == NULL)
   1572 			*charptr = xstrdup(arg);
   1573 		break;
   1574 
   1575 	case oDeprecated:
   1576 		debug("%s line %d: Deprecated option \"%s\"",
   1577 		    filename, linenum, keyword);
   1578 		return 0;
   1579 
   1580 	case oUnsupported:
   1581 		error("%s line %d: Unsupported option \"%s\"",
   1582 		    filename, linenum, keyword);
   1583 		return 0;
   1584 
   1585 	default:
   1586 		fatal("%s: Unimplemented opcode %d", __func__, opcode);
   1587 	}
   1588 
   1589 	/* Check that there is no garbage at end of line. */
   1590 	if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
   1591 		fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
   1592 		    filename, linenum, arg);
   1593 	}
   1594 	return 0;
   1595 }
   1596 
   1597 
   1598 /*
   1599  * Reads the config file and modifies the options accordingly.  Options
   1600  * should already be initialized before this call.  This never returns if
   1601  * there is an error.  If the file does not exist, this returns 0.
   1602  */
   1603 
   1604 int
   1605 read_config_file(const char *filename, struct passwd *pw, const char *host,
   1606     const char *original_host, Options *options, int flags)
   1607 {
   1608 	FILE *f;
   1609 	char line[1024];
   1610 	int active, linenum;
   1611 	int bad_options = 0;
   1612 
   1613 	if ((f = fopen(filename, "r")) == NULL)
   1614 		return 0;
   1615 
   1616 	if (flags & SSHCONF_CHECKPERM) {
   1617 		struct stat sb;
   1618 
   1619 		if (fstat(fileno(f), &sb) == -1)
   1620 			fatal("fstat %s: %s", filename, strerror(errno));
   1621 		if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
   1622 		    (sb.st_mode & 022) != 0))
   1623 			fatal("Bad owner or permissions on %s", filename);
   1624 	}
   1625 
   1626 	debug("Reading configuration data %.200s", filename);
   1627 
   1628 	/*
   1629 	 * Mark that we are now processing the options.  This flag is turned
   1630 	 * on/off by Host specifications.
   1631 	 */
   1632 	active = 1;
   1633 	linenum = 0;
   1634 	while (fgets(line, sizeof(line), f)) {
   1635 		/* Update line number counter. */
   1636 		linenum++;
   1637 		if (process_config_line(options, pw, host, original_host,
   1638 		    line, filename, linenum, &active, flags) != 0)
   1639 			bad_options++;
   1640 	}
   1641 	fclose(f);
   1642 	if (bad_options > 0)
   1643 		fatal("%s: terminating, %d bad configuration options",
   1644 		    filename, bad_options);
   1645 	return 1;
   1646 }
   1647 
   1648 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
   1649 int
   1650 option_clear_or_none(const char *o)
   1651 {
   1652 	return o == NULL || strcasecmp(o, "none") == 0;
   1653 }
   1654 
   1655 /*
   1656  * Initializes options to special values that indicate that they have not yet
   1657  * been set.  Read_config_file will only set options with this value. Options
   1658  * are processed in the following order: command line, user config file,
   1659  * system config file.  Last, fill_default_options is called.
   1660  */
   1661 
   1662 void
   1663 initialize_options(Options * options)
   1664 {
   1665 	memset(options, 'X', sizeof(*options));
   1666 	options->forward_agent = -1;
   1667 	options->forward_x11 = -1;
   1668 	options->forward_x11_trusted = -1;
   1669 	options->forward_x11_timeout = -1;
   1670 	options->exit_on_forward_failure = -1;
   1671 	options->xauth_location = NULL;
   1672 	options->fwd_opts.gateway_ports = -1;
   1673 	options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
   1674 	options->fwd_opts.streamlocal_bind_unlink = -1;
   1675 	options->use_privileged_port = -1;
   1676 	options->rsa_authentication = -1;
   1677 	options->pubkey_authentication = -1;
   1678 	options->challenge_response_authentication = -1;
   1679 #if defined(KRB4) || defined(KRB5)
   1680 	options->kerberos_authentication = -1;
   1681 #endif
   1682 #if defined(AFS) || defined(KRB5)
   1683 	options->kerberos_tgt_passing = -1;
   1684 #endif
   1685 #ifdef AFS
   1686 	options->afs_token_passing = -1;
   1687 #endif
   1688 	options->gss_authentication = -1;
   1689 	options->gss_deleg_creds = -1;
   1690 	options->password_authentication = -1;
   1691 	options->kbd_interactive_authentication = -1;
   1692 	options->kbd_interactive_devices = NULL;
   1693 	options->rhosts_rsa_authentication = -1;
   1694 	options->hostbased_authentication = -1;
   1695 	options->batch_mode = -1;
   1696 	options->check_host_ip = -1;
   1697 	options->strict_host_key_checking = -1;
   1698 	options->compression = -1;
   1699 	options->tcp_keep_alive = -1;
   1700 	options->compression_level = -1;
   1701 	options->port = -1;
   1702 	options->address_family = -1;
   1703 	options->connection_attempts = -1;
   1704 	options->connection_timeout = -1;
   1705 	options->number_of_password_prompts = -1;
   1706 	options->cipher = -1;
   1707 	options->ciphers = NULL;
   1708 	options->macs = NULL;
   1709 	options->kex_algorithms = NULL;
   1710 	options->hostkeyalgorithms = NULL;
   1711 	options->protocol = SSH_PROTO_UNKNOWN;
   1712 	options->num_identity_files = 0;
   1713 	options->hostname = NULL;
   1714 	options->host_key_alias = NULL;
   1715 	options->proxy_command = NULL;
   1716 	options->user = NULL;
   1717 	options->escape_char = -1;
   1718 	options->num_system_hostfiles = 0;
   1719 	options->num_user_hostfiles = 0;
   1720 	options->local_forwards = NULL;
   1721 	options->num_local_forwards = 0;
   1722 	options->remote_forwards = NULL;
   1723 	options->num_remote_forwards = 0;
   1724 	options->clear_forwardings = -1;
   1725 	options->log_level = SYSLOG_LEVEL_NOT_SET;
   1726 	options->preferred_authentications = NULL;
   1727 	options->bind_address = NULL;
   1728 	options->pkcs11_provider = NULL;
   1729 	options->enable_ssh_keysign = - 1;
   1730 	options->no_host_authentication_for_localhost = - 1;
   1731 	options->identities_only = - 1;
   1732 	options->rekey_limit = - 1;
   1733 	options->rekey_interval = -1;
   1734 	options->verify_host_key_dns = -1;
   1735 	options->server_alive_interval = -1;
   1736 	options->server_alive_count_max = -1;
   1737 	options->num_send_env = 0;
   1738 	options->control_path = NULL;
   1739 	options->control_master = -1;
   1740 	options->control_persist = -1;
   1741 	options->control_persist_timeout = 0;
   1742 	options->hash_known_hosts = -1;
   1743 	options->tun_open = -1;
   1744 	options->tun_local = -1;
   1745 	options->tun_remote = -1;
   1746 	options->local_command = NULL;
   1747 	options->permit_local_command = -1;
   1748 	options->use_roaming = -1;
   1749 	options->visual_host_key = -1;
   1750 	options->ip_qos_interactive = -1;
   1751 	options->ip_qos_bulk = -1;
   1752 	options->request_tty = -1;
   1753 	options->proxy_use_fdpass = -1;
   1754 	options->ignored_unknown = NULL;
   1755 	options->num_canonical_domains = 0;
   1756 	options->num_permitted_cnames = 0;
   1757 	options->canonicalize_max_dots = -1;
   1758 	options->canonicalize_fallback_local = -1;
   1759 	options->canonicalize_hostname = -1;
   1760 	options->revoked_host_keys = NULL;
   1761 	options->fingerprint_hash = -1;
   1762 	options->update_hostkeys = -1;
   1763 	options->hostbased_key_types = NULL;
   1764 	options->none_switch = -1;
   1765 	options->none_enabled = -1;
   1766 	options->hpn_disabled = -1;
   1767 	options->hpn_buffer_size = -1;
   1768 	options->tcp_rcv_buf_poll = -1;
   1769 	options->tcp_rcv_buf = -1;
   1770 	options->send_version_first = -1;
   1771 }
   1772 
   1773 /*
   1774  * A petite version of fill_default_options() that just fills the options
   1775  * needed for hostname canonicalization to proceed.
   1776  */
   1777 void
   1778 fill_default_options_for_canonicalization(Options *options)
   1779 {
   1780 	if (options->canonicalize_max_dots == -1)
   1781 		options->canonicalize_max_dots = 1;
   1782 	if (options->canonicalize_fallback_local == -1)
   1783 		options->canonicalize_fallback_local = 1;
   1784 	if (options->canonicalize_hostname == -1)
   1785 		options->canonicalize_hostname = SSH_CANONICALISE_NO;
   1786 }
   1787 
   1788 /*
   1789  * Called after processing other sources of option data, this fills those
   1790  * options for which no value has been specified with their default values.
   1791  */
   1792 void
   1793 fill_default_options(Options * options)
   1794 {
   1795 	if (options->forward_agent == -1)
   1796 		options->forward_agent = 0;
   1797 	if (options->forward_x11 == -1)
   1798 		options->forward_x11 = 0;
   1799 	if (options->forward_x11_trusted == -1)
   1800 		options->forward_x11_trusted = 0;
   1801 	if (options->forward_x11_timeout == -1)
   1802 		options->forward_x11_timeout = 1200;
   1803 	if (options->exit_on_forward_failure == -1)
   1804 		options->exit_on_forward_failure = 0;
   1805 	if (options->xauth_location == NULL)
   1806 		options->xauth_location = __UNCONST(_PATH_XAUTH);
   1807 	if (options->fwd_opts.gateway_ports == -1)
   1808 		options->fwd_opts.gateway_ports = 0;
   1809 	if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
   1810 		options->fwd_opts.streamlocal_bind_mask = 0177;
   1811 	if (options->fwd_opts.streamlocal_bind_unlink == -1)
   1812 		options->fwd_opts.streamlocal_bind_unlink = 0;
   1813 	if (options->use_privileged_port == -1)
   1814 		options->use_privileged_port = 0;
   1815 	if (options->rsa_authentication == -1)
   1816 		options->rsa_authentication = 1;
   1817 	if (options->pubkey_authentication == -1)
   1818 		options->pubkey_authentication = 1;
   1819 	if (options->challenge_response_authentication == -1)
   1820 		options->challenge_response_authentication = 1;
   1821 #if defined(KRB4) || defined(KRB5)
   1822 	if (options->kerberos_authentication == -1)
   1823 		options->kerberos_authentication = 1;
   1824 #endif
   1825 #if defined(AFS) || defined(KRB5)
   1826 	if (options->kerberos_tgt_passing == -1)
   1827 		options->kerberos_tgt_passing = 1;
   1828 #endif
   1829 #ifdef AFS
   1830 	if (options->afs_token_passing == -1)
   1831 		options->afs_token_passing = 1;
   1832 #endif
   1833 	if (options->gss_authentication == -1)
   1834 		options->gss_authentication = 0;
   1835 	if (options->gss_deleg_creds == -1)
   1836 		options->gss_deleg_creds = 0;
   1837 	if (options->password_authentication == -1)
   1838 		options->password_authentication = 1;
   1839 	if (options->kbd_interactive_authentication == -1)
   1840 		options->kbd_interactive_authentication = 1;
   1841 	if (options->rhosts_rsa_authentication == -1)
   1842 		options->rhosts_rsa_authentication = 0;
   1843 	if (options->hostbased_authentication == -1)
   1844 		options->hostbased_authentication = 0;
   1845 	if (options->batch_mode == -1)
   1846 		options->batch_mode = 0;
   1847 	if (options->check_host_ip == -1)
   1848 		options->check_host_ip = 1;
   1849 	if (options->strict_host_key_checking == -1)
   1850 		options->strict_host_key_checking = 2;	/* 2 is default */
   1851 	if (options->compression == -1)
   1852 		options->compression = 0;
   1853 	if (options->tcp_keep_alive == -1)
   1854 		options->tcp_keep_alive = 1;
   1855 	if (options->compression_level == -1)
   1856 		options->compression_level = 6;
   1857 	if (options->port == -1)
   1858 		options->port = 0;	/* Filled in ssh_connect. */
   1859 	if (options->address_family == -1)
   1860 		options->address_family = AF_UNSPEC;
   1861 	if (options->connection_attempts == -1)
   1862 		options->connection_attempts = 1;
   1863 	if (options->number_of_password_prompts == -1)
   1864 		options->number_of_password_prompts = 3;
   1865 	/* Selected in ssh_login(). */
   1866 	if (options->cipher == -1)
   1867 		options->cipher = SSH_CIPHER_NOT_SET;
   1868 	/* options->ciphers, default set in myproposals.h */
   1869 	/* options->macs, default set in myproposals.h */
   1870 	/* options->kex_algorithms, default set in myproposals.h */
   1871 	/* options->hostkeyalgorithms, default set in myproposals.h */
   1872 	if (options->protocol == SSH_PROTO_UNKNOWN)
   1873 		options->protocol = SSH_PROTO_2;
   1874 	if (options->num_identity_files == 0) {
   1875 		if (options->protocol & SSH_PROTO_1) {
   1876 			add_identity_file(options, "~/",
   1877 			    _PATH_SSH_CLIENT_IDENTITY, 0);
   1878 		}
   1879 		if (options->protocol & SSH_PROTO_2) {
   1880 			add_identity_file(options, "~/",
   1881 			    _PATH_SSH_CLIENT_ID_RSA, 0);
   1882 			add_identity_file(options, "~/",
   1883 			    _PATH_SSH_CLIENT_ID_DSA, 0);
   1884 			add_identity_file(options, "~/",
   1885 			    _PATH_SSH_CLIENT_ID_ECDSA, 0);
   1886 			add_identity_file(options, "~/",
   1887 			    _PATH_SSH_CLIENT_ID_ED25519, 0);
   1888 		}
   1889 	}
   1890 	if (options->escape_char == -1)
   1891 		options->escape_char = '~';
   1892 	if (options->num_system_hostfiles == 0) {
   1893 		options->system_hostfiles[options->num_system_hostfiles++] =
   1894 		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
   1895 		options->system_hostfiles[options->num_system_hostfiles++] =
   1896 		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
   1897 	}
   1898 	if (options->num_user_hostfiles == 0) {
   1899 		options->user_hostfiles[options->num_user_hostfiles++] =
   1900 		    xstrdup(_PATH_SSH_USER_HOSTFILE);
   1901 		options->user_hostfiles[options->num_user_hostfiles++] =
   1902 		    xstrdup(_PATH_SSH_USER_HOSTFILE2);
   1903 	}
   1904 	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
   1905 		options->log_level = SYSLOG_LEVEL_INFO;
   1906 	if (options->clear_forwardings == 1)
   1907 		clear_forwardings(options);
   1908 	if (options->no_host_authentication_for_localhost == - 1)
   1909 		options->no_host_authentication_for_localhost = 0;
   1910 	if (options->identities_only == -1)
   1911 		options->identities_only = 0;
   1912 	if (options->enable_ssh_keysign == -1)
   1913 		options->enable_ssh_keysign = 0;
   1914 	if (options->rekey_limit == -1)
   1915 		options->rekey_limit = 0;
   1916 	if (options->rekey_interval == -1)
   1917 		options->rekey_interval = 0;
   1918 	if (options->verify_host_key_dns == -1)
   1919 		options->verify_host_key_dns = 0;
   1920 	if (options->server_alive_interval == -1)
   1921 		options->server_alive_interval = 0;
   1922 	if (options->server_alive_count_max == -1)
   1923 		options->server_alive_count_max = 3;
   1924 	if (options->none_switch == -1)
   1925 	        options->none_switch = 0;
   1926 	if (options->hpn_disabled == -1)
   1927 	        options->hpn_disabled = 0;
   1928 	if (options->hpn_buffer_size > -1)
   1929 	{
   1930 	  /* if a user tries to set the size to 0 set it to 1KB */
   1931 		if (options->hpn_buffer_size == 0)
   1932 		options->hpn_buffer_size = 1024;
   1933 		/*limit the buffer to 64MB*/
   1934 		if (options->hpn_buffer_size > 65536)
   1935 		{
   1936 			options->hpn_buffer_size = 65536*1024;
   1937 			debug("User requested buffer larger than 64MB. Request reverted to 64MB");
   1938 		}
   1939 		debug("hpn_buffer_size set to %d", options->hpn_buffer_size);
   1940 	}
   1941 	if (options->tcp_rcv_buf == 0)
   1942 		options->tcp_rcv_buf = 1;
   1943 	if (options->tcp_rcv_buf > -1)
   1944 		options->tcp_rcv_buf *=1024;
   1945 	if (options->tcp_rcv_buf_poll == -1)
   1946 		options->tcp_rcv_buf_poll = 1;
   1947 	if (options->control_master == -1)
   1948 		options->control_master = 0;
   1949 	if (options->control_persist == -1) {
   1950 		options->control_persist = 0;
   1951 		options->control_persist_timeout = 0;
   1952 	}
   1953 	if (options->hash_known_hosts == -1)
   1954 		options->hash_known_hosts = 0;
   1955 	if (options->tun_open == -1)
   1956 		options->tun_open = SSH_TUNMODE_NO;
   1957 	if (options->tun_local == -1)
   1958 		options->tun_local = SSH_TUNID_ANY;
   1959 	if (options->tun_remote == -1)
   1960 		options->tun_remote = SSH_TUNID_ANY;
   1961 	if (options->permit_local_command == -1)
   1962 		options->permit_local_command = 0;
   1963 	if (options->use_roaming == -1)
   1964 		options->use_roaming = 1;
   1965 	if (options->visual_host_key == -1)
   1966 		options->visual_host_key = 0;
   1967 	if (options->ip_qos_interactive == -1)
   1968 		options->ip_qos_interactive = IPTOS_LOWDELAY;
   1969 	if (options->ip_qos_bulk == -1)
   1970 		options->ip_qos_bulk = IPTOS_THROUGHPUT;
   1971 	if (options->request_tty == -1)
   1972 		options->request_tty = REQUEST_TTY_AUTO;
   1973 	if (options->proxy_use_fdpass == -1)
   1974 		options->proxy_use_fdpass = 0;
   1975 	if (options->canonicalize_max_dots == -1)
   1976 		options->canonicalize_max_dots = 1;
   1977 	if (options->canonicalize_fallback_local == -1)
   1978 		options->canonicalize_fallback_local = 1;
   1979 	if (options->canonicalize_hostname == -1)
   1980 		options->canonicalize_hostname = SSH_CANONICALISE_NO;
   1981 	if (options->fingerprint_hash == -1)
   1982 		options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
   1983 	if (options->update_hostkeys == -1)
   1984 		options->update_hostkeys = 0;
   1985 	if (options->hostbased_key_types == NULL)
   1986 		options->hostbased_key_types = xstrdup("*");
   1987 
   1988 	if (options->send_version_first == -1)
   1989 		options->send_version_first = 1;
   1990 #define CLEAR_ON_NONE(v) \
   1991 	do { \
   1992 		if (option_clear_or_none(v)) { \
   1993 			free(v); \
   1994 			v = NULL; \
   1995 		} \
   1996 	} while(0)
   1997 	CLEAR_ON_NONE(options->local_command);
   1998 	CLEAR_ON_NONE(options->proxy_command);
   1999 	CLEAR_ON_NONE(options->control_path);
   2000 	CLEAR_ON_NONE(options->revoked_host_keys);
   2001 	/* options->user will be set in the main program if appropriate */
   2002 	/* options->hostname will be set in the main program if appropriate */
   2003 	/* options->host_key_alias should not be set by default */
   2004 	/* options->preferred_authentications will be set in ssh */
   2005 }
   2006 
   2007 struct fwdarg {
   2008 	char *arg;
   2009 	int ispath;
   2010 };
   2011 
   2012 /*
   2013  * parse_fwd_field
   2014  * parses the next field in a port forwarding specification.
   2015  * sets fwd to the parsed field and advances p past the colon
   2016  * or sets it to NULL at end of string.
   2017  * returns 0 on success, else non-zero.
   2018  */
   2019 static int
   2020 parse_fwd_field(char **p, struct fwdarg *fwd)
   2021 {
   2022 	char *ep, *cp = *p;
   2023 	int ispath = 0;
   2024 
   2025 	if (*cp == '\0') {
   2026 		*p = NULL;
   2027 		return -1;	/* end of string */
   2028 	}
   2029 
   2030 	/*
   2031 	 * A field escaped with square brackets is used literally.
   2032 	 * XXX - allow ']' to be escaped via backslash?
   2033 	 */
   2034 	if (*cp == '[') {
   2035 		/* find matching ']' */
   2036 		for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
   2037 			if (*ep == '/')
   2038 				ispath = 1;
   2039 		}
   2040 		/* no matching ']' or not at end of field. */
   2041 		if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
   2042 			return -1;
   2043 		/* NUL terminate the field and advance p past the colon */
   2044 		*ep++ = '\0';
   2045 		if (*ep != '\0')
   2046 			*ep++ = '\0';
   2047 		fwd->arg = cp + 1;
   2048 		fwd->ispath = ispath;
   2049 		*p = ep;
   2050 		return 0;
   2051 	}
   2052 
   2053 	for (cp = *p; *cp != '\0'; cp++) {
   2054 		switch (*cp) {
   2055 		case '\\':
   2056 			memmove(cp, cp + 1, strlen(cp + 1) + 1);
   2057 			cp++;
   2058 			break;
   2059 		case '/':
   2060 			ispath = 1;
   2061 			break;
   2062 		case ':':
   2063 			*cp++ = '\0';
   2064 			goto done;
   2065 		}
   2066 	}
   2067 done:
   2068 	fwd->arg = *p;
   2069 	fwd->ispath = ispath;
   2070 	*p = cp;
   2071 	return 0;
   2072 }
   2073 
   2074 /*
   2075  * parse_forward
   2076  * parses a string containing a port forwarding specification of the form:
   2077  *   dynamicfwd == 0
   2078  *	[listenhost:]listenport|listenpath:connecthost:connectport|connectpath
   2079  *	listenpath:connectpath
   2080  *   dynamicfwd == 1
   2081  *	[listenhost:]listenport
   2082  * returns number of arguments parsed or zero on error
   2083  */
   2084 int
   2085 parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
   2086 {
   2087 	struct fwdarg fwdargs[4];
   2088 	char *p, *cp;
   2089 	int i;
   2090 
   2091 	memset(fwd, 0, sizeof(*fwd));
   2092 	memset(fwdargs, 0, sizeof(fwdargs));
   2093 
   2094 	cp = p = xstrdup(fwdspec);
   2095 
   2096 	/* skip leading spaces */
   2097 	while (isspace((u_char)*cp))
   2098 		cp++;
   2099 
   2100 	for (i = 0; i < 4; ++i) {
   2101 		if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
   2102 			break;
   2103 	}
   2104 
   2105 	/* Check for trailing garbage */
   2106 	if (cp != NULL && *cp != '\0') {
   2107 		i = 0;	/* failure */
   2108 	}
   2109 
   2110 	switch (i) {
   2111 	case 1:
   2112 		if (fwdargs[0].ispath) {
   2113 			fwd->listen_path = xstrdup(fwdargs[0].arg);
   2114 			fwd->listen_port = PORT_STREAMLOCAL;
   2115 		} else {
   2116 			fwd->listen_host = NULL;
   2117 			fwd->listen_port = a2port(fwdargs[0].arg);
   2118 		}
   2119 		fwd->connect_host = xstrdup("socks");
   2120 		break;
   2121 
   2122 	case 2:
   2123 		if (fwdargs[0].ispath && fwdargs[1].ispath) {
   2124 			fwd->listen_path = xstrdup(fwdargs[0].arg);
   2125 			fwd->listen_port = PORT_STREAMLOCAL;
   2126 			fwd->connect_path = xstrdup(fwdargs[1].arg);
   2127 			fwd->connect_port = PORT_STREAMLOCAL;
   2128 		} else if (fwdargs[1].ispath) {
   2129 			fwd->listen_host = NULL;
   2130 			fwd->listen_port = a2port(fwdargs[0].arg);
   2131 			fwd->connect_path = xstrdup(fwdargs[1].arg);
   2132 			fwd->connect_port = PORT_STREAMLOCAL;
   2133 		} else {
   2134 			fwd->listen_host = xstrdup(fwdargs[0].arg);
   2135 			fwd->listen_port = a2port(fwdargs[1].arg);
   2136 			fwd->connect_host = xstrdup("socks");
   2137 		}
   2138 		break;
   2139 
   2140 	case 3:
   2141 		if (fwdargs[0].ispath) {
   2142 			fwd->listen_path = xstrdup(fwdargs[0].arg);
   2143 			fwd->listen_port = PORT_STREAMLOCAL;
   2144 			fwd->connect_host = xstrdup(fwdargs[1].arg);
   2145 			fwd->connect_port = a2port(fwdargs[2].arg);
   2146 		} else if (fwdargs[2].ispath) {
   2147 			fwd->listen_host = xstrdup(fwdargs[0].arg);
   2148 			fwd->listen_port = a2port(fwdargs[1].arg);
   2149 			fwd->connect_path = xstrdup(fwdargs[2].arg);
   2150 			fwd->connect_port = PORT_STREAMLOCAL;
   2151 		} else {
   2152 			fwd->listen_host = NULL;
   2153 			fwd->listen_port = a2port(fwdargs[0].arg);
   2154 			fwd->connect_host = xstrdup(fwdargs[1].arg);
   2155 			fwd->connect_port = a2port(fwdargs[2].arg);
   2156 		}
   2157 		break;
   2158 
   2159 	case 4:
   2160 		fwd->listen_host = xstrdup(fwdargs[0].arg);
   2161 		fwd->listen_port = a2port(fwdargs[1].arg);
   2162 		fwd->connect_host = xstrdup(fwdargs[2].arg);
   2163 		fwd->connect_port = a2port(fwdargs[3].arg);
   2164 		break;
   2165 	default:
   2166 		i = 0; /* failure */
   2167 	}
   2168 
   2169 	free(p);
   2170 
   2171 	if (dynamicfwd) {
   2172 		if (!(i == 1 || i == 2))
   2173 			goto fail_free;
   2174 	} else {
   2175 		if (!(i == 3 || i == 4)) {
   2176 			if (fwd->connect_path == NULL &&
   2177 			    fwd->listen_path == NULL)
   2178 				goto fail_free;
   2179 		}
   2180 		if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
   2181 			goto fail_free;
   2182 	}
   2183 
   2184 	if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
   2185 	    (!remotefwd && fwd->listen_port == 0))
   2186 		goto fail_free;
   2187 	if (fwd->connect_host != NULL &&
   2188 	    strlen(fwd->connect_host) >= NI_MAXHOST)
   2189 		goto fail_free;
   2190 	/* XXX - if connecting to a remote socket, max sun len may not match this host */
   2191 	if (fwd->connect_path != NULL &&
   2192 	    strlen(fwd->connect_path) >= PATH_MAX_SUN)
   2193 		goto fail_free;
   2194 	if (fwd->listen_host != NULL &&
   2195 	    strlen(fwd->listen_host) >= NI_MAXHOST)
   2196 		goto fail_free;
   2197 	if (fwd->listen_path != NULL &&
   2198 	    strlen(fwd->listen_path) >= PATH_MAX_SUN)
   2199 		goto fail_free;
   2200 
   2201 	return (i);
   2202 
   2203  fail_free:
   2204 	free(fwd->connect_host);
   2205 	fwd->connect_host = NULL;
   2206 	free(fwd->connect_path);
   2207 	fwd->connect_path = NULL;
   2208 	free(fwd->listen_host);
   2209 	fwd->listen_host = NULL;
   2210 	free(fwd->listen_path);
   2211 	fwd->listen_path = NULL;
   2212 	return (0);
   2213 }
   2214 
   2215 /* XXX the following is a near-vebatim copy from servconf.c; refactor */
   2216 static const char *
   2217 fmt_multistate_int(int val, const struct multistate *m)
   2218 {
   2219 	u_int i;
   2220 
   2221 	for (i = 0; m[i].key != NULL; i++) {
   2222 		if (m[i].value == val)
   2223 			return m[i].key;
   2224 	}
   2225 	return "UNKNOWN";
   2226 }
   2227 
   2228 static const char *
   2229 fmt_intarg(OpCodes code, int val)
   2230 {
   2231 	if (val == -1)
   2232 		return "unset";
   2233 	switch (code) {
   2234 	case oAddressFamily:
   2235 		return fmt_multistate_int(val, multistate_addressfamily);
   2236 	case oVerifyHostKeyDNS:
   2237 	case oStrictHostKeyChecking:
   2238 	case oUpdateHostkeys:
   2239 		return fmt_multistate_int(val, multistate_yesnoask);
   2240 	case oControlMaster:
   2241 		return fmt_multistate_int(val, multistate_controlmaster);
   2242 	case oTunnel:
   2243 		return fmt_multistate_int(val, multistate_tunnel);
   2244 	case oRequestTTY:
   2245 		return fmt_multistate_int(val, multistate_requesttty);
   2246 	case oCanonicalizeHostname:
   2247 		return fmt_multistate_int(val, multistate_canonicalizehostname);
   2248 	case oFingerprintHash:
   2249 		return ssh_digest_alg_name(val);
   2250 	case oProtocol:
   2251 		switch (val) {
   2252 		case SSH_PROTO_1:
   2253 			return "1";
   2254 		case SSH_PROTO_2:
   2255 			return "2";
   2256 		case (SSH_PROTO_1|SSH_PROTO_2):
   2257 			return "2,1";
   2258 		default:
   2259 			return "UNKNOWN";
   2260 		}
   2261 	default:
   2262 		switch (val) {
   2263 		case 0:
   2264 			return "no";
   2265 		case 1:
   2266 			return "yes";
   2267 		default:
   2268 			return "UNKNOWN";
   2269 		}
   2270 	}
   2271 }
   2272 
   2273 static const char *
   2274 lookup_opcode_name(OpCodes code)
   2275 {
   2276 	u_int i;
   2277 
   2278 	for (i = 0; keywords[i].name != NULL; i++)
   2279 		if (keywords[i].opcode == code)
   2280 			return(keywords[i].name);
   2281 	return "UNKNOWN";
   2282 }
   2283 
   2284 static void
   2285 dump_cfg_int(OpCodes code, int val)
   2286 {
   2287 	printf("%s %d\n", lookup_opcode_name(code), val);
   2288 }
   2289 
   2290 static void
   2291 dump_cfg_fmtint(OpCodes code, int val)
   2292 {
   2293 	printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
   2294 }
   2295 
   2296 static void
   2297 dump_cfg_string(OpCodes code, const char *val)
   2298 {
   2299 	if (val == NULL)
   2300 		return;
   2301 	printf("%s %s\n", lookup_opcode_name(code), val);
   2302 }
   2303 
   2304 static void
   2305 dump_cfg_strarray(OpCodes code, u_int count, char **vals)
   2306 {
   2307 	u_int i;
   2308 
   2309 	for (i = 0; i < count; i++)
   2310 		printf("%s %s\n", lookup_opcode_name(code), vals[i]);
   2311 }
   2312 
   2313 static void
   2314 dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals)
   2315 {
   2316 	u_int i;
   2317 
   2318 	printf("%s", lookup_opcode_name(code));
   2319 	for (i = 0; i < count; i++)
   2320 		printf(" %s",  vals[i]);
   2321 	printf("\n");
   2322 }
   2323 
   2324 static void
   2325 dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds)
   2326 {
   2327 	const struct Forward *fwd;
   2328 	u_int i;
   2329 
   2330 	/* oDynamicForward */
   2331 	for (i = 0; i < count; i++) {
   2332 		fwd = &fwds[i];
   2333 		if (code == oDynamicForward &&
   2334 		    strcmp(fwd->connect_host, "socks") != 0)
   2335 			continue;
   2336 		if (code == oLocalForward &&
   2337 		    strcmp(fwd->connect_host, "socks") == 0)
   2338 			continue;
   2339 		printf("%s", lookup_opcode_name(code));
   2340 		if (fwd->listen_port == PORT_STREAMLOCAL)
   2341 			printf(" %s", fwd->listen_path);
   2342 		else if (fwd->listen_host == NULL)
   2343 			printf(" %d", fwd->listen_port);
   2344 		else {
   2345 			printf(" [%s]:%d",
   2346 			    fwd->listen_host, fwd->listen_port);
   2347 		}
   2348 		if (code != oDynamicForward) {
   2349 			if (fwd->connect_port == PORT_STREAMLOCAL)
   2350 				printf(" %s", fwd->connect_path);
   2351 			else if (fwd->connect_host == NULL)
   2352 				printf(" %d", fwd->connect_port);
   2353 			else {
   2354 				printf(" [%s]:%d",
   2355 				    fwd->connect_host, fwd->connect_port);
   2356 			}
   2357 		}
   2358 		printf("\n");
   2359 	}
   2360 }
   2361 
   2362 void
   2363 dump_client_config(Options *o, const char *host)
   2364 {
   2365 	int i;
   2366 	char vbuf[5];
   2367 
   2368 	/* Most interesting options first: user, host, port */
   2369 	dump_cfg_string(oUser, o->user);
   2370 	dump_cfg_string(oHostName, host);
   2371 	dump_cfg_int(oPort, o->port);
   2372 
   2373 	/* Flag options */
   2374 	dump_cfg_fmtint(oAddressFamily, o->address_family);
   2375 	dump_cfg_fmtint(oBatchMode, o->batch_mode);
   2376 	dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local);
   2377 	dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname);
   2378 	dump_cfg_fmtint(oChallengeResponseAuthentication, o->challenge_response_authentication);
   2379 	dump_cfg_fmtint(oCheckHostIP, o->check_host_ip);
   2380 	dump_cfg_fmtint(oCompression, o->compression);
   2381 	dump_cfg_fmtint(oControlMaster, o->control_master);
   2382 	dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
   2383 	dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
   2384 	dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash);
   2385 	dump_cfg_fmtint(oForwardAgent, o->forward_agent);
   2386 	dump_cfg_fmtint(oForwardX11, o->forward_x11);
   2387 	dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted);
   2388 	dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports);
   2389 #ifdef GSSAPI
   2390 	dump_cfg_fmtint(oGssAuthentication, o->gss_authentication);
   2391 	dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds);
   2392 #endif /* GSSAPI */
   2393 	dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);
   2394 	dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);
   2395 	dump_cfg_fmtint(oIdentitiesOnly, o->identities_only);
   2396 	dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication);
   2397 	dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost);
   2398 	dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication);
   2399 	dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command);
   2400 	dump_cfg_fmtint(oProtocol, o->protocol);
   2401 	dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass);
   2402 	dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
   2403 	dump_cfg_fmtint(oRequestTTY, o->request_tty);
   2404 	dump_cfg_fmtint(oRhostsRSAAuthentication, o->rhosts_rsa_authentication);
   2405 	dump_cfg_fmtint(oRSAAuthentication, o->rsa_authentication);
   2406 	dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
   2407 	dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
   2408 	dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
   2409 	dump_cfg_fmtint(oTunnel, o->tun_open);
   2410 	dump_cfg_fmtint(oUsePrivilegedPort, o->use_privileged_port);
   2411 	dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns);
   2412 	dump_cfg_fmtint(oVisualHostKey, o->visual_host_key);
   2413 	dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys);
   2414 
   2415 	/* Integer options */
   2416 	dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots);
   2417 	dump_cfg_int(oCompressionLevel, o->compression_level);
   2418 	dump_cfg_int(oConnectionAttempts, o->connection_attempts);
   2419 	dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout);
   2420 	dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
   2421 	dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
   2422 	dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
   2423 
   2424 	/* String options */
   2425 	dump_cfg_string(oBindAddress, o->bind_address);
   2426 	dump_cfg_string(oCiphers, o->ciphers ? o->ciphers : KEX_CLIENT_ENCRYPT);
   2427 	dump_cfg_string(oControlPath, o->control_path);
   2428 	dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms ? o->hostkeyalgorithms : KEX_DEFAULT_PK_ALG);
   2429 	dump_cfg_string(oHostKeyAlias, o->host_key_alias);
   2430 	dump_cfg_string(oHostbasedKeyTypes, o->hostbased_key_types);
   2431 	dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
   2432 	dump_cfg_string(oKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : KEX_CLIENT_KEX);
   2433 	dump_cfg_string(oLocalCommand, o->local_command);
   2434 	dump_cfg_string(oLogLevel, log_level_name(o->log_level));
   2435 	dump_cfg_string(oMacs, o->macs ? o->macs : KEX_CLIENT_MAC);
   2436 	dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
   2437 	dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
   2438 	dump_cfg_string(oProxyCommand, o->proxy_command);
   2439 	dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
   2440 	dump_cfg_string(oXAuthLocation, o->xauth_location);
   2441 
   2442 	/* Forwards */
   2443 	dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
   2444 	dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards);
   2445 	dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards);
   2446 
   2447 	/* String array options */
   2448 	dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files);
   2449 	dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains);
   2450 	dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles);
   2451 	dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles);
   2452 	dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env);
   2453 
   2454 	/* Special cases */
   2455 
   2456 	/* oConnectTimeout */
   2457 	if (o->connection_timeout == -1)
   2458 		printf("connecttimeout none\n");
   2459 	else
   2460 		dump_cfg_int(oConnectTimeout, o->connection_timeout);
   2461 
   2462 	/* oTunnelDevice */
   2463 	printf("tunneldevice");
   2464 	if (o->tun_local == SSH_TUNID_ANY)
   2465 		printf(" any");
   2466 	else
   2467 		printf(" %d", o->tun_local);
   2468 	if (o->tun_remote == SSH_TUNID_ANY)
   2469 		printf(":any");
   2470 	else
   2471 		printf(":%d", o->tun_remote);
   2472 	printf("\n");
   2473 
   2474 	/* oCanonicalizePermittedCNAMEs */
   2475 	if ( o->num_permitted_cnames > 0) {
   2476 		printf("canonicalizePermittedcnames");
   2477 		for (i = 0; i < o->num_permitted_cnames; i++) {
   2478 			printf(" %s:%s", o->permitted_cnames[i].source_list,
   2479 			    o->permitted_cnames[i].target_list);
   2480 		}
   2481 		printf("\n");
   2482 	}
   2483 
   2484 	/* oCipher */
   2485 	if (o->cipher != SSH_CIPHER_NOT_SET)
   2486 		printf("Cipher %s\n", cipher_name(o->cipher));
   2487 
   2488 	/* oControlPersist */
   2489 	if (o->control_persist == 0 || o->control_persist_timeout == 0)
   2490 		dump_cfg_fmtint(oControlPersist, o->control_persist);
   2491 	else
   2492 		dump_cfg_int(oControlPersist, o->control_persist_timeout);
   2493 
   2494 	/* oEscapeChar */
   2495 	if (o->escape_char == SSH_ESCAPECHAR_NONE)
   2496 		printf("escapechar none\n");
   2497 	else {
   2498 		vis(vbuf, o->escape_char, VIS_WHITE, 0);
   2499 		printf("escapechar %s\n", vbuf);
   2500 	}
   2501 
   2502 	/* oIPQoS */
   2503 	printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
   2504 	printf("%s\n", iptos2str(o->ip_qos_bulk));
   2505 
   2506 	/* oRekeyLimit */
   2507 	printf("rekeylimit %lld %d\n",
   2508 	    (long long)o->rekey_limit, o->rekey_interval);
   2509 
   2510 	/* oStreamLocalBindMask */
   2511 	printf("streamlocalbindmask 0%o\n",
   2512 	    o->fwd_opts.streamlocal_bind_mask);
   2513 }
   2514