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