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