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