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