xref: /freebsd/crypto/openssh/readconf.c (revision 3332f1b444d4a73238e9f59cca27bfc95fe936bd)
1 /* $OpenBSD: readconf.c,v 1.361 2021/07/23 04:04:52 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 __RCSID("$FreeBSD$");
17 
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <sys/socket.h>
21 #include <sys/wait.h>
22 #include <sys/un.h>
23 
24 #include <netinet/in.h>
25 #include <netinet/in_systm.h>
26 #include <netinet/ip.h>
27 #include <arpa/inet.h>
28 
29 #include <ctype.h>
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <limits.h>
33 #include <netdb.h>
34 #ifdef HAVE_PATHS_H
35 # include <paths.h>
36 #endif
37 #include <pwd.h>
38 #include <signal.h>
39 #include <stdio.h>
40 #include <string.h>
41 #include <stdarg.h>
42 #include <unistd.h>
43 #ifdef USE_SYSTEM_GLOB
44 # include <glob.h>
45 #else
46 # include "openbsd-compat/glob.h"
47 #endif
48 #ifdef HAVE_UTIL_H
49 #include <util.h>
50 #endif
51 #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS)
52 # include <vis.h>
53 #endif
54 
55 #include "xmalloc.h"
56 #include "ssh.h"
57 #include "ssherr.h"
58 #include "compat.h"
59 #include "cipher.h"
60 #include "pathnames.h"
61 #include "log.h"
62 #include "sshkey.h"
63 #include "misc.h"
64 #include "readconf.h"
65 #include "match.h"
66 #include "kex.h"
67 #include "mac.h"
68 #include "uidswap.h"
69 #include "myproposal.h"
70 #include "digest.h"
71 #include "version.h"
72 
73 /* Format of the configuration file:
74 
75    # Configuration data is parsed as follows:
76    #  1. command line options
77    #  2. user-specific file
78    #  3. system-wide file
79    # Any configuration value is only changed the first time it is set.
80    # Thus, host-specific definitions should be at the beginning of the
81    # configuration file, and defaults at the end.
82 
83    # Host-specific declarations.  These may override anything above.  A single
84    # host may match multiple declarations; these are processed in the order
85    # that they are given in.
86 
87    Host *.ngs.fi ngs.fi
88      User foo
89 
90    Host fake.com
91      Hostname another.host.name.real.org
92      User blaah
93      Port 34289
94      ForwardX11 no
95      ForwardAgent no
96 
97    Host books.com
98      RemoteForward 9999 shadows.cs.hut.fi:9999
99      Ciphers 3des-cbc
100 
101    Host fascist.blob.com
102      Port 23123
103      User tylonen
104      PasswordAuthentication no
105 
106    Host puukko.hut.fi
107      User t35124p
108      ProxyCommand ssh-proxy %h %p
109 
110    Host *.fr
111      PublicKeyAuthentication no
112 
113    Host *.su
114      Ciphers aes128-ctr
115      PasswordAuthentication no
116 
117    Host vpn.fake.com
118      Tunnel yes
119      TunnelDevice 3
120 
121    # Defaults for various options
122    Host *
123      ForwardAgent no
124      ForwardX11 no
125      PasswordAuthentication yes
126      StrictHostKeyChecking yes
127      TcpKeepAlive no
128      IdentityFile ~/.ssh/identity
129      Port 22
130      EscapeChar ~
131 
132 */
133 
134 static int read_config_file_depth(const char *filename, struct passwd *pw,
135     const char *host, const char *original_host, Options *options,
136     int flags, int *activep, int *want_final_pass, int depth);
137 static int process_config_line_depth(Options *options, struct passwd *pw,
138     const char *host, const char *original_host, char *line,
139     const char *filename, int linenum, int *activep, int flags,
140     int *want_final_pass, int depth);
141 
142 /* Keyword tokens. */
143 
144 typedef enum {
145 	oBadOption,
146 	oVersionAddendum,
147 	oHost, oMatch, oInclude,
148 	oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
149 	oGatewayPorts, oExitOnForwardFailure,
150 	oPasswordAuthentication,
151 	oXAuthLocation,
152 	oIdentityFile, oHostname, oPort, oRemoteForward, oLocalForward,
153 	oPermitRemoteOpen,
154 	oCertificateFile, oAddKeysToAgent, oIdentityAgent,
155 	oUser, oEscapeChar, oProxyCommand,
156 	oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
157 	oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
158 	oTCPKeepAlive, oNumberOfPasswordPrompts,
159 	oLogFacility, oLogLevel, oLogVerbose, oCiphers, oMacs,
160 	oPubkeyAuthentication,
161 	oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
162 	oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
163 	oHostKeyAlgorithms, oBindAddress, oBindInterface, oPKCS11Provider,
164 	oClearAllForwardings, oNoHostAuthenticationForLocalhost,
165 	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
166 	oAddressFamily, oGssAuthentication, oGssDelegateCreds,
167 	oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
168 	oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist,
169 	oHashKnownHosts,
170 	oTunnel, oTunnelDevice,
171 	oLocalCommand, oPermitLocalCommand, oRemoteCommand,
172 	oVisualHostKey,
173 	oKexAlgorithms, oIPQoS, oRequestTTY, oSessionType, oStdinNull,
174 	oForkAfterAuthentication, oIgnoreUnknown, oProxyUseFdpass,
175 	oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
176 	oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
177 	oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
178 	oFingerprintHash, oUpdateHostkeys, oHostbasedAcceptedAlgorithms,
179 	oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump,
180 	oSecurityKeyProvider, oKnownHostsCommand,
181 	oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported
182 } OpCodes;
183 
184 /* Textual representations of the tokens. */
185 
186 static struct {
187 	const char *name;
188 	OpCodes opcode;
189 } keywords[] = {
190 	/* Deprecated options */
191 	{ "protocol", oIgnore }, /* NB. silently ignored */
192 	{ "cipher", oDeprecated },
193 	{ "fallbacktorsh", oDeprecated },
194 	{ "globalknownhostsfile2", oDeprecated },
195 	{ "rhostsauthentication", oDeprecated },
196 	{ "userknownhostsfile2", oDeprecated },
197 	{ "useroaming", oDeprecated },
198 	{ "usersh", oDeprecated },
199 	{ "useprivilegedport", oDeprecated },
200 
201 	/* Unsupported options */
202 	{ "afstokenpassing", oUnsupported },
203 	{ "kerberosauthentication", oUnsupported },
204 	{ "kerberostgtpassing", oUnsupported },
205 	{ "rsaauthentication", oUnsupported },
206 	{ "rhostsrsaauthentication", oUnsupported },
207 	{ "compressionlevel", oUnsupported },
208 
209 	/* Sometimes-unsupported options */
210 #if defined(GSSAPI)
211 	{ "gssapiauthentication", oGssAuthentication },
212 	{ "gssapidelegatecredentials", oGssDelegateCreds },
213 # else
214 	{ "gssapiauthentication", oUnsupported },
215 	{ "gssapidelegatecredentials", oUnsupported },
216 #endif
217 #ifdef ENABLE_PKCS11
218 	{ "pkcs11provider", oPKCS11Provider },
219 	{ "smartcarddevice", oPKCS11Provider },
220 # else
221 	{ "smartcarddevice", oUnsupported },
222 	{ "pkcs11provider", oUnsupported },
223 #endif
224 
225 	{ "forwardagent", oForwardAgent },
226 	{ "forwardx11", oForwardX11 },
227 	{ "forwardx11trusted", oForwardX11Trusted },
228 	{ "forwardx11timeout", oForwardX11Timeout },
229 	{ "exitonforwardfailure", oExitOnForwardFailure },
230 	{ "xauthlocation", oXAuthLocation },
231 	{ "gatewayports", oGatewayPorts },
232 	{ "passwordauthentication", oPasswordAuthentication },
233 	{ "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
234 	{ "kbdinteractivedevices", oKbdInteractiveDevices },
235 	{ "challengeresponseauthentication", oKbdInteractiveAuthentication }, /* alias */
236 	{ "skeyauthentication", oKbdInteractiveAuthentication }, /* alias */
237 	{ "tisauthentication", oKbdInteractiveAuthentication },  /* alias */
238 	{ "pubkeyauthentication", oPubkeyAuthentication },
239 	{ "dsaauthentication", oPubkeyAuthentication },		    /* alias */
240 	{ "hostbasedauthentication", oHostbasedAuthentication },
241 	{ "identityfile", oIdentityFile },
242 	{ "identityfile2", oIdentityFile },			/* obsolete */
243 	{ "identitiesonly", oIdentitiesOnly },
244 	{ "certificatefile", oCertificateFile },
245 	{ "addkeystoagent", oAddKeysToAgent },
246 	{ "identityagent", oIdentityAgent },
247 	{ "hostname", oHostname },
248 	{ "hostkeyalias", oHostKeyAlias },
249 	{ "proxycommand", oProxyCommand },
250 	{ "port", oPort },
251 	{ "ciphers", oCiphers },
252 	{ "macs", oMacs },
253 	{ "remoteforward", oRemoteForward },
254 	{ "localforward", oLocalForward },
255 	{ "permitremoteopen", oPermitRemoteOpen },
256 	{ "user", oUser },
257 	{ "host", oHost },
258 	{ "match", oMatch },
259 	{ "escapechar", oEscapeChar },
260 	{ "globalknownhostsfile", oGlobalKnownHostsFile },
261 	{ "userknownhostsfile", oUserKnownHostsFile },
262 	{ "connectionattempts", oConnectionAttempts },
263 	{ "batchmode", oBatchMode },
264 	{ "checkhostip", oCheckHostIP },
265 	{ "stricthostkeychecking", oStrictHostKeyChecking },
266 	{ "compression", oCompression },
267 	{ "tcpkeepalive", oTCPKeepAlive },
268 	{ "keepalive", oTCPKeepAlive },				/* obsolete */
269 	{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
270 	{ "syslogfacility", oLogFacility },
271 	{ "loglevel", oLogLevel },
272 	{ "logverbose", oLogVerbose },
273 	{ "dynamicforward", oDynamicForward },
274 	{ "preferredauthentications", oPreferredAuthentications },
275 	{ "hostkeyalgorithms", oHostKeyAlgorithms },
276 	{ "casignaturealgorithms", oCASignatureAlgorithms },
277 	{ "bindaddress", oBindAddress },
278 	{ "bindinterface", oBindInterface },
279 	{ "clearallforwardings", oClearAllForwardings },
280 	{ "enablesshkeysign", oEnableSSHKeysign },
281 	{ "verifyhostkeydns", oVerifyHostKeyDNS },
282 	{ "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
283 	{ "rekeylimit", oRekeyLimit },
284 	{ "connecttimeout", oConnectTimeout },
285 	{ "addressfamily", oAddressFamily },
286 	{ "serveraliveinterval", oServerAliveInterval },
287 	{ "serveralivecountmax", oServerAliveCountMax },
288 	{ "sendenv", oSendEnv },
289 	{ "setenv", oSetEnv },
290 	{ "controlpath", oControlPath },
291 	{ "controlmaster", oControlMaster },
292 	{ "controlpersist", oControlPersist },
293 	{ "hashknownhosts", oHashKnownHosts },
294 	{ "include", oInclude },
295 	{ "tunnel", oTunnel },
296 	{ "tunneldevice", oTunnelDevice },
297 	{ "localcommand", oLocalCommand },
298 	{ "permitlocalcommand", oPermitLocalCommand },
299 	{ "remotecommand", oRemoteCommand },
300 	{ "visualhostkey", oVisualHostKey },
301 	{ "kexalgorithms", oKexAlgorithms },
302 	{ "ipqos", oIPQoS },
303 	{ "requesttty", oRequestTTY },
304 	{ "sessiontype", oSessionType },
305 	{ "stdinnull", oStdinNull },
306 	{ "forkafterauthentication", oForkAfterAuthentication },
307 	{ "proxyusefdpass", oProxyUseFdpass },
308 	{ "canonicaldomains", oCanonicalDomains },
309 	{ "canonicalizefallbacklocal", oCanonicalizeFallbackLocal },
310 	{ "canonicalizehostname", oCanonicalizeHostname },
311 	{ "canonicalizemaxdots", oCanonicalizeMaxDots },
312 	{ "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs },
313 	{ "streamlocalbindmask", oStreamLocalBindMask },
314 	{ "streamlocalbindunlink", oStreamLocalBindUnlink },
315 	{ "revokedhostkeys", oRevokedHostKeys },
316 	{ "fingerprinthash", oFingerprintHash },
317 	{ "updatehostkeys", oUpdateHostkeys },
318 	{ "hostbasedacceptedalgorithms", oHostbasedAcceptedAlgorithms },
319 	{ "hostbasedkeytypes", oHostbasedAcceptedAlgorithms }, /* obsolete */
320 	{ "pubkeyacceptedalgorithms", oPubkeyAcceptedAlgorithms },
321 	{ "pubkeyacceptedkeytypes", oPubkeyAcceptedAlgorithms }, /* obsolete */
322 	{ "ignoreunknown", oIgnoreUnknown },
323 	{ "proxyjump", oProxyJump },
324 	{ "securitykeyprovider", oSecurityKeyProvider },
325 	{ "knownhostscommand", oKnownHostsCommand },
326 
327 	{ "hpndisabled", oDeprecated },
328 	{ "hpnbuffersize", oDeprecated },
329 	{ "tcprcvbufpoll", oDeprecated },
330 	{ "tcprcvbuf", oDeprecated },
331 	{ "noneenabled", oUnsupported },
332 	{ "noneswitch", oUnsupported },
333 	{ "versionaddendum", oVersionAddendum },
334 
335 	{ NULL, oBadOption }
336 };
337 
338 static const char *lookup_opcode_name(OpCodes code);
339 
340 const char *
341 kex_default_pk_alg(void)
342 {
343 	static char *pkalgs;
344 
345 	if (pkalgs == NULL) {
346 		char *all_key;
347 
348 		all_key = sshkey_alg_list(0, 0, 1, ',');
349 		pkalgs = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
350 		free(all_key);
351 	}
352 	return pkalgs;
353 }
354 
355 char *
356 ssh_connection_hash(const char *thishost, const char *host, const char *portstr,
357     const char *user)
358 {
359 	struct ssh_digest_ctx *md;
360 	u_char conn_hash[SSH_DIGEST_MAX_LENGTH];
361 
362 	if ((md = ssh_digest_start(SSH_DIGEST_SHA1)) == NULL ||
363 	    ssh_digest_update(md, thishost, strlen(thishost)) < 0 ||
364 	    ssh_digest_update(md, host, strlen(host)) < 0 ||
365 	    ssh_digest_update(md, portstr, strlen(portstr)) < 0 ||
366 	    ssh_digest_update(md, user, strlen(user)) < 0 ||
367 	    ssh_digest_final(md, conn_hash, sizeof(conn_hash)) < 0)
368 		fatal_f("mux digest failed");
369 	ssh_digest_free(md);
370 	return tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1));
371 }
372 
373 /*
374  * Adds a local TCP/IP port forward to options.  Never returns if there is an
375  * error.
376  */
377 
378 void
379 add_local_forward(Options *options, const struct Forward *newfwd)
380 {
381 	struct Forward *fwd;
382 	int i;
383 
384 	/* Don't add duplicates */
385 	for (i = 0; i < options->num_local_forwards; i++) {
386 		if (forward_equals(newfwd, options->local_forwards + i))
387 			return;
388 	}
389 	options->local_forwards = xreallocarray(options->local_forwards,
390 	    options->num_local_forwards + 1,
391 	    sizeof(*options->local_forwards));
392 	fwd = &options->local_forwards[options->num_local_forwards++];
393 
394 	fwd->listen_host = newfwd->listen_host;
395 	fwd->listen_port = newfwd->listen_port;
396 	fwd->listen_path = newfwd->listen_path;
397 	fwd->connect_host = newfwd->connect_host;
398 	fwd->connect_port = newfwd->connect_port;
399 	fwd->connect_path = newfwd->connect_path;
400 }
401 
402 /*
403  * Adds a remote TCP/IP port forward to options.  Never returns if there is
404  * an error.
405  */
406 
407 void
408 add_remote_forward(Options *options, const struct Forward *newfwd)
409 {
410 	struct Forward *fwd;
411 	int i;
412 
413 	/* Don't add duplicates */
414 	for (i = 0; i < options->num_remote_forwards; i++) {
415 		if (forward_equals(newfwd, options->remote_forwards + i))
416 			return;
417 	}
418 	options->remote_forwards = xreallocarray(options->remote_forwards,
419 	    options->num_remote_forwards + 1,
420 	    sizeof(*options->remote_forwards));
421 	fwd = &options->remote_forwards[options->num_remote_forwards++];
422 
423 	fwd->listen_host = newfwd->listen_host;
424 	fwd->listen_port = newfwd->listen_port;
425 	fwd->listen_path = newfwd->listen_path;
426 	fwd->connect_host = newfwd->connect_host;
427 	fwd->connect_port = newfwd->connect_port;
428 	fwd->connect_path = newfwd->connect_path;
429 	fwd->handle = newfwd->handle;
430 	fwd->allocated_port = 0;
431 }
432 
433 static void
434 clear_forwardings(Options *options)
435 {
436 	int i;
437 
438 	for (i = 0; i < options->num_local_forwards; i++) {
439 		free(options->local_forwards[i].listen_host);
440 		free(options->local_forwards[i].listen_path);
441 		free(options->local_forwards[i].connect_host);
442 		free(options->local_forwards[i].connect_path);
443 	}
444 	if (options->num_local_forwards > 0) {
445 		free(options->local_forwards);
446 		options->local_forwards = NULL;
447 	}
448 	options->num_local_forwards = 0;
449 	for (i = 0; i < options->num_remote_forwards; i++) {
450 		free(options->remote_forwards[i].listen_host);
451 		free(options->remote_forwards[i].listen_path);
452 		free(options->remote_forwards[i].connect_host);
453 		free(options->remote_forwards[i].connect_path);
454 	}
455 	if (options->num_remote_forwards > 0) {
456 		free(options->remote_forwards);
457 		options->remote_forwards = NULL;
458 	}
459 	options->num_remote_forwards = 0;
460 	options->tun_open = SSH_TUNMODE_NO;
461 }
462 
463 void
464 add_certificate_file(Options *options, const char *path, int userprovided)
465 {
466 	int i;
467 
468 	if (options->num_certificate_files >= SSH_MAX_CERTIFICATE_FILES)
469 		fatal("Too many certificate files specified (max %d)",
470 		    SSH_MAX_CERTIFICATE_FILES);
471 
472 	/* Avoid registering duplicates */
473 	for (i = 0; i < options->num_certificate_files; i++) {
474 		if (options->certificate_file_userprovided[i] == userprovided &&
475 		    strcmp(options->certificate_files[i], path) == 0) {
476 			debug2_f("ignoring duplicate key %s", path);
477 			return;
478 		}
479 	}
480 
481 	options->certificate_file_userprovided[options->num_certificate_files] =
482 	    userprovided;
483 	options->certificate_files[options->num_certificate_files++] =
484 	    xstrdup(path);
485 }
486 
487 void
488 add_identity_file(Options *options, const char *dir, const char *filename,
489     int userprovided)
490 {
491 	char *path;
492 	int i;
493 
494 	if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
495 		fatal("Too many identity files specified (max %d)",
496 		    SSH_MAX_IDENTITY_FILES);
497 
498 	if (dir == NULL) /* no dir, filename is absolute */
499 		path = xstrdup(filename);
500 	else if (xasprintf(&path, "%s%s", dir, filename) >= PATH_MAX)
501 		fatal("Identity file path %s too long", path);
502 
503 	/* Avoid registering duplicates */
504 	for (i = 0; i < options->num_identity_files; i++) {
505 		if (options->identity_file_userprovided[i] == userprovided &&
506 		    strcmp(options->identity_files[i], path) == 0) {
507 			debug2_f("ignoring duplicate key %s", path);
508 			free(path);
509 			return;
510 		}
511 	}
512 
513 	options->identity_file_userprovided[options->num_identity_files] =
514 	    userprovided;
515 	options->identity_files[options->num_identity_files++] = path;
516 }
517 
518 int
519 default_ssh_port(void)
520 {
521 	static int port;
522 	struct servent *sp;
523 
524 	if (port == 0) {
525 		sp = getservbyname(SSH_SERVICE_NAME, "tcp");
526 		port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT;
527 	}
528 	return port;
529 }
530 
531 /*
532  * Execute a command in a shell.
533  * Return its exit status or -1 on abnormal exit.
534  */
535 static int
536 execute_in_shell(const char *cmd)
537 {
538 	char *shell;
539 	pid_t pid;
540 	int status;
541 
542 	if ((shell = getenv("SHELL")) == NULL)
543 		shell = _PATH_BSHELL;
544 
545 	if (access(shell, X_OK) == -1) {
546 		fatal("Shell \"%s\" is not executable: %s",
547 		    shell, strerror(errno));
548 	}
549 
550 	debug("Executing command: '%.500s'", cmd);
551 
552 	/* Fork and execute the command. */
553 	if ((pid = fork()) == 0) {
554 		char *argv[4];
555 
556 		if (stdfd_devnull(1, 1, 0) == -1)
557 			fatal_f("stdfd_devnull failed");
558 		closefrom(STDERR_FILENO + 1);
559 
560 		argv[0] = shell;
561 		argv[1] = "-c";
562 		argv[2] = xstrdup(cmd);
563 		argv[3] = NULL;
564 
565 		execv(argv[0], argv);
566 		error("Unable to execute '%.100s': %s", cmd, strerror(errno));
567 		/* Die with signal to make this error apparent to parent. */
568 		ssh_signal(SIGTERM, SIG_DFL);
569 		kill(getpid(), SIGTERM);
570 		_exit(1);
571 	}
572 	/* Parent. */
573 	if (pid == -1)
574 		fatal_f("fork: %.100s", strerror(errno));
575 
576 	while (waitpid(pid, &status, 0) == -1) {
577 		if (errno != EINTR && errno != EAGAIN)
578 			fatal_f("waitpid: %s", strerror(errno));
579 	}
580 	if (!WIFEXITED(status)) {
581 		error("command '%.100s' exited abnormally", cmd);
582 		return -1;
583 	}
584 	debug3("command returned status %d", WEXITSTATUS(status));
585 	return WEXITSTATUS(status);
586 }
587 
588 /*
589  * Parse and execute a Match directive.
590  */
591 static int
592 match_cfg_line(Options *options, char **condition, struct passwd *pw,
593     const char *host_arg, const char *original_host, int final_pass,
594     int *want_final_pass, const char *filename, int linenum)
595 {
596 	char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria;
597 	const char *ruser;
598 	int r, port, this_result, result = 1, attributes = 0, negate;
599 	char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
600 	char uidstr[32];
601 
602 	/*
603 	 * Configuration is likely to be incomplete at this point so we
604 	 * must be prepared to use default values.
605 	 */
606 	port = options->port <= 0 ? default_ssh_port() : options->port;
607 	ruser = options->user == NULL ? pw->pw_name : options->user;
608 	if (final_pass) {
609 		host = xstrdup(options->hostname);
610 	} else if (options->hostname != NULL) {
611 		/* NB. Please keep in sync with ssh.c:main() */
612 		host = percent_expand(options->hostname,
613 		    "h", host_arg, (char *)NULL);
614 	} else {
615 		host = xstrdup(host_arg);
616 	}
617 
618 	debug2("checking match for '%s' host %s originally %s",
619 	    cp, host, original_host);
620 	while ((oattrib = attrib = strdelim(&cp)) && *attrib != '\0') {
621 		/* Terminate on comment */
622 		if (*attrib == '#') {
623 			cp = NULL; /* mark all arguments consumed */
624 			break;
625 		}
626 		arg = criteria = NULL;
627 		this_result = 1;
628 		if ((negate = attrib[0] == '!'))
629 			attrib++;
630 		/* Criterion "all" has no argument and must appear alone */
631 		if (strcasecmp(attrib, "all") == 0) {
632 			if (attributes > 1 || ((arg = strdelim(&cp)) != NULL &&
633 			    *arg != '\0' && *arg != '#')) {
634 				error("%.200s line %d: '%s' cannot be combined "
635 				    "with other Match attributes",
636 				    filename, linenum, oattrib);
637 				result = -1;
638 				goto out;
639 			}
640 			if (arg != NULL && *arg == '#')
641 				cp = NULL; /* mark all arguments consumed */
642 			if (result)
643 				result = negate ? 0 : 1;
644 			goto out;
645 		}
646 		attributes++;
647 		/* criteria "final" and "canonical" have no argument */
648 		if (strcasecmp(attrib, "canonical") == 0 ||
649 		    strcasecmp(attrib, "final") == 0) {
650 			/*
651 			 * If the config requests "Match final" then remember
652 			 * this so we can perform a second pass later.
653 			 */
654 			if (strcasecmp(attrib, "final") == 0 &&
655 			    want_final_pass != NULL)
656 				*want_final_pass = 1;
657 			r = !!final_pass;  /* force bitmask member to boolean */
658 			if (r == (negate ? 1 : 0))
659 				this_result = result = 0;
660 			debug3("%.200s line %d: %smatched '%s'",
661 			    filename, linenum,
662 			    this_result ? "" : "not ", oattrib);
663 			continue;
664 		}
665 		/* All other criteria require an argument */
666 		if ((arg = strdelim(&cp)) == NULL ||
667 		    *arg == '\0' || *arg == '#') {
668 			error("Missing Match criteria for %s", attrib);
669 			result = -1;
670 			goto out;
671 		}
672 		if (strcasecmp(attrib, "host") == 0) {
673 			criteria = xstrdup(host);
674 			r = match_hostname(host, arg) == 1;
675 			if (r == (negate ? 1 : 0))
676 				this_result = result = 0;
677 		} else if (strcasecmp(attrib, "originalhost") == 0) {
678 			criteria = xstrdup(original_host);
679 			r = match_hostname(original_host, arg) == 1;
680 			if (r == (negate ? 1 : 0))
681 				this_result = result = 0;
682 		} else if (strcasecmp(attrib, "user") == 0) {
683 			criteria = xstrdup(ruser);
684 			r = match_pattern_list(ruser, arg, 0) == 1;
685 			if (r == (negate ? 1 : 0))
686 				this_result = result = 0;
687 		} else if (strcasecmp(attrib, "localuser") == 0) {
688 			criteria = xstrdup(pw->pw_name);
689 			r = match_pattern_list(pw->pw_name, arg, 0) == 1;
690 			if (r == (negate ? 1 : 0))
691 				this_result = result = 0;
692 		} else if (strcasecmp(attrib, "exec") == 0) {
693 			char *conn_hash_hex, *keyalias;
694 
695 			if (gethostname(thishost, sizeof(thishost)) == -1)
696 				fatal("gethostname: %s", strerror(errno));
697 			strlcpy(shorthost, thishost, sizeof(shorthost));
698 			shorthost[strcspn(thishost, ".")] = '\0';
699 			snprintf(portstr, sizeof(portstr), "%d", port);
700 			snprintf(uidstr, sizeof(uidstr), "%llu",
701 			    (unsigned long long)pw->pw_uid);
702 			conn_hash_hex = ssh_connection_hash(thishost, host,
703 			    portstr, ruser);
704 			keyalias = options->host_key_alias ?
705 			    options->host_key_alias : host;
706 
707 			cmd = percent_expand(arg,
708 			    "C", conn_hash_hex,
709 			    "L", shorthost,
710 			    "d", pw->pw_dir,
711 			    "h", host,
712 			    "k", keyalias,
713 			    "l", thishost,
714 			    "n", original_host,
715 			    "p", portstr,
716 			    "r", ruser,
717 			    "u", pw->pw_name,
718 			    "i", uidstr,
719 			    (char *)NULL);
720 			free(conn_hash_hex);
721 			if (result != 1) {
722 				/* skip execution if prior predicate failed */
723 				debug3("%.200s line %d: skipped exec "
724 				    "\"%.100s\"", filename, linenum, cmd);
725 				free(cmd);
726 				continue;
727 			}
728 			r = execute_in_shell(cmd);
729 			if (r == -1) {
730 				fatal("%.200s line %d: match exec "
731 				    "'%.100s' error", filename,
732 				    linenum, cmd);
733 			}
734 			criteria = xstrdup(cmd);
735 			free(cmd);
736 			/* Force exit status to boolean */
737 			r = r == 0;
738 			if (r == (negate ? 1 : 0))
739 				this_result = result = 0;
740 		} else {
741 			error("Unsupported Match attribute %s", attrib);
742 			result = -1;
743 			goto out;
744 		}
745 		debug3("%.200s line %d: %smatched '%s \"%.100s\"' ",
746 		    filename, linenum, this_result ? "": "not ",
747 		    oattrib, criteria);
748 		free(criteria);
749 	}
750 	if (attributes == 0) {
751 		error("One or more attributes required for Match");
752 		result = -1;
753 		goto out;
754 	}
755  out:
756 	if (result != -1)
757 		debug2("match %sfound", result ? "" : "not ");
758 	*condition = cp;
759 	free(host);
760 	return result;
761 }
762 
763 /* Remove environment variable by pattern */
764 static void
765 rm_env(Options *options, const char *arg, const char *filename, int linenum)
766 {
767 	int i, j, onum_send_env = options->num_send_env;
768 	char *cp;
769 
770 	/* Remove an environment variable */
771 	for (i = 0; i < options->num_send_env; ) {
772 		cp = xstrdup(options->send_env[i]);
773 		if (!match_pattern(cp, arg + 1)) {
774 			free(cp);
775 			i++;
776 			continue;
777 		}
778 		debug3("%s line %d: removing environment %s",
779 		    filename, linenum, cp);
780 		free(cp);
781 		free(options->send_env[i]);
782 		options->send_env[i] = NULL;
783 		for (j = i; j < options->num_send_env - 1; j++) {
784 			options->send_env[j] = options->send_env[j + 1];
785 			options->send_env[j + 1] = NULL;
786 		}
787 		options->num_send_env--;
788 		/* NB. don't increment i */
789 	}
790 	if (onum_send_env != options->num_send_env) {
791 		options->send_env = xrecallocarray(options->send_env,
792 		    onum_send_env, options->num_send_env,
793 		    sizeof(*options->send_env));
794 	}
795 }
796 
797 /*
798  * Returns the number of the token pointed to by cp or oBadOption.
799  */
800 static OpCodes
801 parse_token(const char *cp, const char *filename, int linenum,
802     const char *ignored_unknown)
803 {
804 	int i;
805 
806 	for (i = 0; keywords[i].name; i++)
807 		if (strcmp(cp, keywords[i].name) == 0)
808 			return keywords[i].opcode;
809 	if (ignored_unknown != NULL &&
810 	    match_pattern_list(cp, ignored_unknown, 1) == 1)
811 		return oIgnoredUnknownOption;
812 	error("%s: line %d: Bad configuration option: %s",
813 	    filename, linenum, cp);
814 	return oBadOption;
815 }
816 
817 /* Multistate option parsing */
818 struct multistate {
819 	char *key;
820 	int value;
821 };
822 static const struct multistate multistate_flag[] = {
823 	{ "true",			1 },
824 	{ "false",			0 },
825 	{ "yes",			1 },
826 	{ "no",				0 },
827 	{ NULL, -1 }
828 };
829 static const struct multistate multistate_yesnoask[] = {
830 	{ "true",			1 },
831 	{ "false",			0 },
832 	{ "yes",			1 },
833 	{ "no",				0 },
834 	{ "ask",			2 },
835 	{ NULL, -1 }
836 };
837 static const struct multistate multistate_strict_hostkey[] = {
838 	{ "true",			SSH_STRICT_HOSTKEY_YES },
839 	{ "false",			SSH_STRICT_HOSTKEY_OFF },
840 	{ "yes",			SSH_STRICT_HOSTKEY_YES },
841 	{ "no",				SSH_STRICT_HOSTKEY_OFF },
842 	{ "ask",			SSH_STRICT_HOSTKEY_ASK },
843 	{ "off",			SSH_STRICT_HOSTKEY_OFF },
844 	{ "accept-new",			SSH_STRICT_HOSTKEY_NEW },
845 	{ NULL, -1 }
846 };
847 static const struct multistate multistate_yesnoaskconfirm[] = {
848 	{ "true",			1 },
849 	{ "false",			0 },
850 	{ "yes",			1 },
851 	{ "no",				0 },
852 	{ "ask",			2 },
853 	{ "confirm",			3 },
854 	{ NULL, -1 }
855 };
856 static const struct multistate multistate_addressfamily[] = {
857 	{ "inet",			AF_INET },
858 	{ "inet6",			AF_INET6 },
859 	{ "any",			AF_UNSPEC },
860 	{ NULL, -1 }
861 };
862 static const struct multistate multistate_controlmaster[] = {
863 	{ "true",			SSHCTL_MASTER_YES },
864 	{ "yes",			SSHCTL_MASTER_YES },
865 	{ "false",			SSHCTL_MASTER_NO },
866 	{ "no",				SSHCTL_MASTER_NO },
867 	{ "auto",			SSHCTL_MASTER_AUTO },
868 	{ "ask",			SSHCTL_MASTER_ASK },
869 	{ "autoask",			SSHCTL_MASTER_AUTO_ASK },
870 	{ NULL, -1 }
871 };
872 static const struct multistate multistate_tunnel[] = {
873 	{ "ethernet",			SSH_TUNMODE_ETHERNET },
874 	{ "point-to-point",		SSH_TUNMODE_POINTOPOINT },
875 	{ "true",			SSH_TUNMODE_DEFAULT },
876 	{ "yes",			SSH_TUNMODE_DEFAULT },
877 	{ "false",			SSH_TUNMODE_NO },
878 	{ "no",				SSH_TUNMODE_NO },
879 	{ NULL, -1 }
880 };
881 static const struct multistate multistate_requesttty[] = {
882 	{ "true",			REQUEST_TTY_YES },
883 	{ "yes",			REQUEST_TTY_YES },
884 	{ "false",			REQUEST_TTY_NO },
885 	{ "no",				REQUEST_TTY_NO },
886 	{ "force",			REQUEST_TTY_FORCE },
887 	{ "auto",			REQUEST_TTY_AUTO },
888 	{ NULL, -1 }
889 };
890 static const struct multistate multistate_sessiontype[] = {
891 	{ "none",			SESSION_TYPE_NONE },
892 	{ "subsystem",			SESSION_TYPE_SUBSYSTEM },
893 	{ "default",			SESSION_TYPE_DEFAULT },
894 	{ NULL, -1 }
895 };
896 static const struct multistate multistate_canonicalizehostname[] = {
897 	{ "true",			SSH_CANONICALISE_YES },
898 	{ "false",			SSH_CANONICALISE_NO },
899 	{ "yes",			SSH_CANONICALISE_YES },
900 	{ "no",				SSH_CANONICALISE_NO },
901 	{ "always",			SSH_CANONICALISE_ALWAYS },
902 	{ NULL, -1 }
903 };
904 static const struct multistate multistate_compression[] = {
905 #ifdef WITH_ZLIB
906 	{ "yes",			COMP_ZLIB },
907 #endif
908 	{ "no",				COMP_NONE },
909 	{ NULL, -1 }
910 };
911 
912 static int
913 parse_multistate_value(const char *arg, const char *filename, int linenum,
914     const struct multistate *multistate_ptr)
915 {
916 	int i;
917 
918 	if (!arg || *arg == '\0') {
919 		error("%s line %d: missing argument.", filename, linenum);
920 		return -1;
921 	}
922 	for (i = 0; multistate_ptr[i].key != NULL; i++) {
923 		if (strcasecmp(arg, multistate_ptr[i].key) == 0)
924 			return multistate_ptr[i].value;
925 	}
926 	return -1;
927 }
928 
929 /*
930  * Processes a single option line as used in the configuration files. This
931  * only sets those values that have not already been set.
932  */
933 int
934 process_config_line(Options *options, struct passwd *pw, const char *host,
935     const char *original_host, char *line, const char *filename,
936     int linenum, int *activep, int flags)
937 {
938 	return process_config_line_depth(options, pw, host, original_host,
939 	    line, filename, linenum, activep, flags, NULL, 0);
940 }
941 
942 #define WHITESPACE " \t\r\n"
943 static int
944 process_config_line_depth(Options *options, struct passwd *pw, const char *host,
945     const char *original_host, char *line, const char *filename,
946     int linenum, int *activep, int flags, int *want_final_pass, int depth)
947 {
948 	char *str, **charptr, *endofnumber, *keyword, *arg, *arg2, *p, ch;
949 	char **cpptr, ***cppptr, fwdarg[256];
950 	u_int i, *uintptr, uvalue, max_entries = 0;
951 	int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0;
952 	int remotefwd, dynamicfwd;
953 	LogLevel *log_level_ptr;
954 	SyslogFacility *log_facility_ptr;
955 	long long val64;
956 	size_t len;
957 	struct Forward fwd;
958 	const struct multistate *multistate_ptr;
959 	struct allowed_cname *cname;
960 	glob_t gl;
961 	const char *errstr;
962 	char **oav = NULL, **av;
963 	int oac = 0, ac;
964 	int ret = -1;
965 
966 	if (activep == NULL) { /* We are processing a command line directive */
967 		cmdline = 1;
968 		activep = &cmdline;
969 	}
970 
971 	/* Strip trailing whitespace. Allow \f (form feed) at EOL only */
972 	if ((len = strlen(line)) == 0)
973 		return 0;
974 	for (len--; len > 0; len--) {
975 		if (strchr(WHITESPACE "\f", line[len]) == NULL)
976 			break;
977 		line[len] = '\0';
978 	}
979 
980 	str = line;
981 	/* Get the keyword. (Each line is supposed to begin with a keyword). */
982 	if ((keyword = strdelim(&str)) == NULL)
983 		return 0;
984 	/* Ignore leading whitespace. */
985 	if (*keyword == '\0')
986 		keyword = strdelim(&str);
987 	if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
988 		return 0;
989 	/* Match lowercase keyword */
990 	lowercase(keyword);
991 
992 	/* Prepare to parse remainder of line */
993 	if (str != NULL)
994 		str += strspn(str, WHITESPACE);
995 	if (str == NULL || *str == '\0') {
996 		error("%s line %d: no argument after keyword \"%s\"",
997 		    filename, linenum, keyword);
998 		return -1;
999 	}
1000 	opcode = parse_token(keyword, filename, linenum,
1001 	    options->ignored_unknown);
1002 	if (argv_split(str, &oac, &oav, 1) != 0) {
1003 		error("%s line %d: invalid quotes", filename, linenum);
1004 		return -1;
1005 	}
1006 	ac = oac;
1007 	av = oav;
1008 
1009 	switch (opcode) {
1010 	case oBadOption:
1011 		/* don't panic, but count bad options */
1012 		goto out;
1013 	case oIgnore:
1014 		argv_consume(&ac);
1015 		break;
1016 	case oIgnoredUnknownOption:
1017 		debug("%s line %d: Ignored unknown option \"%s\"",
1018 		    filename, linenum, keyword);
1019 		argv_consume(&ac);
1020 		break;
1021 	case oConnectTimeout:
1022 		intptr = &options->connection_timeout;
1023 parse_time:
1024 		arg = argv_next(&ac, &av);
1025 		if (!arg || *arg == '\0') {
1026 			error("%s line %d: missing time value.",
1027 			    filename, linenum);
1028 			goto out;
1029 		}
1030 		if (strcmp(arg, "none") == 0)
1031 			value = -1;
1032 		else if ((value = convtime(arg)) == -1) {
1033 			error("%s line %d: invalid time value.",
1034 			    filename, linenum);
1035 			goto out;
1036 		}
1037 		if (*activep && *intptr == -1)
1038 			*intptr = value;
1039 		break;
1040 
1041 	case oForwardAgent:
1042 		intptr = &options->forward_agent;
1043 
1044 		arg = argv_next(&ac, &av);
1045 		if (!arg || *arg == '\0') {
1046 			error("%s line %d: missing argument.",
1047 			    filename, linenum);
1048 			goto out;
1049 		}
1050 
1051 		value = -1;
1052 		multistate_ptr = multistate_flag;
1053 		for (i = 0; multistate_ptr[i].key != NULL; i++) {
1054 			if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
1055 				value = multistate_ptr[i].value;
1056 				break;
1057 			}
1058 		}
1059 		if (value != -1) {
1060 			if (*activep && *intptr == -1)
1061 				*intptr = value;
1062 			break;
1063 		}
1064 		/* ForwardAgent wasn't 'yes' or 'no', assume a path */
1065 		if (*activep && *intptr == -1)
1066 			*intptr = 1;
1067 
1068 		charptr = &options->forward_agent_sock_path;
1069 		goto parse_agent_path;
1070 
1071 	case oForwardX11:
1072 		intptr = &options->forward_x11;
1073  parse_flag:
1074 		multistate_ptr = multistate_flag;
1075  parse_multistate:
1076 		arg = argv_next(&ac, &av);
1077 		if ((value = parse_multistate_value(arg, filename, linenum,
1078 		    multistate_ptr)) == -1) {
1079 			error("%s line %d: unsupported option \"%s\".",
1080 			    filename, linenum, arg);
1081 			goto out;
1082 		}
1083 		if (*activep && *intptr == -1)
1084 			*intptr = value;
1085 		break;
1086 
1087 	case oForwardX11Trusted:
1088 		intptr = &options->forward_x11_trusted;
1089 		goto parse_flag;
1090 
1091 	case oForwardX11Timeout:
1092 		intptr = &options->forward_x11_timeout;
1093 		goto parse_time;
1094 
1095 	case oGatewayPorts:
1096 		intptr = &options->fwd_opts.gateway_ports;
1097 		goto parse_flag;
1098 
1099 	case oExitOnForwardFailure:
1100 		intptr = &options->exit_on_forward_failure;
1101 		goto parse_flag;
1102 
1103 	case oPasswordAuthentication:
1104 		intptr = &options->password_authentication;
1105 		goto parse_flag;
1106 
1107 	case oKbdInteractiveAuthentication:
1108 		intptr = &options->kbd_interactive_authentication;
1109 		goto parse_flag;
1110 
1111 	case oKbdInteractiveDevices:
1112 		charptr = &options->kbd_interactive_devices;
1113 		goto parse_string;
1114 
1115 	case oPubkeyAuthentication:
1116 		intptr = &options->pubkey_authentication;
1117 		goto parse_flag;
1118 
1119 	case oHostbasedAuthentication:
1120 		intptr = &options->hostbased_authentication;
1121 		goto parse_flag;
1122 
1123 	case oGssAuthentication:
1124 		intptr = &options->gss_authentication;
1125 		goto parse_flag;
1126 
1127 	case oGssDelegateCreds:
1128 		intptr = &options->gss_deleg_creds;
1129 		goto parse_flag;
1130 
1131 	case oBatchMode:
1132 		intptr = &options->batch_mode;
1133 		goto parse_flag;
1134 
1135 	case oCheckHostIP:
1136 		intptr = &options->check_host_ip;
1137 		goto parse_flag;
1138 
1139 	case oVerifyHostKeyDNS:
1140 		intptr = &options->verify_host_key_dns;
1141 		multistate_ptr = multistate_yesnoask;
1142 		goto parse_multistate;
1143 
1144 	case oStrictHostKeyChecking:
1145 		intptr = &options->strict_host_key_checking;
1146 		multistate_ptr = multistate_strict_hostkey;
1147 		goto parse_multistate;
1148 
1149 	case oCompression:
1150 		intptr = &options->compression;
1151 		multistate_ptr = multistate_compression;
1152 		goto parse_multistate;
1153 
1154 	case oTCPKeepAlive:
1155 		intptr = &options->tcp_keep_alive;
1156 		goto parse_flag;
1157 
1158 	case oNoHostAuthenticationForLocalhost:
1159 		intptr = &options->no_host_authentication_for_localhost;
1160 		goto parse_flag;
1161 
1162 	case oNumberOfPasswordPrompts:
1163 		intptr = &options->number_of_password_prompts;
1164 		goto parse_int;
1165 
1166 	case oRekeyLimit:
1167 		arg = argv_next(&ac, &av);
1168 		if (!arg || *arg == '\0') {
1169 			error("%.200s line %d: Missing argument.", filename,
1170 			    linenum);
1171 			goto out;
1172 		}
1173 		if (strcmp(arg, "default") == 0) {
1174 			val64 = 0;
1175 		} else {
1176 			if (scan_scaled(arg, &val64) == -1) {
1177 				error("%.200s line %d: Bad number '%s': %s",
1178 				    filename, linenum, arg, strerror(errno));
1179 				goto out;
1180 			}
1181 			if (val64 != 0 && val64 < 16) {
1182 				error("%.200s line %d: RekeyLimit too small",
1183 				    filename, linenum);
1184 				goto out;
1185 			}
1186 		}
1187 		if (*activep && options->rekey_limit == -1)
1188 			options->rekey_limit = val64;
1189 		if (ac != 0) { /* optional rekey interval present */
1190 			if (strcmp(av[0], "none") == 0) {
1191 				(void)argv_next(&ac, &av);	/* discard */
1192 				break;
1193 			}
1194 			intptr = &options->rekey_interval;
1195 			goto parse_time;
1196 		}
1197 		break;
1198 
1199 	case oIdentityFile:
1200 		arg = argv_next(&ac, &av);
1201 		if (!arg || *arg == '\0') {
1202 			error("%.200s line %d: Missing argument.",
1203 			    filename, linenum);
1204 			goto out;
1205 		}
1206 		if (*activep) {
1207 			intptr = &options->num_identity_files;
1208 			if (*intptr >= SSH_MAX_IDENTITY_FILES) {
1209 				error("%.200s line %d: Too many identity files "
1210 				    "specified (max %d).", filename, linenum,
1211 				    SSH_MAX_IDENTITY_FILES);
1212 				goto out;
1213 			}
1214 			add_identity_file(options, NULL,
1215 			    arg, flags & SSHCONF_USERCONF);
1216 		}
1217 		break;
1218 
1219 	case oCertificateFile:
1220 		arg = argv_next(&ac, &av);
1221 		if (!arg || *arg == '\0') {
1222 			error("%.200s line %d: Missing argument.",
1223 			    filename, linenum);
1224 			goto out;
1225 		}
1226 		if (*activep) {
1227 			intptr = &options->num_certificate_files;
1228 			if (*intptr >= SSH_MAX_CERTIFICATE_FILES) {
1229 				error("%.200s line %d: Too many certificate "
1230 				    "files specified (max %d).",
1231 				    filename, linenum,
1232 				    SSH_MAX_CERTIFICATE_FILES);
1233 				goto out;
1234 			}
1235 			add_certificate_file(options, arg,
1236 			    flags & SSHCONF_USERCONF);
1237 		}
1238 		break;
1239 
1240 	case oXAuthLocation:
1241 		charptr=&options->xauth_location;
1242 		goto parse_string;
1243 
1244 	case oUser:
1245 		charptr = &options->user;
1246 parse_string:
1247 		arg = argv_next(&ac, &av);
1248 		if (!arg || *arg == '\0') {
1249 			error("%.200s line %d: Missing argument.",
1250 			    filename, linenum);
1251 			goto out;
1252 		}
1253 		if (*activep && *charptr == NULL)
1254 			*charptr = xstrdup(arg);
1255 		break;
1256 
1257 	case oGlobalKnownHostsFile:
1258 		cpptr = (char **)&options->system_hostfiles;
1259 		uintptr = &options->num_system_hostfiles;
1260 		max_entries = SSH_MAX_HOSTS_FILES;
1261 parse_char_array:
1262 		i = 0;
1263 		value = *uintptr == 0; /* was array empty when we started? */
1264 		while ((arg = argv_next(&ac, &av)) != NULL) {
1265 			if (*arg == '\0') {
1266 				error("%s line %d: keyword %s empty argument",
1267 				    filename, linenum, keyword);
1268 				goto out;
1269 			}
1270 			/* Allow "none" only in first position */
1271 			if (strcasecmp(arg, "none") == 0) {
1272 				if (i > 0 || ac > 0) {
1273 					error("%s line %d: keyword %s \"none\" "
1274 					    "argument must appear alone.",
1275 					    filename, linenum, keyword);
1276 					goto out;
1277 				}
1278 			}
1279 			i++;
1280 			if (*activep && value) {
1281 				if ((*uintptr) >= max_entries) {
1282 					error("%s line %d: too many %s "
1283 					    "entries.", filename, linenum,
1284 					    keyword);
1285 					goto out;
1286 				}
1287 				cpptr[(*uintptr)++] = xstrdup(arg);
1288 			}
1289 		}
1290 		break;
1291 
1292 	case oUserKnownHostsFile:
1293 		cpptr = (char **)&options->user_hostfiles;
1294 		uintptr = &options->num_user_hostfiles;
1295 		max_entries = SSH_MAX_HOSTS_FILES;
1296 		goto parse_char_array;
1297 
1298 	case oHostname:
1299 		charptr = &options->hostname;
1300 		goto parse_string;
1301 
1302 	case oHostKeyAlias:
1303 		charptr = &options->host_key_alias;
1304 		goto parse_string;
1305 
1306 	case oPreferredAuthentications:
1307 		charptr = &options->preferred_authentications;
1308 		goto parse_string;
1309 
1310 	case oBindAddress:
1311 		charptr = &options->bind_address;
1312 		goto parse_string;
1313 
1314 	case oBindInterface:
1315 		charptr = &options->bind_interface;
1316 		goto parse_string;
1317 
1318 	case oPKCS11Provider:
1319 		charptr = &options->pkcs11_provider;
1320 		goto parse_string;
1321 
1322 	case oSecurityKeyProvider:
1323 		charptr = &options->sk_provider;
1324 		goto parse_string;
1325 
1326 	case oKnownHostsCommand:
1327 		charptr = &options->known_hosts_command;
1328 		goto parse_command;
1329 
1330 	case oProxyCommand:
1331 		charptr = &options->proxy_command;
1332 		/* Ignore ProxyCommand if ProxyJump already specified */
1333 		if (options->jump_host != NULL)
1334 			charptr = &options->jump_host; /* Skip below */
1335 parse_command:
1336 		if (str == NULL) {
1337 			error("%.200s line %d: Missing argument.",
1338 			    filename, linenum);
1339 			goto out;
1340 		}
1341 		len = strspn(str, WHITESPACE "=");
1342 		if (*activep && *charptr == NULL)
1343 			*charptr = xstrdup(str + len);
1344 		argv_consume(&ac);
1345 		break;
1346 
1347 	case oProxyJump:
1348 		if (str == NULL) {
1349 			error("%.200s line %d: Missing argument.",
1350 			    filename, linenum);
1351 			goto out;
1352 		}
1353 		len = strspn(str, WHITESPACE "=");
1354 		/* XXX use argv? */
1355 		if (parse_jump(str + len, options, *activep) == -1) {
1356 			error("%.200s line %d: Invalid ProxyJump \"%s\"",
1357 			    filename, linenum, str + len);
1358 			goto out;
1359 		}
1360 		argv_consume(&ac);
1361 		break;
1362 
1363 	case oPort:
1364 		arg = argv_next(&ac, &av);
1365 		if (!arg || *arg == '\0') {
1366 			error("%.200s line %d: Missing argument.",
1367 			    filename, linenum);
1368 			goto out;
1369 		}
1370 		value = a2port(arg);
1371 		if (value <= 0) {
1372 			error("%.200s line %d: Bad port '%s'.",
1373 			    filename, linenum, arg);
1374 			goto out;
1375 		}
1376 		if (*activep && options->port == -1)
1377 			options->port = value;
1378 		break;
1379 
1380 	case oConnectionAttempts:
1381 		intptr = &options->connection_attempts;
1382 parse_int:
1383 		arg = argv_next(&ac, &av);
1384 		if ((errstr = atoi_err(arg, &value)) != NULL) {
1385 			error("%s line %d: integer value %s.",
1386 			    filename, linenum, errstr);
1387 			goto out;
1388 		}
1389 		if (*activep && *intptr == -1)
1390 			*intptr = value;
1391 		break;
1392 
1393 	case oCiphers:
1394 		arg = argv_next(&ac, &av);
1395 		if (!arg || *arg == '\0') {
1396 			error("%.200s line %d: Missing argument.",
1397 			    filename, linenum);
1398 			goto out;
1399 		}
1400 		if (*arg != '-' &&
1401 		    !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)){
1402 			error("%.200s line %d: Bad SSH2 cipher spec '%s'.",
1403 			    filename, linenum, arg ? arg : "<NONE>");
1404 			goto out;
1405 		}
1406 		if (*activep && options->ciphers == NULL)
1407 			options->ciphers = xstrdup(arg);
1408 		break;
1409 
1410 	case oMacs:
1411 		arg = argv_next(&ac, &av);
1412 		if (!arg || *arg == '\0') {
1413 			error("%.200s line %d: Missing argument.",
1414 			    filename, linenum);
1415 			goto out;
1416 		}
1417 		if (*arg != '-' &&
1418 		    !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) {
1419 			error("%.200s line %d: Bad SSH2 MAC spec '%s'.",
1420 			    filename, linenum, arg ? arg : "<NONE>");
1421 			goto out;
1422 		}
1423 		if (*activep && options->macs == NULL)
1424 			options->macs = xstrdup(arg);
1425 		break;
1426 
1427 	case oKexAlgorithms:
1428 		arg = argv_next(&ac, &av);
1429 		if (!arg || *arg == '\0') {
1430 			error("%.200s line %d: Missing argument.",
1431 			    filename, linenum);
1432 			goto out;
1433 		}
1434 		if (*arg != '-' &&
1435 		    !kex_names_valid(*arg == '+' || *arg == '^' ?
1436 		    arg + 1 : arg)) {
1437 			error("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
1438 			    filename, linenum, arg ? arg : "<NONE>");
1439 			goto out;
1440 		}
1441 		if (*activep && options->kex_algorithms == NULL)
1442 			options->kex_algorithms = xstrdup(arg);
1443 		break;
1444 
1445 	case oHostKeyAlgorithms:
1446 		charptr = &options->hostkeyalgorithms;
1447 parse_pubkey_algos:
1448 		arg = argv_next(&ac, &av);
1449 		if (!arg || *arg == '\0') {
1450 			error("%.200s line %d: Missing argument.",
1451 			    filename, linenum);
1452 			goto out;
1453 		}
1454 		if (*arg != '-' &&
1455 		    !sshkey_names_valid2(*arg == '+' || *arg == '^' ?
1456 		    arg + 1 : arg, 1)) {
1457 			error("%s line %d: Bad key types '%s'.",
1458 			    filename, linenum, arg ? arg : "<NONE>");
1459 			goto out;
1460 		}
1461 		if (*activep && *charptr == NULL)
1462 			*charptr = xstrdup(arg);
1463 		break;
1464 
1465 	case oCASignatureAlgorithms:
1466 		charptr = &options->ca_sign_algorithms;
1467 		goto parse_pubkey_algos;
1468 
1469 	case oLogLevel:
1470 		log_level_ptr = &options->log_level;
1471 		arg = argv_next(&ac, &av);
1472 		value = log_level_number(arg);
1473 		if (value == SYSLOG_LEVEL_NOT_SET) {
1474 			error("%.200s line %d: unsupported log level '%s'",
1475 			    filename, linenum, arg ? arg : "<NONE>");
1476 			goto out;
1477 		}
1478 		if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
1479 			*log_level_ptr = (LogLevel) value;
1480 		break;
1481 
1482 	case oLogFacility:
1483 		log_facility_ptr = &options->log_facility;
1484 		arg = argv_next(&ac, &av);
1485 		value = log_facility_number(arg);
1486 		if (value == SYSLOG_FACILITY_NOT_SET) {
1487 			error("%.200s line %d: unsupported log facility '%s'",
1488 			    filename, linenum, arg ? arg : "<NONE>");
1489 			goto out;
1490 		}
1491 		if (*log_facility_ptr == -1)
1492 			*log_facility_ptr = (SyslogFacility) value;
1493 		break;
1494 
1495 	case oLogVerbose:
1496 		cppptr = &options->log_verbose;
1497 		uintptr = &options->num_log_verbose;
1498 		i = 0;
1499 		while ((arg = argv_next(&ac, &av)) != NULL) {
1500 			if (*arg == '\0') {
1501 				error("%s line %d: keyword %s empty argument",
1502 				    filename, linenum, keyword);
1503 				goto out;
1504 			}
1505 			/* Allow "none" only in first position */
1506 			if (strcasecmp(arg, "none") == 0) {
1507 				if (i > 0 || ac > 0) {
1508 					error("%s line %d: keyword %s \"none\" "
1509 					    "argument must appear alone.",
1510 					    filename, linenum, keyword);
1511 					goto out;
1512 				}
1513 			}
1514 			i++;
1515 			if (*activep && *uintptr == 0) {
1516 				*cppptr = xrecallocarray(*cppptr, *uintptr,
1517 				    *uintptr + 1, sizeof(**cppptr));
1518 				(*cppptr)[(*uintptr)++] = xstrdup(arg);
1519 			}
1520 		}
1521 		break;
1522 
1523 	case oLocalForward:
1524 	case oRemoteForward:
1525 	case oDynamicForward:
1526 		arg = argv_next(&ac, &av);
1527 		if (!arg || *arg == '\0') {
1528 			error("%.200s line %d: Missing argument.",
1529 			    filename, linenum);
1530 			goto out;
1531 		}
1532 
1533 		remotefwd = (opcode == oRemoteForward);
1534 		dynamicfwd = (opcode == oDynamicForward);
1535 
1536 		if (!dynamicfwd) {
1537 			arg2 = argv_next(&ac, &av);
1538 			if (arg2 == NULL || *arg2 == '\0') {
1539 				if (remotefwd)
1540 					dynamicfwd = 1;
1541 				else {
1542 					error("%.200s line %d: Missing target "
1543 					    "argument.", filename, linenum);
1544 					goto out;
1545 				}
1546 			} else {
1547 				/* construct a string for parse_forward */
1548 				snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg,
1549 				    arg2);
1550 			}
1551 		}
1552 		if (dynamicfwd)
1553 			strlcpy(fwdarg, arg, sizeof(fwdarg));
1554 
1555 		if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0) {
1556 			error("%.200s line %d: Bad forwarding specification.",
1557 			    filename, linenum);
1558 			goto out;
1559 		}
1560 
1561 		if (*activep) {
1562 			if (remotefwd) {
1563 				add_remote_forward(options, &fwd);
1564 			} else {
1565 				add_local_forward(options, &fwd);
1566 			}
1567 		}
1568 		break;
1569 
1570 	case oPermitRemoteOpen:
1571 		uintptr = &options->num_permitted_remote_opens;
1572 		cppptr = &options->permitted_remote_opens;
1573 		arg = argv_next(&ac, &av);
1574 		if (!arg || *arg == '\0')
1575 			fatal("%s line %d: missing %s specification",
1576 			    filename, linenum, lookup_opcode_name(opcode));
1577 		uvalue = *uintptr;	/* modified later */
1578 		if (strcmp(arg, "any") == 0 || strcmp(arg, "none") == 0) {
1579 			if (*activep && uvalue == 0) {
1580 				*uintptr = 1;
1581 				*cppptr = xcalloc(1, sizeof(**cppptr));
1582 				(*cppptr)[0] = xstrdup(arg);
1583 			}
1584 			break;
1585 		}
1586 		while ((arg = argv_next(&ac, &av)) != NULL) {
1587 			arg2 = xstrdup(arg);
1588 			ch = '\0';
1589 			p = hpdelim2(&arg, &ch);
1590 			if (p == NULL || ch == '/') {
1591 				fatal("%s line %d: missing host in %s",
1592 				    filename, linenum,
1593 				    lookup_opcode_name(opcode));
1594 			}
1595 			p = cleanhostname(p);
1596 			/*
1597 			 * don't want to use permitopen_port to avoid
1598 			 * dependency on channels.[ch] here.
1599 			 */
1600 			if (arg == NULL ||
1601 			    (strcmp(arg, "*") != 0 && a2port(arg) <= 0)) {
1602 				fatal("%s line %d: bad port number in %s",
1603 				    filename, linenum,
1604 				    lookup_opcode_name(opcode));
1605 			}
1606 			if (*activep && uvalue == 0) {
1607 				opt_array_append(filename, linenum,
1608 				    lookup_opcode_name(opcode),
1609 				    cppptr, uintptr, arg2);
1610 			}
1611 			free(arg2);
1612 		}
1613 		break;
1614 
1615 	case oClearAllForwardings:
1616 		intptr = &options->clear_forwardings;
1617 		goto parse_flag;
1618 
1619 	case oHost:
1620 		if (cmdline) {
1621 			error("Host directive not supported as a command-line "
1622 			    "option");
1623 			goto out;
1624 		}
1625 		*activep = 0;
1626 		arg2 = NULL;
1627 		while ((arg = argv_next(&ac, &av)) != NULL) {
1628 			if (*arg == '\0') {
1629 				error("%s line %d: keyword %s empty argument",
1630 				    filename, linenum, keyword);
1631 				goto out;
1632 			}
1633 			if ((flags & SSHCONF_NEVERMATCH) != 0) {
1634 				argv_consume(&ac);
1635 				break;
1636 			}
1637 			negated = *arg == '!';
1638 			if (negated)
1639 				arg++;
1640 			if (match_pattern(host, arg)) {
1641 				if (negated) {
1642 					debug("%.200s line %d: Skipping Host "
1643 					    "block because of negated match "
1644 					    "for %.100s", filename, linenum,
1645 					    arg);
1646 					*activep = 0;
1647 					argv_consume(&ac);
1648 					break;
1649 				}
1650 				if (!*activep)
1651 					arg2 = arg; /* logged below */
1652 				*activep = 1;
1653 			}
1654 		}
1655 		if (*activep)
1656 			debug("%.200s line %d: Applying options for %.100s",
1657 			    filename, linenum, arg2);
1658 		break;
1659 
1660 	case oMatch:
1661 		if (cmdline) {
1662 			error("Host directive not supported as a command-line "
1663 			    "option");
1664 			goto out;
1665 		}
1666 		value = match_cfg_line(options, &str, pw, host, original_host,
1667 		    flags & SSHCONF_FINAL, want_final_pass,
1668 		    filename, linenum);
1669 		if (value < 0) {
1670 			error("%.200s line %d: Bad Match condition", filename,
1671 			    linenum);
1672 			goto out;
1673 		}
1674 		*activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value;
1675 		/*
1676 		 * If match_cfg_line() didn't consume all its arguments then
1677 		 * arrange for the extra arguments check below to fail.
1678 		 */
1679 
1680 		if (str == NULL || *str == '\0')
1681 			argv_consume(&ac);
1682 		break;
1683 
1684 	case oEscapeChar:
1685 		intptr = &options->escape_char;
1686 		arg = argv_next(&ac, &av);
1687 		if (!arg || *arg == '\0') {
1688 			error("%.200s line %d: Missing argument.",
1689 			    filename, linenum);
1690 			goto out;
1691 		}
1692 		if (strcmp(arg, "none") == 0)
1693 			value = SSH_ESCAPECHAR_NONE;
1694 		else if (arg[1] == '\0')
1695 			value = (u_char) arg[0];
1696 		else if (arg[0] == '^' && arg[2] == 0 &&
1697 		    (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
1698 			value = (u_char) arg[1] & 31;
1699 		else {
1700 			error("%.200s line %d: Bad escape character.",
1701 			    filename, linenum);
1702 			goto out;
1703 		}
1704 		if (*activep && *intptr == -1)
1705 			*intptr = value;
1706 		break;
1707 
1708 	case oAddressFamily:
1709 		intptr = &options->address_family;
1710 		multistate_ptr = multistate_addressfamily;
1711 		goto parse_multistate;
1712 
1713 	case oEnableSSHKeysign:
1714 		intptr = &options->enable_ssh_keysign;
1715 		goto parse_flag;
1716 
1717 	case oIdentitiesOnly:
1718 		intptr = &options->identities_only;
1719 		goto parse_flag;
1720 
1721 	case oServerAliveInterval:
1722 		intptr = &options->server_alive_interval;
1723 		goto parse_time;
1724 
1725 	case oServerAliveCountMax:
1726 		intptr = &options->server_alive_count_max;
1727 		goto parse_int;
1728 
1729 	case oSendEnv:
1730 		while ((arg = argv_next(&ac, &av)) != NULL) {
1731 			if (*arg == '\0' || strchr(arg, '=') != NULL) {
1732 				error("%s line %d: Invalid environment name.",
1733 				    filename, linenum);
1734 				goto out;
1735 			}
1736 			if (!*activep)
1737 				continue;
1738 			if (*arg == '-') {
1739 				/* Removing an env var */
1740 				rm_env(options, arg, filename, linenum);
1741 				continue;
1742 			} else {
1743 				/* Adding an env var */
1744 				if (options->num_send_env >= INT_MAX) {
1745 					error("%s line %d: too many send env.",
1746 					    filename, linenum);
1747 					goto out;
1748 				}
1749 				options->send_env = xrecallocarray(
1750 				    options->send_env, options->num_send_env,
1751 				    options->num_send_env + 1,
1752 				    sizeof(*options->send_env));
1753 				options->send_env[options->num_send_env++] =
1754 				    xstrdup(arg);
1755 			}
1756 		}
1757 		break;
1758 
1759 	case oSetEnv:
1760 		value = options->num_setenv;
1761 		while ((arg = argv_next(&ac, &av)) != NULL) {
1762 			if (strchr(arg, '=') == NULL) {
1763 				error("%s line %d: Invalid SetEnv.",
1764 				    filename, linenum);
1765 				goto out;
1766 			}
1767 			if (!*activep || value != 0)
1768 				continue;
1769 			/* Adding a setenv var */
1770 			if (options->num_setenv >= INT_MAX) {
1771 				error("%s line %d: too many SetEnv.",
1772 				    filename, linenum);
1773 				goto out;
1774 			}
1775 			options->setenv = xrecallocarray(
1776 			    options->setenv, options->num_setenv,
1777 			    options->num_setenv + 1, sizeof(*options->setenv));
1778 			options->setenv[options->num_setenv++] = xstrdup(arg);
1779 		}
1780 		break;
1781 
1782 	case oControlPath:
1783 		charptr = &options->control_path;
1784 		goto parse_string;
1785 
1786 	case oControlMaster:
1787 		intptr = &options->control_master;
1788 		multistate_ptr = multistate_controlmaster;
1789 		goto parse_multistate;
1790 
1791 	case oControlPersist:
1792 		/* no/false/yes/true, or a time spec */
1793 		intptr = &options->control_persist;
1794 		arg = argv_next(&ac, &av);
1795 		if (!arg || *arg == '\0') {
1796 			error("%.200s line %d: Missing ControlPersist"
1797 			    " argument.", filename, linenum);
1798 			goto out;
1799 		}
1800 		value = 0;
1801 		value2 = 0;	/* timeout */
1802 		if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
1803 			value = 0;
1804 		else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
1805 			value = 1;
1806 		else if ((value2 = convtime(arg)) >= 0)
1807 			value = 1;
1808 		else {
1809 			error("%.200s line %d: Bad ControlPersist argument.",
1810 			    filename, linenum);
1811 			goto out;
1812 		}
1813 		if (*activep && *intptr == -1) {
1814 			*intptr = value;
1815 			options->control_persist_timeout = value2;
1816 		}
1817 		break;
1818 
1819 	case oHashKnownHosts:
1820 		intptr = &options->hash_known_hosts;
1821 		goto parse_flag;
1822 
1823 	case oTunnel:
1824 		intptr = &options->tun_open;
1825 		multistate_ptr = multistate_tunnel;
1826 		goto parse_multistate;
1827 
1828 	case oTunnelDevice:
1829 		arg = argv_next(&ac, &av);
1830 		if (!arg || *arg == '\0') {
1831 			error("%.200s line %d: Missing argument.",
1832 			    filename, linenum);
1833 			goto out;
1834 		}
1835 		value = a2tun(arg, &value2);
1836 		if (value == SSH_TUNID_ERR) {
1837 			error("%.200s line %d: Bad tun device.",
1838 			    filename, linenum);
1839 			goto out;
1840 		}
1841 		if (*activep && options->tun_local == -1) {
1842 			options->tun_local = value;
1843 			options->tun_remote = value2;
1844 		}
1845 		break;
1846 
1847 	case oLocalCommand:
1848 		charptr = &options->local_command;
1849 		goto parse_command;
1850 
1851 	case oPermitLocalCommand:
1852 		intptr = &options->permit_local_command;
1853 		goto parse_flag;
1854 
1855 	case oRemoteCommand:
1856 		charptr = &options->remote_command;
1857 		goto parse_command;
1858 
1859 	case oVisualHostKey:
1860 		intptr = &options->visual_host_key;
1861 		goto parse_flag;
1862 
1863 	case oInclude:
1864 		if (cmdline) {
1865 			error("Include directive not supported as a "
1866 			    "command-line option");
1867 			goto out;
1868 		}
1869 		value = 0;
1870 		while ((arg = argv_next(&ac, &av)) != NULL) {
1871 			if (*arg == '\0') {
1872 				error("%s line %d: keyword %s empty argument",
1873 				    filename, linenum, keyword);
1874 				goto out;
1875 			}
1876 			/*
1877 			 * Ensure all paths are anchored. User configuration
1878 			 * files may begin with '~/' but system configurations
1879 			 * must not. If the path is relative, then treat it
1880 			 * as living in ~/.ssh for user configurations or
1881 			 * /etc/ssh for system ones.
1882 			 */
1883 			if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0) {
1884 				error("%.200s line %d: bad include path %s.",
1885 				    filename, linenum, arg);
1886 				goto out;
1887 			}
1888 			if (!path_absolute(arg) && *arg != '~') {
1889 				xasprintf(&arg2, "%s/%s",
1890 				    (flags & SSHCONF_USERCONF) ?
1891 				    "~/" _PATH_SSH_USER_DIR : SSHDIR, arg);
1892 			} else
1893 				arg2 = xstrdup(arg);
1894 			memset(&gl, 0, sizeof(gl));
1895 			r = glob(arg2, GLOB_TILDE, NULL, &gl);
1896 			if (r == GLOB_NOMATCH) {
1897 				debug("%.200s line %d: include %s matched no "
1898 				    "files",filename, linenum, arg2);
1899 				free(arg2);
1900 				continue;
1901 			} else if (r != 0) {
1902 				error("%.200s line %d: glob failed for %s.",
1903 				    filename, linenum, arg2);
1904 				goto out;
1905 			}
1906 			free(arg2);
1907 			oactive = *activep;
1908 			for (i = 0; i < gl.gl_pathc; i++) {
1909 				debug3("%.200s line %d: Including file %s "
1910 				    "depth %d%s", filename, linenum,
1911 				    gl.gl_pathv[i], depth,
1912 				    oactive ? "" : " (parse only)");
1913 				r = read_config_file_depth(gl.gl_pathv[i],
1914 				    pw, host, original_host, options,
1915 				    flags | SSHCONF_CHECKPERM |
1916 				    (oactive ? 0 : SSHCONF_NEVERMATCH),
1917 				    activep, want_final_pass, depth + 1);
1918 				if (r != 1 && errno != ENOENT) {
1919 					error("Can't open user config file "
1920 					    "%.100s: %.100s", gl.gl_pathv[i],
1921 					    strerror(errno));
1922 					globfree(&gl);
1923 					goto out;
1924 				}
1925 				/*
1926 				 * don't let Match in includes clobber the
1927 				 * containing file's Match state.
1928 				 */
1929 				*activep = oactive;
1930 				if (r != 1)
1931 					value = -1;
1932 			}
1933 			globfree(&gl);
1934 		}
1935 		if (value != 0)
1936 			ret = value;
1937 		break;
1938 
1939 	case oIPQoS:
1940 		arg = argv_next(&ac, &av);
1941 		if ((value = parse_ipqos(arg)) == -1) {
1942 			error("%s line %d: Bad IPQoS value: %s",
1943 			    filename, linenum, arg);
1944 			goto out;
1945 		}
1946 		arg = argv_next(&ac, &av);
1947 		if (arg == NULL)
1948 			value2 = value;
1949 		else if ((value2 = parse_ipqos(arg)) == -1) {
1950 			error("%s line %d: Bad IPQoS value: %s",
1951 			    filename, linenum, arg);
1952 			goto out;
1953 		}
1954 		if (*activep && options->ip_qos_interactive == -1) {
1955 			options->ip_qos_interactive = value;
1956 			options->ip_qos_bulk = value2;
1957 		}
1958 		break;
1959 
1960 	case oRequestTTY:
1961 		intptr = &options->request_tty;
1962 		multistate_ptr = multistate_requesttty;
1963 		goto parse_multistate;
1964 
1965 	case oSessionType:
1966 		intptr = &options->session_type;
1967 		multistate_ptr = multistate_sessiontype;
1968 		goto parse_multistate;
1969 
1970 	case oStdinNull:
1971 		intptr = &options->stdin_null;
1972 		goto parse_flag;
1973 
1974 	case oForkAfterAuthentication:
1975 		intptr = &options->fork_after_authentication;
1976 		goto parse_flag;
1977 
1978 	case oVersionAddendum:
1979 		if (str == NULL)
1980 			fatal("%.200s line %d: Missing argument.", filename,
1981 			    linenum);
1982 		len = strspn(str, WHITESPACE);
1983 		if (*activep && options->version_addendum == NULL) {
1984 			if (strcasecmp(str + len, "none") == 0)
1985 				options->version_addendum = xstrdup("");
1986 			else if (strchr(str + len, '\r') != NULL)
1987 				fatal("%.200s line %d: Invalid argument",
1988 				    filename, linenum);
1989 			else
1990 				options->version_addendum = xstrdup(str + len);
1991 		}
1992 		return 0;
1993 
1994 	case oIgnoreUnknown:
1995 		charptr = &options->ignored_unknown;
1996 		goto parse_string;
1997 
1998 	case oProxyUseFdpass:
1999 		intptr = &options->proxy_use_fdpass;
2000 		goto parse_flag;
2001 
2002 	case oCanonicalDomains:
2003 		value = options->num_canonical_domains != 0;
2004 		i = 0;
2005 		while ((arg = argv_next(&ac, &av)) != NULL) {
2006 			if (*arg == '\0') {
2007 				error("%s line %d: keyword %s empty argument",
2008 				    filename, linenum, keyword);
2009 				goto out;
2010 			}
2011 			/* Allow "none" only in first position */
2012 			if (strcasecmp(arg, "none") == 0) {
2013 				if (i > 0 || ac > 0) {
2014 					error("%s line %d: keyword %s \"none\" "
2015 					    "argument must appear alone.",
2016 					    filename, linenum, keyword);
2017 					goto out;
2018 				}
2019 			}
2020 			i++;
2021 			if (!valid_domain(arg, 1, &errstr)) {
2022 				error("%s line %d: %s", filename, linenum,
2023 				    errstr);
2024 				goto out;
2025 			}
2026 			if (!*activep || value)
2027 				continue;
2028 			if (options->num_canonical_domains >=
2029 			    MAX_CANON_DOMAINS) {
2030 				error("%s line %d: too many hostname suffixes.",
2031 				    filename, linenum);
2032 				goto out;
2033 			}
2034 			options->canonical_domains[
2035 			    options->num_canonical_domains++] = xstrdup(arg);
2036 		}
2037 		break;
2038 
2039 	case oCanonicalizePermittedCNAMEs:
2040 		value = options->num_permitted_cnames != 0;
2041 		while ((arg = argv_next(&ac, &av)) != NULL) {
2042 			/* Either '*' for everything or 'list:list' */
2043 			if (strcmp(arg, "*") == 0)
2044 				arg2 = arg;
2045 			else {
2046 				lowercase(arg);
2047 				if ((arg2 = strchr(arg, ':')) == NULL ||
2048 				    arg2[1] == '\0') {
2049 					error("%s line %d: "
2050 					    "Invalid permitted CNAME \"%s\"",
2051 					    filename, linenum, arg);
2052 					goto out;
2053 				}
2054 				*arg2 = '\0';
2055 				arg2++;
2056 			}
2057 			if (!*activep || value)
2058 				continue;
2059 			if (options->num_permitted_cnames >=
2060 			    MAX_CANON_DOMAINS) {
2061 				error("%s line %d: too many permitted CNAMEs.",
2062 				    filename, linenum);
2063 				goto out;
2064 			}
2065 			cname = options->permitted_cnames +
2066 			    options->num_permitted_cnames++;
2067 			cname->source_list = xstrdup(arg);
2068 			cname->target_list = xstrdup(arg2);
2069 		}
2070 		break;
2071 
2072 	case oCanonicalizeHostname:
2073 		intptr = &options->canonicalize_hostname;
2074 		multistate_ptr = multistate_canonicalizehostname;
2075 		goto parse_multistate;
2076 
2077 	case oCanonicalizeMaxDots:
2078 		intptr = &options->canonicalize_max_dots;
2079 		goto parse_int;
2080 
2081 	case oCanonicalizeFallbackLocal:
2082 		intptr = &options->canonicalize_fallback_local;
2083 		goto parse_flag;
2084 
2085 	case oStreamLocalBindMask:
2086 		arg = argv_next(&ac, &av);
2087 		if (!arg || *arg == '\0') {
2088 			error("%.200s line %d: Missing StreamLocalBindMask "
2089 			    "argument.", filename, linenum);
2090 			goto out;
2091 		}
2092 		/* Parse mode in octal format */
2093 		value = strtol(arg, &endofnumber, 8);
2094 		if (arg == endofnumber || value < 0 || value > 0777) {
2095 			error("%.200s line %d: Bad mask.", filename, linenum);
2096 			goto out;
2097 		}
2098 		options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
2099 		break;
2100 
2101 	case oStreamLocalBindUnlink:
2102 		intptr = &options->fwd_opts.streamlocal_bind_unlink;
2103 		goto parse_flag;
2104 
2105 	case oRevokedHostKeys:
2106 		charptr = &options->revoked_host_keys;
2107 		goto parse_string;
2108 
2109 	case oFingerprintHash:
2110 		intptr = &options->fingerprint_hash;
2111 		arg = argv_next(&ac, &av);
2112 		if (!arg || *arg == '\0') {
2113 			error("%.200s line %d: Missing argument.",
2114 			    filename, linenum);
2115 			goto out;
2116 		}
2117 		if ((value = ssh_digest_alg_by_name(arg)) == -1) {
2118 			error("%.200s line %d: Invalid hash algorithm \"%s\".",
2119 			    filename, linenum, arg);
2120 			goto out;
2121 		}
2122 		if (*activep && *intptr == -1)
2123 			*intptr = value;
2124 		break;
2125 
2126 	case oUpdateHostkeys:
2127 		intptr = &options->update_hostkeys;
2128 		multistate_ptr = multistate_yesnoask;
2129 		goto parse_multistate;
2130 
2131 	case oHostbasedAcceptedAlgorithms:
2132 		charptr = &options->hostbased_accepted_algos;
2133 		goto parse_pubkey_algos;
2134 
2135 	case oPubkeyAcceptedAlgorithms:
2136 		charptr = &options->pubkey_accepted_algos;
2137 		goto parse_pubkey_algos;
2138 
2139 	case oAddKeysToAgent:
2140 		arg = argv_next(&ac, &av);
2141 		arg2 = argv_next(&ac, &av);
2142 		value = parse_multistate_value(arg, filename, linenum,
2143 		    multistate_yesnoaskconfirm);
2144 		value2 = 0; /* unlimited lifespan by default */
2145 		if (value == 3 && arg2 != NULL) {
2146 			/* allow "AddKeysToAgent confirm 5m" */
2147 			if ((value2 = convtime(arg2)) == -1 ||
2148 			    value2 > INT_MAX) {
2149 				error("%s line %d: invalid time value.",
2150 				    filename, linenum);
2151 				goto out;
2152 			}
2153 		} else if (value == -1 && arg2 == NULL) {
2154 			if ((value2 = convtime(arg)) == -1 ||
2155 			    value2 > INT_MAX) {
2156 				error("%s line %d: unsupported option",
2157 				    filename, linenum);
2158 				goto out;
2159 			}
2160 			value = 1; /* yes */
2161 		} else if (value == -1 || arg2 != NULL) {
2162 			error("%s line %d: unsupported option",
2163 			    filename, linenum);
2164 			goto out;
2165 		}
2166 		if (*activep && options->add_keys_to_agent == -1) {
2167 			options->add_keys_to_agent = value;
2168 			options->add_keys_to_agent_lifespan = value2;
2169 		}
2170 		break;
2171 
2172 	case oIdentityAgent:
2173 		charptr = &options->identity_agent;
2174 		arg = argv_next(&ac, &av);
2175 		if (!arg || *arg == '\0') {
2176 			error("%.200s line %d: Missing argument.",
2177 			    filename, linenum);
2178 			goto out;
2179 		}
2180   parse_agent_path:
2181 		/* Extra validation if the string represents an env var. */
2182 		if ((arg2 = dollar_expand(&r, arg)) == NULL || r) {
2183 			error("%.200s line %d: Invalid environment expansion "
2184 			    "%s.", filename, linenum, arg);
2185 			goto out;
2186 		}
2187 		free(arg2);
2188 		/* check for legacy environment format */
2189 		if (arg[0] == '$' && arg[1] != '{' &&
2190 		    !valid_env_name(arg + 1)) {
2191 			error("%.200s line %d: Invalid environment name %s.",
2192 			    filename, linenum, arg);
2193 			goto out;
2194 		}
2195 		if (*activep && *charptr == NULL)
2196 			*charptr = xstrdup(arg);
2197 		break;
2198 
2199 	case oDeprecated:
2200 		debug("%s line %d: Deprecated option \"%s\"",
2201 		    filename, linenum, keyword);
2202 		argv_consume(&ac);
2203 		break;
2204 
2205 	case oUnsupported:
2206 		error("%s line %d: Unsupported option \"%s\"",
2207 		    filename, linenum, keyword);
2208 		argv_consume(&ac);
2209 		break;
2210 
2211 	default:
2212 		error("%s line %d: Unimplemented opcode %d",
2213 		    filename, linenum, opcode);
2214 		goto out;
2215 	}
2216 
2217 	/* Check that there is no garbage at end of line. */
2218 	if (ac > 0) {
2219 		error("%.200s line %d: keyword %s extra arguments "
2220 		    "at end of line", filename, linenum, keyword);
2221 		goto out;
2222 	}
2223 
2224 	/* success */
2225 	ret = 0;
2226  out:
2227 	argv_free(oav, oac);
2228 	return ret;
2229 }
2230 
2231 /*
2232  * Reads the config file and modifies the options accordingly.  Options
2233  * should already be initialized before this call.  This never returns if
2234  * there is an error.  If the file does not exist, this returns 0.
2235  */
2236 int
2237 read_config_file(const char *filename, struct passwd *pw, const char *host,
2238     const char *original_host, Options *options, int flags,
2239     int *want_final_pass)
2240 {
2241 	int active = 1;
2242 
2243 	return read_config_file_depth(filename, pw, host, original_host,
2244 	    options, flags, &active, want_final_pass, 0);
2245 }
2246 
2247 #define READCONF_MAX_DEPTH	16
2248 static int
2249 read_config_file_depth(const char *filename, struct passwd *pw,
2250     const char *host, const char *original_host, Options *options,
2251     int flags, int *activep, int *want_final_pass, int depth)
2252 {
2253 	FILE *f;
2254 	char *line = NULL;
2255 	size_t linesize = 0;
2256 	int linenum;
2257 	int bad_options = 0;
2258 
2259 	if (depth < 0 || depth > READCONF_MAX_DEPTH)
2260 		fatal("Too many recursive configuration includes");
2261 
2262 	if ((f = fopen(filename, "r")) == NULL)
2263 		return 0;
2264 
2265 	if (flags & SSHCONF_CHECKPERM) {
2266 		struct stat sb;
2267 
2268 		if (fstat(fileno(f), &sb) == -1)
2269 			fatal("fstat %s: %s", filename, strerror(errno));
2270 		if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
2271 		    (sb.st_mode & 022) != 0))
2272 			fatal("Bad owner or permissions on %s", filename);
2273 	}
2274 
2275 	debug("Reading configuration data %.200s", filename);
2276 
2277 	/*
2278 	 * Mark that we are now processing the options.  This flag is turned
2279 	 * on/off by Host specifications.
2280 	 */
2281 	linenum = 0;
2282 	while (getline(&line, &linesize, f) != -1) {
2283 		/* Update line number counter. */
2284 		linenum++;
2285 		/*
2286 		 * Trim out comments and strip whitespace.
2287 		 * NB - preserve newlines, they are needed to reproduce
2288 		 * line numbers later for error messages.
2289 		 */
2290 		if (process_config_line_depth(options, pw, host, original_host,
2291 		    line, filename, linenum, activep, flags, want_final_pass,
2292 		    depth) != 0)
2293 			bad_options++;
2294 	}
2295 	free(line);
2296 	fclose(f);
2297 	if (bad_options > 0)
2298 		fatal("%s: terminating, %d bad configuration options",
2299 		    filename, bad_options);
2300 	return 1;
2301 }
2302 
2303 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
2304 int
2305 option_clear_or_none(const char *o)
2306 {
2307 	return o == NULL || strcasecmp(o, "none") == 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->version_addendum = NULL;
2322 	options->forward_agent = -1;
2323 	options->forward_agent_sock_path = NULL;
2324 	options->forward_x11 = -1;
2325 	options->forward_x11_trusted = -1;
2326 	options->forward_x11_timeout = -1;
2327 	options->stdio_forward_host = NULL;
2328 	options->stdio_forward_port = 0;
2329 	options->clear_forwardings = -1;
2330 	options->exit_on_forward_failure = -1;
2331 	options->xauth_location = NULL;
2332 	options->fwd_opts.gateway_ports = -1;
2333 	options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
2334 	options->fwd_opts.streamlocal_bind_unlink = -1;
2335 	options->pubkey_authentication = -1;
2336 	options->gss_authentication = -1;
2337 	options->gss_deleg_creds = -1;
2338 	options->password_authentication = -1;
2339 	options->kbd_interactive_authentication = -1;
2340 	options->kbd_interactive_devices = NULL;
2341 	options->hostbased_authentication = -1;
2342 	options->batch_mode = -1;
2343 	options->check_host_ip = -1;
2344 	options->strict_host_key_checking = -1;
2345 	options->compression = -1;
2346 	options->tcp_keep_alive = -1;
2347 	options->port = -1;
2348 	options->address_family = -1;
2349 	options->connection_attempts = -1;
2350 	options->connection_timeout = -1;
2351 	options->number_of_password_prompts = -1;
2352 	options->ciphers = NULL;
2353 	options->macs = NULL;
2354 	options->kex_algorithms = NULL;
2355 	options->hostkeyalgorithms = NULL;
2356 	options->ca_sign_algorithms = NULL;
2357 	options->num_identity_files = 0;
2358 	memset(options->identity_keys, 0, sizeof(options->identity_keys));
2359 	options->num_certificate_files = 0;
2360 	memset(options->certificates, 0, sizeof(options->certificates));
2361 	options->hostname = NULL;
2362 	options->host_key_alias = NULL;
2363 	options->proxy_command = NULL;
2364 	options->jump_user = NULL;
2365 	options->jump_host = NULL;
2366 	options->jump_port = -1;
2367 	options->jump_extra = NULL;
2368 	options->user = NULL;
2369 	options->escape_char = -1;
2370 	options->num_system_hostfiles = 0;
2371 	options->num_user_hostfiles = 0;
2372 	options->local_forwards = NULL;
2373 	options->num_local_forwards = 0;
2374 	options->remote_forwards = NULL;
2375 	options->num_remote_forwards = 0;
2376 	options->permitted_remote_opens = NULL;
2377 	options->num_permitted_remote_opens = 0;
2378 	options->log_facility = SYSLOG_FACILITY_NOT_SET;
2379 	options->log_level = SYSLOG_LEVEL_NOT_SET;
2380 	options->num_log_verbose = 0;
2381 	options->log_verbose = NULL;
2382 	options->preferred_authentications = NULL;
2383 	options->bind_address = NULL;
2384 	options->bind_interface = NULL;
2385 	options->pkcs11_provider = NULL;
2386 	options->sk_provider = NULL;
2387 	options->enable_ssh_keysign = - 1;
2388 	options->no_host_authentication_for_localhost = - 1;
2389 	options->identities_only = - 1;
2390 	options->rekey_limit = - 1;
2391 	options->rekey_interval = -1;
2392 	options->verify_host_key_dns = -1;
2393 	options->server_alive_interval = -1;
2394 	options->server_alive_count_max = -1;
2395 	options->send_env = NULL;
2396 	options->num_send_env = 0;
2397 	options->setenv = NULL;
2398 	options->num_setenv = 0;
2399 	options->control_path = NULL;
2400 	options->control_master = -1;
2401 	options->control_persist = -1;
2402 	options->control_persist_timeout = 0;
2403 	options->hash_known_hosts = -1;
2404 	options->tun_open = -1;
2405 	options->tun_local = -1;
2406 	options->tun_remote = -1;
2407 	options->local_command = NULL;
2408 	options->permit_local_command = -1;
2409 	options->remote_command = NULL;
2410 	options->add_keys_to_agent = -1;
2411 	options->add_keys_to_agent_lifespan = -1;
2412 	options->identity_agent = NULL;
2413 	options->visual_host_key = -1;
2414 	options->ip_qos_interactive = -1;
2415 	options->ip_qos_bulk = -1;
2416 	options->request_tty = -1;
2417 	options->session_type = -1;
2418 	options->stdin_null = -1;
2419 	options->fork_after_authentication = -1;
2420 	options->proxy_use_fdpass = -1;
2421 	options->ignored_unknown = NULL;
2422 	options->num_canonical_domains = 0;
2423 	options->num_permitted_cnames = 0;
2424 	options->canonicalize_max_dots = -1;
2425 	options->canonicalize_fallback_local = -1;
2426 	options->canonicalize_hostname = -1;
2427 	options->revoked_host_keys = NULL;
2428 	options->fingerprint_hash = -1;
2429 	options->update_hostkeys = -1;
2430 	options->hostbased_accepted_algos = NULL;
2431 	options->pubkey_accepted_algos = NULL;
2432 	options->known_hosts_command = NULL;
2433 }
2434 
2435 /*
2436  * A petite version of fill_default_options() that just fills the options
2437  * needed for hostname canonicalization to proceed.
2438  */
2439 void
2440 fill_default_options_for_canonicalization(Options *options)
2441 {
2442 	if (options->canonicalize_max_dots == -1)
2443 		options->canonicalize_max_dots = 1;
2444 	if (options->canonicalize_fallback_local == -1)
2445 		options->canonicalize_fallback_local = 1;
2446 	if (options->canonicalize_hostname == -1)
2447 		options->canonicalize_hostname = SSH_CANONICALISE_NO;
2448 }
2449 
2450 /*
2451  * Called after processing other sources of option data, this fills those
2452  * options for which no value has been specified with their default values.
2453  */
2454 int
2455 fill_default_options(Options * options)
2456 {
2457 	char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig;
2458 	char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig;
2459 	int ret = 0, r;
2460 
2461 	if (options->forward_agent == -1)
2462 		options->forward_agent = 0;
2463 	if (options->forward_x11 == -1)
2464 		options->forward_x11 = 0;
2465 	if (options->forward_x11_trusted == -1)
2466 		options->forward_x11_trusted = 0;
2467 	if (options->forward_x11_timeout == -1)
2468 		options->forward_x11_timeout = 1200;
2469 	/*
2470 	 * stdio forwarding (-W) changes the default for these but we defer
2471 	 * setting the values so they can be overridden.
2472 	 */
2473 	if (options->exit_on_forward_failure == -1)
2474 		options->exit_on_forward_failure =
2475 		    options->stdio_forward_host != NULL ? 1 : 0;
2476 	if (options->clear_forwardings == -1)
2477 		options->clear_forwardings =
2478 		    options->stdio_forward_host != NULL ? 1 : 0;
2479 	if (options->clear_forwardings == 1)
2480 		clear_forwardings(options);
2481 
2482 	if (options->xauth_location == NULL)
2483 		options->xauth_location = xstrdup(_PATH_XAUTH);
2484 	if (options->fwd_opts.gateway_ports == -1)
2485 		options->fwd_opts.gateway_ports = 0;
2486 	if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
2487 		options->fwd_opts.streamlocal_bind_mask = 0177;
2488 	if (options->fwd_opts.streamlocal_bind_unlink == -1)
2489 		options->fwd_opts.streamlocal_bind_unlink = 0;
2490 	if (options->pubkey_authentication == -1)
2491 		options->pubkey_authentication = 1;
2492 	if (options->gss_authentication == -1)
2493 		options->gss_authentication = 0;
2494 	if (options->gss_deleg_creds == -1)
2495 		options->gss_deleg_creds = 0;
2496 	if (options->password_authentication == -1)
2497 		options->password_authentication = 1;
2498 	if (options->kbd_interactive_authentication == -1)
2499 		options->kbd_interactive_authentication = 1;
2500 	if (options->hostbased_authentication == -1)
2501 		options->hostbased_authentication = 0;
2502 	if (options->batch_mode == -1)
2503 		options->batch_mode = 0;
2504 	if (options->check_host_ip == -1)
2505 		options->check_host_ip = 0;
2506 	if (options->strict_host_key_checking == -1)
2507 		options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK;
2508 	if (options->compression == -1)
2509 		options->compression = 0;
2510 	if (options->tcp_keep_alive == -1)
2511 		options->tcp_keep_alive = 1;
2512 	if (options->port == -1)
2513 		options->port = 0;	/* Filled in ssh_connect. */
2514 	if (options->address_family == -1)
2515 		options->address_family = AF_UNSPEC;
2516 	if (options->connection_attempts == -1)
2517 		options->connection_attempts = 1;
2518 	if (options->number_of_password_prompts == -1)
2519 		options->number_of_password_prompts = 3;
2520 	/* options->hostkeyalgorithms, default set in myproposals.h */
2521 	if (options->add_keys_to_agent == -1) {
2522 		options->add_keys_to_agent = 0;
2523 		options->add_keys_to_agent_lifespan = 0;
2524 	}
2525 	if (options->num_identity_files == 0) {
2526 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0);
2527 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0);
2528 #ifdef OPENSSL_HAS_ECC
2529 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0);
2530 		add_identity_file(options, "~/",
2531 		    _PATH_SSH_CLIENT_ID_ECDSA_SK, 0);
2532 #endif
2533 		add_identity_file(options, "~/",
2534 		    _PATH_SSH_CLIENT_ID_ED25519, 0);
2535 		add_identity_file(options, "~/",
2536 		    _PATH_SSH_CLIENT_ID_ED25519_SK, 0);
2537 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0);
2538 	}
2539 	if (options->escape_char == -1)
2540 		options->escape_char = '~';
2541 	if (options->num_system_hostfiles == 0) {
2542 		options->system_hostfiles[options->num_system_hostfiles++] =
2543 		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
2544 		options->system_hostfiles[options->num_system_hostfiles++] =
2545 		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
2546 	}
2547 	if (options->update_hostkeys == -1) {
2548 		if (options->verify_host_key_dns <= 0 &&
2549 		    (options->num_user_hostfiles == 0 ||
2550 		    (options->num_user_hostfiles == 1 && strcmp(options->
2551 		    user_hostfiles[0], _PATH_SSH_USER_HOSTFILE) == 0)))
2552 			options->update_hostkeys = SSH_UPDATE_HOSTKEYS_YES;
2553 		else
2554 			options->update_hostkeys = SSH_UPDATE_HOSTKEYS_NO;
2555 	}
2556 	if (options->num_user_hostfiles == 0) {
2557 		options->user_hostfiles[options->num_user_hostfiles++] =
2558 		    xstrdup(_PATH_SSH_USER_HOSTFILE);
2559 		options->user_hostfiles[options->num_user_hostfiles++] =
2560 		    xstrdup(_PATH_SSH_USER_HOSTFILE2);
2561 	}
2562 	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
2563 		options->log_level = SYSLOG_LEVEL_INFO;
2564 	if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
2565 		options->log_facility = SYSLOG_FACILITY_USER;
2566 	if (options->no_host_authentication_for_localhost == - 1)
2567 		options->no_host_authentication_for_localhost = 0;
2568 	if (options->identities_only == -1)
2569 		options->identities_only = 0;
2570 	if (options->enable_ssh_keysign == -1)
2571 		options->enable_ssh_keysign = 0;
2572 	if (options->rekey_limit == -1)
2573 		options->rekey_limit = 0;
2574 	if (options->rekey_interval == -1)
2575 		options->rekey_interval = 0;
2576 #if HAVE_LDNS
2577 	if (options->verify_host_key_dns == -1)
2578 		/* automatically trust a verified SSHFP record */
2579 		options->verify_host_key_dns = 1;
2580 #else
2581 	if (options->verify_host_key_dns == -1)
2582 		options->verify_host_key_dns = 0;
2583 #endif
2584 	if (options->server_alive_interval == -1)
2585 		options->server_alive_interval = 0;
2586 	if (options->server_alive_count_max == -1)
2587 		options->server_alive_count_max = 3;
2588 	if (options->control_master == -1)
2589 		options->control_master = 0;
2590 	if (options->control_persist == -1) {
2591 		options->control_persist = 0;
2592 		options->control_persist_timeout = 0;
2593 	}
2594 	if (options->hash_known_hosts == -1)
2595 		options->hash_known_hosts = 0;
2596 	if (options->tun_open == -1)
2597 		options->tun_open = SSH_TUNMODE_NO;
2598 	if (options->tun_local == -1)
2599 		options->tun_local = SSH_TUNID_ANY;
2600 	if (options->tun_remote == -1)
2601 		options->tun_remote = SSH_TUNID_ANY;
2602 	if (options->permit_local_command == -1)
2603 		options->permit_local_command = 0;
2604 	if (options->visual_host_key == -1)
2605 		options->visual_host_key = 0;
2606 	if (options->ip_qos_interactive == -1)
2607 		options->ip_qos_interactive = IPTOS_DSCP_AF21;
2608 	if (options->ip_qos_bulk == -1)
2609 		options->ip_qos_bulk = IPTOS_DSCP_CS1;
2610 	if (options->request_tty == -1)
2611 		options->request_tty = REQUEST_TTY_AUTO;
2612 	if (options->session_type == -1)
2613 		options->session_type = SESSION_TYPE_DEFAULT;
2614 	if (options->stdin_null == -1)
2615 		options->stdin_null = 0;
2616 	if (options->fork_after_authentication == -1)
2617 		options->fork_after_authentication = 0;
2618 	if (options->proxy_use_fdpass == -1)
2619 		options->proxy_use_fdpass = 0;
2620 	if (options->canonicalize_max_dots == -1)
2621 		options->canonicalize_max_dots = 1;
2622 	if (options->canonicalize_fallback_local == -1)
2623 		options->canonicalize_fallback_local = 1;
2624 	if (options->canonicalize_hostname == -1)
2625 		options->canonicalize_hostname = SSH_CANONICALISE_NO;
2626 	if (options->fingerprint_hash == -1)
2627 		options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
2628 #ifdef ENABLE_SK_INTERNAL
2629 	if (options->sk_provider == NULL)
2630 		options->sk_provider = xstrdup("internal");
2631 #else
2632 	if (options->sk_provider == NULL)
2633 		options->sk_provider = xstrdup("$SSH_SK_PROVIDER");
2634 #endif
2635 
2636 	/* Expand KEX name lists */
2637 	all_cipher = cipher_alg_list(',', 0);
2638 	all_mac = mac_alg_list(',');
2639 	all_kex = kex_alg_list(',');
2640 	all_key = sshkey_alg_list(0, 0, 1, ',');
2641 	all_sig = sshkey_alg_list(0, 1, 1, ',');
2642 	/* remove unsupported algos from default lists */
2643 	def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher);
2644 	def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac);
2645 	def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex);
2646 	def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
2647 	def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig);
2648 #define ASSEMBLE(what, defaults, all) \
2649 	do { \
2650 		if ((r = kex_assemble_names(&options->what, \
2651 		    defaults, all)) != 0) { \
2652 			error_fr(r, "%s", #what); \
2653 			goto fail; \
2654 		} \
2655 	} while (0)
2656 	ASSEMBLE(ciphers, def_cipher, all_cipher);
2657 	ASSEMBLE(macs, def_mac, all_mac);
2658 	ASSEMBLE(kex_algorithms, def_kex, all_kex);
2659 	ASSEMBLE(hostbased_accepted_algos, def_key, all_key);
2660 	ASSEMBLE(pubkey_accepted_algos, def_key, all_key);
2661 	ASSEMBLE(ca_sign_algorithms, def_sig, all_sig);
2662 #undef ASSEMBLE
2663 
2664 #define CLEAR_ON_NONE(v) \
2665 	do { \
2666 		if (option_clear_or_none(v)) { \
2667 			free(v); \
2668 			v = NULL; \
2669 		} \
2670 	} while(0)
2671 	CLEAR_ON_NONE(options->local_command);
2672 	CLEAR_ON_NONE(options->remote_command);
2673 	CLEAR_ON_NONE(options->proxy_command);
2674 	CLEAR_ON_NONE(options->control_path);
2675 	CLEAR_ON_NONE(options->revoked_host_keys);
2676 	CLEAR_ON_NONE(options->pkcs11_provider);
2677 	CLEAR_ON_NONE(options->sk_provider);
2678 	CLEAR_ON_NONE(options->known_hosts_command);
2679 	if (options->jump_host != NULL &&
2680 	    strcmp(options->jump_host, "none") == 0 &&
2681 	    options->jump_port == 0 && options->jump_user == NULL) {
2682 		free(options->jump_host);
2683 		options->jump_host = NULL;
2684 	}
2685 	/* options->identity_agent distinguishes NULL from 'none' */
2686 	/* options->user will be set in the main program if appropriate */
2687 	/* options->hostname will be set in the main program if appropriate */
2688 	/* options->host_key_alias should not be set by default */
2689 	/* options->preferred_authentications will be set in ssh */
2690 	if (options->version_addendum == NULL)
2691 		options->version_addendum = xstrdup(SSH_VERSION_FREEBSD);
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 	if ( o->num_permitted_cnames > 0) {
3403 		printf("canonicalizePermittedcnames");
3404 		for (i = 0; i < o->num_permitted_cnames; i++) {
3405 			printf(" %s:%s", o->permitted_cnames[i].source_list,
3406 			    o->permitted_cnames[i].target_list);
3407 		}
3408 		printf("\n");
3409 	}
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