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