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