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