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