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