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