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