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