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