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