xref: /freebsd/crypto/openssh/readconf.c (revision 94e21add45344f0669f910ea77db499e8c892c90)
1 /* $OpenBSD: readconf.c,v 1.371 2023/01/02 07:03:30 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 		uvalue = *uintptr;	/* modified later */
1578 		i = 0;
1579 		while ((arg = argv_next(&ac, &av)) != NULL) {
1580 			arg2 = xstrdup(arg);
1581 			/* Allow any/none only in first position */
1582 			if (strcasecmp(arg, "none") == 0 ||
1583 			    strcasecmp(arg, "any") == 0) {
1584 				if (i > 0 || ac > 0) {
1585 					error("%s line %d: keyword %s \"%s\" "
1586 					    "argument must appear alone.",
1587 					    filename, linenum, keyword, arg);
1588 					goto out;
1589 				}
1590 			} else {
1591 				p = hpdelim(&arg);
1592 				if (p == NULL) {
1593 					fatal("%s line %d: missing host in %s",
1594 					    filename, linenum,
1595 					    lookup_opcode_name(opcode));
1596 				}
1597 				p = cleanhostname(p);
1598 				/*
1599 				 * don't want to use permitopen_port to avoid
1600 				 * dependency on channels.[ch] here.
1601 				 */
1602 				if (arg == NULL || (strcmp(arg, "*") != 0 &&
1603 				    a2port(arg) <= 0)) {
1604 					fatal("%s line %d: bad port number "
1605 					    "in %s", filename, linenum,
1606 					    lookup_opcode_name(opcode));
1607 				}
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 			i++;
1616 		}
1617 		if (i == 0)
1618 			fatal("%s line %d: missing %s specification",
1619 			    filename, linenum, lookup_opcode_name(opcode));
1620 		break;
1621 
1622 	case oClearAllForwardings:
1623 		intptr = &options->clear_forwardings;
1624 		goto parse_flag;
1625 
1626 	case oHost:
1627 		if (cmdline) {
1628 			error("Host directive not supported as a command-line "
1629 			    "option");
1630 			goto out;
1631 		}
1632 		*activep = 0;
1633 		arg2 = NULL;
1634 		while ((arg = argv_next(&ac, &av)) != NULL) {
1635 			if (*arg == '\0') {
1636 				error("%s line %d: keyword %s empty argument",
1637 				    filename, linenum, keyword);
1638 				goto out;
1639 			}
1640 			if ((flags & SSHCONF_NEVERMATCH) != 0) {
1641 				argv_consume(&ac);
1642 				break;
1643 			}
1644 			negated = *arg == '!';
1645 			if (negated)
1646 				arg++;
1647 			if (match_pattern(host, arg)) {
1648 				if (negated) {
1649 					debug("%.200s line %d: Skipping Host "
1650 					    "block because of negated match "
1651 					    "for %.100s", filename, linenum,
1652 					    arg);
1653 					*activep = 0;
1654 					argv_consume(&ac);
1655 					break;
1656 				}
1657 				if (!*activep)
1658 					arg2 = arg; /* logged below */
1659 				*activep = 1;
1660 			}
1661 		}
1662 		if (*activep)
1663 			debug("%.200s line %d: Applying options for %.100s",
1664 			    filename, linenum, arg2);
1665 		break;
1666 
1667 	case oMatch:
1668 		if (cmdline) {
1669 			error("Host directive not supported as a command-line "
1670 			    "option");
1671 			goto out;
1672 		}
1673 		value = match_cfg_line(options, &str, pw, host, original_host,
1674 		    flags & SSHCONF_FINAL, want_final_pass,
1675 		    filename, linenum);
1676 		if (value < 0) {
1677 			error("%.200s line %d: Bad Match condition", filename,
1678 			    linenum);
1679 			goto out;
1680 		}
1681 		*activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value;
1682 		/*
1683 		 * If match_cfg_line() didn't consume all its arguments then
1684 		 * arrange for the extra arguments check below to fail.
1685 		 */
1686 
1687 		if (str == NULL || *str == '\0')
1688 			argv_consume(&ac);
1689 		break;
1690 
1691 	case oEscapeChar:
1692 		intptr = &options->escape_char;
1693 		arg = argv_next(&ac, &av);
1694 		if (!arg || *arg == '\0') {
1695 			error("%.200s line %d: Missing argument.",
1696 			    filename, linenum);
1697 			goto out;
1698 		}
1699 		if (strcmp(arg, "none") == 0)
1700 			value = SSH_ESCAPECHAR_NONE;
1701 		else if (arg[1] == '\0')
1702 			value = (u_char) arg[0];
1703 		else if (arg[0] == '^' && arg[2] == 0 &&
1704 		    (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
1705 			value = (u_char) arg[1] & 31;
1706 		else {
1707 			error("%.200s line %d: Bad escape character.",
1708 			    filename, linenum);
1709 			goto out;
1710 		}
1711 		if (*activep && *intptr == -1)
1712 			*intptr = value;
1713 		break;
1714 
1715 	case oAddressFamily:
1716 		intptr = &options->address_family;
1717 		multistate_ptr = multistate_addressfamily;
1718 		goto parse_multistate;
1719 
1720 	case oEnableSSHKeysign:
1721 		intptr = &options->enable_ssh_keysign;
1722 		goto parse_flag;
1723 
1724 	case oIdentitiesOnly:
1725 		intptr = &options->identities_only;
1726 		goto parse_flag;
1727 
1728 	case oServerAliveInterval:
1729 		intptr = &options->server_alive_interval;
1730 		goto parse_time;
1731 
1732 	case oServerAliveCountMax:
1733 		intptr = &options->server_alive_count_max;
1734 		goto parse_int;
1735 
1736 	case oSendEnv:
1737 		while ((arg = argv_next(&ac, &av)) != NULL) {
1738 			if (*arg == '\0' || strchr(arg, '=') != NULL) {
1739 				error("%s line %d: Invalid environment name.",
1740 				    filename, linenum);
1741 				goto out;
1742 			}
1743 			if (!*activep)
1744 				continue;
1745 			if (*arg == '-') {
1746 				/* Removing an env var */
1747 				rm_env(options, arg, filename, linenum);
1748 				continue;
1749 			}
1750 			opt_array_append(filename, linenum,
1751 			    lookup_opcode_name(opcode),
1752 			    &options->send_env, &options->num_send_env, arg);
1753 		}
1754 		break;
1755 
1756 	case oSetEnv:
1757 		value = options->num_setenv;
1758 		while ((arg = argv_next(&ac, &av)) != NULL) {
1759 			if (strchr(arg, '=') == NULL) {
1760 				error("%s line %d: Invalid SetEnv.",
1761 				    filename, linenum);
1762 				goto out;
1763 			}
1764 			if (!*activep || value != 0)
1765 				continue;
1766 			if (lookup_setenv_in_list(arg, options->setenv,
1767 			    options->num_setenv) != NULL) {
1768 				debug2("%s line %d: ignoring duplicate env "
1769 				    "name \"%.64s\"", filename, linenum, arg);
1770 				continue;
1771 			}
1772 			opt_array_append(filename, linenum,
1773 			    lookup_opcode_name(opcode),
1774 			    &options->setenv, &options->num_setenv, arg);
1775 		}
1776 		break;
1777 
1778 	case oControlPath:
1779 		charptr = &options->control_path;
1780 		goto parse_string;
1781 
1782 	case oControlMaster:
1783 		intptr = &options->control_master;
1784 		multistate_ptr = multistate_controlmaster;
1785 		goto parse_multistate;
1786 
1787 	case oControlPersist:
1788 		/* no/false/yes/true, or a time spec */
1789 		intptr = &options->control_persist;
1790 		arg = argv_next(&ac, &av);
1791 		if (!arg || *arg == '\0') {
1792 			error("%.200s line %d: Missing ControlPersist"
1793 			    " argument.", filename, linenum);
1794 			goto out;
1795 		}
1796 		value = 0;
1797 		value2 = 0;	/* timeout */
1798 		if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
1799 			value = 0;
1800 		else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
1801 			value = 1;
1802 		else if ((value2 = convtime(arg)) >= 0)
1803 			value = 1;
1804 		else {
1805 			error("%.200s line %d: Bad ControlPersist argument.",
1806 			    filename, linenum);
1807 			goto out;
1808 		}
1809 		if (*activep && *intptr == -1) {
1810 			*intptr = value;
1811 			options->control_persist_timeout = value2;
1812 		}
1813 		break;
1814 
1815 	case oHashKnownHosts:
1816 		intptr = &options->hash_known_hosts;
1817 		goto parse_flag;
1818 
1819 	case oTunnel:
1820 		intptr = &options->tun_open;
1821 		multistate_ptr = multistate_tunnel;
1822 		goto parse_multistate;
1823 
1824 	case oTunnelDevice:
1825 		arg = argv_next(&ac, &av);
1826 		if (!arg || *arg == '\0') {
1827 			error("%.200s line %d: Missing argument.",
1828 			    filename, linenum);
1829 			goto out;
1830 		}
1831 		value = a2tun(arg, &value2);
1832 		if (value == SSH_TUNID_ERR) {
1833 			error("%.200s line %d: Bad tun device.",
1834 			    filename, linenum);
1835 			goto out;
1836 		}
1837 		if (*activep && options->tun_local == -1) {
1838 			options->tun_local = value;
1839 			options->tun_remote = value2;
1840 		}
1841 		break;
1842 
1843 	case oLocalCommand:
1844 		charptr = &options->local_command;
1845 		goto parse_command;
1846 
1847 	case oPermitLocalCommand:
1848 		intptr = &options->permit_local_command;
1849 		goto parse_flag;
1850 
1851 	case oRemoteCommand:
1852 		charptr = &options->remote_command;
1853 		goto parse_command;
1854 
1855 	case oVisualHostKey:
1856 		intptr = &options->visual_host_key;
1857 		goto parse_flag;
1858 
1859 	case oInclude:
1860 		if (cmdline) {
1861 			error("Include directive not supported as a "
1862 			    "command-line option");
1863 			goto out;
1864 		}
1865 		value = 0;
1866 		while ((arg = argv_next(&ac, &av)) != NULL) {
1867 			if (*arg == '\0') {
1868 				error("%s line %d: keyword %s empty argument",
1869 				    filename, linenum, keyword);
1870 				goto out;
1871 			}
1872 			/*
1873 			 * Ensure all paths are anchored. User configuration
1874 			 * files may begin with '~/' but system configurations
1875 			 * must not. If the path is relative, then treat it
1876 			 * as living in ~/.ssh for user configurations or
1877 			 * /etc/ssh for system ones.
1878 			 */
1879 			if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0) {
1880 				error("%.200s line %d: bad include path %s.",
1881 				    filename, linenum, arg);
1882 				goto out;
1883 			}
1884 			if (!path_absolute(arg) && *arg != '~') {
1885 				xasprintf(&arg2, "%s/%s",
1886 				    (flags & SSHCONF_USERCONF) ?
1887 				    "~/" _PATH_SSH_USER_DIR : SSHDIR, arg);
1888 			} else
1889 				arg2 = xstrdup(arg);
1890 			memset(&gl, 0, sizeof(gl));
1891 			r = glob(arg2, GLOB_TILDE, NULL, &gl);
1892 			if (r == GLOB_NOMATCH) {
1893 				debug("%.200s line %d: include %s matched no "
1894 				    "files",filename, linenum, arg2);
1895 				free(arg2);
1896 				continue;
1897 			} else if (r != 0) {
1898 				error("%.200s line %d: glob failed for %s.",
1899 				    filename, linenum, arg2);
1900 				goto out;
1901 			}
1902 			free(arg2);
1903 			oactive = *activep;
1904 			for (i = 0; i < gl.gl_pathc; i++) {
1905 				debug3("%.200s line %d: Including file %s "
1906 				    "depth %d%s", filename, linenum,
1907 				    gl.gl_pathv[i], depth,
1908 				    oactive ? "" : " (parse only)");
1909 				r = read_config_file_depth(gl.gl_pathv[i],
1910 				    pw, host, original_host, options,
1911 				    flags | SSHCONF_CHECKPERM |
1912 				    (oactive ? 0 : SSHCONF_NEVERMATCH),
1913 				    activep, want_final_pass, depth + 1);
1914 				if (r != 1 && errno != ENOENT) {
1915 					error("Can't open user config file "
1916 					    "%.100s: %.100s", gl.gl_pathv[i],
1917 					    strerror(errno));
1918 					globfree(&gl);
1919 					goto out;
1920 				}
1921 				/*
1922 				 * don't let Match in includes clobber the
1923 				 * containing file's Match state.
1924 				 */
1925 				*activep = oactive;
1926 				if (r != 1)
1927 					value = -1;
1928 			}
1929 			globfree(&gl);
1930 		}
1931 		if (value != 0)
1932 			ret = value;
1933 		break;
1934 
1935 	case oIPQoS:
1936 		arg = argv_next(&ac, &av);
1937 		if ((value = parse_ipqos(arg)) == -1) {
1938 			error("%s line %d: Bad IPQoS value: %s",
1939 			    filename, linenum, arg);
1940 			goto out;
1941 		}
1942 		arg = argv_next(&ac, &av);
1943 		if (arg == NULL)
1944 			value2 = value;
1945 		else if ((value2 = parse_ipqos(arg)) == -1) {
1946 			error("%s line %d: Bad IPQoS value: %s",
1947 			    filename, linenum, arg);
1948 			goto out;
1949 		}
1950 		if (*activep && options->ip_qos_interactive == -1) {
1951 			options->ip_qos_interactive = value;
1952 			options->ip_qos_bulk = value2;
1953 		}
1954 		break;
1955 
1956 	case oRequestTTY:
1957 		intptr = &options->request_tty;
1958 		multistate_ptr = multistate_requesttty;
1959 		goto parse_multistate;
1960 
1961 	case oSessionType:
1962 		intptr = &options->session_type;
1963 		multistate_ptr = multistate_sessiontype;
1964 		goto parse_multistate;
1965 
1966 	case oStdinNull:
1967 		intptr = &options->stdin_null;
1968 		goto parse_flag;
1969 
1970 	case oForkAfterAuthentication:
1971 		intptr = &options->fork_after_authentication;
1972 		goto parse_flag;
1973 
1974 	case oIgnoreUnknown:
1975 		charptr = &options->ignored_unknown;
1976 		goto parse_string;
1977 
1978 	case oProxyUseFdpass:
1979 		intptr = &options->proxy_use_fdpass;
1980 		goto parse_flag;
1981 
1982 	case oCanonicalDomains:
1983 		value = options->num_canonical_domains != 0;
1984 		i = 0;
1985 		while ((arg = argv_next(&ac, &av)) != NULL) {
1986 			if (*arg == '\0') {
1987 				error("%s line %d: keyword %s empty argument",
1988 				    filename, linenum, keyword);
1989 				goto out;
1990 			}
1991 			/* Allow "none" only in first position */
1992 			if (strcasecmp(arg, "none") == 0) {
1993 				if (i > 0 || ac > 0) {
1994 					error("%s line %d: keyword %s \"none\" "
1995 					    "argument must appear alone.",
1996 					    filename, linenum, keyword);
1997 					goto out;
1998 				}
1999 			}
2000 			i++;
2001 			if (!valid_domain(arg, 1, &errstr)) {
2002 				error("%s line %d: %s", filename, linenum,
2003 				    errstr);
2004 				goto out;
2005 			}
2006 			if (!*activep || value)
2007 				continue;
2008 			if (options->num_canonical_domains >=
2009 			    MAX_CANON_DOMAINS) {
2010 				error("%s line %d: too many hostname suffixes.",
2011 				    filename, linenum);
2012 				goto out;
2013 			}
2014 			options->canonical_domains[
2015 			    options->num_canonical_domains++] = xstrdup(arg);
2016 		}
2017 		break;
2018 
2019 	case oCanonicalizePermittedCNAMEs:
2020 		value = options->num_permitted_cnames != 0;
2021 		i = 0;
2022 		while ((arg = argv_next(&ac, &av)) != NULL) {
2023 			/*
2024 			 * Either 'none' (only in first position), '*' for
2025 			 * everything or 'list:list'
2026 			 */
2027 			if (strcasecmp(arg, "none") == 0) {
2028 				if (i > 0 || ac > 0) {
2029 					error("%s line %d: keyword %s \"none\" "
2030 					    "argument must appear alone.",
2031 					    filename, linenum, keyword);
2032 					goto out;
2033 				}
2034 				arg2 = "";
2035 			} else if (strcmp(arg, "*") == 0) {
2036 				arg2 = arg;
2037 			} else {
2038 				lowercase(arg);
2039 				if ((arg2 = strchr(arg, ':')) == NULL ||
2040 				    arg2[1] == '\0') {
2041 					error("%s line %d: "
2042 					    "Invalid permitted CNAME \"%s\"",
2043 					    filename, linenum, arg);
2044 					goto out;
2045 				}
2046 				*arg2 = '\0';
2047 				arg2++;
2048 			}
2049 			i++;
2050 			if (!*activep || value)
2051 				continue;
2052 			if (options->num_permitted_cnames >=
2053 			    MAX_CANON_DOMAINS) {
2054 				error("%s line %d: too many permitted CNAMEs.",
2055 				    filename, linenum);
2056 				goto out;
2057 			}
2058 			cname = options->permitted_cnames +
2059 			    options->num_permitted_cnames++;
2060 			cname->source_list = xstrdup(arg);
2061 			cname->target_list = xstrdup(arg2);
2062 		}
2063 		break;
2064 
2065 	case oCanonicalizeHostname:
2066 		intptr = &options->canonicalize_hostname;
2067 		multistate_ptr = multistate_canonicalizehostname;
2068 		goto parse_multistate;
2069 
2070 	case oCanonicalizeMaxDots:
2071 		intptr = &options->canonicalize_max_dots;
2072 		goto parse_int;
2073 
2074 	case oCanonicalizeFallbackLocal:
2075 		intptr = &options->canonicalize_fallback_local;
2076 		goto parse_flag;
2077 
2078 	case oStreamLocalBindMask:
2079 		arg = argv_next(&ac, &av);
2080 		if (!arg || *arg == '\0') {
2081 			error("%.200s line %d: Missing StreamLocalBindMask "
2082 			    "argument.", filename, linenum);
2083 			goto out;
2084 		}
2085 		/* Parse mode in octal format */
2086 		value = strtol(arg, &endofnumber, 8);
2087 		if (arg == endofnumber || value < 0 || value > 0777) {
2088 			error("%.200s line %d: Bad mask.", filename, linenum);
2089 			goto out;
2090 		}
2091 		options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
2092 		break;
2093 
2094 	case oStreamLocalBindUnlink:
2095 		intptr = &options->fwd_opts.streamlocal_bind_unlink;
2096 		goto parse_flag;
2097 
2098 	case oRevokedHostKeys:
2099 		charptr = &options->revoked_host_keys;
2100 		goto parse_string;
2101 
2102 	case oFingerprintHash:
2103 		intptr = &options->fingerprint_hash;
2104 		arg = argv_next(&ac, &av);
2105 		if (!arg || *arg == '\0') {
2106 			error("%.200s line %d: Missing argument.",
2107 			    filename, linenum);
2108 			goto out;
2109 		}
2110 		if ((value = ssh_digest_alg_by_name(arg)) == -1) {
2111 			error("%.200s line %d: Invalid hash algorithm \"%s\".",
2112 			    filename, linenum, arg);
2113 			goto out;
2114 		}
2115 		if (*activep && *intptr == -1)
2116 			*intptr = value;
2117 		break;
2118 
2119 	case oUpdateHostkeys:
2120 		intptr = &options->update_hostkeys;
2121 		multistate_ptr = multistate_yesnoask;
2122 		goto parse_multistate;
2123 
2124 	case oHostbasedAcceptedAlgorithms:
2125 		charptr = &options->hostbased_accepted_algos;
2126 		goto parse_pubkey_algos;
2127 
2128 	case oPubkeyAcceptedAlgorithms:
2129 		charptr = &options->pubkey_accepted_algos;
2130 		goto parse_pubkey_algos;
2131 
2132 	case oAddKeysToAgent:
2133 		arg = argv_next(&ac, &av);
2134 		arg2 = argv_next(&ac, &av);
2135 		value = parse_multistate_value(arg, filename, linenum,
2136 		    multistate_yesnoaskconfirm);
2137 		value2 = 0; /* unlimited lifespan by default */
2138 		if (value == 3 && arg2 != NULL) {
2139 			/* allow "AddKeysToAgent confirm 5m" */
2140 			if ((value2 = convtime(arg2)) == -1 ||
2141 			    value2 > INT_MAX) {
2142 				error("%s line %d: invalid time value.",
2143 				    filename, linenum);
2144 				goto out;
2145 			}
2146 		} else if (value == -1 && arg2 == NULL) {
2147 			if ((value2 = convtime(arg)) == -1 ||
2148 			    value2 > INT_MAX) {
2149 				error("%s line %d: unsupported option",
2150 				    filename, linenum);
2151 				goto out;
2152 			}
2153 			value = 1; /* yes */
2154 		} else if (value == -1 || arg2 != NULL) {
2155 			error("%s line %d: unsupported option",
2156 			    filename, linenum);
2157 			goto out;
2158 		}
2159 		if (*activep && options->add_keys_to_agent == -1) {
2160 			options->add_keys_to_agent = value;
2161 			options->add_keys_to_agent_lifespan = value2;
2162 		}
2163 		break;
2164 
2165 	case oIdentityAgent:
2166 		charptr = &options->identity_agent;
2167 		arg = argv_next(&ac, &av);
2168 		if (!arg || *arg == '\0') {
2169 			error("%.200s line %d: Missing argument.",
2170 			    filename, linenum);
2171 			goto out;
2172 		}
2173   parse_agent_path:
2174 		/* Extra validation if the string represents an env var. */
2175 		if ((arg2 = dollar_expand(&r, arg)) == NULL || r) {
2176 			error("%.200s line %d: Invalid environment expansion "
2177 			    "%s.", filename, linenum, arg);
2178 			goto out;
2179 		}
2180 		free(arg2);
2181 		/* check for legacy environment format */
2182 		if (arg[0] == '$' && arg[1] != '{' &&
2183 		    !valid_env_name(arg + 1)) {
2184 			error("%.200s line %d: Invalid environment name %s.",
2185 			    filename, linenum, arg);
2186 			goto out;
2187 		}
2188 		if (*activep && *charptr == NULL)
2189 			*charptr = xstrdup(arg);
2190 		break;
2191 
2192 	case oRequiredRSASize:
2193 		intptr = &options->required_rsa_size;
2194 		goto parse_int;
2195 
2196 	case oDeprecated:
2197 		debug("%s line %d: Deprecated option \"%s\"",
2198 		    filename, linenum, keyword);
2199 		argv_consume(&ac);
2200 		break;
2201 
2202 	case oUnsupported:
2203 		error("%s line %d: Unsupported option \"%s\"",
2204 		    filename, linenum, keyword);
2205 		argv_consume(&ac);
2206 		break;
2207 
2208 	default:
2209 		error("%s line %d: Unimplemented opcode %d",
2210 		    filename, linenum, opcode);
2211 		goto out;
2212 	}
2213 
2214 	/* Check that there is no garbage at end of line. */
2215 	if (ac > 0) {
2216 		error("%.200s line %d: keyword %s extra arguments "
2217 		    "at end of line", filename, linenum, keyword);
2218 		goto out;
2219 	}
2220 
2221 	/* success */
2222 	ret = 0;
2223  out:
2224 	argv_free(oav, oac);
2225 	return ret;
2226 }
2227 
2228 /*
2229  * Reads the config file and modifies the options accordingly.  Options
2230  * should already be initialized before this call.  This never returns if
2231  * there is an error.  If the file does not exist, this returns 0.
2232  */
2233 int
2234 read_config_file(const char *filename, struct passwd *pw, const char *host,
2235     const char *original_host, Options *options, int flags,
2236     int *want_final_pass)
2237 {
2238 	int active = 1;
2239 
2240 	return read_config_file_depth(filename, pw, host, original_host,
2241 	    options, flags, &active, want_final_pass, 0);
2242 }
2243 
2244 #define READCONF_MAX_DEPTH	16
2245 static int
2246 read_config_file_depth(const char *filename, struct passwd *pw,
2247     const char *host, const char *original_host, Options *options,
2248     int flags, int *activep, int *want_final_pass, int depth)
2249 {
2250 	FILE *f;
2251 	char *line = NULL;
2252 	size_t linesize = 0;
2253 	int linenum;
2254 	int bad_options = 0;
2255 
2256 	if (depth < 0 || depth > READCONF_MAX_DEPTH)
2257 		fatal("Too many recursive configuration includes");
2258 
2259 	if ((f = fopen(filename, "r")) == NULL)
2260 		return 0;
2261 
2262 	if (flags & SSHCONF_CHECKPERM) {
2263 		struct stat sb;
2264 
2265 		if (fstat(fileno(f), &sb) == -1)
2266 			fatal("fstat %s: %s", filename, strerror(errno));
2267 		if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
2268 		    (sb.st_mode & 022) != 0))
2269 			fatal("Bad owner or permissions on %s", filename);
2270 	}
2271 
2272 	debug("Reading configuration data %.200s", filename);
2273 
2274 	/*
2275 	 * Mark that we are now processing the options.  This flag is turned
2276 	 * on/off by Host specifications.
2277 	 */
2278 	linenum = 0;
2279 	while (getline(&line, &linesize, f) != -1) {
2280 		/* Update line number counter. */
2281 		linenum++;
2282 		/*
2283 		 * Trim out comments and strip whitespace.
2284 		 * NB - preserve newlines, they are needed to reproduce
2285 		 * line numbers later for error messages.
2286 		 */
2287 		if (process_config_line_depth(options, pw, host, original_host,
2288 		    line, filename, linenum, activep, flags, want_final_pass,
2289 		    depth) != 0)
2290 			bad_options++;
2291 	}
2292 	free(line);
2293 	fclose(f);
2294 	if (bad_options > 0)
2295 		fatal("%s: terminating, %d bad configuration options",
2296 		    filename, bad_options);
2297 	return 1;
2298 }
2299 
2300 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
2301 int
2302 option_clear_or_none(const char *o)
2303 {
2304 	return o == NULL || strcasecmp(o, "none") == 0;
2305 }
2306 
2307 /*
2308  * Returns 1 if CanonicalizePermittedCNAMEs have been specified, 0 otherwise.
2309  * Allowed to be called on non-final configuration.
2310  */
2311 int
2312 config_has_permitted_cnames(Options *options)
2313 {
2314 	if (options->num_permitted_cnames == 1 &&
2315 	    strcasecmp(options->permitted_cnames[0].source_list, "none") == 0 &&
2316 	    strcmp(options->permitted_cnames[0].target_list, "") == 0)
2317 		return 0;
2318 	return options->num_permitted_cnames > 0;
2319 }
2320 
2321 /*
2322  * Initializes options to special values that indicate that they have not yet
2323  * been set.  Read_config_file will only set options with this value. Options
2324  * are processed in the following order: command line, user config file,
2325  * system config file.  Last, fill_default_options is called.
2326  */
2327 
2328 void
2329 initialize_options(Options * options)
2330 {
2331 	memset(options, 'X', sizeof(*options));
2332 	options->forward_agent = -1;
2333 	options->forward_agent_sock_path = NULL;
2334 	options->forward_x11 = -1;
2335 	options->forward_x11_trusted = -1;
2336 	options->forward_x11_timeout = -1;
2337 	options->stdio_forward_host = NULL;
2338 	options->stdio_forward_port = 0;
2339 	options->clear_forwardings = -1;
2340 	options->exit_on_forward_failure = -1;
2341 	options->xauth_location = NULL;
2342 	options->fwd_opts.gateway_ports = -1;
2343 	options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
2344 	options->fwd_opts.streamlocal_bind_unlink = -1;
2345 	options->pubkey_authentication = -1;
2346 	options->gss_authentication = -1;
2347 	options->gss_deleg_creds = -1;
2348 	options->password_authentication = -1;
2349 	options->kbd_interactive_authentication = -1;
2350 	options->kbd_interactive_devices = NULL;
2351 	options->hostbased_authentication = -1;
2352 	options->batch_mode = -1;
2353 	options->check_host_ip = -1;
2354 	options->strict_host_key_checking = -1;
2355 	options->compression = -1;
2356 	options->tcp_keep_alive = -1;
2357 	options->port = -1;
2358 	options->address_family = -1;
2359 	options->connection_attempts = -1;
2360 	options->connection_timeout = -1;
2361 	options->number_of_password_prompts = -1;
2362 	options->ciphers = NULL;
2363 	options->macs = NULL;
2364 	options->kex_algorithms = NULL;
2365 	options->hostkeyalgorithms = NULL;
2366 	options->ca_sign_algorithms = NULL;
2367 	options->num_identity_files = 0;
2368 	memset(options->identity_keys, 0, sizeof(options->identity_keys));
2369 	options->num_certificate_files = 0;
2370 	memset(options->certificates, 0, sizeof(options->certificates));
2371 	options->hostname = NULL;
2372 	options->host_key_alias = NULL;
2373 	options->proxy_command = NULL;
2374 	options->jump_user = NULL;
2375 	options->jump_host = NULL;
2376 	options->jump_port = -1;
2377 	options->jump_extra = NULL;
2378 	options->user = NULL;
2379 	options->escape_char = -1;
2380 	options->num_system_hostfiles = 0;
2381 	options->num_user_hostfiles = 0;
2382 	options->local_forwards = NULL;
2383 	options->num_local_forwards = 0;
2384 	options->remote_forwards = NULL;
2385 	options->num_remote_forwards = 0;
2386 	options->permitted_remote_opens = NULL;
2387 	options->num_permitted_remote_opens = 0;
2388 	options->log_facility = SYSLOG_FACILITY_NOT_SET;
2389 	options->log_level = SYSLOG_LEVEL_NOT_SET;
2390 	options->num_log_verbose = 0;
2391 	options->log_verbose = NULL;
2392 	options->preferred_authentications = NULL;
2393 	options->bind_address = NULL;
2394 	options->bind_interface = NULL;
2395 	options->pkcs11_provider = NULL;
2396 	options->sk_provider = NULL;
2397 	options->enable_ssh_keysign = - 1;
2398 	options->no_host_authentication_for_localhost = - 1;
2399 	options->identities_only = - 1;
2400 	options->rekey_limit = - 1;
2401 	options->rekey_interval = -1;
2402 	options->verify_host_key_dns = -1;
2403 	options->server_alive_interval = -1;
2404 	options->server_alive_count_max = -1;
2405 	options->send_env = NULL;
2406 	options->num_send_env = 0;
2407 	options->setenv = NULL;
2408 	options->num_setenv = 0;
2409 	options->control_path = NULL;
2410 	options->control_master = -1;
2411 	options->control_persist = -1;
2412 	options->control_persist_timeout = 0;
2413 	options->hash_known_hosts = -1;
2414 	options->tun_open = -1;
2415 	options->tun_local = -1;
2416 	options->tun_remote = -1;
2417 	options->local_command = NULL;
2418 	options->permit_local_command = -1;
2419 	options->remote_command = NULL;
2420 	options->add_keys_to_agent = -1;
2421 	options->add_keys_to_agent_lifespan = -1;
2422 	options->identity_agent = NULL;
2423 	options->visual_host_key = -1;
2424 	options->ip_qos_interactive = -1;
2425 	options->ip_qos_bulk = -1;
2426 	options->request_tty = -1;
2427 	options->session_type = -1;
2428 	options->stdin_null = -1;
2429 	options->fork_after_authentication = -1;
2430 	options->proxy_use_fdpass = -1;
2431 	options->ignored_unknown = NULL;
2432 	options->num_canonical_domains = 0;
2433 	options->num_permitted_cnames = 0;
2434 	options->canonicalize_max_dots = -1;
2435 	options->canonicalize_fallback_local = -1;
2436 	options->canonicalize_hostname = -1;
2437 	options->revoked_host_keys = NULL;
2438 	options->fingerprint_hash = -1;
2439 	options->update_hostkeys = -1;
2440 	options->hostbased_accepted_algos = NULL;
2441 	options->pubkey_accepted_algos = NULL;
2442 	options->known_hosts_command = NULL;
2443 	options->required_rsa_size = -1;
2444 }
2445 
2446 /*
2447  * A petite version of fill_default_options() that just fills the options
2448  * needed for hostname canonicalization to proceed.
2449  */
2450 void
2451 fill_default_options_for_canonicalization(Options *options)
2452 {
2453 	if (options->canonicalize_max_dots == -1)
2454 		options->canonicalize_max_dots = 1;
2455 	if (options->canonicalize_fallback_local == -1)
2456 		options->canonicalize_fallback_local = 1;
2457 	if (options->canonicalize_hostname == -1)
2458 		options->canonicalize_hostname = SSH_CANONICALISE_NO;
2459 }
2460 
2461 /*
2462  * Called after processing other sources of option data, this fills those
2463  * options for which no value has been specified with their default values.
2464  */
2465 int
2466 fill_default_options(Options * options)
2467 {
2468 	char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig;
2469 	char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig;
2470 	int ret = 0, r;
2471 
2472 	if (options->forward_agent == -1)
2473 		options->forward_agent = 0;
2474 	if (options->forward_x11 == -1)
2475 		options->forward_x11 = 0;
2476 	if (options->forward_x11_trusted == -1)
2477 		options->forward_x11_trusted = 0;
2478 	if (options->forward_x11_timeout == -1)
2479 		options->forward_x11_timeout = 1200;
2480 	/*
2481 	 * stdio forwarding (-W) changes the default for these but we defer
2482 	 * setting the values so they can be overridden.
2483 	 */
2484 	if (options->exit_on_forward_failure == -1)
2485 		options->exit_on_forward_failure =
2486 		    options->stdio_forward_host != NULL ? 1 : 0;
2487 	if (options->clear_forwardings == -1)
2488 		options->clear_forwardings =
2489 		    options->stdio_forward_host != NULL ? 1 : 0;
2490 	if (options->clear_forwardings == 1)
2491 		clear_forwardings(options);
2492 
2493 	if (options->xauth_location == NULL)
2494 		options->xauth_location = xstrdup(_PATH_XAUTH);
2495 	if (options->fwd_opts.gateway_ports == -1)
2496 		options->fwd_opts.gateway_ports = 0;
2497 	if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
2498 		options->fwd_opts.streamlocal_bind_mask = 0177;
2499 	if (options->fwd_opts.streamlocal_bind_unlink == -1)
2500 		options->fwd_opts.streamlocal_bind_unlink = 0;
2501 	if (options->pubkey_authentication == -1)
2502 		options->pubkey_authentication = SSH_PUBKEY_AUTH_ALL;
2503 	if (options->gss_authentication == -1)
2504 		options->gss_authentication = 0;
2505 	if (options->gss_deleg_creds == -1)
2506 		options->gss_deleg_creds = 0;
2507 	if (options->password_authentication == -1)
2508 		options->password_authentication = 1;
2509 	if (options->kbd_interactive_authentication == -1)
2510 		options->kbd_interactive_authentication = 1;
2511 	if (options->hostbased_authentication == -1)
2512 		options->hostbased_authentication = 0;
2513 	if (options->batch_mode == -1)
2514 		options->batch_mode = 0;
2515 	if (options->check_host_ip == -1)
2516 		options->check_host_ip = 0;
2517 	if (options->strict_host_key_checking == -1)
2518 		options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK;
2519 	if (options->compression == -1)
2520 		options->compression = 0;
2521 	if (options->tcp_keep_alive == -1)
2522 		options->tcp_keep_alive = 1;
2523 	if (options->port == -1)
2524 		options->port = 0;	/* Filled in ssh_connect. */
2525 	if (options->address_family == -1)
2526 		options->address_family = AF_UNSPEC;
2527 	if (options->connection_attempts == -1)
2528 		options->connection_attempts = 1;
2529 	if (options->number_of_password_prompts == -1)
2530 		options->number_of_password_prompts = 3;
2531 	/* options->hostkeyalgorithms, default set in myproposals.h */
2532 	if (options->add_keys_to_agent == -1) {
2533 		options->add_keys_to_agent = 0;
2534 		options->add_keys_to_agent_lifespan = 0;
2535 	}
2536 	if (options->num_identity_files == 0) {
2537 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0);
2538 #ifdef OPENSSL_HAS_ECC
2539 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0);
2540 		add_identity_file(options, "~/",
2541 		    _PATH_SSH_CLIENT_ID_ECDSA_SK, 0);
2542 #endif
2543 		add_identity_file(options, "~/",
2544 		    _PATH_SSH_CLIENT_ID_ED25519, 0);
2545 		add_identity_file(options, "~/",
2546 		    _PATH_SSH_CLIENT_ID_ED25519_SK, 0);
2547 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0);
2548 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0);
2549 	}
2550 	if (options->escape_char == -1)
2551 		options->escape_char = '~';
2552 	if (options->num_system_hostfiles == 0) {
2553 		options->system_hostfiles[options->num_system_hostfiles++] =
2554 		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
2555 		options->system_hostfiles[options->num_system_hostfiles++] =
2556 		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
2557 	}
2558 	if (options->update_hostkeys == -1) {
2559 		if (options->verify_host_key_dns <= 0 &&
2560 		    (options->num_user_hostfiles == 0 ||
2561 		    (options->num_user_hostfiles == 1 && strcmp(options->
2562 		    user_hostfiles[0], _PATH_SSH_USER_HOSTFILE) == 0)))
2563 			options->update_hostkeys = SSH_UPDATE_HOSTKEYS_YES;
2564 		else
2565 			options->update_hostkeys = SSH_UPDATE_HOSTKEYS_NO;
2566 	}
2567 	if (options->num_user_hostfiles == 0) {
2568 		options->user_hostfiles[options->num_user_hostfiles++] =
2569 		    xstrdup(_PATH_SSH_USER_HOSTFILE);
2570 		options->user_hostfiles[options->num_user_hostfiles++] =
2571 		    xstrdup(_PATH_SSH_USER_HOSTFILE2);
2572 	}
2573 	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
2574 		options->log_level = SYSLOG_LEVEL_INFO;
2575 	if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
2576 		options->log_facility = SYSLOG_FACILITY_USER;
2577 	if (options->no_host_authentication_for_localhost == - 1)
2578 		options->no_host_authentication_for_localhost = 0;
2579 	if (options->identities_only == -1)
2580 		options->identities_only = 0;
2581 	if (options->enable_ssh_keysign == -1)
2582 		options->enable_ssh_keysign = 0;
2583 	if (options->rekey_limit == -1)
2584 		options->rekey_limit = 0;
2585 	if (options->rekey_interval == -1)
2586 		options->rekey_interval = 0;
2587 #if HAVE_LDNS
2588 	if (options->verify_host_key_dns == -1)
2589 		/* automatically trust a verified SSHFP record */
2590 		options->verify_host_key_dns = 1;
2591 #else
2592 	if (options->verify_host_key_dns == -1)
2593 		options->verify_host_key_dns = 0;
2594 #endif
2595 	if (options->server_alive_interval == -1)
2596 		options->server_alive_interval = 0;
2597 	if (options->server_alive_count_max == -1)
2598 		options->server_alive_count_max = 3;
2599 	if (options->control_master == -1)
2600 		options->control_master = 0;
2601 	if (options->control_persist == -1) {
2602 		options->control_persist = 0;
2603 		options->control_persist_timeout = 0;
2604 	}
2605 	if (options->hash_known_hosts == -1)
2606 		options->hash_known_hosts = 0;
2607 	if (options->tun_open == -1)
2608 		options->tun_open = SSH_TUNMODE_NO;
2609 	if (options->tun_local == -1)
2610 		options->tun_local = SSH_TUNID_ANY;
2611 	if (options->tun_remote == -1)
2612 		options->tun_remote = SSH_TUNID_ANY;
2613 	if (options->permit_local_command == -1)
2614 		options->permit_local_command = 0;
2615 	if (options->visual_host_key == -1)
2616 		options->visual_host_key = 0;
2617 	if (options->ip_qos_interactive == -1)
2618 		options->ip_qos_interactive = IPTOS_DSCP_AF21;
2619 	if (options->ip_qos_bulk == -1)
2620 		options->ip_qos_bulk = IPTOS_DSCP_CS1;
2621 	if (options->request_tty == -1)
2622 		options->request_tty = REQUEST_TTY_AUTO;
2623 	if (options->session_type == -1)
2624 		options->session_type = SESSION_TYPE_DEFAULT;
2625 	if (options->stdin_null == -1)
2626 		options->stdin_null = 0;
2627 	if (options->fork_after_authentication == -1)
2628 		options->fork_after_authentication = 0;
2629 	if (options->proxy_use_fdpass == -1)
2630 		options->proxy_use_fdpass = 0;
2631 	if (options->canonicalize_max_dots == -1)
2632 		options->canonicalize_max_dots = 1;
2633 	if (options->canonicalize_fallback_local == -1)
2634 		options->canonicalize_fallback_local = 1;
2635 	if (options->canonicalize_hostname == -1)
2636 		options->canonicalize_hostname = SSH_CANONICALISE_NO;
2637 	if (options->fingerprint_hash == -1)
2638 		options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
2639 #ifdef ENABLE_SK_INTERNAL
2640 	if (options->sk_provider == NULL)
2641 		options->sk_provider = xstrdup("internal");
2642 #else
2643 	if (options->sk_provider == NULL)
2644 		options->sk_provider = xstrdup("$SSH_SK_PROVIDER");
2645 #endif
2646 	if (options->required_rsa_size == -1)
2647 		options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
2648 
2649 	/* Expand KEX name lists */
2650 	all_cipher = cipher_alg_list(',', 0);
2651 	all_mac = mac_alg_list(',');
2652 	all_kex = kex_alg_list(',');
2653 	all_key = sshkey_alg_list(0, 0, 1, ',');
2654 	all_sig = sshkey_alg_list(0, 1, 1, ',');
2655 	/* remove unsupported algos from default lists */
2656 	def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher);
2657 	def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac);
2658 	def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex);
2659 	def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
2660 	def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig);
2661 #define ASSEMBLE(what, defaults, all) \
2662 	do { \
2663 		if ((r = kex_assemble_names(&options->what, \
2664 		    defaults, all)) != 0) { \
2665 			error_fr(r, "%s", #what); \
2666 			goto fail; \
2667 		} \
2668 	} while (0)
2669 	ASSEMBLE(ciphers, def_cipher, all_cipher);
2670 	ASSEMBLE(macs, def_mac, all_mac);
2671 	ASSEMBLE(kex_algorithms, def_kex, all_kex);
2672 	ASSEMBLE(hostbased_accepted_algos, def_key, all_key);
2673 	ASSEMBLE(pubkey_accepted_algos, def_key, all_key);
2674 	ASSEMBLE(ca_sign_algorithms, def_sig, all_sig);
2675 #undef ASSEMBLE
2676 
2677 #define CLEAR_ON_NONE(v) \
2678 	do { \
2679 		if (option_clear_or_none(v)) { \
2680 			free(v); \
2681 			v = NULL; \
2682 		} \
2683 	} while(0)
2684 	CLEAR_ON_NONE(options->local_command);
2685 	CLEAR_ON_NONE(options->remote_command);
2686 	CLEAR_ON_NONE(options->proxy_command);
2687 	CLEAR_ON_NONE(options->control_path);
2688 	CLEAR_ON_NONE(options->revoked_host_keys);
2689 	CLEAR_ON_NONE(options->pkcs11_provider);
2690 	CLEAR_ON_NONE(options->sk_provider);
2691 	CLEAR_ON_NONE(options->known_hosts_command);
2692 	if (options->jump_host != NULL &&
2693 	    strcmp(options->jump_host, "none") == 0 &&
2694 	    options->jump_port == 0 && options->jump_user == NULL) {
2695 		free(options->jump_host);
2696 		options->jump_host = NULL;
2697 	}
2698 	if (options->num_permitted_cnames == 1 &&
2699 	    !config_has_permitted_cnames(options)) {
2700 		/* clean up CanonicalizePermittedCNAMEs=none */
2701 		free(options->permitted_cnames[0].source_list);
2702 		free(options->permitted_cnames[0].target_list);
2703 		memset(options->permitted_cnames, '\0',
2704 		    sizeof(*options->permitted_cnames));
2705 		options->num_permitted_cnames = 0;
2706 	}
2707 	/* options->identity_agent distinguishes NULL from 'none' */
2708 	/* options->user will be set in the main program if appropriate */
2709 	/* options->hostname will be set in the main program if appropriate */
2710 	/* options->host_key_alias should not be set by default */
2711 	/* options->preferred_authentications will be set in ssh */
2712 
2713 	/* success */
2714 	ret = 0;
2715  fail:
2716 	free(all_cipher);
2717 	free(all_mac);
2718 	free(all_kex);
2719 	free(all_key);
2720 	free(all_sig);
2721 	free(def_cipher);
2722 	free(def_mac);
2723 	free(def_kex);
2724 	free(def_key);
2725 	free(def_sig);
2726 	return ret;
2727 }
2728 
2729 void
2730 free_options(Options *o)
2731 {
2732 	int i;
2733 
2734 	if (o == NULL)
2735 		return;
2736 
2737 #define FREE_ARRAY(type, n, a) \
2738 	do { \
2739 		type _i; \
2740 		for (_i = 0; _i < (n); _i++) \
2741 			free((a)[_i]); \
2742 	} while (0)
2743 
2744 	free(o->forward_agent_sock_path);
2745 	free(o->xauth_location);
2746 	FREE_ARRAY(u_int, o->num_log_verbose, o->log_verbose);
2747 	free(o->log_verbose);
2748 	free(o->ciphers);
2749 	free(o->macs);
2750 	free(o->hostkeyalgorithms);
2751 	free(o->kex_algorithms);
2752 	free(o->ca_sign_algorithms);
2753 	free(o->hostname);
2754 	free(o->host_key_alias);
2755 	free(o->proxy_command);
2756 	free(o->user);
2757 	FREE_ARRAY(u_int, o->num_system_hostfiles, o->system_hostfiles);
2758 	FREE_ARRAY(u_int, o->num_user_hostfiles, o->user_hostfiles);
2759 	free(o->preferred_authentications);
2760 	free(o->bind_address);
2761 	free(o->bind_interface);
2762 	free(o->pkcs11_provider);
2763 	free(o->sk_provider);
2764 	for (i = 0; i < o->num_identity_files; i++) {
2765 		free(o->identity_files[i]);
2766 		sshkey_free(o->identity_keys[i]);
2767 	}
2768 	for (i = 0; i < o->num_certificate_files; i++) {
2769 		free(o->certificate_files[i]);
2770 		sshkey_free(o->certificates[i]);
2771 	}
2772 	free(o->identity_agent);
2773 	for (i = 0; i < o->num_local_forwards; i++) {
2774 		free(o->local_forwards[i].listen_host);
2775 		free(o->local_forwards[i].listen_path);
2776 		free(o->local_forwards[i].connect_host);
2777 		free(o->local_forwards[i].connect_path);
2778 	}
2779 	free(o->local_forwards);
2780 	for (i = 0; i < o->num_remote_forwards; i++) {
2781 		free(o->remote_forwards[i].listen_host);
2782 		free(o->remote_forwards[i].listen_path);
2783 		free(o->remote_forwards[i].connect_host);
2784 		free(o->remote_forwards[i].connect_path);
2785 	}
2786 	free(o->remote_forwards);
2787 	free(o->stdio_forward_host);
2788 	FREE_ARRAY(u_int, o->num_send_env, o->send_env);
2789 	free(o->send_env);
2790 	FREE_ARRAY(u_int, o->num_setenv, o->setenv);
2791 	free(o->setenv);
2792 	free(o->control_path);
2793 	free(o->local_command);
2794 	free(o->remote_command);
2795 	FREE_ARRAY(int, o->num_canonical_domains, o->canonical_domains);
2796 	for (i = 0; i < o->num_permitted_cnames; i++) {
2797 		free(o->permitted_cnames[i].source_list);
2798 		free(o->permitted_cnames[i].target_list);
2799 	}
2800 	free(o->revoked_host_keys);
2801 	free(o->hostbased_accepted_algos);
2802 	free(o->pubkey_accepted_algos);
2803 	free(o->jump_user);
2804 	free(o->jump_host);
2805 	free(o->jump_extra);
2806 	free(o->ignored_unknown);
2807 	explicit_bzero(o, sizeof(*o));
2808 #undef FREE_ARRAY
2809 }
2810 
2811 struct fwdarg {
2812 	char *arg;
2813 	int ispath;
2814 };
2815 
2816 /*
2817  * parse_fwd_field
2818  * parses the next field in a port forwarding specification.
2819  * sets fwd to the parsed field and advances p past the colon
2820  * or sets it to NULL at end of string.
2821  * returns 0 on success, else non-zero.
2822  */
2823 static int
2824 parse_fwd_field(char **p, struct fwdarg *fwd)
2825 {
2826 	char *ep, *cp = *p;
2827 	int ispath = 0;
2828 
2829 	if (*cp == '\0') {
2830 		*p = NULL;
2831 		return -1;	/* end of string */
2832 	}
2833 
2834 	/*
2835 	 * A field escaped with square brackets is used literally.
2836 	 * XXX - allow ']' to be escaped via backslash?
2837 	 */
2838 	if (*cp == '[') {
2839 		/* find matching ']' */
2840 		for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
2841 			if (*ep == '/')
2842 				ispath = 1;
2843 		}
2844 		/* no matching ']' or not at end of field. */
2845 		if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
2846 			return -1;
2847 		/* NUL terminate the field and advance p past the colon */
2848 		*ep++ = '\0';
2849 		if (*ep != '\0')
2850 			*ep++ = '\0';
2851 		fwd->arg = cp + 1;
2852 		fwd->ispath = ispath;
2853 		*p = ep;
2854 		return 0;
2855 	}
2856 
2857 	for (cp = *p; *cp != '\0'; cp++) {
2858 		switch (*cp) {
2859 		case '\\':
2860 			memmove(cp, cp + 1, strlen(cp + 1) + 1);
2861 			if (*cp == '\0')
2862 				return -1;
2863 			break;
2864 		case '/':
2865 			ispath = 1;
2866 			break;
2867 		case ':':
2868 			*cp++ = '\0';
2869 			goto done;
2870 		}
2871 	}
2872 done:
2873 	fwd->arg = *p;
2874 	fwd->ispath = ispath;
2875 	*p = cp;
2876 	return 0;
2877 }
2878 
2879 /*
2880  * parse_forward
2881  * parses a string containing a port forwarding specification of the form:
2882  *   dynamicfwd == 0
2883  *	[listenhost:]listenport|listenpath:connecthost:connectport|connectpath
2884  *	listenpath:connectpath
2885  *   dynamicfwd == 1
2886  *	[listenhost:]listenport
2887  * returns number of arguments parsed or zero on error
2888  */
2889 int
2890 parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
2891 {
2892 	struct fwdarg fwdargs[4];
2893 	char *p, *cp;
2894 	int i, err;
2895 
2896 	memset(fwd, 0, sizeof(*fwd));
2897 	memset(fwdargs, 0, sizeof(fwdargs));
2898 
2899 	/*
2900 	 * We expand environment variables before checking if we think they're
2901 	 * paths so that if ${VAR} expands to a fully qualified path it is
2902 	 * treated as a path.
2903 	 */
2904 	cp = p = dollar_expand(&err, fwdspec);
2905 	if (p == NULL || err)
2906 		return 0;
2907 
2908 	/* skip leading spaces */
2909 	while (isspace((u_char)*cp))
2910 		cp++;
2911 
2912 	for (i = 0; i < 4; ++i) {
2913 		if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
2914 			break;
2915 	}
2916 
2917 	/* Check for trailing garbage */
2918 	if (cp != NULL && *cp != '\0') {
2919 		i = 0;	/* failure */
2920 	}
2921 
2922 	switch (i) {
2923 	case 1:
2924 		if (fwdargs[0].ispath) {
2925 			fwd->listen_path = xstrdup(fwdargs[0].arg);
2926 			fwd->listen_port = PORT_STREAMLOCAL;
2927 		} else {
2928 			fwd->listen_host = NULL;
2929 			fwd->listen_port = a2port(fwdargs[0].arg);
2930 		}
2931 		fwd->connect_host = xstrdup("socks");
2932 		break;
2933 
2934 	case 2:
2935 		if (fwdargs[0].ispath && fwdargs[1].ispath) {
2936 			fwd->listen_path = xstrdup(fwdargs[0].arg);
2937 			fwd->listen_port = PORT_STREAMLOCAL;
2938 			fwd->connect_path = xstrdup(fwdargs[1].arg);
2939 			fwd->connect_port = PORT_STREAMLOCAL;
2940 		} else if (fwdargs[1].ispath) {
2941 			fwd->listen_host = NULL;
2942 			fwd->listen_port = a2port(fwdargs[0].arg);
2943 			fwd->connect_path = xstrdup(fwdargs[1].arg);
2944 			fwd->connect_port = PORT_STREAMLOCAL;
2945 		} else {
2946 			fwd->listen_host = xstrdup(fwdargs[0].arg);
2947 			fwd->listen_port = a2port(fwdargs[1].arg);
2948 			fwd->connect_host = xstrdup("socks");
2949 		}
2950 		break;
2951 
2952 	case 3:
2953 		if (fwdargs[0].ispath) {
2954 			fwd->listen_path = xstrdup(fwdargs[0].arg);
2955 			fwd->listen_port = PORT_STREAMLOCAL;
2956 			fwd->connect_host = xstrdup(fwdargs[1].arg);
2957 			fwd->connect_port = a2port(fwdargs[2].arg);
2958 		} else if (fwdargs[2].ispath) {
2959 			fwd->listen_host = xstrdup(fwdargs[0].arg);
2960 			fwd->listen_port = a2port(fwdargs[1].arg);
2961 			fwd->connect_path = xstrdup(fwdargs[2].arg);
2962 			fwd->connect_port = PORT_STREAMLOCAL;
2963 		} else {
2964 			fwd->listen_host = NULL;
2965 			fwd->listen_port = a2port(fwdargs[0].arg);
2966 			fwd->connect_host = xstrdup(fwdargs[1].arg);
2967 			fwd->connect_port = a2port(fwdargs[2].arg);
2968 		}
2969 		break;
2970 
2971 	case 4:
2972 		fwd->listen_host = xstrdup(fwdargs[0].arg);
2973 		fwd->listen_port = a2port(fwdargs[1].arg);
2974 		fwd->connect_host = xstrdup(fwdargs[2].arg);
2975 		fwd->connect_port = a2port(fwdargs[3].arg);
2976 		break;
2977 	default:
2978 		i = 0; /* failure */
2979 	}
2980 
2981 	free(p);
2982 
2983 	if (dynamicfwd) {
2984 		if (!(i == 1 || i == 2))
2985 			goto fail_free;
2986 	} else {
2987 		if (!(i == 3 || i == 4)) {
2988 			if (fwd->connect_path == NULL &&
2989 			    fwd->listen_path == NULL)
2990 				goto fail_free;
2991 		}
2992 		if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
2993 			goto fail_free;
2994 	}
2995 
2996 	if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
2997 	    (!remotefwd && fwd->listen_port == 0))
2998 		goto fail_free;
2999 	if (fwd->connect_host != NULL &&
3000 	    strlen(fwd->connect_host) >= NI_MAXHOST)
3001 		goto fail_free;
3002 	/*
3003 	 * XXX - if connecting to a remote socket, max sun len may not
3004 	 * match this host
3005 	 */
3006 	if (fwd->connect_path != NULL &&
3007 	    strlen(fwd->connect_path) >= PATH_MAX_SUN)
3008 		goto fail_free;
3009 	if (fwd->listen_host != NULL &&
3010 	    strlen(fwd->listen_host) >= NI_MAXHOST)
3011 		goto fail_free;
3012 	if (fwd->listen_path != NULL &&
3013 	    strlen(fwd->listen_path) >= PATH_MAX_SUN)
3014 		goto fail_free;
3015 
3016 	return (i);
3017 
3018  fail_free:
3019 	free(fwd->connect_host);
3020 	fwd->connect_host = NULL;
3021 	free(fwd->connect_path);
3022 	fwd->connect_path = NULL;
3023 	free(fwd->listen_host);
3024 	fwd->listen_host = NULL;
3025 	free(fwd->listen_path);
3026 	fwd->listen_path = NULL;
3027 	return (0);
3028 }
3029 
3030 int
3031 parse_jump(const char *s, Options *o, int active)
3032 {
3033 	char *orig, *sdup, *cp;
3034 	char *host = NULL, *user = NULL;
3035 	int r, ret = -1, port = -1, first;
3036 
3037 	active &= o->proxy_command == NULL && o->jump_host == NULL;
3038 
3039 	orig = sdup = xstrdup(s);
3040 
3041 	/* Remove comment and trailing whitespace */
3042 	if ((cp = strchr(orig, '#')) != NULL)
3043 		*cp = '\0';
3044 	rtrim(orig);
3045 
3046 	first = active;
3047 	do {
3048 		if (strcasecmp(s, "none") == 0)
3049 			break;
3050 		if ((cp = strrchr(sdup, ',')) == NULL)
3051 			cp = sdup; /* last */
3052 		else
3053 			*cp++ = '\0';
3054 
3055 		if (first) {
3056 			/* First argument and configuration is active */
3057 			r = parse_ssh_uri(cp, &user, &host, &port);
3058 			if (r == -1 || (r == 1 &&
3059 			    parse_user_host_port(cp, &user, &host, &port) != 0))
3060 				goto out;
3061 		} else {
3062 			/* Subsequent argument or inactive configuration */
3063 			r = parse_ssh_uri(cp, NULL, NULL, NULL);
3064 			if (r == -1 || (r == 1 &&
3065 			    parse_user_host_port(cp, NULL, NULL, NULL) != 0))
3066 				goto out;
3067 		}
3068 		first = 0; /* only check syntax for subsequent hosts */
3069 	} while (cp != sdup);
3070 	/* success */
3071 	if (active) {
3072 		if (strcasecmp(s, "none") == 0) {
3073 			o->jump_host = xstrdup("none");
3074 			o->jump_port = 0;
3075 		} else {
3076 			o->jump_user = user;
3077 			o->jump_host = host;
3078 			o->jump_port = port;
3079 			o->proxy_command = xstrdup("none");
3080 			user = host = NULL;
3081 			if ((cp = strrchr(s, ',')) != NULL && cp != s) {
3082 				o->jump_extra = xstrdup(s);
3083 				o->jump_extra[cp - s] = '\0';
3084 			}
3085 		}
3086 	}
3087 	ret = 0;
3088  out:
3089 	free(orig);
3090 	free(user);
3091 	free(host);
3092 	return ret;
3093 }
3094 
3095 int
3096 parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp)
3097 {
3098 	char *user = NULL, *host = NULL, *path = NULL;
3099 	int r, port;
3100 
3101 	r = parse_uri("ssh", uri, &user, &host, &port, &path);
3102 	if (r == 0 && path != NULL)
3103 		r = -1;		/* path not allowed */
3104 	if (r == 0) {
3105 		if (userp != NULL) {
3106 			*userp = user;
3107 			user = NULL;
3108 		}
3109 		if (hostp != NULL) {
3110 			*hostp = host;
3111 			host = NULL;
3112 		}
3113 		if (portp != NULL)
3114 			*portp = port;
3115 	}
3116 	free(user);
3117 	free(host);
3118 	free(path);
3119 	return r;
3120 }
3121 
3122 /* XXX the following is a near-vebatim copy from servconf.c; refactor */
3123 static const char *
3124 fmt_multistate_int(int val, const struct multistate *m)
3125 {
3126 	u_int i;
3127 
3128 	for (i = 0; m[i].key != NULL; i++) {
3129 		if (m[i].value == val)
3130 			return m[i].key;
3131 	}
3132 	return "UNKNOWN";
3133 }
3134 
3135 static const char *
3136 fmt_intarg(OpCodes code, int val)
3137 {
3138 	if (val == -1)
3139 		return "unset";
3140 	switch (code) {
3141 	case oAddressFamily:
3142 		return fmt_multistate_int(val, multistate_addressfamily);
3143 	case oVerifyHostKeyDNS:
3144 	case oUpdateHostkeys:
3145 		return fmt_multistate_int(val, multistate_yesnoask);
3146 	case oStrictHostKeyChecking:
3147 		return fmt_multistate_int(val, multistate_strict_hostkey);
3148 	case oControlMaster:
3149 		return fmt_multistate_int(val, multistate_controlmaster);
3150 	case oTunnel:
3151 		return fmt_multistate_int(val, multistate_tunnel);
3152 	case oRequestTTY:
3153 		return fmt_multistate_int(val, multistate_requesttty);
3154 	case oSessionType:
3155 		return fmt_multistate_int(val, multistate_sessiontype);
3156 	case oCanonicalizeHostname:
3157 		return fmt_multistate_int(val, multistate_canonicalizehostname);
3158 	case oAddKeysToAgent:
3159 		return fmt_multistate_int(val, multistate_yesnoaskconfirm);
3160 	case oPubkeyAuthentication:
3161 		return fmt_multistate_int(val, multistate_pubkey_auth);
3162 	case oFingerprintHash:
3163 		return ssh_digest_alg_name(val);
3164 	default:
3165 		switch (val) {
3166 		case 0:
3167 			return "no";
3168 		case 1:
3169 			return "yes";
3170 		default:
3171 			return "UNKNOWN";
3172 		}
3173 	}
3174 }
3175 
3176 static const char *
3177 lookup_opcode_name(OpCodes code)
3178 {
3179 	u_int i;
3180 
3181 	for (i = 0; keywords[i].name != NULL; i++)
3182 		if (keywords[i].opcode == code)
3183 			return(keywords[i].name);
3184 	return "UNKNOWN";
3185 }
3186 
3187 static void
3188 dump_cfg_int(OpCodes code, int val)
3189 {
3190 	printf("%s %d\n", lookup_opcode_name(code), val);
3191 }
3192 
3193 static void
3194 dump_cfg_fmtint(OpCodes code, int val)
3195 {
3196 	printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
3197 }
3198 
3199 static void
3200 dump_cfg_string(OpCodes code, const char *val)
3201 {
3202 	if (val == NULL)
3203 		return;
3204 	printf("%s %s\n", lookup_opcode_name(code), val);
3205 }
3206 
3207 static void
3208 dump_cfg_strarray(OpCodes code, u_int count, char **vals)
3209 {
3210 	u_int i;
3211 
3212 	for (i = 0; i < count; i++)
3213 		printf("%s %s\n", lookup_opcode_name(code), vals[i]);
3214 }
3215 
3216 static void
3217 dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals)
3218 {
3219 	u_int i;
3220 
3221 	printf("%s", lookup_opcode_name(code));
3222 	if (count == 0)
3223 		printf(" none");
3224 	for (i = 0; i < count; i++)
3225 		printf(" %s",  vals[i]);
3226 	printf("\n");
3227 }
3228 
3229 static void
3230 dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds)
3231 {
3232 	const struct Forward *fwd;
3233 	u_int i;
3234 
3235 	/* oDynamicForward */
3236 	for (i = 0; i < count; i++) {
3237 		fwd = &fwds[i];
3238 		if (code == oDynamicForward && fwd->connect_host != NULL &&
3239 		    strcmp(fwd->connect_host, "socks") != 0)
3240 			continue;
3241 		if (code == oLocalForward && fwd->connect_host != NULL &&
3242 		    strcmp(fwd->connect_host, "socks") == 0)
3243 			continue;
3244 		printf("%s", lookup_opcode_name(code));
3245 		if (fwd->listen_port == PORT_STREAMLOCAL)
3246 			printf(" %s", fwd->listen_path);
3247 		else if (fwd->listen_host == NULL)
3248 			printf(" %d", fwd->listen_port);
3249 		else {
3250 			printf(" [%s]:%d",
3251 			    fwd->listen_host, fwd->listen_port);
3252 		}
3253 		if (code != oDynamicForward) {
3254 			if (fwd->connect_port == PORT_STREAMLOCAL)
3255 				printf(" %s", fwd->connect_path);
3256 			else if (fwd->connect_host == NULL)
3257 				printf(" %d", fwd->connect_port);
3258 			else {
3259 				printf(" [%s]:%d",
3260 				    fwd->connect_host, fwd->connect_port);
3261 			}
3262 		}
3263 		printf("\n");
3264 	}
3265 }
3266 
3267 void
3268 dump_client_config(Options *o, const char *host)
3269 {
3270 	int i, r;
3271 	char buf[8], *all_key;
3272 
3273 	/*
3274 	 * Expand HostKeyAlgorithms name lists. This isn't handled in
3275 	 * fill_default_options() like the other algorithm lists because
3276 	 * the host key algorithms are by default dynamically chosen based
3277 	 * on the host's keys found in known_hosts.
3278 	 */
3279 	all_key = sshkey_alg_list(0, 0, 1, ',');
3280 	if ((r = kex_assemble_names(&o->hostkeyalgorithms, kex_default_pk_alg(),
3281 	    all_key)) != 0)
3282 		fatal_fr(r, "expand HostKeyAlgorithms");
3283 	free(all_key);
3284 
3285 	/* Most interesting options first: user, host, port */
3286 	dump_cfg_string(oUser, o->user);
3287 	dump_cfg_string(oHostname, host);
3288 	dump_cfg_int(oPort, o->port);
3289 
3290 	/* Flag options */
3291 	dump_cfg_fmtint(oAddressFamily, o->address_family);
3292 	dump_cfg_fmtint(oBatchMode, o->batch_mode);
3293 	dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local);
3294 	dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname);
3295 	dump_cfg_fmtint(oCheckHostIP, o->check_host_ip);
3296 	dump_cfg_fmtint(oCompression, o->compression);
3297 	dump_cfg_fmtint(oControlMaster, o->control_master);
3298 	dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
3299 	dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings);
3300 	dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
3301 	dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash);
3302 	dump_cfg_fmtint(oForwardX11, o->forward_x11);
3303 	dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted);
3304 	dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports);
3305 #ifdef GSSAPI
3306 	dump_cfg_fmtint(oGssAuthentication, o->gss_authentication);
3307 	dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds);
3308 #endif /* GSSAPI */
3309 	dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);
3310 	dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);
3311 	dump_cfg_fmtint(oIdentitiesOnly, o->identities_only);
3312 	dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication);
3313 	dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost);
3314 	dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication);
3315 	dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command);
3316 	dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass);
3317 	dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
3318 	dump_cfg_fmtint(oRequestTTY, o->request_tty);
3319 	dump_cfg_fmtint(oSessionType, o->session_type);
3320 	dump_cfg_fmtint(oStdinNull, o->stdin_null);
3321 	dump_cfg_fmtint(oForkAfterAuthentication, o->fork_after_authentication);
3322 	dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
3323 	dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
3324 	dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
3325 	dump_cfg_fmtint(oTunnel, o->tun_open);
3326 	dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns);
3327 	dump_cfg_fmtint(oVisualHostKey, o->visual_host_key);
3328 	dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys);
3329 
3330 	/* Integer options */
3331 	dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots);
3332 	dump_cfg_int(oConnectionAttempts, o->connection_attempts);
3333 	dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout);
3334 	dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
3335 	dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
3336 	dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
3337 	dump_cfg_int(oRequiredRSASize, o->required_rsa_size);
3338 
3339 	/* String options */
3340 	dump_cfg_string(oBindAddress, o->bind_address);
3341 	dump_cfg_string(oBindInterface, o->bind_interface);
3342 	dump_cfg_string(oCiphers, o->ciphers);
3343 	dump_cfg_string(oControlPath, o->control_path);
3344 	dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms);
3345 	dump_cfg_string(oHostKeyAlias, o->host_key_alias);
3346 	dump_cfg_string(oHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos);
3347 	dump_cfg_string(oIdentityAgent, o->identity_agent);
3348 	dump_cfg_string(oIgnoreUnknown, o->ignored_unknown);
3349 	dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
3350 	dump_cfg_string(oKexAlgorithms, o->kex_algorithms);
3351 	dump_cfg_string(oCASignatureAlgorithms, o->ca_sign_algorithms);
3352 	dump_cfg_string(oLocalCommand, o->local_command);
3353 	dump_cfg_string(oRemoteCommand, o->remote_command);
3354 	dump_cfg_string(oLogLevel, log_level_name(o->log_level));
3355 	dump_cfg_string(oMacs, o->macs);
3356 #ifdef ENABLE_PKCS11
3357 	dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
3358 #endif
3359 	dump_cfg_string(oSecurityKeyProvider, o->sk_provider);
3360 	dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
3361 	dump_cfg_string(oPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos);
3362 	dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
3363 	dump_cfg_string(oXAuthLocation, o->xauth_location);
3364 	dump_cfg_string(oKnownHostsCommand, o->known_hosts_command);
3365 
3366 	/* Forwards */
3367 	dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
3368 	dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards);
3369 	dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards);
3370 
3371 	/* String array options */
3372 	dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files);
3373 	dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains);
3374 	dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files);
3375 	dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles);
3376 	dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles);
3377 	dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env);
3378 	dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv);
3379 	dump_cfg_strarray_oneline(oLogVerbose,
3380 	    o->num_log_verbose, o->log_verbose);
3381 
3382 	/* Special cases */
3383 
3384 	/* PermitRemoteOpen */
3385 	if (o->num_permitted_remote_opens == 0)
3386 		printf("%s any\n", lookup_opcode_name(oPermitRemoteOpen));
3387 	else
3388 		dump_cfg_strarray_oneline(oPermitRemoteOpen,
3389 		    o->num_permitted_remote_opens, o->permitted_remote_opens);
3390 
3391 	/* AddKeysToAgent */
3392 	if (o->add_keys_to_agent_lifespan <= 0)
3393 		dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent);
3394 	else {
3395 		printf("addkeystoagent%s %d\n",
3396 		    o->add_keys_to_agent == 3 ? " confirm" : "",
3397 		    o->add_keys_to_agent_lifespan);
3398 	}
3399 
3400 	/* oForwardAgent */
3401 	if (o->forward_agent_sock_path == NULL)
3402 		dump_cfg_fmtint(oForwardAgent, o->forward_agent);
3403 	else
3404 		dump_cfg_string(oForwardAgent, o->forward_agent_sock_path);
3405 
3406 	/* oConnectTimeout */
3407 	if (o->connection_timeout == -1)
3408 		printf("connecttimeout none\n");
3409 	else
3410 		dump_cfg_int(oConnectTimeout, o->connection_timeout);
3411 
3412 	/* oTunnelDevice */
3413 	printf("tunneldevice");
3414 	if (o->tun_local == SSH_TUNID_ANY)
3415 		printf(" any");
3416 	else
3417 		printf(" %d", o->tun_local);
3418 	if (o->tun_remote == SSH_TUNID_ANY)
3419 		printf(":any");
3420 	else
3421 		printf(":%d", o->tun_remote);
3422 	printf("\n");
3423 
3424 	/* oCanonicalizePermittedCNAMEs */
3425 	printf("canonicalizePermittedcnames");
3426 	if (o->num_permitted_cnames == 0)
3427 		printf(" none");
3428 	for (i = 0; i < o->num_permitted_cnames; i++) {
3429 		printf(" %s:%s", o->permitted_cnames[i].source_list,
3430 		    o->permitted_cnames[i].target_list);
3431 	}
3432 	printf("\n");
3433 
3434 	/* oControlPersist */
3435 	if (o->control_persist == 0 || o->control_persist_timeout == 0)
3436 		dump_cfg_fmtint(oControlPersist, o->control_persist);
3437 	else
3438 		dump_cfg_int(oControlPersist, o->control_persist_timeout);
3439 
3440 	/* oEscapeChar */
3441 	if (o->escape_char == SSH_ESCAPECHAR_NONE)
3442 		printf("escapechar none\n");
3443 	else {
3444 		vis(buf, o->escape_char, VIS_WHITE, 0);
3445 		printf("escapechar %s\n", buf);
3446 	}
3447 
3448 	/* oIPQoS */
3449 	printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
3450 	printf("%s\n", iptos2str(o->ip_qos_bulk));
3451 
3452 	/* oRekeyLimit */
3453 	printf("rekeylimit %llu %d\n",
3454 	    (unsigned long long)o->rekey_limit, o->rekey_interval);
3455 
3456 	/* oStreamLocalBindMask */
3457 	printf("streamlocalbindmask 0%o\n",
3458 	    o->fwd_opts.streamlocal_bind_mask);
3459 
3460 	/* oLogFacility */
3461 	printf("syslogfacility %s\n", log_facility_name(o->log_facility));
3462 
3463 	/* oProxyCommand / oProxyJump */
3464 	if (o->jump_host == NULL)
3465 		dump_cfg_string(oProxyCommand, o->proxy_command);
3466 	else {
3467 		/* Check for numeric addresses */
3468 		i = strchr(o->jump_host, ':') != NULL ||
3469 		    strspn(o->jump_host, "1234567890.") == strlen(o->jump_host);
3470 		snprintf(buf, sizeof(buf), "%d", o->jump_port);
3471 		printf("proxyjump %s%s%s%s%s%s%s%s%s\n",
3472 		    /* optional additional jump spec */
3473 		    o->jump_extra == NULL ? "" : o->jump_extra,
3474 		    o->jump_extra == NULL ? "" : ",",
3475 		    /* optional user */
3476 		    o->jump_user == NULL ? "" : o->jump_user,
3477 		    o->jump_user == NULL ? "" : "@",
3478 		    /* opening [ if hostname is numeric */
3479 		    i ? "[" : "",
3480 		    /* mandatory hostname */
3481 		    o->jump_host,
3482 		    /* closing ] if hostname is numeric */
3483 		    i ? "]" : "",
3484 		    /* optional port number */
3485 		    o->jump_port <= 0 ? "" : ":",
3486 		    o->jump_port <= 0 ? "" : buf);
3487 	}
3488 }
3489