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