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