xref: /openbsd-src/usr.bin/ssh/readconf.c (revision 3374c67d44f9b75b98444cbf63020f777792342e)
1 /* $OpenBSD: readconf.c,v 1.371 2023/01/02 07:03:30 djm 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->forward_agent = -1;
2317 	options->forward_agent_sock_path = NULL;
2318 	options->forward_x11 = -1;
2319 	options->forward_x11_trusted = -1;
2320 	options->forward_x11_timeout = -1;
2321 	options->stdio_forward_host = NULL;
2322 	options->stdio_forward_port = 0;
2323 	options->clear_forwardings = -1;
2324 	options->exit_on_forward_failure = -1;
2325 	options->xauth_location = NULL;
2326 	options->fwd_opts.gateway_ports = -1;
2327 	options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
2328 	options->fwd_opts.streamlocal_bind_unlink = -1;
2329 	options->pubkey_authentication = -1;
2330 	options->gss_authentication = -1;
2331 	options->gss_deleg_creds = -1;
2332 	options->password_authentication = -1;
2333 	options->kbd_interactive_authentication = -1;
2334 	options->kbd_interactive_devices = NULL;
2335 	options->hostbased_authentication = -1;
2336 	options->batch_mode = -1;
2337 	options->check_host_ip = -1;
2338 	options->strict_host_key_checking = -1;
2339 	options->compression = -1;
2340 	options->tcp_keep_alive = -1;
2341 	options->port = -1;
2342 	options->address_family = -1;
2343 	options->connection_attempts = -1;
2344 	options->connection_timeout = -1;
2345 	options->number_of_password_prompts = -1;
2346 	options->ciphers = NULL;
2347 	options->macs = NULL;
2348 	options->kex_algorithms = NULL;
2349 	options->hostkeyalgorithms = NULL;
2350 	options->ca_sign_algorithms = NULL;
2351 	options->num_identity_files = 0;
2352 	memset(options->identity_keys, 0, sizeof(options->identity_keys));
2353 	options->num_certificate_files = 0;
2354 	memset(options->certificates, 0, sizeof(options->certificates));
2355 	options->hostname = NULL;
2356 	options->host_key_alias = NULL;
2357 	options->proxy_command = NULL;
2358 	options->jump_user = NULL;
2359 	options->jump_host = NULL;
2360 	options->jump_port = -1;
2361 	options->jump_extra = NULL;
2362 	options->user = NULL;
2363 	options->escape_char = -1;
2364 	options->num_system_hostfiles = 0;
2365 	options->num_user_hostfiles = 0;
2366 	options->local_forwards = NULL;
2367 	options->num_local_forwards = 0;
2368 	options->remote_forwards = NULL;
2369 	options->num_remote_forwards = 0;
2370 	options->permitted_remote_opens = NULL;
2371 	options->num_permitted_remote_opens = 0;
2372 	options->log_facility = SYSLOG_FACILITY_NOT_SET;
2373 	options->log_level = SYSLOG_LEVEL_NOT_SET;
2374 	options->num_log_verbose = 0;
2375 	options->log_verbose = NULL;
2376 	options->preferred_authentications = NULL;
2377 	options->bind_address = NULL;
2378 	options->bind_interface = NULL;
2379 	options->pkcs11_provider = NULL;
2380 	options->sk_provider = NULL;
2381 	options->enable_ssh_keysign = - 1;
2382 	options->no_host_authentication_for_localhost = - 1;
2383 	options->identities_only = - 1;
2384 	options->rekey_limit = - 1;
2385 	options->rekey_interval = -1;
2386 	options->verify_host_key_dns = -1;
2387 	options->server_alive_interval = -1;
2388 	options->server_alive_count_max = -1;
2389 	options->send_env = NULL;
2390 	options->num_send_env = 0;
2391 	options->setenv = NULL;
2392 	options->num_setenv = 0;
2393 	options->control_path = NULL;
2394 	options->control_master = -1;
2395 	options->control_persist = -1;
2396 	options->control_persist_timeout = 0;
2397 	options->hash_known_hosts = -1;
2398 	options->tun_open = -1;
2399 	options->tun_local = -1;
2400 	options->tun_remote = -1;
2401 	options->local_command = NULL;
2402 	options->permit_local_command = -1;
2403 	options->remote_command = NULL;
2404 	options->add_keys_to_agent = -1;
2405 	options->add_keys_to_agent_lifespan = -1;
2406 	options->identity_agent = NULL;
2407 	options->visual_host_key = -1;
2408 	options->ip_qos_interactive = -1;
2409 	options->ip_qos_bulk = -1;
2410 	options->request_tty = -1;
2411 	options->session_type = -1;
2412 	options->stdin_null = -1;
2413 	options->fork_after_authentication = -1;
2414 	options->proxy_use_fdpass = -1;
2415 	options->ignored_unknown = NULL;
2416 	options->num_canonical_domains = 0;
2417 	options->num_permitted_cnames = 0;
2418 	options->canonicalize_max_dots = -1;
2419 	options->canonicalize_fallback_local = -1;
2420 	options->canonicalize_hostname = -1;
2421 	options->revoked_host_keys = NULL;
2422 	options->fingerprint_hash = -1;
2423 	options->update_hostkeys = -1;
2424 	options->hostbased_accepted_algos = NULL;
2425 	options->pubkey_accepted_algos = NULL;
2426 	options->known_hosts_command = NULL;
2427 	options->required_rsa_size = -1;
2428 	options->enable_escape_commandline = -1;
2429 }
2430 
2431 /*
2432  * A petite version of fill_default_options() that just fills the options
2433  * needed for hostname canonicalization to proceed.
2434  */
2435 void
2436 fill_default_options_for_canonicalization(Options *options)
2437 {
2438 	if (options->canonicalize_max_dots == -1)
2439 		options->canonicalize_max_dots = 1;
2440 	if (options->canonicalize_fallback_local == -1)
2441 		options->canonicalize_fallback_local = 1;
2442 	if (options->canonicalize_hostname == -1)
2443 		options->canonicalize_hostname = SSH_CANONICALISE_NO;
2444 }
2445 
2446 /*
2447  * Called after processing other sources of option data, this fills those
2448  * options for which no value has been specified with their default values.
2449  */
2450 int
2451 fill_default_options(Options * options)
2452 {
2453 	char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig;
2454 	char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig;
2455 	int ret = 0, r;
2456 
2457 	if (options->forward_agent == -1)
2458 		options->forward_agent = 0;
2459 	if (options->forward_x11 == -1)
2460 		options->forward_x11 = 0;
2461 	if (options->forward_x11_trusted == -1)
2462 		options->forward_x11_trusted = 0;
2463 	if (options->forward_x11_timeout == -1)
2464 		options->forward_x11_timeout = 1200;
2465 	/*
2466 	 * stdio forwarding (-W) changes the default for these but we defer
2467 	 * setting the values so they can be overridden.
2468 	 */
2469 	if (options->exit_on_forward_failure == -1)
2470 		options->exit_on_forward_failure =
2471 		    options->stdio_forward_host != NULL ? 1 : 0;
2472 	if (options->clear_forwardings == -1)
2473 		options->clear_forwardings =
2474 		    options->stdio_forward_host != NULL ? 1 : 0;
2475 	if (options->clear_forwardings == 1)
2476 		clear_forwardings(options);
2477 
2478 	if (options->xauth_location == NULL)
2479 		options->xauth_location = xstrdup(_PATH_XAUTH);
2480 	if (options->fwd_opts.gateway_ports == -1)
2481 		options->fwd_opts.gateway_ports = 0;
2482 	if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
2483 		options->fwd_opts.streamlocal_bind_mask = 0177;
2484 	if (options->fwd_opts.streamlocal_bind_unlink == -1)
2485 		options->fwd_opts.streamlocal_bind_unlink = 0;
2486 	if (options->pubkey_authentication == -1)
2487 		options->pubkey_authentication = SSH_PUBKEY_AUTH_ALL;
2488 	if (options->gss_authentication == -1)
2489 		options->gss_authentication = 0;
2490 	if (options->gss_deleg_creds == -1)
2491 		options->gss_deleg_creds = 0;
2492 	if (options->password_authentication == -1)
2493 		options->password_authentication = 1;
2494 	if (options->kbd_interactive_authentication == -1)
2495 		options->kbd_interactive_authentication = 1;
2496 	if (options->hostbased_authentication == -1)
2497 		options->hostbased_authentication = 0;
2498 	if (options->batch_mode == -1)
2499 		options->batch_mode = 0;
2500 	if (options->check_host_ip == -1)
2501 		options->check_host_ip = 0;
2502 	if (options->strict_host_key_checking == -1)
2503 		options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK;
2504 	if (options->compression == -1)
2505 		options->compression = 0;
2506 	if (options->tcp_keep_alive == -1)
2507 		options->tcp_keep_alive = 1;
2508 	if (options->port == -1)
2509 		options->port = 0;	/* Filled in ssh_connect. */
2510 	if (options->address_family == -1)
2511 		options->address_family = AF_UNSPEC;
2512 	if (options->connection_attempts == -1)
2513 		options->connection_attempts = 1;
2514 	if (options->number_of_password_prompts == -1)
2515 		options->number_of_password_prompts = 3;
2516 	/* options->hostkeyalgorithms, default set in myproposals.h */
2517 	if (options->add_keys_to_agent == -1) {
2518 		options->add_keys_to_agent = 0;
2519 		options->add_keys_to_agent_lifespan = 0;
2520 	}
2521 	if (options->num_identity_files == 0) {
2522 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0);
2523 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0);
2524 		add_identity_file(options, "~/",
2525 		    _PATH_SSH_CLIENT_ID_ECDSA_SK, 0);
2526 		add_identity_file(options, "~/",
2527 		    _PATH_SSH_CLIENT_ID_ED25519, 0);
2528 		add_identity_file(options, "~/",
2529 		    _PATH_SSH_CLIENT_ID_ED25519_SK, 0);
2530 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0);
2531 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0);
2532 	}
2533 	if (options->escape_char == -1)
2534 		options->escape_char = '~';
2535 	if (options->num_system_hostfiles == 0) {
2536 		options->system_hostfiles[options->num_system_hostfiles++] =
2537 		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
2538 		options->system_hostfiles[options->num_system_hostfiles++] =
2539 		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
2540 	}
2541 	if (options->update_hostkeys == -1) {
2542 		if (options->verify_host_key_dns <= 0 &&
2543 		    (options->num_user_hostfiles == 0 ||
2544 		    (options->num_user_hostfiles == 1 && strcmp(options->
2545 		    user_hostfiles[0], _PATH_SSH_USER_HOSTFILE) == 0)))
2546 			options->update_hostkeys = SSH_UPDATE_HOSTKEYS_YES;
2547 		else
2548 			options->update_hostkeys = SSH_UPDATE_HOSTKEYS_NO;
2549 	}
2550 	if (options->num_user_hostfiles == 0) {
2551 		options->user_hostfiles[options->num_user_hostfiles++] =
2552 		    xstrdup(_PATH_SSH_USER_HOSTFILE);
2553 		options->user_hostfiles[options->num_user_hostfiles++] =
2554 		    xstrdup(_PATH_SSH_USER_HOSTFILE2);
2555 	}
2556 	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
2557 		options->log_level = SYSLOG_LEVEL_INFO;
2558 	if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
2559 		options->log_facility = SYSLOG_FACILITY_USER;
2560 	if (options->no_host_authentication_for_localhost == - 1)
2561 		options->no_host_authentication_for_localhost = 0;
2562 	if (options->identities_only == -1)
2563 		options->identities_only = 0;
2564 	if (options->enable_ssh_keysign == -1)
2565 		options->enable_ssh_keysign = 0;
2566 	if (options->rekey_limit == -1)
2567 		options->rekey_limit = 0;
2568 	if (options->rekey_interval == -1)
2569 		options->rekey_interval = 0;
2570 	if (options->verify_host_key_dns == -1)
2571 		options->verify_host_key_dns = 0;
2572 	if (options->server_alive_interval == -1)
2573 		options->server_alive_interval = 0;
2574 	if (options->server_alive_count_max == -1)
2575 		options->server_alive_count_max = 3;
2576 	if (options->control_master == -1)
2577 		options->control_master = 0;
2578 	if (options->control_persist == -1) {
2579 		options->control_persist = 0;
2580 		options->control_persist_timeout = 0;
2581 	}
2582 	if (options->hash_known_hosts == -1)
2583 		options->hash_known_hosts = 0;
2584 	if (options->tun_open == -1)
2585 		options->tun_open = SSH_TUNMODE_NO;
2586 	if (options->tun_local == -1)
2587 		options->tun_local = SSH_TUNID_ANY;
2588 	if (options->tun_remote == -1)
2589 		options->tun_remote = SSH_TUNID_ANY;
2590 	if (options->permit_local_command == -1)
2591 		options->permit_local_command = 0;
2592 	if (options->visual_host_key == -1)
2593 		options->visual_host_key = 0;
2594 	if (options->ip_qos_interactive == -1)
2595 		options->ip_qos_interactive = IPTOS_DSCP_AF21;
2596 	if (options->ip_qos_bulk == -1)
2597 		options->ip_qos_bulk = IPTOS_DSCP_CS1;
2598 	if (options->request_tty == -1)
2599 		options->request_tty = REQUEST_TTY_AUTO;
2600 	if (options->session_type == -1)
2601 		options->session_type = SESSION_TYPE_DEFAULT;
2602 	if (options->stdin_null == -1)
2603 		options->stdin_null = 0;
2604 	if (options->fork_after_authentication == -1)
2605 		options->fork_after_authentication = 0;
2606 	if (options->proxy_use_fdpass == -1)
2607 		options->proxy_use_fdpass = 0;
2608 	if (options->canonicalize_max_dots == -1)
2609 		options->canonicalize_max_dots = 1;
2610 	if (options->canonicalize_fallback_local == -1)
2611 		options->canonicalize_fallback_local = 1;
2612 	if (options->canonicalize_hostname == -1)
2613 		options->canonicalize_hostname = SSH_CANONICALISE_NO;
2614 	if (options->fingerprint_hash == -1)
2615 		options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
2616 	if (options->sk_provider == NULL)
2617 		options->sk_provider = xstrdup("internal");
2618 	if (options->required_rsa_size == -1)
2619 		options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
2620 	if (options->enable_escape_commandline == -1)
2621 		options->enable_escape_commandline = 0;
2622 
2623 	/* Expand KEX name lists */
2624 	all_cipher = cipher_alg_list(',', 0);
2625 	all_mac = mac_alg_list(',');
2626 	all_kex = kex_alg_list(',');
2627 	all_key = sshkey_alg_list(0, 0, 1, ',');
2628 	all_sig = sshkey_alg_list(0, 1, 1, ',');
2629 	/* remove unsupported algos from default lists */
2630 	def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher);
2631 	def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac);
2632 	def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex);
2633 	def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
2634 	def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig);
2635 #define ASSEMBLE(what, defaults, all) \
2636 	do { \
2637 		if ((r = kex_assemble_names(&options->what, \
2638 		    defaults, all)) != 0) { \
2639 			error_fr(r, "%s", #what); \
2640 			goto fail; \
2641 		} \
2642 	} while (0)
2643 	ASSEMBLE(ciphers, def_cipher, all_cipher);
2644 	ASSEMBLE(macs, def_mac, all_mac);
2645 	ASSEMBLE(kex_algorithms, def_kex, all_kex);
2646 	ASSEMBLE(hostbased_accepted_algos, def_key, all_key);
2647 	ASSEMBLE(pubkey_accepted_algos, def_key, all_key);
2648 	ASSEMBLE(ca_sign_algorithms, def_sig, all_sig);
2649 #undef ASSEMBLE
2650 
2651 #define CLEAR_ON_NONE(v) \
2652 	do { \
2653 		if (option_clear_or_none(v)) { \
2654 			free(v); \
2655 			v = NULL; \
2656 		} \
2657 	} while(0)
2658 	CLEAR_ON_NONE(options->local_command);
2659 	CLEAR_ON_NONE(options->remote_command);
2660 	CLEAR_ON_NONE(options->proxy_command);
2661 	CLEAR_ON_NONE(options->control_path);
2662 	CLEAR_ON_NONE(options->revoked_host_keys);
2663 	CLEAR_ON_NONE(options->pkcs11_provider);
2664 	CLEAR_ON_NONE(options->sk_provider);
2665 	CLEAR_ON_NONE(options->known_hosts_command);
2666 	if (options->jump_host != NULL &&
2667 	    strcmp(options->jump_host, "none") == 0 &&
2668 	    options->jump_port == 0 && options->jump_user == NULL) {
2669 		free(options->jump_host);
2670 		options->jump_host = NULL;
2671 	}
2672 	if (options->num_permitted_cnames == 1 &&
2673 	    !config_has_permitted_cnames(options)) {
2674 		/* clean up CanonicalizePermittedCNAMEs=none */
2675 		free(options->permitted_cnames[0].source_list);
2676 		free(options->permitted_cnames[0].target_list);
2677 		memset(options->permitted_cnames, '\0',
2678 		    sizeof(*options->permitted_cnames));
2679 		options->num_permitted_cnames = 0;
2680 	}
2681 	/* options->identity_agent distinguishes NULL from 'none' */
2682 	/* options->user will be set in the main program if appropriate */
2683 	/* options->hostname will be set in the main program if appropriate */
2684 	/* options->host_key_alias should not be set by default */
2685 	/* options->preferred_authentications will be set in ssh */
2686 
2687 	/* success */
2688 	ret = 0;
2689  fail:
2690 	free(all_cipher);
2691 	free(all_mac);
2692 	free(all_kex);
2693 	free(all_key);
2694 	free(all_sig);
2695 	free(def_cipher);
2696 	free(def_mac);
2697 	free(def_kex);
2698 	free(def_key);
2699 	free(def_sig);
2700 	return ret;
2701 }
2702 
2703 void
2704 free_options(Options *o)
2705 {
2706 	int i;
2707 
2708 	if (o == NULL)
2709 		return;
2710 
2711 #define FREE_ARRAY(type, n, a) \
2712 	do { \
2713 		type _i; \
2714 		for (_i = 0; _i < (n); _i++) \
2715 			free((a)[_i]); \
2716 	} while (0)
2717 
2718 	free(o->forward_agent_sock_path);
2719 	free(o->xauth_location);
2720 	FREE_ARRAY(u_int, o->num_log_verbose, o->log_verbose);
2721 	free(o->log_verbose);
2722 	free(o->ciphers);
2723 	free(o->macs);
2724 	free(o->hostkeyalgorithms);
2725 	free(o->kex_algorithms);
2726 	free(o->ca_sign_algorithms);
2727 	free(o->hostname);
2728 	free(o->host_key_alias);
2729 	free(o->proxy_command);
2730 	free(o->user);
2731 	FREE_ARRAY(u_int, o->num_system_hostfiles, o->system_hostfiles);
2732 	FREE_ARRAY(u_int, o->num_user_hostfiles, o->user_hostfiles);
2733 	free(o->preferred_authentications);
2734 	free(o->bind_address);
2735 	free(o->bind_interface);
2736 	free(o->pkcs11_provider);
2737 	free(o->sk_provider);
2738 	for (i = 0; i < o->num_identity_files; i++) {
2739 		free(o->identity_files[i]);
2740 		sshkey_free(o->identity_keys[i]);
2741 	}
2742 	for (i = 0; i < o->num_certificate_files; i++) {
2743 		free(o->certificate_files[i]);
2744 		sshkey_free(o->certificates[i]);
2745 	}
2746 	free(o->identity_agent);
2747 	for (i = 0; i < o->num_local_forwards; i++) {
2748 		free(o->local_forwards[i].listen_host);
2749 		free(o->local_forwards[i].listen_path);
2750 		free(o->local_forwards[i].connect_host);
2751 		free(o->local_forwards[i].connect_path);
2752 	}
2753 	free(o->local_forwards);
2754 	for (i = 0; i < o->num_remote_forwards; i++) {
2755 		free(o->remote_forwards[i].listen_host);
2756 		free(o->remote_forwards[i].listen_path);
2757 		free(o->remote_forwards[i].connect_host);
2758 		free(o->remote_forwards[i].connect_path);
2759 	}
2760 	free(o->remote_forwards);
2761 	free(o->stdio_forward_host);
2762 	FREE_ARRAY(u_int, o->num_send_env, o->send_env);
2763 	free(o->send_env);
2764 	FREE_ARRAY(u_int, o->num_setenv, o->setenv);
2765 	free(o->setenv);
2766 	free(o->control_path);
2767 	free(o->local_command);
2768 	free(o->remote_command);
2769 	FREE_ARRAY(int, o->num_canonical_domains, o->canonical_domains);
2770 	for (i = 0; i < o->num_permitted_cnames; i++) {
2771 		free(o->permitted_cnames[i].source_list);
2772 		free(o->permitted_cnames[i].target_list);
2773 	}
2774 	free(o->revoked_host_keys);
2775 	free(o->hostbased_accepted_algos);
2776 	free(o->pubkey_accepted_algos);
2777 	free(o->jump_user);
2778 	free(o->jump_host);
2779 	free(o->jump_extra);
2780 	free(o->ignored_unknown);
2781 	explicit_bzero(o, sizeof(*o));
2782 #undef FREE_ARRAY
2783 }
2784 
2785 struct fwdarg {
2786 	char *arg;
2787 	int ispath;
2788 };
2789 
2790 /*
2791  * parse_fwd_field
2792  * parses the next field in a port forwarding specification.
2793  * sets fwd to the parsed field and advances p past the colon
2794  * or sets it to NULL at end of string.
2795  * returns 0 on success, else non-zero.
2796  */
2797 static int
2798 parse_fwd_field(char **p, struct fwdarg *fwd)
2799 {
2800 	char *ep, *cp = *p;
2801 	int ispath = 0;
2802 
2803 	if (*cp == '\0') {
2804 		*p = NULL;
2805 		return -1;	/* end of string */
2806 	}
2807 
2808 	/*
2809 	 * A field escaped with square brackets is used literally.
2810 	 * XXX - allow ']' to be escaped via backslash?
2811 	 */
2812 	if (*cp == '[') {
2813 		/* find matching ']' */
2814 		for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
2815 			if (*ep == '/')
2816 				ispath = 1;
2817 		}
2818 		/* no matching ']' or not at end of field. */
2819 		if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
2820 			return -1;
2821 		/* NUL terminate the field and advance p past the colon */
2822 		*ep++ = '\0';
2823 		if (*ep != '\0')
2824 			*ep++ = '\0';
2825 		fwd->arg = cp + 1;
2826 		fwd->ispath = ispath;
2827 		*p = ep;
2828 		return 0;
2829 	}
2830 
2831 	for (cp = *p; *cp != '\0'; cp++) {
2832 		switch (*cp) {
2833 		case '\\':
2834 			memmove(cp, cp + 1, strlen(cp + 1) + 1);
2835 			if (*cp == '\0')
2836 				return -1;
2837 			break;
2838 		case '/':
2839 			ispath = 1;
2840 			break;
2841 		case ':':
2842 			*cp++ = '\0';
2843 			goto done;
2844 		}
2845 	}
2846 done:
2847 	fwd->arg = *p;
2848 	fwd->ispath = ispath;
2849 	*p = cp;
2850 	return 0;
2851 }
2852 
2853 /*
2854  * parse_forward
2855  * parses a string containing a port forwarding specification of the form:
2856  *   dynamicfwd == 0
2857  *	[listenhost:]listenport|listenpath:connecthost:connectport|connectpath
2858  *	listenpath:connectpath
2859  *   dynamicfwd == 1
2860  *	[listenhost:]listenport
2861  * returns number of arguments parsed or zero on error
2862  */
2863 int
2864 parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
2865 {
2866 	struct fwdarg fwdargs[4];
2867 	char *p, *cp;
2868 	int i, err;
2869 
2870 	memset(fwd, 0, sizeof(*fwd));
2871 	memset(fwdargs, 0, sizeof(fwdargs));
2872 
2873 	/*
2874 	 * We expand environment variables before checking if we think they're
2875 	 * paths so that if ${VAR} expands to a fully qualified path it is
2876 	 * treated as a path.
2877 	 */
2878 	cp = p = dollar_expand(&err, fwdspec);
2879 	if (p == NULL || err)
2880 		return 0;
2881 
2882 	/* skip leading spaces */
2883 	while (isspace((u_char)*cp))
2884 		cp++;
2885 
2886 	for (i = 0; i < 4; ++i) {
2887 		if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
2888 			break;
2889 	}
2890 
2891 	/* Check for trailing garbage */
2892 	if (cp != NULL && *cp != '\0') {
2893 		i = 0;	/* failure */
2894 	}
2895 
2896 	switch (i) {
2897 	case 1:
2898 		if (fwdargs[0].ispath) {
2899 			fwd->listen_path = xstrdup(fwdargs[0].arg);
2900 			fwd->listen_port = PORT_STREAMLOCAL;
2901 		} else {
2902 			fwd->listen_host = NULL;
2903 			fwd->listen_port = a2port(fwdargs[0].arg);
2904 		}
2905 		fwd->connect_host = xstrdup("socks");
2906 		break;
2907 
2908 	case 2:
2909 		if (fwdargs[0].ispath && fwdargs[1].ispath) {
2910 			fwd->listen_path = xstrdup(fwdargs[0].arg);
2911 			fwd->listen_port = PORT_STREAMLOCAL;
2912 			fwd->connect_path = xstrdup(fwdargs[1].arg);
2913 			fwd->connect_port = PORT_STREAMLOCAL;
2914 		} else if (fwdargs[1].ispath) {
2915 			fwd->listen_host = NULL;
2916 			fwd->listen_port = a2port(fwdargs[0].arg);
2917 			fwd->connect_path = xstrdup(fwdargs[1].arg);
2918 			fwd->connect_port = PORT_STREAMLOCAL;
2919 		} else {
2920 			fwd->listen_host = xstrdup(fwdargs[0].arg);
2921 			fwd->listen_port = a2port(fwdargs[1].arg);
2922 			fwd->connect_host = xstrdup("socks");
2923 		}
2924 		break;
2925 
2926 	case 3:
2927 		if (fwdargs[0].ispath) {
2928 			fwd->listen_path = xstrdup(fwdargs[0].arg);
2929 			fwd->listen_port = PORT_STREAMLOCAL;
2930 			fwd->connect_host = xstrdup(fwdargs[1].arg);
2931 			fwd->connect_port = a2port(fwdargs[2].arg);
2932 		} else if (fwdargs[2].ispath) {
2933 			fwd->listen_host = xstrdup(fwdargs[0].arg);
2934 			fwd->listen_port = a2port(fwdargs[1].arg);
2935 			fwd->connect_path = xstrdup(fwdargs[2].arg);
2936 			fwd->connect_port = PORT_STREAMLOCAL;
2937 		} else {
2938 			fwd->listen_host = NULL;
2939 			fwd->listen_port = a2port(fwdargs[0].arg);
2940 			fwd->connect_host = xstrdup(fwdargs[1].arg);
2941 			fwd->connect_port = a2port(fwdargs[2].arg);
2942 		}
2943 		break;
2944 
2945 	case 4:
2946 		fwd->listen_host = xstrdup(fwdargs[0].arg);
2947 		fwd->listen_port = a2port(fwdargs[1].arg);
2948 		fwd->connect_host = xstrdup(fwdargs[2].arg);
2949 		fwd->connect_port = a2port(fwdargs[3].arg);
2950 		break;
2951 	default:
2952 		i = 0; /* failure */
2953 	}
2954 
2955 	free(p);
2956 
2957 	if (dynamicfwd) {
2958 		if (!(i == 1 || i == 2))
2959 			goto fail_free;
2960 	} else {
2961 		if (!(i == 3 || i == 4)) {
2962 			if (fwd->connect_path == NULL &&
2963 			    fwd->listen_path == NULL)
2964 				goto fail_free;
2965 		}
2966 		if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
2967 			goto fail_free;
2968 	}
2969 
2970 	if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
2971 	    (!remotefwd && fwd->listen_port == 0))
2972 		goto fail_free;
2973 	if (fwd->connect_host != NULL &&
2974 	    strlen(fwd->connect_host) >= NI_MAXHOST)
2975 		goto fail_free;
2976 	/*
2977 	 * XXX - if connecting to a remote socket, max sun len may not
2978 	 * match this host
2979 	 */
2980 	if (fwd->connect_path != NULL &&
2981 	    strlen(fwd->connect_path) >= PATH_MAX_SUN)
2982 		goto fail_free;
2983 	if (fwd->listen_host != NULL &&
2984 	    strlen(fwd->listen_host) >= NI_MAXHOST)
2985 		goto fail_free;
2986 	if (fwd->listen_path != NULL &&
2987 	    strlen(fwd->listen_path) >= PATH_MAX_SUN)
2988 		goto fail_free;
2989 
2990 	return (i);
2991 
2992  fail_free:
2993 	free(fwd->connect_host);
2994 	fwd->connect_host = NULL;
2995 	free(fwd->connect_path);
2996 	fwd->connect_path = NULL;
2997 	free(fwd->listen_host);
2998 	fwd->listen_host = NULL;
2999 	free(fwd->listen_path);
3000 	fwd->listen_path = NULL;
3001 	return (0);
3002 }
3003 
3004 int
3005 parse_jump(const char *s, Options *o, int active)
3006 {
3007 	char *orig, *sdup, *cp;
3008 	char *host = NULL, *user = NULL;
3009 	int r, ret = -1, port = -1, first;
3010 
3011 	active &= o->proxy_command == NULL && o->jump_host == NULL;
3012 
3013 	orig = sdup = xstrdup(s);
3014 
3015 	/* Remove comment and trailing whitespace */
3016 	if ((cp = strchr(orig, '#')) != NULL)
3017 		*cp = '\0';
3018 	rtrim(orig);
3019 
3020 	first = active;
3021 	do {
3022 		if (strcasecmp(s, "none") == 0)
3023 			break;
3024 		if ((cp = strrchr(sdup, ',')) == NULL)
3025 			cp = sdup; /* last */
3026 		else
3027 			*cp++ = '\0';
3028 
3029 		if (first) {
3030 			/* First argument and configuration is active */
3031 			r = parse_ssh_uri(cp, &user, &host, &port);
3032 			if (r == -1 || (r == 1 &&
3033 			    parse_user_host_port(cp, &user, &host, &port) != 0))
3034 				goto out;
3035 		} else {
3036 			/* Subsequent argument or inactive configuration */
3037 			r = parse_ssh_uri(cp, NULL, NULL, NULL);
3038 			if (r == -1 || (r == 1 &&
3039 			    parse_user_host_port(cp, NULL, NULL, NULL) != 0))
3040 				goto out;
3041 		}
3042 		first = 0; /* only check syntax for subsequent hosts */
3043 	} while (cp != sdup);
3044 	/* success */
3045 	if (active) {
3046 		if (strcasecmp(s, "none") == 0) {
3047 			o->jump_host = xstrdup("none");
3048 			o->jump_port = 0;
3049 		} else {
3050 			o->jump_user = user;
3051 			o->jump_host = host;
3052 			o->jump_port = port;
3053 			o->proxy_command = xstrdup("none");
3054 			user = host = NULL;
3055 			if ((cp = strrchr(s, ',')) != NULL && cp != s) {
3056 				o->jump_extra = xstrdup(s);
3057 				o->jump_extra[cp - s] = '\0';
3058 			}
3059 		}
3060 	}
3061 	ret = 0;
3062  out:
3063 	free(orig);
3064 	free(user);
3065 	free(host);
3066 	return ret;
3067 }
3068 
3069 int
3070 parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp)
3071 {
3072 	char *user = NULL, *host = NULL, *path = NULL;
3073 	int r, port;
3074 
3075 	r = parse_uri("ssh", uri, &user, &host, &port, &path);
3076 	if (r == 0 && path != NULL)
3077 		r = -1;		/* path not allowed */
3078 	if (r == 0) {
3079 		if (userp != NULL) {
3080 			*userp = user;
3081 			user = NULL;
3082 		}
3083 		if (hostp != NULL) {
3084 			*hostp = host;
3085 			host = NULL;
3086 		}
3087 		if (portp != NULL)
3088 			*portp = port;
3089 	}
3090 	free(user);
3091 	free(host);
3092 	free(path);
3093 	return r;
3094 }
3095 
3096 /* XXX the following is a near-vebatim copy from servconf.c; refactor */
3097 static const char *
3098 fmt_multistate_int(int val, const struct multistate *m)
3099 {
3100 	u_int i;
3101 
3102 	for (i = 0; m[i].key != NULL; i++) {
3103 		if (m[i].value == val)
3104 			return m[i].key;
3105 	}
3106 	return "UNKNOWN";
3107 }
3108 
3109 static const char *
3110 fmt_intarg(OpCodes code, int val)
3111 {
3112 	if (val == -1)
3113 		return "unset";
3114 	switch (code) {
3115 	case oAddressFamily:
3116 		return fmt_multistate_int(val, multistate_addressfamily);
3117 	case oVerifyHostKeyDNS:
3118 	case oUpdateHostkeys:
3119 		return fmt_multistate_int(val, multistate_yesnoask);
3120 	case oStrictHostKeyChecking:
3121 		return fmt_multistate_int(val, multistate_strict_hostkey);
3122 	case oControlMaster:
3123 		return fmt_multistate_int(val, multistate_controlmaster);
3124 	case oTunnel:
3125 		return fmt_multistate_int(val, multistate_tunnel);
3126 	case oRequestTTY:
3127 		return fmt_multistate_int(val, multistate_requesttty);
3128 	case oSessionType:
3129 		return fmt_multistate_int(val, multistate_sessiontype);
3130 	case oCanonicalizeHostname:
3131 		return fmt_multistate_int(val, multistate_canonicalizehostname);
3132 	case oAddKeysToAgent:
3133 		return fmt_multistate_int(val, multistate_yesnoaskconfirm);
3134 	case oPubkeyAuthentication:
3135 		return fmt_multistate_int(val, multistate_pubkey_auth);
3136 	case oFingerprintHash:
3137 		return ssh_digest_alg_name(val);
3138 	default:
3139 		switch (val) {
3140 		case 0:
3141 			return "no";
3142 		case 1:
3143 			return "yes";
3144 		default:
3145 			return "UNKNOWN";
3146 		}
3147 	}
3148 }
3149 
3150 static const char *
3151 lookup_opcode_name(OpCodes code)
3152 {
3153 	u_int i;
3154 
3155 	for (i = 0; keywords[i].name != NULL; i++)
3156 		if (keywords[i].opcode == code)
3157 			return(keywords[i].name);
3158 	return "UNKNOWN";
3159 }
3160 
3161 static void
3162 dump_cfg_int(OpCodes code, int val)
3163 {
3164 	printf("%s %d\n", lookup_opcode_name(code), val);
3165 }
3166 
3167 static void
3168 dump_cfg_fmtint(OpCodes code, int val)
3169 {
3170 	printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
3171 }
3172 
3173 static void
3174 dump_cfg_string(OpCodes code, const char *val)
3175 {
3176 	if (val == NULL)
3177 		return;
3178 	printf("%s %s\n", lookup_opcode_name(code), val);
3179 }
3180 
3181 static void
3182 dump_cfg_strarray(OpCodes code, u_int count, char **vals)
3183 {
3184 	u_int i;
3185 
3186 	for (i = 0; i < count; i++)
3187 		printf("%s %s\n", lookup_opcode_name(code), vals[i]);
3188 }
3189 
3190 static void
3191 dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals)
3192 {
3193 	u_int i;
3194 
3195 	printf("%s", lookup_opcode_name(code));
3196 	if (count == 0)
3197 		printf(" none");
3198 	for (i = 0; i < count; i++)
3199 		printf(" %s",  vals[i]);
3200 	printf("\n");
3201 }
3202 
3203 static void
3204 dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds)
3205 {
3206 	const struct Forward *fwd;
3207 	u_int i;
3208 
3209 	/* oDynamicForward */
3210 	for (i = 0; i < count; i++) {
3211 		fwd = &fwds[i];
3212 		if (code == oDynamicForward && fwd->connect_host != NULL &&
3213 		    strcmp(fwd->connect_host, "socks") != 0)
3214 			continue;
3215 		if (code == oLocalForward && fwd->connect_host != NULL &&
3216 		    strcmp(fwd->connect_host, "socks") == 0)
3217 			continue;
3218 		printf("%s", lookup_opcode_name(code));
3219 		if (fwd->listen_port == PORT_STREAMLOCAL)
3220 			printf(" %s", fwd->listen_path);
3221 		else if (fwd->listen_host == NULL)
3222 			printf(" %d", fwd->listen_port);
3223 		else {
3224 			printf(" [%s]:%d",
3225 			    fwd->listen_host, fwd->listen_port);
3226 		}
3227 		if (code != oDynamicForward) {
3228 			if (fwd->connect_port == PORT_STREAMLOCAL)
3229 				printf(" %s", fwd->connect_path);
3230 			else if (fwd->connect_host == NULL)
3231 				printf(" %d", fwd->connect_port);
3232 			else {
3233 				printf(" [%s]:%d",
3234 				    fwd->connect_host, fwd->connect_port);
3235 			}
3236 		}
3237 		printf("\n");
3238 	}
3239 }
3240 
3241 void
3242 dump_client_config(Options *o, const char *host)
3243 {
3244 	int i, r;
3245 	char buf[8], *all_key;
3246 
3247 	/*
3248 	 * Expand HostKeyAlgorithms name lists. This isn't handled in
3249 	 * fill_default_options() like the other algorithm lists because
3250 	 * the host key algorithms are by default dynamically chosen based
3251 	 * on the host's keys found in known_hosts.
3252 	 */
3253 	all_key = sshkey_alg_list(0, 0, 1, ',');
3254 	if ((r = kex_assemble_names(&o->hostkeyalgorithms, kex_default_pk_alg(),
3255 	    all_key)) != 0)
3256 		fatal_fr(r, "expand HostKeyAlgorithms");
3257 	free(all_key);
3258 
3259 	/* Most interesting options first: user, host, port */
3260 	dump_cfg_string(oUser, o->user);
3261 	dump_cfg_string(oHostname, host);
3262 	dump_cfg_int(oPort, o->port);
3263 
3264 	/* Flag options */
3265 	dump_cfg_fmtint(oAddressFamily, o->address_family);
3266 	dump_cfg_fmtint(oBatchMode, o->batch_mode);
3267 	dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local);
3268 	dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname);
3269 	dump_cfg_fmtint(oCheckHostIP, o->check_host_ip);
3270 	dump_cfg_fmtint(oCompression, o->compression);
3271 	dump_cfg_fmtint(oControlMaster, o->control_master);
3272 	dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
3273 	dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings);
3274 	dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
3275 	dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash);
3276 	dump_cfg_fmtint(oForwardX11, o->forward_x11);
3277 	dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted);
3278 	dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports);
3279 #ifdef GSSAPI
3280 	dump_cfg_fmtint(oGssAuthentication, o->gss_authentication);
3281 	dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds);
3282 #endif /* GSSAPI */
3283 	dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);
3284 	dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);
3285 	dump_cfg_fmtint(oIdentitiesOnly, o->identities_only);
3286 	dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication);
3287 	dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost);
3288 	dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication);
3289 	dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command);
3290 	dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass);
3291 	dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
3292 	dump_cfg_fmtint(oRequestTTY, o->request_tty);
3293 	dump_cfg_fmtint(oSessionType, o->session_type);
3294 	dump_cfg_fmtint(oStdinNull, o->stdin_null);
3295 	dump_cfg_fmtint(oForkAfterAuthentication, o->fork_after_authentication);
3296 	dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
3297 	dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
3298 	dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
3299 	dump_cfg_fmtint(oTunnel, o->tun_open);
3300 	dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns);
3301 	dump_cfg_fmtint(oVisualHostKey, o->visual_host_key);
3302 	dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys);
3303 	dump_cfg_fmtint(oEnableEscapeCommandline, o->enable_escape_commandline);
3304 
3305 	/* Integer options */
3306 	dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots);
3307 	dump_cfg_int(oConnectionAttempts, o->connection_attempts);
3308 	dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout);
3309 	dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
3310 	dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
3311 	dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
3312 	dump_cfg_int(oRequiredRSASize, o->required_rsa_size);
3313 
3314 	/* String options */
3315 	dump_cfg_string(oBindAddress, o->bind_address);
3316 	dump_cfg_string(oBindInterface, o->bind_interface);
3317 	dump_cfg_string(oCiphers, o->ciphers);
3318 	dump_cfg_string(oControlPath, o->control_path);
3319 	dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms);
3320 	dump_cfg_string(oHostKeyAlias, o->host_key_alias);
3321 	dump_cfg_string(oHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos);
3322 	dump_cfg_string(oIdentityAgent, o->identity_agent);
3323 	dump_cfg_string(oIgnoreUnknown, o->ignored_unknown);
3324 	dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
3325 	dump_cfg_string(oKexAlgorithms, o->kex_algorithms);
3326 	dump_cfg_string(oCASignatureAlgorithms, o->ca_sign_algorithms);
3327 	dump_cfg_string(oLocalCommand, o->local_command);
3328 	dump_cfg_string(oRemoteCommand, o->remote_command);
3329 	dump_cfg_string(oLogLevel, log_level_name(o->log_level));
3330 	dump_cfg_string(oMacs, o->macs);
3331 #ifdef ENABLE_PKCS11
3332 	dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
3333 #endif
3334 	dump_cfg_string(oSecurityKeyProvider, o->sk_provider);
3335 	dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
3336 	dump_cfg_string(oPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos);
3337 	dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
3338 	dump_cfg_string(oXAuthLocation, o->xauth_location);
3339 	dump_cfg_string(oKnownHostsCommand, o->known_hosts_command);
3340 
3341 	/* Forwards */
3342 	dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
3343 	dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards);
3344 	dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards);
3345 
3346 	/* String array options */
3347 	dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files);
3348 	dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains);
3349 	dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files);
3350 	dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles);
3351 	dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles);
3352 	dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env);
3353 	dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv);
3354 	dump_cfg_strarray_oneline(oLogVerbose,
3355 	    o->num_log_verbose, o->log_verbose);
3356 
3357 	/* Special cases */
3358 
3359 	/* PermitRemoteOpen */
3360 	if (o->num_permitted_remote_opens == 0)
3361 		printf("%s any\n", lookup_opcode_name(oPermitRemoteOpen));
3362 	else
3363 		dump_cfg_strarray_oneline(oPermitRemoteOpen,
3364 		    o->num_permitted_remote_opens, o->permitted_remote_opens);
3365 
3366 	/* AddKeysToAgent */
3367 	if (o->add_keys_to_agent_lifespan <= 0)
3368 		dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent);
3369 	else {
3370 		printf("addkeystoagent%s %d\n",
3371 		    o->add_keys_to_agent == 3 ? " confirm" : "",
3372 		    o->add_keys_to_agent_lifespan);
3373 	}
3374 
3375 	/* oForwardAgent */
3376 	if (o->forward_agent_sock_path == NULL)
3377 		dump_cfg_fmtint(oForwardAgent, o->forward_agent);
3378 	else
3379 		dump_cfg_string(oForwardAgent, o->forward_agent_sock_path);
3380 
3381 	/* oConnectTimeout */
3382 	if (o->connection_timeout == -1)
3383 		printf("connecttimeout none\n");
3384 	else
3385 		dump_cfg_int(oConnectTimeout, o->connection_timeout);
3386 
3387 	/* oTunnelDevice */
3388 	printf("tunneldevice");
3389 	if (o->tun_local == SSH_TUNID_ANY)
3390 		printf(" any");
3391 	else
3392 		printf(" %d", o->tun_local);
3393 	if (o->tun_remote == SSH_TUNID_ANY)
3394 		printf(":any");
3395 	else
3396 		printf(":%d", o->tun_remote);
3397 	printf("\n");
3398 
3399 	/* oCanonicalizePermittedCNAMEs */
3400 	printf("canonicalizePermittedcnames");
3401 	if (o->num_permitted_cnames == 0)
3402 		printf(" none");
3403 	for (i = 0; i < o->num_permitted_cnames; i++) {
3404 		printf(" %s:%s", o->permitted_cnames[i].source_list,
3405 		    o->permitted_cnames[i].target_list);
3406 	}
3407 	printf("\n");
3408 
3409 	/* oControlPersist */
3410 	if (o->control_persist == 0 || o->control_persist_timeout == 0)
3411 		dump_cfg_fmtint(oControlPersist, o->control_persist);
3412 	else
3413 		dump_cfg_int(oControlPersist, o->control_persist_timeout);
3414 
3415 	/* oEscapeChar */
3416 	if (o->escape_char == SSH_ESCAPECHAR_NONE)
3417 		printf("escapechar none\n");
3418 	else {
3419 		vis(buf, o->escape_char, VIS_WHITE, 0);
3420 		printf("escapechar %s\n", buf);
3421 	}
3422 
3423 	/* oIPQoS */
3424 	printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
3425 	printf("%s\n", iptos2str(o->ip_qos_bulk));
3426 
3427 	/* oRekeyLimit */
3428 	printf("rekeylimit %llu %d\n",
3429 	    (unsigned long long)o->rekey_limit, o->rekey_interval);
3430 
3431 	/* oStreamLocalBindMask */
3432 	printf("streamlocalbindmask 0%o\n",
3433 	    o->fwd_opts.streamlocal_bind_mask);
3434 
3435 	/* oLogFacility */
3436 	printf("syslogfacility %s\n", log_facility_name(o->log_facility));
3437 
3438 	/* oProxyCommand / oProxyJump */
3439 	if (o->jump_host == NULL)
3440 		dump_cfg_string(oProxyCommand, o->proxy_command);
3441 	else {
3442 		/* Check for numeric addresses */
3443 		i = strchr(o->jump_host, ':') != NULL ||
3444 		    strspn(o->jump_host, "1234567890.") == strlen(o->jump_host);
3445 		snprintf(buf, sizeof(buf), "%d", o->jump_port);
3446 		printf("proxyjump %s%s%s%s%s%s%s%s%s\n",
3447 		    /* optional additional jump spec */
3448 		    o->jump_extra == NULL ? "" : o->jump_extra,
3449 		    o->jump_extra == NULL ? "" : ",",
3450 		    /* optional user */
3451 		    o->jump_user == NULL ? "" : o->jump_user,
3452 		    o->jump_user == NULL ? "" : "@",
3453 		    /* opening [ if hostname is numeric */
3454 		    i ? "[" : "",
3455 		    /* mandatory hostname */
3456 		    o->jump_host,
3457 		    /* closing ] if hostname is numeric */
3458 		    i ? "]" : "",
3459 		    /* optional port number */
3460 		    o->jump_port <= 0 ? "" : ":",
3461 		    o->jump_port <= 0 ? "" : buf);
3462 	}
3463 }
3464