xref: /openbsd-src/usr.bin/ssh/readconf.c (revision c1a45aed656e7d5627c30c92421893a76f370ccb)
1 /* $OpenBSD: readconf.c,v 1.367 2022/04/20 15:56:49 millert 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 
744 	/* Remove an environment variable */
745 	for (i = 0; i < options->num_send_env; ) {
746 		if (!match_pattern(options->send_env[i], arg + 1)) {
747 			i++;
748 			continue;
749 		}
750 		debug3("%s line %d: removing environment %s",
751 		    filename, linenum, options->send_env[i]);
752 		free(options->send_env[i]);
753 		options->send_env[i] = NULL;
754 		for (j = i; j < options->num_send_env - 1; j++) {
755 			options->send_env[j] = options->send_env[j + 1];
756 			options->send_env[j + 1] = NULL;
757 		}
758 		options->num_send_env--;
759 		/* NB. don't increment i */
760 	}
761 	if (onum_send_env != options->num_send_env) {
762 		options->send_env = xrecallocarray(options->send_env,
763 		    onum_send_env, options->num_send_env,
764 		    sizeof(*options->send_env));
765 	}
766 }
767 
768 /*
769  * Returns the number of the token pointed to by cp or oBadOption.
770  */
771 static OpCodes
772 parse_token(const char *cp, const char *filename, int linenum,
773     const char *ignored_unknown)
774 {
775 	int i;
776 
777 	for (i = 0; keywords[i].name; i++)
778 		if (strcmp(cp, keywords[i].name) == 0)
779 			return keywords[i].opcode;
780 	if (ignored_unknown != NULL &&
781 	    match_pattern_list(cp, ignored_unknown, 1) == 1)
782 		return oIgnoredUnknownOption;
783 	error("%s: line %d: Bad configuration option: %s",
784 	    filename, linenum, cp);
785 	return oBadOption;
786 }
787 
788 /* Multistate option parsing */
789 struct multistate {
790 	char *key;
791 	int value;
792 };
793 static const struct multistate multistate_flag[] = {
794 	{ "true",			1 },
795 	{ "false",			0 },
796 	{ "yes",			1 },
797 	{ "no",				0 },
798 	{ NULL, -1 }
799 };
800 static const struct multistate multistate_yesnoask[] = {
801 	{ "true",			1 },
802 	{ "false",			0 },
803 	{ "yes",			1 },
804 	{ "no",				0 },
805 	{ "ask",			2 },
806 	{ NULL, -1 }
807 };
808 static const struct multistate multistate_strict_hostkey[] = {
809 	{ "true",			SSH_STRICT_HOSTKEY_YES },
810 	{ "false",			SSH_STRICT_HOSTKEY_OFF },
811 	{ "yes",			SSH_STRICT_HOSTKEY_YES },
812 	{ "no",				SSH_STRICT_HOSTKEY_OFF },
813 	{ "ask",			SSH_STRICT_HOSTKEY_ASK },
814 	{ "off",			SSH_STRICT_HOSTKEY_OFF },
815 	{ "accept-new",			SSH_STRICT_HOSTKEY_NEW },
816 	{ NULL, -1 }
817 };
818 static const struct multistate multistate_yesnoaskconfirm[] = {
819 	{ "true",			1 },
820 	{ "false",			0 },
821 	{ "yes",			1 },
822 	{ "no",				0 },
823 	{ "ask",			2 },
824 	{ "confirm",			3 },
825 	{ NULL, -1 }
826 };
827 static const struct multistate multistate_addressfamily[] = {
828 	{ "inet",			AF_INET },
829 	{ "inet6",			AF_INET6 },
830 	{ "any",			AF_UNSPEC },
831 	{ NULL, -1 }
832 };
833 static const struct multistate multistate_controlmaster[] = {
834 	{ "true",			SSHCTL_MASTER_YES },
835 	{ "yes",			SSHCTL_MASTER_YES },
836 	{ "false",			SSHCTL_MASTER_NO },
837 	{ "no",				SSHCTL_MASTER_NO },
838 	{ "auto",			SSHCTL_MASTER_AUTO },
839 	{ "ask",			SSHCTL_MASTER_ASK },
840 	{ "autoask",			SSHCTL_MASTER_AUTO_ASK },
841 	{ NULL, -1 }
842 };
843 static const struct multistate multistate_tunnel[] = {
844 	{ "ethernet",			SSH_TUNMODE_ETHERNET },
845 	{ "point-to-point",		SSH_TUNMODE_POINTOPOINT },
846 	{ "true",			SSH_TUNMODE_DEFAULT },
847 	{ "yes",			SSH_TUNMODE_DEFAULT },
848 	{ "false",			SSH_TUNMODE_NO },
849 	{ "no",				SSH_TUNMODE_NO },
850 	{ NULL, -1 }
851 };
852 static const struct multistate multistate_requesttty[] = {
853 	{ "true",			REQUEST_TTY_YES },
854 	{ "yes",			REQUEST_TTY_YES },
855 	{ "false",			REQUEST_TTY_NO },
856 	{ "no",				REQUEST_TTY_NO },
857 	{ "force",			REQUEST_TTY_FORCE },
858 	{ "auto",			REQUEST_TTY_AUTO },
859 	{ NULL, -1 }
860 };
861 static const struct multistate multistate_sessiontype[] = {
862 	{ "none",			SESSION_TYPE_NONE },
863 	{ "subsystem",			SESSION_TYPE_SUBSYSTEM },
864 	{ "default",			SESSION_TYPE_DEFAULT },
865 	{ NULL, -1 }
866 };
867 static const struct multistate multistate_canonicalizehostname[] = {
868 	{ "true",			SSH_CANONICALISE_YES },
869 	{ "false",			SSH_CANONICALISE_NO },
870 	{ "yes",			SSH_CANONICALISE_YES },
871 	{ "no",				SSH_CANONICALISE_NO },
872 	{ "always",			SSH_CANONICALISE_ALWAYS },
873 	{ NULL, -1 }
874 };
875 static const struct multistate multistate_pubkey_auth[] = {
876 	{ "true",			SSH_PUBKEY_AUTH_ALL },
877 	{ "false",			SSH_PUBKEY_AUTH_NO },
878 	{ "yes",			SSH_PUBKEY_AUTH_ALL },
879 	{ "no",				SSH_PUBKEY_AUTH_NO },
880 	{ "unbound",			SSH_PUBKEY_AUTH_UNBOUND },
881 	{ "host-bound",			SSH_PUBKEY_AUTH_HBOUND },
882 	{ NULL, -1 }
883 };
884 static const struct multistate multistate_compression[] = {
885 #ifdef WITH_ZLIB
886 	{ "yes",			COMP_ZLIB },
887 #endif
888 	{ "no",				COMP_NONE },
889 	{ NULL, -1 }
890 };
891 
892 static int
893 parse_multistate_value(const char *arg, const char *filename, int linenum,
894     const struct multistate *multistate_ptr)
895 {
896 	int i;
897 
898 	if (!arg || *arg == '\0') {
899 		error("%s line %d: missing argument.", filename, linenum);
900 		return -1;
901 	}
902 	for (i = 0; multistate_ptr[i].key != NULL; i++) {
903 		if (strcasecmp(arg, multistate_ptr[i].key) == 0)
904 			return multistate_ptr[i].value;
905 	}
906 	return -1;
907 }
908 
909 /*
910  * Processes a single option line as used in the configuration files. This
911  * only sets those values that have not already been set.
912  */
913 int
914 process_config_line(Options *options, struct passwd *pw, const char *host,
915     const char *original_host, char *line, const char *filename,
916     int linenum, int *activep, int flags)
917 {
918 	return process_config_line_depth(options, pw, host, original_host,
919 	    line, filename, linenum, activep, flags, NULL, 0);
920 }
921 
922 #define WHITESPACE " \t\r\n"
923 static int
924 process_config_line_depth(Options *options, struct passwd *pw, const char *host,
925     const char *original_host, char *line, const char *filename,
926     int linenum, int *activep, int flags, int *want_final_pass, int depth)
927 {
928 	char *str, **charptr, *endofnumber, *keyword, *arg, *arg2, *p;
929 	char **cpptr, ***cppptr, fwdarg[256];
930 	u_int i, *uintptr, uvalue, max_entries = 0;
931 	int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0;
932 	int remotefwd, dynamicfwd;
933 	LogLevel *log_level_ptr;
934 	SyslogFacility *log_facility_ptr;
935 	long long val64;
936 	size_t len;
937 	struct Forward fwd;
938 	const struct multistate *multistate_ptr;
939 	struct allowed_cname *cname;
940 	glob_t gl;
941 	const char *errstr;
942 	char **oav = NULL, **av;
943 	int oac = 0, ac;
944 	int ret = -1;
945 
946 	if (activep == NULL) { /* We are processing a command line directive */
947 		cmdline = 1;
948 		activep = &cmdline;
949 	}
950 
951 	/* Strip trailing whitespace. Allow \f (form feed) at EOL only */
952 	if ((len = strlen(line)) == 0)
953 		return 0;
954 	for (len--; len > 0; len--) {
955 		if (strchr(WHITESPACE "\f", line[len]) == NULL)
956 			break;
957 		line[len] = '\0';
958 	}
959 
960 	str = line;
961 	/* Get the keyword. (Each line is supposed to begin with a keyword). */
962 	if ((keyword = strdelim(&str)) == NULL)
963 		return 0;
964 	/* Ignore leading whitespace. */
965 	if (*keyword == '\0')
966 		keyword = strdelim(&str);
967 	if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
968 		return 0;
969 	/* Match lowercase keyword */
970 	lowercase(keyword);
971 
972 	/* Prepare to parse remainder of line */
973 	if (str != NULL)
974 		str += strspn(str, WHITESPACE);
975 	if (str == NULL || *str == '\0') {
976 		error("%s line %d: no argument after keyword \"%s\"",
977 		    filename, linenum, keyword);
978 		return -1;
979 	}
980 	opcode = parse_token(keyword, filename, linenum,
981 	    options->ignored_unknown);
982 	if (argv_split(str, &oac, &oav, 1) != 0) {
983 		error("%s line %d: invalid quotes", filename, linenum);
984 		return -1;
985 	}
986 	ac = oac;
987 	av = oav;
988 
989 	switch (opcode) {
990 	case oBadOption:
991 		/* don't panic, but count bad options */
992 		goto out;
993 	case oIgnore:
994 		argv_consume(&ac);
995 		break;
996 	case oIgnoredUnknownOption:
997 		debug("%s line %d: Ignored unknown option \"%s\"",
998 		    filename, linenum, keyword);
999 		argv_consume(&ac);
1000 		break;
1001 	case oConnectTimeout:
1002 		intptr = &options->connection_timeout;
1003 parse_time:
1004 		arg = argv_next(&ac, &av);
1005 		if (!arg || *arg == '\0') {
1006 			error("%s line %d: missing time value.",
1007 			    filename, linenum);
1008 			goto out;
1009 		}
1010 		if (strcmp(arg, "none") == 0)
1011 			value = -1;
1012 		else if ((value = convtime(arg)) == -1) {
1013 			error("%s line %d: invalid time value.",
1014 			    filename, linenum);
1015 			goto out;
1016 		}
1017 		if (*activep && *intptr == -1)
1018 			*intptr = value;
1019 		break;
1020 
1021 	case oForwardAgent:
1022 		intptr = &options->forward_agent;
1023 
1024 		arg = argv_next(&ac, &av);
1025 		if (!arg || *arg == '\0') {
1026 			error("%s line %d: missing argument.",
1027 			    filename, linenum);
1028 			goto out;
1029 		}
1030 
1031 		value = -1;
1032 		multistate_ptr = multistate_flag;
1033 		for (i = 0; multistate_ptr[i].key != NULL; i++) {
1034 			if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
1035 				value = multistate_ptr[i].value;
1036 				break;
1037 			}
1038 		}
1039 		if (value != -1) {
1040 			if (*activep && *intptr == -1)
1041 				*intptr = value;
1042 			break;
1043 		}
1044 		/* ForwardAgent wasn't 'yes' or 'no', assume a path */
1045 		if (*activep && *intptr == -1)
1046 			*intptr = 1;
1047 
1048 		charptr = &options->forward_agent_sock_path;
1049 		goto parse_agent_path;
1050 
1051 	case oForwardX11:
1052 		intptr = &options->forward_x11;
1053  parse_flag:
1054 		multistate_ptr = multistate_flag;
1055  parse_multistate:
1056 		arg = argv_next(&ac, &av);
1057 		if ((value = parse_multistate_value(arg, filename, linenum,
1058 		    multistate_ptr)) == -1) {
1059 			error("%s line %d: unsupported option \"%s\".",
1060 			    filename, linenum, arg);
1061 			goto out;
1062 		}
1063 		if (*activep && *intptr == -1)
1064 			*intptr = value;
1065 		break;
1066 
1067 	case oForwardX11Trusted:
1068 		intptr = &options->forward_x11_trusted;
1069 		goto parse_flag;
1070 
1071 	case oForwardX11Timeout:
1072 		intptr = &options->forward_x11_timeout;
1073 		goto parse_time;
1074 
1075 	case oGatewayPorts:
1076 		intptr = &options->fwd_opts.gateway_ports;
1077 		goto parse_flag;
1078 
1079 	case oExitOnForwardFailure:
1080 		intptr = &options->exit_on_forward_failure;
1081 		goto parse_flag;
1082 
1083 	case oPasswordAuthentication:
1084 		intptr = &options->password_authentication;
1085 		goto parse_flag;
1086 
1087 	case oKbdInteractiveAuthentication:
1088 		intptr = &options->kbd_interactive_authentication;
1089 		goto parse_flag;
1090 
1091 	case oKbdInteractiveDevices:
1092 		charptr = &options->kbd_interactive_devices;
1093 		goto parse_string;
1094 
1095 	case oPubkeyAuthentication:
1096 		multistate_ptr = multistate_pubkey_auth;
1097 		intptr = &options->pubkey_authentication;
1098 		goto parse_multistate;
1099 
1100 	case oHostbasedAuthentication:
1101 		intptr = &options->hostbased_authentication;
1102 		goto parse_flag;
1103 
1104 	case oGssAuthentication:
1105 		intptr = &options->gss_authentication;
1106 		goto parse_flag;
1107 
1108 	case oGssDelegateCreds:
1109 		intptr = &options->gss_deleg_creds;
1110 		goto parse_flag;
1111 
1112 	case oBatchMode:
1113 		intptr = &options->batch_mode;
1114 		goto parse_flag;
1115 
1116 	case oCheckHostIP:
1117 		intptr = &options->check_host_ip;
1118 		goto parse_flag;
1119 
1120 	case oVerifyHostKeyDNS:
1121 		intptr = &options->verify_host_key_dns;
1122 		multistate_ptr = multistate_yesnoask;
1123 		goto parse_multistate;
1124 
1125 	case oStrictHostKeyChecking:
1126 		intptr = &options->strict_host_key_checking;
1127 		multistate_ptr = multistate_strict_hostkey;
1128 		goto parse_multistate;
1129 
1130 	case oCompression:
1131 		intptr = &options->compression;
1132 		multistate_ptr = multistate_compression;
1133 		goto parse_multistate;
1134 
1135 	case oTCPKeepAlive:
1136 		intptr = &options->tcp_keep_alive;
1137 		goto parse_flag;
1138 
1139 	case oNoHostAuthenticationForLocalhost:
1140 		intptr = &options->no_host_authentication_for_localhost;
1141 		goto parse_flag;
1142 
1143 	case oNumberOfPasswordPrompts:
1144 		intptr = &options->number_of_password_prompts;
1145 		goto parse_int;
1146 
1147 	case oRekeyLimit:
1148 		arg = argv_next(&ac, &av);
1149 		if (!arg || *arg == '\0') {
1150 			error("%.200s line %d: Missing argument.", filename,
1151 			    linenum);
1152 			goto out;
1153 		}
1154 		if (strcmp(arg, "default") == 0) {
1155 			val64 = 0;
1156 		} else {
1157 			if (scan_scaled(arg, &val64) == -1) {
1158 				error("%.200s line %d: Bad number '%s': %s",
1159 				    filename, linenum, arg, strerror(errno));
1160 				goto out;
1161 			}
1162 			if (val64 != 0 && val64 < 16) {
1163 				error("%.200s line %d: RekeyLimit too small",
1164 				    filename, linenum);
1165 				goto out;
1166 			}
1167 		}
1168 		if (*activep && options->rekey_limit == -1)
1169 			options->rekey_limit = val64;
1170 		if (ac != 0) { /* optional rekey interval present */
1171 			if (strcmp(av[0], "none") == 0) {
1172 				(void)argv_next(&ac, &av);	/* discard */
1173 				break;
1174 			}
1175 			intptr = &options->rekey_interval;
1176 			goto parse_time;
1177 		}
1178 		break;
1179 
1180 	case oIdentityFile:
1181 		arg = argv_next(&ac, &av);
1182 		if (!arg || *arg == '\0') {
1183 			error("%.200s line %d: Missing argument.",
1184 			    filename, linenum);
1185 			goto out;
1186 		}
1187 		if (*activep) {
1188 			intptr = &options->num_identity_files;
1189 			if (*intptr >= SSH_MAX_IDENTITY_FILES) {
1190 				error("%.200s line %d: Too many identity files "
1191 				    "specified (max %d).", filename, linenum,
1192 				    SSH_MAX_IDENTITY_FILES);
1193 				goto out;
1194 			}
1195 			add_identity_file(options, NULL,
1196 			    arg, flags & SSHCONF_USERCONF);
1197 		}
1198 		break;
1199 
1200 	case oCertificateFile:
1201 		arg = argv_next(&ac, &av);
1202 		if (!arg || *arg == '\0') {
1203 			error("%.200s line %d: Missing argument.",
1204 			    filename, linenum);
1205 			goto out;
1206 		}
1207 		if (*activep) {
1208 			intptr = &options->num_certificate_files;
1209 			if (*intptr >= SSH_MAX_CERTIFICATE_FILES) {
1210 				error("%.200s line %d: Too many certificate "
1211 				    "files specified (max %d).",
1212 				    filename, linenum,
1213 				    SSH_MAX_CERTIFICATE_FILES);
1214 				goto out;
1215 			}
1216 			add_certificate_file(options, arg,
1217 			    flags & SSHCONF_USERCONF);
1218 		}
1219 		break;
1220 
1221 	case oXAuthLocation:
1222 		charptr=&options->xauth_location;
1223 		goto parse_string;
1224 
1225 	case oUser:
1226 		charptr = &options->user;
1227 parse_string:
1228 		arg = argv_next(&ac, &av);
1229 		if (!arg || *arg == '\0') {
1230 			error("%.200s line %d: Missing argument.",
1231 			    filename, linenum);
1232 			goto out;
1233 		}
1234 		if (*activep && *charptr == NULL)
1235 			*charptr = xstrdup(arg);
1236 		break;
1237 
1238 	case oGlobalKnownHostsFile:
1239 		cpptr = (char **)&options->system_hostfiles;
1240 		uintptr = &options->num_system_hostfiles;
1241 		max_entries = SSH_MAX_HOSTS_FILES;
1242 parse_char_array:
1243 		i = 0;
1244 		value = *uintptr == 0; /* was array empty when we started? */
1245 		while ((arg = argv_next(&ac, &av)) != NULL) {
1246 			if (*arg == '\0') {
1247 				error("%s line %d: keyword %s empty argument",
1248 				    filename, linenum, keyword);
1249 				goto out;
1250 			}
1251 			/* Allow "none" only in first position */
1252 			if (strcasecmp(arg, "none") == 0) {
1253 				if (i > 0 || ac > 0) {
1254 					error("%s line %d: keyword %s \"none\" "
1255 					    "argument must appear alone.",
1256 					    filename, linenum, keyword);
1257 					goto out;
1258 				}
1259 			}
1260 			i++;
1261 			if (*activep && value) {
1262 				if ((*uintptr) >= max_entries) {
1263 					error("%s line %d: too many %s "
1264 					    "entries.", filename, linenum,
1265 					    keyword);
1266 					goto out;
1267 				}
1268 				cpptr[(*uintptr)++] = xstrdup(arg);
1269 			}
1270 		}
1271 		break;
1272 
1273 	case oUserKnownHostsFile:
1274 		cpptr = (char **)&options->user_hostfiles;
1275 		uintptr = &options->num_user_hostfiles;
1276 		max_entries = SSH_MAX_HOSTS_FILES;
1277 		goto parse_char_array;
1278 
1279 	case oHostname:
1280 		charptr = &options->hostname;
1281 		goto parse_string;
1282 
1283 	case oHostKeyAlias:
1284 		charptr = &options->host_key_alias;
1285 		goto parse_string;
1286 
1287 	case oPreferredAuthentications:
1288 		charptr = &options->preferred_authentications;
1289 		goto parse_string;
1290 
1291 	case oBindAddress:
1292 		charptr = &options->bind_address;
1293 		goto parse_string;
1294 
1295 	case oBindInterface:
1296 		charptr = &options->bind_interface;
1297 		goto parse_string;
1298 
1299 	case oPKCS11Provider:
1300 		charptr = &options->pkcs11_provider;
1301 		goto parse_string;
1302 
1303 	case oSecurityKeyProvider:
1304 		charptr = &options->sk_provider;
1305 		goto parse_string;
1306 
1307 	case oKnownHostsCommand:
1308 		charptr = &options->known_hosts_command;
1309 		goto parse_command;
1310 
1311 	case oProxyCommand:
1312 		charptr = &options->proxy_command;
1313 		/* Ignore ProxyCommand if ProxyJump already specified */
1314 		if (options->jump_host != NULL)
1315 			charptr = &options->jump_host; /* Skip below */
1316 parse_command:
1317 		if (str == NULL) {
1318 			error("%.200s line %d: Missing argument.",
1319 			    filename, linenum);
1320 			goto out;
1321 		}
1322 		len = strspn(str, WHITESPACE "=");
1323 		if (*activep && *charptr == NULL)
1324 			*charptr = xstrdup(str + len);
1325 		argv_consume(&ac);
1326 		break;
1327 
1328 	case oProxyJump:
1329 		if (str == NULL) {
1330 			error("%.200s line %d: Missing argument.",
1331 			    filename, linenum);
1332 			goto out;
1333 		}
1334 		len = strspn(str, WHITESPACE "=");
1335 		/* XXX use argv? */
1336 		if (parse_jump(str + len, options, *activep) == -1) {
1337 			error("%.200s line %d: Invalid ProxyJump \"%s\"",
1338 			    filename, linenum, str + len);
1339 			goto out;
1340 		}
1341 		argv_consume(&ac);
1342 		break;
1343 
1344 	case oPort:
1345 		arg = argv_next(&ac, &av);
1346 		if (!arg || *arg == '\0') {
1347 			error("%.200s line %d: Missing argument.",
1348 			    filename, linenum);
1349 			goto out;
1350 		}
1351 		value = a2port(arg);
1352 		if (value <= 0) {
1353 			error("%.200s line %d: Bad port '%s'.",
1354 			    filename, linenum, arg);
1355 			goto out;
1356 		}
1357 		if (*activep && options->port == -1)
1358 			options->port = value;
1359 		break;
1360 
1361 	case oConnectionAttempts:
1362 		intptr = &options->connection_attempts;
1363 parse_int:
1364 		arg = argv_next(&ac, &av);
1365 		if ((errstr = atoi_err(arg, &value)) != NULL) {
1366 			error("%s line %d: integer value %s.",
1367 			    filename, linenum, errstr);
1368 			goto out;
1369 		}
1370 		if (*activep && *intptr == -1)
1371 			*intptr = value;
1372 		break;
1373 
1374 	case oCiphers:
1375 		arg = argv_next(&ac, &av);
1376 		if (!arg || *arg == '\0') {
1377 			error("%.200s line %d: Missing argument.",
1378 			    filename, linenum);
1379 			goto out;
1380 		}
1381 		if (*arg != '-' &&
1382 		    !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)){
1383 			error("%.200s line %d: Bad SSH2 cipher spec '%s'.",
1384 			    filename, linenum, arg ? arg : "<NONE>");
1385 			goto out;
1386 		}
1387 		if (*activep && options->ciphers == NULL)
1388 			options->ciphers = xstrdup(arg);
1389 		break;
1390 
1391 	case oMacs:
1392 		arg = argv_next(&ac, &av);
1393 		if (!arg || *arg == '\0') {
1394 			error("%.200s line %d: Missing argument.",
1395 			    filename, linenum);
1396 			goto out;
1397 		}
1398 		if (*arg != '-' &&
1399 		    !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) {
1400 			error("%.200s line %d: Bad SSH2 MAC spec '%s'.",
1401 			    filename, linenum, arg ? arg : "<NONE>");
1402 			goto out;
1403 		}
1404 		if (*activep && options->macs == NULL)
1405 			options->macs = xstrdup(arg);
1406 		break;
1407 
1408 	case oKexAlgorithms:
1409 		arg = argv_next(&ac, &av);
1410 		if (!arg || *arg == '\0') {
1411 			error("%.200s line %d: Missing argument.",
1412 			    filename, linenum);
1413 			goto out;
1414 		}
1415 		if (*arg != '-' &&
1416 		    !kex_names_valid(*arg == '+' || *arg == '^' ?
1417 		    arg + 1 : arg)) {
1418 			error("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
1419 			    filename, linenum, arg ? arg : "<NONE>");
1420 			goto out;
1421 		}
1422 		if (*activep && options->kex_algorithms == NULL)
1423 			options->kex_algorithms = xstrdup(arg);
1424 		break;
1425 
1426 	case oHostKeyAlgorithms:
1427 		charptr = &options->hostkeyalgorithms;
1428 parse_pubkey_algos:
1429 		arg = argv_next(&ac, &av);
1430 		if (!arg || *arg == '\0') {
1431 			error("%.200s line %d: Missing argument.",
1432 			    filename, linenum);
1433 			goto out;
1434 		}
1435 		if (*arg != '-' &&
1436 		    !sshkey_names_valid2(*arg == '+' || *arg == '^' ?
1437 		    arg + 1 : arg, 1)) {
1438 			error("%s line %d: Bad key types '%s'.",
1439 			    filename, linenum, arg ? arg : "<NONE>");
1440 			goto out;
1441 		}
1442 		if (*activep && *charptr == NULL)
1443 			*charptr = xstrdup(arg);
1444 		break;
1445 
1446 	case oCASignatureAlgorithms:
1447 		charptr = &options->ca_sign_algorithms;
1448 		goto parse_pubkey_algos;
1449 
1450 	case oLogLevel:
1451 		log_level_ptr = &options->log_level;
1452 		arg = argv_next(&ac, &av);
1453 		value = log_level_number(arg);
1454 		if (value == SYSLOG_LEVEL_NOT_SET) {
1455 			error("%.200s line %d: unsupported log level '%s'",
1456 			    filename, linenum, arg ? arg : "<NONE>");
1457 			goto out;
1458 		}
1459 		if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
1460 			*log_level_ptr = (LogLevel) value;
1461 		break;
1462 
1463 	case oLogFacility:
1464 		log_facility_ptr = &options->log_facility;
1465 		arg = argv_next(&ac, &av);
1466 		value = log_facility_number(arg);
1467 		if (value == SYSLOG_FACILITY_NOT_SET) {
1468 			error("%.200s line %d: unsupported log facility '%s'",
1469 			    filename, linenum, arg ? arg : "<NONE>");
1470 			goto out;
1471 		}
1472 		if (*log_facility_ptr == -1)
1473 			*log_facility_ptr = (SyslogFacility) value;
1474 		break;
1475 
1476 	case oLogVerbose:
1477 		cppptr = &options->log_verbose;
1478 		uintptr = &options->num_log_verbose;
1479 		i = 0;
1480 		while ((arg = argv_next(&ac, &av)) != NULL) {
1481 			if (*arg == '\0') {
1482 				error("%s line %d: keyword %s empty argument",
1483 				    filename, linenum, keyword);
1484 				goto out;
1485 			}
1486 			/* Allow "none" only in first position */
1487 			if (strcasecmp(arg, "none") == 0) {
1488 				if (i > 0 || ac > 0) {
1489 					error("%s line %d: keyword %s \"none\" "
1490 					    "argument must appear alone.",
1491 					    filename, linenum, keyword);
1492 					goto out;
1493 				}
1494 			}
1495 			i++;
1496 			if (*activep && *uintptr == 0) {
1497 				*cppptr = xrecallocarray(*cppptr, *uintptr,
1498 				    *uintptr + 1, sizeof(**cppptr));
1499 				(*cppptr)[(*uintptr)++] = xstrdup(arg);
1500 			}
1501 		}
1502 		break;
1503 
1504 	case oLocalForward:
1505 	case oRemoteForward:
1506 	case oDynamicForward:
1507 		arg = argv_next(&ac, &av);
1508 		if (!arg || *arg == '\0') {
1509 			error("%.200s line %d: Missing argument.",
1510 			    filename, linenum);
1511 			goto out;
1512 		}
1513 
1514 		remotefwd = (opcode == oRemoteForward);
1515 		dynamicfwd = (opcode == oDynamicForward);
1516 
1517 		if (!dynamicfwd) {
1518 			arg2 = argv_next(&ac, &av);
1519 			if (arg2 == NULL || *arg2 == '\0') {
1520 				if (remotefwd)
1521 					dynamicfwd = 1;
1522 				else {
1523 					error("%.200s line %d: Missing target "
1524 					    "argument.", filename, linenum);
1525 					goto out;
1526 				}
1527 			} else {
1528 				/* construct a string for parse_forward */
1529 				snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg,
1530 				    arg2);
1531 			}
1532 		}
1533 		if (dynamicfwd)
1534 			strlcpy(fwdarg, arg, sizeof(fwdarg));
1535 
1536 		if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0) {
1537 			error("%.200s line %d: Bad forwarding specification.",
1538 			    filename, linenum);
1539 			goto out;
1540 		}
1541 
1542 		if (*activep) {
1543 			if (remotefwd) {
1544 				add_remote_forward(options, &fwd);
1545 			} else {
1546 				add_local_forward(options, &fwd);
1547 			}
1548 		}
1549 		break;
1550 
1551 	case oPermitRemoteOpen:
1552 		uintptr = &options->num_permitted_remote_opens;
1553 		cppptr = &options->permitted_remote_opens;
1554 		arg = argv_next(&ac, &av);
1555 		if (!arg || *arg == '\0')
1556 			fatal("%s line %d: missing %s specification",
1557 			    filename, linenum, lookup_opcode_name(opcode));
1558 		uvalue = *uintptr;	/* modified later */
1559 		if (strcmp(arg, "any") == 0 || strcmp(arg, "none") == 0) {
1560 			if (*activep && uvalue == 0) {
1561 				*uintptr = 1;
1562 				*cppptr = xcalloc(1, sizeof(**cppptr));
1563 				(*cppptr)[0] = xstrdup(arg);
1564 			}
1565 			break;
1566 		}
1567 		while ((arg = argv_next(&ac, &av)) != NULL) {
1568 			arg2 = xstrdup(arg);
1569 			p = hpdelim(&arg);
1570 			if (p == NULL) {
1571 				fatal("%s line %d: missing host in %s",
1572 				    filename, linenum,
1573 				    lookup_opcode_name(opcode));
1574 			}
1575 			p = cleanhostname(p);
1576 			/*
1577 			 * don't want to use permitopen_port to avoid
1578 			 * dependency on channels.[ch] here.
1579 			 */
1580 			if (arg == NULL ||
1581 			    (strcmp(arg, "*") != 0 && a2port(arg) <= 0)) {
1582 				fatal("%s line %d: bad port number in %s",
1583 				    filename, linenum,
1584 				    lookup_opcode_name(opcode));
1585 			}
1586 			if (*activep && uvalue == 0) {
1587 				opt_array_append(filename, linenum,
1588 				    lookup_opcode_name(opcode),
1589 				    cppptr, uintptr, arg2);
1590 			}
1591 			free(arg2);
1592 		}
1593 		break;
1594 
1595 	case oClearAllForwardings:
1596 		intptr = &options->clear_forwardings;
1597 		goto parse_flag;
1598 
1599 	case oHost:
1600 		if (cmdline) {
1601 			error("Host directive not supported as a command-line "
1602 			    "option");
1603 			goto out;
1604 		}
1605 		*activep = 0;
1606 		arg2 = NULL;
1607 		while ((arg = argv_next(&ac, &av)) != NULL) {
1608 			if (*arg == '\0') {
1609 				error("%s line %d: keyword %s empty argument",
1610 				    filename, linenum, keyword);
1611 				goto out;
1612 			}
1613 			if ((flags & SSHCONF_NEVERMATCH) != 0) {
1614 				argv_consume(&ac);
1615 				break;
1616 			}
1617 			negated = *arg == '!';
1618 			if (negated)
1619 				arg++;
1620 			if (match_pattern(host, arg)) {
1621 				if (negated) {
1622 					debug("%.200s line %d: Skipping Host "
1623 					    "block because of negated match "
1624 					    "for %.100s", filename, linenum,
1625 					    arg);
1626 					*activep = 0;
1627 					argv_consume(&ac);
1628 					break;
1629 				}
1630 				if (!*activep)
1631 					arg2 = arg; /* logged below */
1632 				*activep = 1;
1633 			}
1634 		}
1635 		if (*activep)
1636 			debug("%.200s line %d: Applying options for %.100s",
1637 			    filename, linenum, arg2);
1638 		break;
1639 
1640 	case oMatch:
1641 		if (cmdline) {
1642 			error("Host directive not supported as a command-line "
1643 			    "option");
1644 			goto out;
1645 		}
1646 		value = match_cfg_line(options, &str, pw, host, original_host,
1647 		    flags & SSHCONF_FINAL, want_final_pass,
1648 		    filename, linenum);
1649 		if (value < 0) {
1650 			error("%.200s line %d: Bad Match condition", filename,
1651 			    linenum);
1652 			goto out;
1653 		}
1654 		*activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value;
1655 		/*
1656 		 * If match_cfg_line() didn't consume all its arguments then
1657 		 * arrange for the extra arguments check below to fail.
1658 		 */
1659 
1660 		if (str == NULL || *str == '\0')
1661 			argv_consume(&ac);
1662 		break;
1663 
1664 	case oEscapeChar:
1665 		intptr = &options->escape_char;
1666 		arg = argv_next(&ac, &av);
1667 		if (!arg || *arg == '\0') {
1668 			error("%.200s line %d: Missing argument.",
1669 			    filename, linenum);
1670 			goto out;
1671 		}
1672 		if (strcmp(arg, "none") == 0)
1673 			value = SSH_ESCAPECHAR_NONE;
1674 		else if (arg[1] == '\0')
1675 			value = (u_char) arg[0];
1676 		else if (arg[0] == '^' && arg[2] == 0 &&
1677 		    (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
1678 			value = (u_char) arg[1] & 31;
1679 		else {
1680 			error("%.200s line %d: Bad escape character.",
1681 			    filename, linenum);
1682 			goto out;
1683 		}
1684 		if (*activep && *intptr == -1)
1685 			*intptr = value;
1686 		break;
1687 
1688 	case oAddressFamily:
1689 		intptr = &options->address_family;
1690 		multistate_ptr = multistate_addressfamily;
1691 		goto parse_multistate;
1692 
1693 	case oEnableSSHKeysign:
1694 		intptr = &options->enable_ssh_keysign;
1695 		goto parse_flag;
1696 
1697 	case oIdentitiesOnly:
1698 		intptr = &options->identities_only;
1699 		goto parse_flag;
1700 
1701 	case oServerAliveInterval:
1702 		intptr = &options->server_alive_interval;
1703 		goto parse_time;
1704 
1705 	case oServerAliveCountMax:
1706 		intptr = &options->server_alive_count_max;
1707 		goto parse_int;
1708 
1709 	case oSendEnv:
1710 		while ((arg = argv_next(&ac, &av)) != NULL) {
1711 			if (*arg == '\0' || strchr(arg, '=') != NULL) {
1712 				error("%s line %d: Invalid environment name.",
1713 				    filename, linenum);
1714 				goto out;
1715 			}
1716 			if (!*activep)
1717 				continue;
1718 			if (*arg == '-') {
1719 				/* Removing an env var */
1720 				rm_env(options, arg, filename, linenum);
1721 				continue;
1722 			} else {
1723 				/* Adding an env var */
1724 				if (options->num_send_env >= INT_MAX) {
1725 					error("%s line %d: too many send env.",
1726 					    filename, linenum);
1727 					goto out;
1728 				}
1729 				options->send_env = xrecallocarray(
1730 				    options->send_env, options->num_send_env,
1731 				    options->num_send_env + 1,
1732 				    sizeof(*options->send_env));
1733 				options->send_env[options->num_send_env++] =
1734 				    xstrdup(arg);
1735 			}
1736 		}
1737 		break;
1738 
1739 	case oSetEnv:
1740 		value = options->num_setenv;
1741 		while ((arg = argv_next(&ac, &av)) != NULL) {
1742 			if (strchr(arg, '=') == NULL) {
1743 				error("%s line %d: Invalid SetEnv.",
1744 				    filename, linenum);
1745 				goto out;
1746 			}
1747 			if (!*activep || value != 0)
1748 				continue;
1749 			/* Adding a setenv var */
1750 			if (options->num_setenv >= INT_MAX) {
1751 				error("%s line %d: too many SetEnv.",
1752 				    filename, linenum);
1753 				goto out;
1754 			}
1755 			options->setenv = xrecallocarray(
1756 			    options->setenv, options->num_setenv,
1757 			    options->num_setenv + 1, sizeof(*options->setenv));
1758 			options->setenv[options->num_setenv++] = xstrdup(arg);
1759 		}
1760 		break;
1761 
1762 	case oControlPath:
1763 		charptr = &options->control_path;
1764 		goto parse_string;
1765 
1766 	case oControlMaster:
1767 		intptr = &options->control_master;
1768 		multistate_ptr = multistate_controlmaster;
1769 		goto parse_multistate;
1770 
1771 	case oControlPersist:
1772 		/* no/false/yes/true, or a time spec */
1773 		intptr = &options->control_persist;
1774 		arg = argv_next(&ac, &av);
1775 		if (!arg || *arg == '\0') {
1776 			error("%.200s line %d: Missing ControlPersist"
1777 			    " argument.", filename, linenum);
1778 			goto out;
1779 		}
1780 		value = 0;
1781 		value2 = 0;	/* timeout */
1782 		if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
1783 			value = 0;
1784 		else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
1785 			value = 1;
1786 		else if ((value2 = convtime(arg)) >= 0)
1787 			value = 1;
1788 		else {
1789 			error("%.200s line %d: Bad ControlPersist argument.",
1790 			    filename, linenum);
1791 			goto out;
1792 		}
1793 		if (*activep && *intptr == -1) {
1794 			*intptr = value;
1795 			options->control_persist_timeout = value2;
1796 		}
1797 		break;
1798 
1799 	case oHashKnownHosts:
1800 		intptr = &options->hash_known_hosts;
1801 		goto parse_flag;
1802 
1803 	case oTunnel:
1804 		intptr = &options->tun_open;
1805 		multistate_ptr = multistate_tunnel;
1806 		goto parse_multistate;
1807 
1808 	case oTunnelDevice:
1809 		arg = argv_next(&ac, &av);
1810 		if (!arg || *arg == '\0') {
1811 			error("%.200s line %d: Missing argument.",
1812 			    filename, linenum);
1813 			goto out;
1814 		}
1815 		value = a2tun(arg, &value2);
1816 		if (value == SSH_TUNID_ERR) {
1817 			error("%.200s line %d: Bad tun device.",
1818 			    filename, linenum);
1819 			goto out;
1820 		}
1821 		if (*activep && options->tun_local == -1) {
1822 			options->tun_local = value;
1823 			options->tun_remote = value2;
1824 		}
1825 		break;
1826 
1827 	case oLocalCommand:
1828 		charptr = &options->local_command;
1829 		goto parse_command;
1830 
1831 	case oPermitLocalCommand:
1832 		intptr = &options->permit_local_command;
1833 		goto parse_flag;
1834 
1835 	case oRemoteCommand:
1836 		charptr = &options->remote_command;
1837 		goto parse_command;
1838 
1839 	case oVisualHostKey:
1840 		intptr = &options->visual_host_key;
1841 		goto parse_flag;
1842 
1843 	case oInclude:
1844 		if (cmdline) {
1845 			error("Include directive not supported as a "
1846 			    "command-line option");
1847 			goto out;
1848 		}
1849 		value = 0;
1850 		while ((arg = argv_next(&ac, &av)) != NULL) {
1851 			if (*arg == '\0') {
1852 				error("%s line %d: keyword %s empty argument",
1853 				    filename, linenum, keyword);
1854 				goto out;
1855 			}
1856 			/*
1857 			 * Ensure all paths are anchored. User configuration
1858 			 * files may begin with '~/' but system configurations
1859 			 * must not. If the path is relative, then treat it
1860 			 * as living in ~/.ssh for user configurations or
1861 			 * /etc/ssh for system ones.
1862 			 */
1863 			if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0) {
1864 				error("%.200s line %d: bad include path %s.",
1865 				    filename, linenum, arg);
1866 				goto out;
1867 			}
1868 			if (!path_absolute(arg) && *arg != '~') {
1869 				xasprintf(&arg2, "%s/%s",
1870 				    (flags & SSHCONF_USERCONF) ?
1871 				    "~/" _PATH_SSH_USER_DIR : SSHDIR, arg);
1872 			} else
1873 				arg2 = xstrdup(arg);
1874 			memset(&gl, 0, sizeof(gl));
1875 			r = glob(arg2, GLOB_TILDE, NULL, &gl);
1876 			if (r == GLOB_NOMATCH) {
1877 				debug("%.200s line %d: include %s matched no "
1878 				    "files",filename, linenum, arg2);
1879 				free(arg2);
1880 				continue;
1881 			} else if (r != 0) {
1882 				error("%.200s line %d: glob failed for %s.",
1883 				    filename, linenum, arg2);
1884 				goto out;
1885 			}
1886 			free(arg2);
1887 			oactive = *activep;
1888 			for (i = 0; i < gl.gl_pathc; i++) {
1889 				debug3("%.200s line %d: Including file %s "
1890 				    "depth %d%s", filename, linenum,
1891 				    gl.gl_pathv[i], depth,
1892 				    oactive ? "" : " (parse only)");
1893 				r = read_config_file_depth(gl.gl_pathv[i],
1894 				    pw, host, original_host, options,
1895 				    flags | SSHCONF_CHECKPERM |
1896 				    (oactive ? 0 : SSHCONF_NEVERMATCH),
1897 				    activep, want_final_pass, depth + 1);
1898 				if (r != 1 && errno != ENOENT) {
1899 					error("Can't open user config file "
1900 					    "%.100s: %.100s", gl.gl_pathv[i],
1901 					    strerror(errno));
1902 					globfree(&gl);
1903 					goto out;
1904 				}
1905 				/*
1906 				 * don't let Match in includes clobber the
1907 				 * containing file's Match state.
1908 				 */
1909 				*activep = oactive;
1910 				if (r != 1)
1911 					value = -1;
1912 			}
1913 			globfree(&gl);
1914 		}
1915 		if (value != 0)
1916 			ret = value;
1917 		break;
1918 
1919 	case oIPQoS:
1920 		arg = argv_next(&ac, &av);
1921 		if ((value = parse_ipqos(arg)) == -1) {
1922 			error("%s line %d: Bad IPQoS value: %s",
1923 			    filename, linenum, arg);
1924 			goto out;
1925 		}
1926 		arg = argv_next(&ac, &av);
1927 		if (arg == NULL)
1928 			value2 = value;
1929 		else if ((value2 = parse_ipqos(arg)) == -1) {
1930 			error("%s line %d: Bad IPQoS value: %s",
1931 			    filename, linenum, arg);
1932 			goto out;
1933 		}
1934 		if (*activep && options->ip_qos_interactive == -1) {
1935 			options->ip_qos_interactive = value;
1936 			options->ip_qos_bulk = value2;
1937 		}
1938 		break;
1939 
1940 	case oRequestTTY:
1941 		intptr = &options->request_tty;
1942 		multistate_ptr = multistate_requesttty;
1943 		goto parse_multistate;
1944 
1945 	case oSessionType:
1946 		intptr = &options->session_type;
1947 		multistate_ptr = multistate_sessiontype;
1948 		goto parse_multistate;
1949 
1950 	case oStdinNull:
1951 		intptr = &options->stdin_null;
1952 		goto parse_flag;
1953 
1954 	case oForkAfterAuthentication:
1955 		intptr = &options->fork_after_authentication;
1956 		goto parse_flag;
1957 
1958 	case oIgnoreUnknown:
1959 		charptr = &options->ignored_unknown;
1960 		goto parse_string;
1961 
1962 	case oProxyUseFdpass:
1963 		intptr = &options->proxy_use_fdpass;
1964 		goto parse_flag;
1965 
1966 	case oCanonicalDomains:
1967 		value = options->num_canonical_domains != 0;
1968 		i = 0;
1969 		while ((arg = argv_next(&ac, &av)) != NULL) {
1970 			if (*arg == '\0') {
1971 				error("%s line %d: keyword %s empty argument",
1972 				    filename, linenum, keyword);
1973 				goto out;
1974 			}
1975 			/* Allow "none" only in first position */
1976 			if (strcasecmp(arg, "none") == 0) {
1977 				if (i > 0 || ac > 0) {
1978 					error("%s line %d: keyword %s \"none\" "
1979 					    "argument must appear alone.",
1980 					    filename, linenum, keyword);
1981 					goto out;
1982 				}
1983 			}
1984 			i++;
1985 			if (!valid_domain(arg, 1, &errstr)) {
1986 				error("%s line %d: %s", filename, linenum,
1987 				    errstr);
1988 				goto out;
1989 			}
1990 			if (!*activep || value)
1991 				continue;
1992 			if (options->num_canonical_domains >=
1993 			    MAX_CANON_DOMAINS) {
1994 				error("%s line %d: too many hostname suffixes.",
1995 				    filename, linenum);
1996 				goto out;
1997 			}
1998 			options->canonical_domains[
1999 			    options->num_canonical_domains++] = xstrdup(arg);
2000 		}
2001 		break;
2002 
2003 	case oCanonicalizePermittedCNAMEs:
2004 		value = options->num_permitted_cnames != 0;
2005 		i = 0;
2006 		while ((arg = argv_next(&ac, &av)) != NULL) {
2007 			/*
2008 			 * Either 'none' (only in first position), '*' for
2009 			 * everything or 'list:list'
2010 			 */
2011 			if (strcasecmp(arg, "none") == 0) {
2012 				if (i > 0 || ac > 0) {
2013 					error("%s line %d: keyword %s \"none\" "
2014 					    "argument must appear alone.",
2015 					    filename, linenum, keyword);
2016 					goto out;
2017 				}
2018 				arg2 = "";
2019 			} else if (strcmp(arg, "*") == 0) {
2020 				arg2 = arg;
2021 			} else {
2022 				lowercase(arg);
2023 				if ((arg2 = strchr(arg, ':')) == NULL ||
2024 				    arg2[1] == '\0') {
2025 					error("%s line %d: "
2026 					    "Invalid permitted CNAME \"%s\"",
2027 					    filename, linenum, arg);
2028 					goto out;
2029 				}
2030 				*arg2 = '\0';
2031 				arg2++;
2032 			}
2033 			i++;
2034 			if (!*activep || value)
2035 				continue;
2036 			if (options->num_permitted_cnames >=
2037 			    MAX_CANON_DOMAINS) {
2038 				error("%s line %d: too many permitted CNAMEs.",
2039 				    filename, linenum);
2040 				goto out;
2041 			}
2042 			cname = options->permitted_cnames +
2043 			    options->num_permitted_cnames++;
2044 			cname->source_list = xstrdup(arg);
2045 			cname->target_list = xstrdup(arg2);
2046 		}
2047 		break;
2048 
2049 	case oCanonicalizeHostname:
2050 		intptr = &options->canonicalize_hostname;
2051 		multistate_ptr = multistate_canonicalizehostname;
2052 		goto parse_multistate;
2053 
2054 	case oCanonicalizeMaxDots:
2055 		intptr = &options->canonicalize_max_dots;
2056 		goto parse_int;
2057 
2058 	case oCanonicalizeFallbackLocal:
2059 		intptr = &options->canonicalize_fallback_local;
2060 		goto parse_flag;
2061 
2062 	case oStreamLocalBindMask:
2063 		arg = argv_next(&ac, &av);
2064 		if (!arg || *arg == '\0') {
2065 			error("%.200s line %d: Missing StreamLocalBindMask "
2066 			    "argument.", filename, linenum);
2067 			goto out;
2068 		}
2069 		/* Parse mode in octal format */
2070 		value = strtol(arg, &endofnumber, 8);
2071 		if (arg == endofnumber || value < 0 || value > 0777) {
2072 			error("%.200s line %d: Bad mask.", filename, linenum);
2073 			goto out;
2074 		}
2075 		options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
2076 		break;
2077 
2078 	case oStreamLocalBindUnlink:
2079 		intptr = &options->fwd_opts.streamlocal_bind_unlink;
2080 		goto parse_flag;
2081 
2082 	case oRevokedHostKeys:
2083 		charptr = &options->revoked_host_keys;
2084 		goto parse_string;
2085 
2086 	case oFingerprintHash:
2087 		intptr = &options->fingerprint_hash;
2088 		arg = argv_next(&ac, &av);
2089 		if (!arg || *arg == '\0') {
2090 			error("%.200s line %d: Missing argument.",
2091 			    filename, linenum);
2092 			goto out;
2093 		}
2094 		if ((value = ssh_digest_alg_by_name(arg)) == -1) {
2095 			error("%.200s line %d: Invalid hash algorithm \"%s\".",
2096 			    filename, linenum, arg);
2097 			goto out;
2098 		}
2099 		if (*activep && *intptr == -1)
2100 			*intptr = value;
2101 		break;
2102 
2103 	case oUpdateHostkeys:
2104 		intptr = &options->update_hostkeys;
2105 		multistate_ptr = multistate_yesnoask;
2106 		goto parse_multistate;
2107 
2108 	case oHostbasedAcceptedAlgorithms:
2109 		charptr = &options->hostbased_accepted_algos;
2110 		goto parse_pubkey_algos;
2111 
2112 	case oPubkeyAcceptedAlgorithms:
2113 		charptr = &options->pubkey_accepted_algos;
2114 		goto parse_pubkey_algos;
2115 
2116 	case oAddKeysToAgent:
2117 		arg = argv_next(&ac, &av);
2118 		arg2 = argv_next(&ac, &av);
2119 		value = parse_multistate_value(arg, filename, linenum,
2120 		    multistate_yesnoaskconfirm);
2121 		value2 = 0; /* unlimited lifespan by default */
2122 		if (value == 3 && arg2 != NULL) {
2123 			/* allow "AddKeysToAgent confirm 5m" */
2124 			if ((value2 = convtime(arg2)) == -1 ||
2125 			    value2 > INT_MAX) {
2126 				error("%s line %d: invalid time value.",
2127 				    filename, linenum);
2128 				goto out;
2129 			}
2130 		} else if (value == -1 && arg2 == NULL) {
2131 			if ((value2 = convtime(arg)) == -1 ||
2132 			    value2 > INT_MAX) {
2133 				error("%s line %d: unsupported option",
2134 				    filename, linenum);
2135 				goto out;
2136 			}
2137 			value = 1; /* yes */
2138 		} else if (value == -1 || arg2 != NULL) {
2139 			error("%s line %d: unsupported option",
2140 			    filename, linenum);
2141 			goto out;
2142 		}
2143 		if (*activep && options->add_keys_to_agent == -1) {
2144 			options->add_keys_to_agent = value;
2145 			options->add_keys_to_agent_lifespan = value2;
2146 		}
2147 		break;
2148 
2149 	case oIdentityAgent:
2150 		charptr = &options->identity_agent;
2151 		arg = argv_next(&ac, &av);
2152 		if (!arg || *arg == '\0') {
2153 			error("%.200s line %d: Missing argument.",
2154 			    filename, linenum);
2155 			goto out;
2156 		}
2157   parse_agent_path:
2158 		/* Extra validation if the string represents an env var. */
2159 		if ((arg2 = dollar_expand(&r, arg)) == NULL || r) {
2160 			error("%.200s line %d: Invalid environment expansion "
2161 			    "%s.", filename, linenum, arg);
2162 			goto out;
2163 		}
2164 		free(arg2);
2165 		/* check for legacy environment format */
2166 		if (arg[0] == '$' && arg[1] != '{' &&
2167 		    !valid_env_name(arg + 1)) {
2168 			error("%.200s line %d: Invalid environment name %s.",
2169 			    filename, linenum, arg);
2170 			goto out;
2171 		}
2172 		if (*activep && *charptr == NULL)
2173 			*charptr = xstrdup(arg);
2174 		break;
2175 
2176 	case oDeprecated:
2177 		debug("%s line %d: Deprecated option \"%s\"",
2178 		    filename, linenum, keyword);
2179 		argv_consume(&ac);
2180 		break;
2181 
2182 	case oUnsupported:
2183 		error("%s line %d: Unsupported option \"%s\"",
2184 		    filename, linenum, keyword);
2185 		argv_consume(&ac);
2186 		break;
2187 
2188 	default:
2189 		error("%s line %d: Unimplemented opcode %d",
2190 		    filename, linenum, opcode);
2191 		goto out;
2192 	}
2193 
2194 	/* Check that there is no garbage at end of line. */
2195 	if (ac > 0) {
2196 		error("%.200s line %d: keyword %s extra arguments "
2197 		    "at end of line", filename, linenum, keyword);
2198 		goto out;
2199 	}
2200 
2201 	/* success */
2202 	ret = 0;
2203  out:
2204 	argv_free(oav, oac);
2205 	return ret;
2206 }
2207 
2208 /*
2209  * Reads the config file and modifies the options accordingly.  Options
2210  * should already be initialized before this call.  This never returns if
2211  * there is an error.  If the file does not exist, this returns 0.
2212  */
2213 int
2214 read_config_file(const char *filename, struct passwd *pw, const char *host,
2215     const char *original_host, Options *options, int flags,
2216     int *want_final_pass)
2217 {
2218 	int active = 1;
2219 
2220 	return read_config_file_depth(filename, pw, host, original_host,
2221 	    options, flags, &active, want_final_pass, 0);
2222 }
2223 
2224 #define READCONF_MAX_DEPTH	16
2225 static int
2226 read_config_file_depth(const char *filename, struct passwd *pw,
2227     const char *host, const char *original_host, Options *options,
2228     int flags, int *activep, int *want_final_pass, int depth)
2229 {
2230 	FILE *f;
2231 	char *line = NULL;
2232 	size_t linesize = 0;
2233 	int linenum;
2234 	int bad_options = 0;
2235 
2236 	if (depth < 0 || depth > READCONF_MAX_DEPTH)
2237 		fatal("Too many recursive configuration includes");
2238 
2239 	if ((f = fopen(filename, "r")) == NULL)
2240 		return 0;
2241 
2242 	if (flags & SSHCONF_CHECKPERM) {
2243 		struct stat sb;
2244 
2245 		if (fstat(fileno(f), &sb) == -1)
2246 			fatal("fstat %s: %s", filename, strerror(errno));
2247 		if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
2248 		    (sb.st_mode & 022) != 0))
2249 			fatal("Bad owner or permissions on %s", filename);
2250 	}
2251 
2252 	debug("Reading configuration data %.200s", filename);
2253 
2254 	/*
2255 	 * Mark that we are now processing the options.  This flag is turned
2256 	 * on/off by Host specifications.
2257 	 */
2258 	linenum = 0;
2259 	while (getline(&line, &linesize, f) != -1) {
2260 		/* Update line number counter. */
2261 		linenum++;
2262 		/*
2263 		 * Trim out comments and strip whitespace.
2264 		 * NB - preserve newlines, they are needed to reproduce
2265 		 * line numbers later for error messages.
2266 		 */
2267 		if (process_config_line_depth(options, pw, host, original_host,
2268 		    line, filename, linenum, activep, flags, want_final_pass,
2269 		    depth) != 0)
2270 			bad_options++;
2271 	}
2272 	free(line);
2273 	fclose(f);
2274 	if (bad_options > 0)
2275 		fatal("%s: terminating, %d bad configuration options",
2276 		    filename, bad_options);
2277 	return 1;
2278 }
2279 
2280 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
2281 int
2282 option_clear_or_none(const char *o)
2283 {
2284 	return o == NULL || strcasecmp(o, "none") == 0;
2285 }
2286 
2287 /*
2288  * Returns 1 if CanonicalizePermittedCNAMEs have been specified, 0 otherwise.
2289  * Allowed to be called on non-final configuration.
2290  */
2291 int
2292 config_has_permitted_cnames(Options *options)
2293 {
2294 	if (options->num_permitted_cnames == 1 &&
2295 	    strcasecmp(options->permitted_cnames[0].source_list, "none") == 0 &&
2296 	    strcmp(options->permitted_cnames[0].target_list, "") == 0)
2297 		return 0;
2298 	return options->num_permitted_cnames > 0;
2299 }
2300 
2301 /*
2302  * Initializes options to special values that indicate that they have not yet
2303  * been set.  Read_config_file will only set options with this value. Options
2304  * are processed in the following order: command line, user config file,
2305  * system config file.  Last, fill_default_options is called.
2306  */
2307 
2308 void
2309 initialize_options(Options * options)
2310 {
2311 	memset(options, 'X', sizeof(*options));
2312 	options->forward_agent = -1;
2313 	options->forward_agent_sock_path = NULL;
2314 	options->forward_x11 = -1;
2315 	options->forward_x11_trusted = -1;
2316 	options->forward_x11_timeout = -1;
2317 	options->stdio_forward_host = NULL;
2318 	options->stdio_forward_port = 0;
2319 	options->clear_forwardings = -1;
2320 	options->exit_on_forward_failure = -1;
2321 	options->xauth_location = NULL;
2322 	options->fwd_opts.gateway_ports = -1;
2323 	options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
2324 	options->fwd_opts.streamlocal_bind_unlink = -1;
2325 	options->pubkey_authentication = -1;
2326 	options->gss_authentication = -1;
2327 	options->gss_deleg_creds = -1;
2328 	options->password_authentication = -1;
2329 	options->kbd_interactive_authentication = -1;
2330 	options->kbd_interactive_devices = NULL;
2331 	options->hostbased_authentication = -1;
2332 	options->batch_mode = -1;
2333 	options->check_host_ip = -1;
2334 	options->strict_host_key_checking = -1;
2335 	options->compression = -1;
2336 	options->tcp_keep_alive = -1;
2337 	options->port = -1;
2338 	options->address_family = -1;
2339 	options->connection_attempts = -1;
2340 	options->connection_timeout = -1;
2341 	options->number_of_password_prompts = -1;
2342 	options->ciphers = NULL;
2343 	options->macs = NULL;
2344 	options->kex_algorithms = NULL;
2345 	options->hostkeyalgorithms = NULL;
2346 	options->ca_sign_algorithms = NULL;
2347 	options->num_identity_files = 0;
2348 	memset(options->identity_keys, 0, sizeof(options->identity_keys));
2349 	options->num_certificate_files = 0;
2350 	memset(options->certificates, 0, sizeof(options->certificates));
2351 	options->hostname = NULL;
2352 	options->host_key_alias = NULL;
2353 	options->proxy_command = NULL;
2354 	options->jump_user = NULL;
2355 	options->jump_host = NULL;
2356 	options->jump_port = -1;
2357 	options->jump_extra = NULL;
2358 	options->user = NULL;
2359 	options->escape_char = -1;
2360 	options->num_system_hostfiles = 0;
2361 	options->num_user_hostfiles = 0;
2362 	options->local_forwards = NULL;
2363 	options->num_local_forwards = 0;
2364 	options->remote_forwards = NULL;
2365 	options->num_remote_forwards = 0;
2366 	options->permitted_remote_opens = NULL;
2367 	options->num_permitted_remote_opens = 0;
2368 	options->log_facility = SYSLOG_FACILITY_NOT_SET;
2369 	options->log_level = SYSLOG_LEVEL_NOT_SET;
2370 	options->num_log_verbose = 0;
2371 	options->log_verbose = NULL;
2372 	options->preferred_authentications = NULL;
2373 	options->bind_address = NULL;
2374 	options->bind_interface = NULL;
2375 	options->pkcs11_provider = NULL;
2376 	options->sk_provider = NULL;
2377 	options->enable_ssh_keysign = - 1;
2378 	options->no_host_authentication_for_localhost = - 1;
2379 	options->identities_only = - 1;
2380 	options->rekey_limit = - 1;
2381 	options->rekey_interval = -1;
2382 	options->verify_host_key_dns = -1;
2383 	options->server_alive_interval = -1;
2384 	options->server_alive_count_max = -1;
2385 	options->send_env = NULL;
2386 	options->num_send_env = 0;
2387 	options->setenv = NULL;
2388 	options->num_setenv = 0;
2389 	options->control_path = NULL;
2390 	options->control_master = -1;
2391 	options->control_persist = -1;
2392 	options->control_persist_timeout = 0;
2393 	options->hash_known_hosts = -1;
2394 	options->tun_open = -1;
2395 	options->tun_local = -1;
2396 	options->tun_remote = -1;
2397 	options->local_command = NULL;
2398 	options->permit_local_command = -1;
2399 	options->remote_command = NULL;
2400 	options->add_keys_to_agent = -1;
2401 	options->add_keys_to_agent_lifespan = -1;
2402 	options->identity_agent = NULL;
2403 	options->visual_host_key = -1;
2404 	options->ip_qos_interactive = -1;
2405 	options->ip_qos_bulk = -1;
2406 	options->request_tty = -1;
2407 	options->session_type = -1;
2408 	options->stdin_null = -1;
2409 	options->fork_after_authentication = -1;
2410 	options->proxy_use_fdpass = -1;
2411 	options->ignored_unknown = NULL;
2412 	options->num_canonical_domains = 0;
2413 	options->num_permitted_cnames = 0;
2414 	options->canonicalize_max_dots = -1;
2415 	options->canonicalize_fallback_local = -1;
2416 	options->canonicalize_hostname = -1;
2417 	options->revoked_host_keys = NULL;
2418 	options->fingerprint_hash = -1;
2419 	options->update_hostkeys = -1;
2420 	options->hostbased_accepted_algos = NULL;
2421 	options->pubkey_accepted_algos = NULL;
2422 	options->known_hosts_command = NULL;
2423 }
2424 
2425 /*
2426  * A petite version of fill_default_options() that just fills the options
2427  * needed for hostname canonicalization to proceed.
2428  */
2429 void
2430 fill_default_options_for_canonicalization(Options *options)
2431 {
2432 	if (options->canonicalize_max_dots == -1)
2433 		options->canonicalize_max_dots = 1;
2434 	if (options->canonicalize_fallback_local == -1)
2435 		options->canonicalize_fallback_local = 1;
2436 	if (options->canonicalize_hostname == -1)
2437 		options->canonicalize_hostname = SSH_CANONICALISE_NO;
2438 }
2439 
2440 /*
2441  * Called after processing other sources of option data, this fills those
2442  * options for which no value has been specified with their default values.
2443  */
2444 int
2445 fill_default_options(Options * options)
2446 {
2447 	char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig;
2448 	char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig;
2449 	int ret = 0, r;
2450 
2451 	if (options->forward_agent == -1)
2452 		options->forward_agent = 0;
2453 	if (options->forward_x11 == -1)
2454 		options->forward_x11 = 0;
2455 	if (options->forward_x11_trusted == -1)
2456 		options->forward_x11_trusted = 0;
2457 	if (options->forward_x11_timeout == -1)
2458 		options->forward_x11_timeout = 1200;
2459 	/*
2460 	 * stdio forwarding (-W) changes the default for these but we defer
2461 	 * setting the values so they can be overridden.
2462 	 */
2463 	if (options->exit_on_forward_failure == -1)
2464 		options->exit_on_forward_failure =
2465 		    options->stdio_forward_host != NULL ? 1 : 0;
2466 	if (options->clear_forwardings == -1)
2467 		options->clear_forwardings =
2468 		    options->stdio_forward_host != NULL ? 1 : 0;
2469 	if (options->clear_forwardings == 1)
2470 		clear_forwardings(options);
2471 
2472 	if (options->xauth_location == NULL)
2473 		options->xauth_location = xstrdup(_PATH_XAUTH);
2474 	if (options->fwd_opts.gateway_ports == -1)
2475 		options->fwd_opts.gateway_ports = 0;
2476 	if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
2477 		options->fwd_opts.streamlocal_bind_mask = 0177;
2478 	if (options->fwd_opts.streamlocal_bind_unlink == -1)
2479 		options->fwd_opts.streamlocal_bind_unlink = 0;
2480 	if (options->pubkey_authentication == -1)
2481 		options->pubkey_authentication = SSH_PUBKEY_AUTH_ALL;
2482 	if (options->gss_authentication == -1)
2483 		options->gss_authentication = 0;
2484 	if (options->gss_deleg_creds == -1)
2485 		options->gss_deleg_creds = 0;
2486 	if (options->password_authentication == -1)
2487 		options->password_authentication = 1;
2488 	if (options->kbd_interactive_authentication == -1)
2489 		options->kbd_interactive_authentication = 1;
2490 	if (options->hostbased_authentication == -1)
2491 		options->hostbased_authentication = 0;
2492 	if (options->batch_mode == -1)
2493 		options->batch_mode = 0;
2494 	if (options->check_host_ip == -1)
2495 		options->check_host_ip = 0;
2496 	if (options->strict_host_key_checking == -1)
2497 		options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK;
2498 	if (options->compression == -1)
2499 		options->compression = 0;
2500 	if (options->tcp_keep_alive == -1)
2501 		options->tcp_keep_alive = 1;
2502 	if (options->port == -1)
2503 		options->port = 0;	/* Filled in ssh_connect. */
2504 	if (options->address_family == -1)
2505 		options->address_family = AF_UNSPEC;
2506 	if (options->connection_attempts == -1)
2507 		options->connection_attempts = 1;
2508 	if (options->number_of_password_prompts == -1)
2509 		options->number_of_password_prompts = 3;
2510 	/* options->hostkeyalgorithms, default set in myproposals.h */
2511 	if (options->add_keys_to_agent == -1) {
2512 		options->add_keys_to_agent = 0;
2513 		options->add_keys_to_agent_lifespan = 0;
2514 	}
2515 	if (options->num_identity_files == 0) {
2516 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0);
2517 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0);
2518 		add_identity_file(options, "~/",
2519 		    _PATH_SSH_CLIENT_ID_ECDSA_SK, 0);
2520 		add_identity_file(options, "~/",
2521 		    _PATH_SSH_CLIENT_ID_ED25519, 0);
2522 		add_identity_file(options, "~/",
2523 		    _PATH_SSH_CLIENT_ID_ED25519_SK, 0);
2524 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0);
2525 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0);
2526 	}
2527 	if (options->escape_char == -1)
2528 		options->escape_char = '~';
2529 	if (options->num_system_hostfiles == 0) {
2530 		options->system_hostfiles[options->num_system_hostfiles++] =
2531 		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
2532 		options->system_hostfiles[options->num_system_hostfiles++] =
2533 		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
2534 	}
2535 	if (options->update_hostkeys == -1) {
2536 		if (options->verify_host_key_dns <= 0 &&
2537 		    (options->num_user_hostfiles == 0 ||
2538 		    (options->num_user_hostfiles == 1 && strcmp(options->
2539 		    user_hostfiles[0], _PATH_SSH_USER_HOSTFILE) == 0)))
2540 			options->update_hostkeys = SSH_UPDATE_HOSTKEYS_YES;
2541 		else
2542 			options->update_hostkeys = SSH_UPDATE_HOSTKEYS_NO;
2543 	}
2544 	if (options->num_user_hostfiles == 0) {
2545 		options->user_hostfiles[options->num_user_hostfiles++] =
2546 		    xstrdup(_PATH_SSH_USER_HOSTFILE);
2547 		options->user_hostfiles[options->num_user_hostfiles++] =
2548 		    xstrdup(_PATH_SSH_USER_HOSTFILE2);
2549 	}
2550 	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
2551 		options->log_level = SYSLOG_LEVEL_INFO;
2552 	if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
2553 		options->log_facility = SYSLOG_FACILITY_USER;
2554 	if (options->no_host_authentication_for_localhost == - 1)
2555 		options->no_host_authentication_for_localhost = 0;
2556 	if (options->identities_only == -1)
2557 		options->identities_only = 0;
2558 	if (options->enable_ssh_keysign == -1)
2559 		options->enable_ssh_keysign = 0;
2560 	if (options->rekey_limit == -1)
2561 		options->rekey_limit = 0;
2562 	if (options->rekey_interval == -1)
2563 		options->rekey_interval = 0;
2564 	if (options->verify_host_key_dns == -1)
2565 		options->verify_host_key_dns = 0;
2566 	if (options->server_alive_interval == -1)
2567 		options->server_alive_interval = 0;
2568 	if (options->server_alive_count_max == -1)
2569 		options->server_alive_count_max = 3;
2570 	if (options->control_master == -1)
2571 		options->control_master = 0;
2572 	if (options->control_persist == -1) {
2573 		options->control_persist = 0;
2574 		options->control_persist_timeout = 0;
2575 	}
2576 	if (options->hash_known_hosts == -1)
2577 		options->hash_known_hosts = 0;
2578 	if (options->tun_open == -1)
2579 		options->tun_open = SSH_TUNMODE_NO;
2580 	if (options->tun_local == -1)
2581 		options->tun_local = SSH_TUNID_ANY;
2582 	if (options->tun_remote == -1)
2583 		options->tun_remote = SSH_TUNID_ANY;
2584 	if (options->permit_local_command == -1)
2585 		options->permit_local_command = 0;
2586 	if (options->visual_host_key == -1)
2587 		options->visual_host_key = 0;
2588 	if (options->ip_qos_interactive == -1)
2589 		options->ip_qos_interactive = IPTOS_DSCP_AF21;
2590 	if (options->ip_qos_bulk == -1)
2591 		options->ip_qos_bulk = IPTOS_DSCP_CS1;
2592 	if (options->request_tty == -1)
2593 		options->request_tty = REQUEST_TTY_AUTO;
2594 	if (options->session_type == -1)
2595 		options->session_type = SESSION_TYPE_DEFAULT;
2596 	if (options->stdin_null == -1)
2597 		options->stdin_null = 0;
2598 	if (options->fork_after_authentication == -1)
2599 		options->fork_after_authentication = 0;
2600 	if (options->proxy_use_fdpass == -1)
2601 		options->proxy_use_fdpass = 0;
2602 	if (options->canonicalize_max_dots == -1)
2603 		options->canonicalize_max_dots = 1;
2604 	if (options->canonicalize_fallback_local == -1)
2605 		options->canonicalize_fallback_local = 1;
2606 	if (options->canonicalize_hostname == -1)
2607 		options->canonicalize_hostname = SSH_CANONICALISE_NO;
2608 	if (options->fingerprint_hash == -1)
2609 		options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
2610 	if (options->sk_provider == NULL)
2611 		options->sk_provider = xstrdup("internal");
2612 
2613 	/* Expand KEX name lists */
2614 	all_cipher = cipher_alg_list(',', 0);
2615 	all_mac = mac_alg_list(',');
2616 	all_kex = kex_alg_list(',');
2617 	all_key = sshkey_alg_list(0, 0, 1, ',');
2618 	all_sig = sshkey_alg_list(0, 1, 1, ',');
2619 	/* remove unsupported algos from default lists */
2620 	def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher);
2621 	def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac);
2622 	def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex);
2623 	def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
2624 	def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig);
2625 #define ASSEMBLE(what, defaults, all) \
2626 	do { \
2627 		if ((r = kex_assemble_names(&options->what, \
2628 		    defaults, all)) != 0) { \
2629 			error_fr(r, "%s", #what); \
2630 			goto fail; \
2631 		} \
2632 	} while (0)
2633 	ASSEMBLE(ciphers, def_cipher, all_cipher);
2634 	ASSEMBLE(macs, def_mac, all_mac);
2635 	ASSEMBLE(kex_algorithms, def_kex, all_kex);
2636 	ASSEMBLE(hostbased_accepted_algos, def_key, all_key);
2637 	ASSEMBLE(pubkey_accepted_algos, def_key, all_key);
2638 	ASSEMBLE(ca_sign_algorithms, def_sig, all_sig);
2639 #undef ASSEMBLE
2640 
2641 #define CLEAR_ON_NONE(v) \
2642 	do { \
2643 		if (option_clear_or_none(v)) { \
2644 			free(v); \
2645 			v = NULL; \
2646 		} \
2647 	} while(0)
2648 	CLEAR_ON_NONE(options->local_command);
2649 	CLEAR_ON_NONE(options->remote_command);
2650 	CLEAR_ON_NONE(options->proxy_command);
2651 	CLEAR_ON_NONE(options->control_path);
2652 	CLEAR_ON_NONE(options->revoked_host_keys);
2653 	CLEAR_ON_NONE(options->pkcs11_provider);
2654 	CLEAR_ON_NONE(options->sk_provider);
2655 	CLEAR_ON_NONE(options->known_hosts_command);
2656 	if (options->jump_host != NULL &&
2657 	    strcmp(options->jump_host, "none") == 0 &&
2658 	    options->jump_port == 0 && options->jump_user == NULL) {
2659 		free(options->jump_host);
2660 		options->jump_host = NULL;
2661 	}
2662 	if (options->num_permitted_cnames == 1 &&
2663 	    !config_has_permitted_cnames(options)) {
2664 		/* clean up CanonicalizePermittedCNAMEs=none */
2665 		free(options->permitted_cnames[0].source_list);
2666 		free(options->permitted_cnames[0].target_list);
2667 		memset(options->permitted_cnames, '\0',
2668 		    sizeof(*options->permitted_cnames));
2669 		options->num_permitted_cnames = 0;
2670 	}
2671 	/* options->identity_agent distinguishes NULL from 'none' */
2672 	/* options->user will be set in the main program if appropriate */
2673 	/* options->hostname will be set in the main program if appropriate */
2674 	/* options->host_key_alias should not be set by default */
2675 	/* options->preferred_authentications will be set in ssh */
2676 
2677 	/* success */
2678 	ret = 0;
2679  fail:
2680 	free(all_cipher);
2681 	free(all_mac);
2682 	free(all_kex);
2683 	free(all_key);
2684 	free(all_sig);
2685 	free(def_cipher);
2686 	free(def_mac);
2687 	free(def_kex);
2688 	free(def_key);
2689 	free(def_sig);
2690 	return ret;
2691 }
2692 
2693 void
2694 free_options(Options *o)
2695 {
2696 	int i;
2697 
2698 	if (o == NULL)
2699 		return;
2700 
2701 #define FREE_ARRAY(type, n, a) \
2702 	do { \
2703 		type _i; \
2704 		for (_i = 0; _i < (n); _i++) \
2705 			free((a)[_i]); \
2706 	} while (0)
2707 
2708 	free(o->forward_agent_sock_path);
2709 	free(o->xauth_location);
2710 	FREE_ARRAY(u_int, o->num_log_verbose, o->log_verbose);
2711 	free(o->log_verbose);
2712 	free(o->ciphers);
2713 	free(o->macs);
2714 	free(o->hostkeyalgorithms);
2715 	free(o->kex_algorithms);
2716 	free(o->ca_sign_algorithms);
2717 	free(o->hostname);
2718 	free(o->host_key_alias);
2719 	free(o->proxy_command);
2720 	free(o->user);
2721 	FREE_ARRAY(u_int, o->num_system_hostfiles, o->system_hostfiles);
2722 	FREE_ARRAY(u_int, o->num_user_hostfiles, o->user_hostfiles);
2723 	free(o->preferred_authentications);
2724 	free(o->bind_address);
2725 	free(o->bind_interface);
2726 	free(o->pkcs11_provider);
2727 	free(o->sk_provider);
2728 	for (i = 0; i < o->num_identity_files; i++) {
2729 		free(o->identity_files[i]);
2730 		sshkey_free(o->identity_keys[i]);
2731 	}
2732 	for (i = 0; i < o->num_certificate_files; i++) {
2733 		free(o->certificate_files[i]);
2734 		sshkey_free(o->certificates[i]);
2735 	}
2736 	free(o->identity_agent);
2737 	for (i = 0; i < o->num_local_forwards; i++) {
2738 		free(o->local_forwards[i].listen_host);
2739 		free(o->local_forwards[i].listen_path);
2740 		free(o->local_forwards[i].connect_host);
2741 		free(o->local_forwards[i].connect_path);
2742 	}
2743 	free(o->local_forwards);
2744 	for (i = 0; i < o->num_remote_forwards; i++) {
2745 		free(o->remote_forwards[i].listen_host);
2746 		free(o->remote_forwards[i].listen_path);
2747 		free(o->remote_forwards[i].connect_host);
2748 		free(o->remote_forwards[i].connect_path);
2749 	}
2750 	free(o->remote_forwards);
2751 	free(o->stdio_forward_host);
2752 	FREE_ARRAY(int, o->num_send_env, o->send_env);
2753 	free(o->send_env);
2754 	FREE_ARRAY(int, o->num_setenv, o->setenv);
2755 	free(o->setenv);
2756 	free(o->control_path);
2757 	free(o->local_command);
2758 	free(o->remote_command);
2759 	FREE_ARRAY(int, o->num_canonical_domains, o->canonical_domains);
2760 	for (i = 0; i < o->num_permitted_cnames; i++) {
2761 		free(o->permitted_cnames[i].source_list);
2762 		free(o->permitted_cnames[i].target_list);
2763 	}
2764 	free(o->revoked_host_keys);
2765 	free(o->hostbased_accepted_algos);
2766 	free(o->pubkey_accepted_algos);
2767 	free(o->jump_user);
2768 	free(o->jump_host);
2769 	free(o->jump_extra);
2770 	free(o->ignored_unknown);
2771 	explicit_bzero(o, sizeof(*o));
2772 #undef FREE_ARRAY
2773 }
2774 
2775 struct fwdarg {
2776 	char *arg;
2777 	int ispath;
2778 };
2779 
2780 /*
2781  * parse_fwd_field
2782  * parses the next field in a port forwarding specification.
2783  * sets fwd to the parsed field and advances p past the colon
2784  * or sets it to NULL at end of string.
2785  * returns 0 on success, else non-zero.
2786  */
2787 static int
2788 parse_fwd_field(char **p, struct fwdarg *fwd)
2789 {
2790 	char *ep, *cp = *p;
2791 	int ispath = 0;
2792 
2793 	if (*cp == '\0') {
2794 		*p = NULL;
2795 		return -1;	/* end of string */
2796 	}
2797 
2798 	/*
2799 	 * A field escaped with square brackets is used literally.
2800 	 * XXX - allow ']' to be escaped via backslash?
2801 	 */
2802 	if (*cp == '[') {
2803 		/* find matching ']' */
2804 		for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
2805 			if (*ep == '/')
2806 				ispath = 1;
2807 		}
2808 		/* no matching ']' or not at end of field. */
2809 		if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
2810 			return -1;
2811 		/* NUL terminate the field and advance p past the colon */
2812 		*ep++ = '\0';
2813 		if (*ep != '\0')
2814 			*ep++ = '\0';
2815 		fwd->arg = cp + 1;
2816 		fwd->ispath = ispath;
2817 		*p = ep;
2818 		return 0;
2819 	}
2820 
2821 	for (cp = *p; *cp != '\0'; cp++) {
2822 		switch (*cp) {
2823 		case '\\':
2824 			memmove(cp, cp + 1, strlen(cp + 1) + 1);
2825 			if (*cp == '\0')
2826 				return -1;
2827 			break;
2828 		case '/':
2829 			ispath = 1;
2830 			break;
2831 		case ':':
2832 			*cp++ = '\0';
2833 			goto done;
2834 		}
2835 	}
2836 done:
2837 	fwd->arg = *p;
2838 	fwd->ispath = ispath;
2839 	*p = cp;
2840 	return 0;
2841 }
2842 
2843 /*
2844  * parse_forward
2845  * parses a string containing a port forwarding specification of the form:
2846  *   dynamicfwd == 0
2847  *	[listenhost:]listenport|listenpath:connecthost:connectport|connectpath
2848  *	listenpath:connectpath
2849  *   dynamicfwd == 1
2850  *	[listenhost:]listenport
2851  * returns number of arguments parsed or zero on error
2852  */
2853 int
2854 parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
2855 {
2856 	struct fwdarg fwdargs[4];
2857 	char *p, *cp;
2858 	int i, err;
2859 
2860 	memset(fwd, 0, sizeof(*fwd));
2861 	memset(fwdargs, 0, sizeof(fwdargs));
2862 
2863 	/*
2864 	 * We expand environment variables before checking if we think they're
2865 	 * paths so that if ${VAR} expands to a fully qualified path it is
2866 	 * treated as a path.
2867 	 */
2868 	cp = p = dollar_expand(&err, fwdspec);
2869 	if (p == NULL || err)
2870 		return 0;
2871 
2872 	/* skip leading spaces */
2873 	while (isspace((u_char)*cp))
2874 		cp++;
2875 
2876 	for (i = 0; i < 4; ++i) {
2877 		if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
2878 			break;
2879 	}
2880 
2881 	/* Check for trailing garbage */
2882 	if (cp != NULL && *cp != '\0') {
2883 		i = 0;	/* failure */
2884 	}
2885 
2886 	switch (i) {
2887 	case 1:
2888 		if (fwdargs[0].ispath) {
2889 			fwd->listen_path = xstrdup(fwdargs[0].arg);
2890 			fwd->listen_port = PORT_STREAMLOCAL;
2891 		} else {
2892 			fwd->listen_host = NULL;
2893 			fwd->listen_port = a2port(fwdargs[0].arg);
2894 		}
2895 		fwd->connect_host = xstrdup("socks");
2896 		break;
2897 
2898 	case 2:
2899 		if (fwdargs[0].ispath && fwdargs[1].ispath) {
2900 			fwd->listen_path = xstrdup(fwdargs[0].arg);
2901 			fwd->listen_port = PORT_STREAMLOCAL;
2902 			fwd->connect_path = xstrdup(fwdargs[1].arg);
2903 			fwd->connect_port = PORT_STREAMLOCAL;
2904 		} else if (fwdargs[1].ispath) {
2905 			fwd->listen_host = NULL;
2906 			fwd->listen_port = a2port(fwdargs[0].arg);
2907 			fwd->connect_path = xstrdup(fwdargs[1].arg);
2908 			fwd->connect_port = PORT_STREAMLOCAL;
2909 		} else {
2910 			fwd->listen_host = xstrdup(fwdargs[0].arg);
2911 			fwd->listen_port = a2port(fwdargs[1].arg);
2912 			fwd->connect_host = xstrdup("socks");
2913 		}
2914 		break;
2915 
2916 	case 3:
2917 		if (fwdargs[0].ispath) {
2918 			fwd->listen_path = xstrdup(fwdargs[0].arg);
2919 			fwd->listen_port = PORT_STREAMLOCAL;
2920 			fwd->connect_host = xstrdup(fwdargs[1].arg);
2921 			fwd->connect_port = a2port(fwdargs[2].arg);
2922 		} else if (fwdargs[2].ispath) {
2923 			fwd->listen_host = xstrdup(fwdargs[0].arg);
2924 			fwd->listen_port = a2port(fwdargs[1].arg);
2925 			fwd->connect_path = xstrdup(fwdargs[2].arg);
2926 			fwd->connect_port = PORT_STREAMLOCAL;
2927 		} else {
2928 			fwd->listen_host = NULL;
2929 			fwd->listen_port = a2port(fwdargs[0].arg);
2930 			fwd->connect_host = xstrdup(fwdargs[1].arg);
2931 			fwd->connect_port = a2port(fwdargs[2].arg);
2932 		}
2933 		break;
2934 
2935 	case 4:
2936 		fwd->listen_host = xstrdup(fwdargs[0].arg);
2937 		fwd->listen_port = a2port(fwdargs[1].arg);
2938 		fwd->connect_host = xstrdup(fwdargs[2].arg);
2939 		fwd->connect_port = a2port(fwdargs[3].arg);
2940 		break;
2941 	default:
2942 		i = 0; /* failure */
2943 	}
2944 
2945 	free(p);
2946 
2947 	if (dynamicfwd) {
2948 		if (!(i == 1 || i == 2))
2949 			goto fail_free;
2950 	} else {
2951 		if (!(i == 3 || i == 4)) {
2952 			if (fwd->connect_path == NULL &&
2953 			    fwd->listen_path == NULL)
2954 				goto fail_free;
2955 		}
2956 		if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
2957 			goto fail_free;
2958 	}
2959 
2960 	if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
2961 	    (!remotefwd && fwd->listen_port == 0))
2962 		goto fail_free;
2963 	if (fwd->connect_host != NULL &&
2964 	    strlen(fwd->connect_host) >= NI_MAXHOST)
2965 		goto fail_free;
2966 	/*
2967 	 * XXX - if connecting to a remote socket, max sun len may not
2968 	 * match this host
2969 	 */
2970 	if (fwd->connect_path != NULL &&
2971 	    strlen(fwd->connect_path) >= PATH_MAX_SUN)
2972 		goto fail_free;
2973 	if (fwd->listen_host != NULL &&
2974 	    strlen(fwd->listen_host) >= NI_MAXHOST)
2975 		goto fail_free;
2976 	if (fwd->listen_path != NULL &&
2977 	    strlen(fwd->listen_path) >= PATH_MAX_SUN)
2978 		goto fail_free;
2979 
2980 	return (i);
2981 
2982  fail_free:
2983 	free(fwd->connect_host);
2984 	fwd->connect_host = NULL;
2985 	free(fwd->connect_path);
2986 	fwd->connect_path = NULL;
2987 	free(fwd->listen_host);
2988 	fwd->listen_host = NULL;
2989 	free(fwd->listen_path);
2990 	fwd->listen_path = NULL;
2991 	return (0);
2992 }
2993 
2994 int
2995 parse_jump(const char *s, Options *o, int active)
2996 {
2997 	char *orig, *sdup, *cp;
2998 	char *host = NULL, *user = NULL;
2999 	int r, ret = -1, port = -1, first;
3000 
3001 	active &= o->proxy_command == NULL && o->jump_host == NULL;
3002 
3003 	orig = sdup = xstrdup(s);
3004 
3005 	/* Remove comment and trailing whitespace */
3006 	if ((cp = strchr(orig, '#')) != NULL)
3007 		*cp = '\0';
3008 	rtrim(orig);
3009 
3010 	first = active;
3011 	do {
3012 		if (strcasecmp(s, "none") == 0)
3013 			break;
3014 		if ((cp = strrchr(sdup, ',')) == NULL)
3015 			cp = sdup; /* last */
3016 		else
3017 			*cp++ = '\0';
3018 
3019 		if (first) {
3020 			/* First argument and configuration is active */
3021 			r = parse_ssh_uri(cp, &user, &host, &port);
3022 			if (r == -1 || (r == 1 &&
3023 			    parse_user_host_port(cp, &user, &host, &port) != 0))
3024 				goto out;
3025 		} else {
3026 			/* Subsequent argument or inactive configuration */
3027 			r = parse_ssh_uri(cp, NULL, NULL, NULL);
3028 			if (r == -1 || (r == 1 &&
3029 			    parse_user_host_port(cp, NULL, NULL, NULL) != 0))
3030 				goto out;
3031 		}
3032 		first = 0; /* only check syntax for subsequent hosts */
3033 	} while (cp != sdup);
3034 	/* success */
3035 	if (active) {
3036 		if (strcasecmp(s, "none") == 0) {
3037 			o->jump_host = xstrdup("none");
3038 			o->jump_port = 0;
3039 		} else {
3040 			o->jump_user = user;
3041 			o->jump_host = host;
3042 			o->jump_port = port;
3043 			o->proxy_command = xstrdup("none");
3044 			user = host = NULL;
3045 			if ((cp = strrchr(s, ',')) != NULL && cp != s) {
3046 				o->jump_extra = xstrdup(s);
3047 				o->jump_extra[cp - s] = '\0';
3048 			}
3049 		}
3050 	}
3051 	ret = 0;
3052  out:
3053 	free(orig);
3054 	free(user);
3055 	free(host);
3056 	return ret;
3057 }
3058 
3059 int
3060 parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp)
3061 {
3062 	char *user = NULL, *host = NULL, *path = NULL;
3063 	int r, port;
3064 
3065 	r = parse_uri("ssh", uri, &user, &host, &port, &path);
3066 	if (r == 0 && path != NULL)
3067 		r = -1;		/* path not allowed */
3068 	if (r == 0) {
3069 		if (userp != NULL) {
3070 			*userp = user;
3071 			user = NULL;
3072 		}
3073 		if (hostp != NULL) {
3074 			*hostp = host;
3075 			host = NULL;
3076 		}
3077 		if (portp != NULL)
3078 			*portp = port;
3079 	}
3080 	free(user);
3081 	free(host);
3082 	free(path);
3083 	return r;
3084 }
3085 
3086 /* XXX the following is a near-vebatim copy from servconf.c; refactor */
3087 static const char *
3088 fmt_multistate_int(int val, const struct multistate *m)
3089 {
3090 	u_int i;
3091 
3092 	for (i = 0; m[i].key != NULL; i++) {
3093 		if (m[i].value == val)
3094 			return m[i].key;
3095 	}
3096 	return "UNKNOWN";
3097 }
3098 
3099 static const char *
3100 fmt_intarg(OpCodes code, int val)
3101 {
3102 	if (val == -1)
3103 		return "unset";
3104 	switch (code) {
3105 	case oAddressFamily:
3106 		return fmt_multistate_int(val, multistate_addressfamily);
3107 	case oVerifyHostKeyDNS:
3108 	case oUpdateHostkeys:
3109 		return fmt_multistate_int(val, multistate_yesnoask);
3110 	case oStrictHostKeyChecking:
3111 		return fmt_multistate_int(val, multistate_strict_hostkey);
3112 	case oControlMaster:
3113 		return fmt_multistate_int(val, multistate_controlmaster);
3114 	case oTunnel:
3115 		return fmt_multistate_int(val, multistate_tunnel);
3116 	case oRequestTTY:
3117 		return fmt_multistate_int(val, multistate_requesttty);
3118 	case oSessionType:
3119 		return fmt_multistate_int(val, multistate_sessiontype);
3120 	case oCanonicalizeHostname:
3121 		return fmt_multistate_int(val, multistate_canonicalizehostname);
3122 	case oAddKeysToAgent:
3123 		return fmt_multistate_int(val, multistate_yesnoaskconfirm);
3124 	case oPubkeyAuthentication:
3125 		return fmt_multistate_int(val, multistate_pubkey_auth);
3126 	case oFingerprintHash:
3127 		return ssh_digest_alg_name(val);
3128 	default:
3129 		switch (val) {
3130 		case 0:
3131 			return "no";
3132 		case 1:
3133 			return "yes";
3134 		default:
3135 			return "UNKNOWN";
3136 		}
3137 	}
3138 }
3139 
3140 static const char *
3141 lookup_opcode_name(OpCodes code)
3142 {
3143 	u_int i;
3144 
3145 	for (i = 0; keywords[i].name != NULL; i++)
3146 		if (keywords[i].opcode == code)
3147 			return(keywords[i].name);
3148 	return "UNKNOWN";
3149 }
3150 
3151 static void
3152 dump_cfg_int(OpCodes code, int val)
3153 {
3154 	printf("%s %d\n", lookup_opcode_name(code), val);
3155 }
3156 
3157 static void
3158 dump_cfg_fmtint(OpCodes code, int val)
3159 {
3160 	printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
3161 }
3162 
3163 static void
3164 dump_cfg_string(OpCodes code, const char *val)
3165 {
3166 	if (val == NULL)
3167 		return;
3168 	printf("%s %s\n", lookup_opcode_name(code), val);
3169 }
3170 
3171 static void
3172 dump_cfg_strarray(OpCodes code, u_int count, char **vals)
3173 {
3174 	u_int i;
3175 
3176 	for (i = 0; i < count; i++)
3177 		printf("%s %s\n", lookup_opcode_name(code), vals[i]);
3178 }
3179 
3180 static void
3181 dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals)
3182 {
3183 	u_int i;
3184 
3185 	printf("%s", lookup_opcode_name(code));
3186 	if (count == 0)
3187 		printf(" none");
3188 	for (i = 0; i < count; i++)
3189 		printf(" %s",  vals[i]);
3190 	printf("\n");
3191 }
3192 
3193 static void
3194 dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds)
3195 {
3196 	const struct Forward *fwd;
3197 	u_int i;
3198 
3199 	/* oDynamicForward */
3200 	for (i = 0; i < count; i++) {
3201 		fwd = &fwds[i];
3202 		if (code == oDynamicForward && fwd->connect_host != NULL &&
3203 		    strcmp(fwd->connect_host, "socks") != 0)
3204 			continue;
3205 		if (code == oLocalForward && fwd->connect_host != NULL &&
3206 		    strcmp(fwd->connect_host, "socks") == 0)
3207 			continue;
3208 		printf("%s", lookup_opcode_name(code));
3209 		if (fwd->listen_port == PORT_STREAMLOCAL)
3210 			printf(" %s", fwd->listen_path);
3211 		else if (fwd->listen_host == NULL)
3212 			printf(" %d", fwd->listen_port);
3213 		else {
3214 			printf(" [%s]:%d",
3215 			    fwd->listen_host, fwd->listen_port);
3216 		}
3217 		if (code != oDynamicForward) {
3218 			if (fwd->connect_port == PORT_STREAMLOCAL)
3219 				printf(" %s", fwd->connect_path);
3220 			else if (fwd->connect_host == NULL)
3221 				printf(" %d", fwd->connect_port);
3222 			else {
3223 				printf(" [%s]:%d",
3224 				    fwd->connect_host, fwd->connect_port);
3225 			}
3226 		}
3227 		printf("\n");
3228 	}
3229 }
3230 
3231 void
3232 dump_client_config(Options *o, const char *host)
3233 {
3234 	int i, r;
3235 	char buf[8], *all_key;
3236 
3237 	/*
3238 	 * Expand HostKeyAlgorithms name lists. This isn't handled in
3239 	 * fill_default_options() like the other algorithm lists because
3240 	 * the host key algorithms are by default dynamically chosen based
3241 	 * on the host's keys found in known_hosts.
3242 	 */
3243 	all_key = sshkey_alg_list(0, 0, 1, ',');
3244 	if ((r = kex_assemble_names(&o->hostkeyalgorithms, kex_default_pk_alg(),
3245 	    all_key)) != 0)
3246 		fatal_fr(r, "expand HostKeyAlgorithms");
3247 	free(all_key);
3248 
3249 	/* Most interesting options first: user, host, port */
3250 	dump_cfg_string(oUser, o->user);
3251 	dump_cfg_string(oHostname, host);
3252 	dump_cfg_int(oPort, o->port);
3253 
3254 	/* Flag options */
3255 	dump_cfg_fmtint(oAddressFamily, o->address_family);
3256 	dump_cfg_fmtint(oBatchMode, o->batch_mode);
3257 	dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local);
3258 	dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname);
3259 	dump_cfg_fmtint(oCheckHostIP, o->check_host_ip);
3260 	dump_cfg_fmtint(oCompression, o->compression);
3261 	dump_cfg_fmtint(oControlMaster, o->control_master);
3262 	dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
3263 	dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings);
3264 	dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
3265 	dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash);
3266 	dump_cfg_fmtint(oForwardX11, o->forward_x11);
3267 	dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted);
3268 	dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports);
3269 #ifdef GSSAPI
3270 	dump_cfg_fmtint(oGssAuthentication, o->gss_authentication);
3271 	dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds);
3272 #endif /* GSSAPI */
3273 	dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);
3274 	dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);
3275 	dump_cfg_fmtint(oIdentitiesOnly, o->identities_only);
3276 	dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication);
3277 	dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost);
3278 	dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication);
3279 	dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command);
3280 	dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass);
3281 	dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
3282 	dump_cfg_fmtint(oRequestTTY, o->request_tty);
3283 	dump_cfg_fmtint(oSessionType, o->session_type);
3284 	dump_cfg_fmtint(oStdinNull, o->stdin_null);
3285 	dump_cfg_fmtint(oForkAfterAuthentication, o->fork_after_authentication);
3286 	dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
3287 	dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
3288 	dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
3289 	dump_cfg_fmtint(oTunnel, o->tun_open);
3290 	dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns);
3291 	dump_cfg_fmtint(oVisualHostKey, o->visual_host_key);
3292 	dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys);
3293 
3294 	/* Integer options */
3295 	dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots);
3296 	dump_cfg_int(oConnectionAttempts, o->connection_attempts);
3297 	dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout);
3298 	dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
3299 	dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
3300 	dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
3301 
3302 	/* String options */
3303 	dump_cfg_string(oBindAddress, o->bind_address);
3304 	dump_cfg_string(oBindInterface, o->bind_interface);
3305 	dump_cfg_string(oCiphers, o->ciphers);
3306 	dump_cfg_string(oControlPath, o->control_path);
3307 	dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms);
3308 	dump_cfg_string(oHostKeyAlias, o->host_key_alias);
3309 	dump_cfg_string(oHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos);
3310 	dump_cfg_string(oIdentityAgent, o->identity_agent);
3311 	dump_cfg_string(oIgnoreUnknown, o->ignored_unknown);
3312 	dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
3313 	dump_cfg_string(oKexAlgorithms, o->kex_algorithms);
3314 	dump_cfg_string(oCASignatureAlgorithms, o->ca_sign_algorithms);
3315 	dump_cfg_string(oLocalCommand, o->local_command);
3316 	dump_cfg_string(oRemoteCommand, o->remote_command);
3317 	dump_cfg_string(oLogLevel, log_level_name(o->log_level));
3318 	dump_cfg_string(oMacs, o->macs);
3319 #ifdef ENABLE_PKCS11
3320 	dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
3321 #endif
3322 	dump_cfg_string(oSecurityKeyProvider, o->sk_provider);
3323 	dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
3324 	dump_cfg_string(oPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos);
3325 	dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
3326 	dump_cfg_string(oXAuthLocation, o->xauth_location);
3327 	dump_cfg_string(oKnownHostsCommand, o->known_hosts_command);
3328 
3329 	/* Forwards */
3330 	dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
3331 	dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards);
3332 	dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards);
3333 
3334 	/* String array options */
3335 	dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files);
3336 	dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains);
3337 	dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files);
3338 	dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles);
3339 	dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles);
3340 	dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env);
3341 	dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv);
3342 	dump_cfg_strarray_oneline(oLogVerbose,
3343 	    o->num_log_verbose, o->log_verbose);
3344 
3345 	/* Special cases */
3346 
3347 	/* PermitRemoteOpen */
3348 	if (o->num_permitted_remote_opens == 0)
3349 		printf("%s any\n", lookup_opcode_name(oPermitRemoteOpen));
3350 	else
3351 		dump_cfg_strarray_oneline(oPermitRemoteOpen,
3352 		    o->num_permitted_remote_opens, o->permitted_remote_opens);
3353 
3354 	/* AddKeysToAgent */
3355 	if (o->add_keys_to_agent_lifespan <= 0)
3356 		dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent);
3357 	else {
3358 		printf("addkeystoagent%s %d\n",
3359 		    o->add_keys_to_agent == 3 ? " confirm" : "",
3360 		    o->add_keys_to_agent_lifespan);
3361 	}
3362 
3363 	/* oForwardAgent */
3364 	if (o->forward_agent_sock_path == NULL)
3365 		dump_cfg_fmtint(oForwardAgent, o->forward_agent);
3366 	else
3367 		dump_cfg_string(oForwardAgent, o->forward_agent_sock_path);
3368 
3369 	/* oConnectTimeout */
3370 	if (o->connection_timeout == -1)
3371 		printf("connecttimeout none\n");
3372 	else
3373 		dump_cfg_int(oConnectTimeout, o->connection_timeout);
3374 
3375 	/* oTunnelDevice */
3376 	printf("tunneldevice");
3377 	if (o->tun_local == SSH_TUNID_ANY)
3378 		printf(" any");
3379 	else
3380 		printf(" %d", o->tun_local);
3381 	if (o->tun_remote == SSH_TUNID_ANY)
3382 		printf(":any");
3383 	else
3384 		printf(":%d", o->tun_remote);
3385 	printf("\n");
3386 
3387 	/* oCanonicalizePermittedCNAMEs */
3388 	printf("canonicalizePermittedcnames");
3389 	if (o->num_permitted_cnames == 0)
3390 		printf(" none");
3391 	for (i = 0; i < o->num_permitted_cnames; i++) {
3392 		printf(" %s:%s", o->permitted_cnames[i].source_list,
3393 		    o->permitted_cnames[i].target_list);
3394 	}
3395 	printf("\n");
3396 
3397 	/* oControlPersist */
3398 	if (o->control_persist == 0 || o->control_persist_timeout == 0)
3399 		dump_cfg_fmtint(oControlPersist, o->control_persist);
3400 	else
3401 		dump_cfg_int(oControlPersist, o->control_persist_timeout);
3402 
3403 	/* oEscapeChar */
3404 	if (o->escape_char == SSH_ESCAPECHAR_NONE)
3405 		printf("escapechar none\n");
3406 	else {
3407 		vis(buf, o->escape_char, VIS_WHITE, 0);
3408 		printf("escapechar %s\n", buf);
3409 	}
3410 
3411 	/* oIPQoS */
3412 	printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
3413 	printf("%s\n", iptos2str(o->ip_qos_bulk));
3414 
3415 	/* oRekeyLimit */
3416 	printf("rekeylimit %llu %d\n",
3417 	    (unsigned long long)o->rekey_limit, o->rekey_interval);
3418 
3419 	/* oStreamLocalBindMask */
3420 	printf("streamlocalbindmask 0%o\n",
3421 	    o->fwd_opts.streamlocal_bind_mask);
3422 
3423 	/* oLogFacility */
3424 	printf("syslogfacility %s\n", log_facility_name(o->log_facility));
3425 
3426 	/* oProxyCommand / oProxyJump */
3427 	if (o->jump_host == NULL)
3428 		dump_cfg_string(oProxyCommand, o->proxy_command);
3429 	else {
3430 		/* Check for numeric addresses */
3431 		i = strchr(o->jump_host, ':') != NULL ||
3432 		    strspn(o->jump_host, "1234567890.") == strlen(o->jump_host);
3433 		snprintf(buf, sizeof(buf), "%d", o->jump_port);
3434 		printf("proxyjump %s%s%s%s%s%s%s%s%s\n",
3435 		    /* optional additional jump spec */
3436 		    o->jump_extra == NULL ? "" : o->jump_extra,
3437 		    o->jump_extra == NULL ? "" : ",",
3438 		    /* optional user */
3439 		    o->jump_user == NULL ? "" : o->jump_user,
3440 		    o->jump_user == NULL ? "" : "@",
3441 		    /* opening [ if hostname is numeric */
3442 		    i ? "[" : "",
3443 		    /* mandatory hostname */
3444 		    o->jump_host,
3445 		    /* closing ] if hostname is numeric */
3446 		    i ? "]" : "",
3447 		    /* optional port number */
3448 		    o->jump_port <= 0 ? "" : ":",
3449 		    o->jump_port <= 0 ? "" : buf);
3450 	}
3451 }
3452