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