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