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