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