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