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