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