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