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