xref: /openbsd-src/usr.bin/ssh/readconf.c (revision ae9fff4e069831c9c5d6ce0723c2c553634334e0)
1 /* $OpenBSD: readconf.c,v 1.343 2020/11/30 05:36:39 dtucker 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 *cp, *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 		/*
1920 		 * Trim out comments and strip whitespace.
1921 		 * NB - preserve newlines, they are needed to reproduce
1922 		 * line numbers later for error messages.
1923 		 */
1924 		if ((cp = strchr(line, '#')) != NULL)
1925 			*cp = '\0';
1926 		if (process_config_line_depth(options, pw, host, original_host,
1927 		    line, filename, linenum, activep, flags, want_final_pass,
1928 		    depth) != 0)
1929 			bad_options++;
1930 	}
1931 	free(line);
1932 	fclose(f);
1933 	if (bad_options > 0)
1934 		fatal("%s: terminating, %d bad configuration options",
1935 		    filename, bad_options);
1936 	return 1;
1937 }
1938 
1939 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
1940 int
1941 option_clear_or_none(const char *o)
1942 {
1943 	return o == NULL || strcasecmp(o, "none") == 0;
1944 }
1945 
1946 /*
1947  * Initializes options to special values that indicate that they have not yet
1948  * been set.  Read_config_file will only set options with this value. Options
1949  * are processed in the following order: command line, user config file,
1950  * system config file.  Last, fill_default_options is called.
1951  */
1952 
1953 void
1954 initialize_options(Options * options)
1955 {
1956 	memset(options, 'X', sizeof(*options));
1957 	options->forward_agent = -1;
1958 	options->forward_agent_sock_path = NULL;
1959 	options->forward_x11 = -1;
1960 	options->forward_x11_trusted = -1;
1961 	options->forward_x11_timeout = -1;
1962 	options->stdio_forward_host = NULL;
1963 	options->stdio_forward_port = 0;
1964 	options->clear_forwardings = -1;
1965 	options->exit_on_forward_failure = -1;
1966 	options->xauth_location = NULL;
1967 	options->fwd_opts.gateway_ports = -1;
1968 	options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
1969 	options->fwd_opts.streamlocal_bind_unlink = -1;
1970 	options->pubkey_authentication = -1;
1971 	options->challenge_response_authentication = -1;
1972 	options->gss_authentication = -1;
1973 	options->gss_deleg_creds = -1;
1974 	options->password_authentication = -1;
1975 	options->kbd_interactive_authentication = -1;
1976 	options->kbd_interactive_devices = NULL;
1977 	options->hostbased_authentication = -1;
1978 	options->batch_mode = -1;
1979 	options->check_host_ip = -1;
1980 	options->strict_host_key_checking = -1;
1981 	options->compression = -1;
1982 	options->tcp_keep_alive = -1;
1983 	options->port = -1;
1984 	options->address_family = -1;
1985 	options->connection_attempts = -1;
1986 	options->connection_timeout = -1;
1987 	options->number_of_password_prompts = -1;
1988 	options->ciphers = NULL;
1989 	options->macs = NULL;
1990 	options->kex_algorithms = NULL;
1991 	options->hostkeyalgorithms = NULL;
1992 	options->ca_sign_algorithms = NULL;
1993 	options->num_identity_files = 0;
1994 	options->num_certificate_files = 0;
1995 	options->hostname = NULL;
1996 	options->host_key_alias = NULL;
1997 	options->proxy_command = NULL;
1998 	options->jump_user = NULL;
1999 	options->jump_host = NULL;
2000 	options->jump_port = -1;
2001 	options->jump_extra = NULL;
2002 	options->user = NULL;
2003 	options->escape_char = -1;
2004 	options->num_system_hostfiles = 0;
2005 	options->num_user_hostfiles = 0;
2006 	options->local_forwards = NULL;
2007 	options->num_local_forwards = 0;
2008 	options->remote_forwards = NULL;
2009 	options->num_remote_forwards = 0;
2010 	options->log_facility = SYSLOG_FACILITY_NOT_SET;
2011 	options->log_level = SYSLOG_LEVEL_NOT_SET;
2012 	options->num_log_verbose = 0;
2013 	options->log_verbose = NULL;
2014 	options->preferred_authentications = NULL;
2015 	options->bind_address = NULL;
2016 	options->bind_interface = NULL;
2017 	options->pkcs11_provider = NULL;
2018 	options->sk_provider = NULL;
2019 	options->enable_ssh_keysign = - 1;
2020 	options->no_host_authentication_for_localhost = - 1;
2021 	options->identities_only = - 1;
2022 	options->rekey_limit = - 1;
2023 	options->rekey_interval = -1;
2024 	options->verify_host_key_dns = -1;
2025 	options->server_alive_interval = -1;
2026 	options->server_alive_count_max = -1;
2027 	options->send_env = NULL;
2028 	options->num_send_env = 0;
2029 	options->setenv = NULL;
2030 	options->num_setenv = 0;
2031 	options->control_path = NULL;
2032 	options->control_master = -1;
2033 	options->control_persist = -1;
2034 	options->control_persist_timeout = 0;
2035 	options->hash_known_hosts = -1;
2036 	options->tun_open = -1;
2037 	options->tun_local = -1;
2038 	options->tun_remote = -1;
2039 	options->local_command = NULL;
2040 	options->permit_local_command = -1;
2041 	options->remote_command = NULL;
2042 	options->add_keys_to_agent = -1;
2043 	options->add_keys_to_agent_lifespan = -1;
2044 	options->identity_agent = NULL;
2045 	options->visual_host_key = -1;
2046 	options->ip_qos_interactive = -1;
2047 	options->ip_qos_bulk = -1;
2048 	options->request_tty = -1;
2049 	options->proxy_use_fdpass = -1;
2050 	options->ignored_unknown = NULL;
2051 	options->num_canonical_domains = 0;
2052 	options->num_permitted_cnames = 0;
2053 	options->canonicalize_max_dots = -1;
2054 	options->canonicalize_fallback_local = -1;
2055 	options->canonicalize_hostname = -1;
2056 	options->revoked_host_keys = NULL;
2057 	options->fingerprint_hash = -1;
2058 	options->update_hostkeys = -1;
2059 	options->hostbased_key_types = NULL;
2060 	options->pubkey_key_types = NULL;
2061 }
2062 
2063 /*
2064  * A petite version of fill_default_options() that just fills the options
2065  * needed for hostname canonicalization to proceed.
2066  */
2067 void
2068 fill_default_options_for_canonicalization(Options *options)
2069 {
2070 	if (options->canonicalize_max_dots == -1)
2071 		options->canonicalize_max_dots = 1;
2072 	if (options->canonicalize_fallback_local == -1)
2073 		options->canonicalize_fallback_local = 1;
2074 	if (options->canonicalize_hostname == -1)
2075 		options->canonicalize_hostname = SSH_CANONICALISE_NO;
2076 }
2077 
2078 /*
2079  * Called after processing other sources of option data, this fills those
2080  * options for which no value has been specified with their default values.
2081  */
2082 void
2083 fill_default_options(Options * options)
2084 {
2085 	char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig;
2086 	char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig;
2087 	int r;
2088 
2089 	if (options->forward_agent == -1)
2090 		options->forward_agent = 0;
2091 	if (options->forward_x11 == -1)
2092 		options->forward_x11 = 0;
2093 	if (options->forward_x11_trusted == -1)
2094 		options->forward_x11_trusted = 0;
2095 	if (options->forward_x11_timeout == -1)
2096 		options->forward_x11_timeout = 1200;
2097 	/*
2098 	 * stdio forwarding (-W) changes the default for these but we defer
2099 	 * setting the values so they can be overridden.
2100 	 */
2101 	if (options->exit_on_forward_failure == -1)
2102 		options->exit_on_forward_failure =
2103 		    options->stdio_forward_host != NULL ? 1 : 0;
2104 	if (options->clear_forwardings == -1)
2105 		options->clear_forwardings =
2106 		    options->stdio_forward_host != NULL ? 1 : 0;
2107 	if (options->clear_forwardings == 1)
2108 		clear_forwardings(options);
2109 
2110 	if (options->xauth_location == NULL)
2111 		options->xauth_location = _PATH_XAUTH;
2112 	if (options->fwd_opts.gateway_ports == -1)
2113 		options->fwd_opts.gateway_ports = 0;
2114 	if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
2115 		options->fwd_opts.streamlocal_bind_mask = 0177;
2116 	if (options->fwd_opts.streamlocal_bind_unlink == -1)
2117 		options->fwd_opts.streamlocal_bind_unlink = 0;
2118 	if (options->pubkey_authentication == -1)
2119 		options->pubkey_authentication = 1;
2120 	if (options->challenge_response_authentication == -1)
2121 		options->challenge_response_authentication = 1;
2122 	if (options->gss_authentication == -1)
2123 		options->gss_authentication = 0;
2124 	if (options->gss_deleg_creds == -1)
2125 		options->gss_deleg_creds = 0;
2126 	if (options->password_authentication == -1)
2127 		options->password_authentication = 1;
2128 	if (options->kbd_interactive_authentication == -1)
2129 		options->kbd_interactive_authentication = 1;
2130 	if (options->hostbased_authentication == -1)
2131 		options->hostbased_authentication = 0;
2132 	if (options->batch_mode == -1)
2133 		options->batch_mode = 0;
2134 	if (options->check_host_ip == -1)
2135 		options->check_host_ip = 1;
2136 	if (options->strict_host_key_checking == -1)
2137 		options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK;
2138 	if (options->compression == -1)
2139 		options->compression = 0;
2140 	if (options->tcp_keep_alive == -1)
2141 		options->tcp_keep_alive = 1;
2142 	if (options->port == -1)
2143 		options->port = 0;	/* Filled in ssh_connect. */
2144 	if (options->address_family == -1)
2145 		options->address_family = AF_UNSPEC;
2146 	if (options->connection_attempts == -1)
2147 		options->connection_attempts = 1;
2148 	if (options->number_of_password_prompts == -1)
2149 		options->number_of_password_prompts = 3;
2150 	/* options->hostkeyalgorithms, default set in myproposals.h */
2151 	if (options->add_keys_to_agent == -1) {
2152 		options->add_keys_to_agent = 0;
2153 		options->add_keys_to_agent_lifespan = 0;
2154 	}
2155 	if (options->num_identity_files == 0) {
2156 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0);
2157 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0);
2158 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0);
2159 		add_identity_file(options, "~/",
2160 		    _PATH_SSH_CLIENT_ID_ECDSA_SK, 0);
2161 		add_identity_file(options, "~/",
2162 		    _PATH_SSH_CLIENT_ID_ED25519, 0);
2163 		add_identity_file(options, "~/",
2164 		    _PATH_SSH_CLIENT_ID_ED25519_SK, 0);
2165 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0);
2166 	}
2167 	if (options->escape_char == -1)
2168 		options->escape_char = '~';
2169 	if (options->num_system_hostfiles == 0) {
2170 		options->system_hostfiles[options->num_system_hostfiles++] =
2171 		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
2172 		options->system_hostfiles[options->num_system_hostfiles++] =
2173 		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
2174 	}
2175 	if (options->update_hostkeys == -1) {
2176 		if (options->verify_host_key_dns <= 0 &&
2177 		    (options->num_user_hostfiles == 0 ||
2178 		    (options->num_user_hostfiles == 1 && strcmp(options->
2179 		    user_hostfiles[0], _PATH_SSH_USER_HOSTFILE) == 0)))
2180 			options->update_hostkeys = SSH_UPDATE_HOSTKEYS_YES;
2181 		else
2182 			options->update_hostkeys = SSH_UPDATE_HOSTKEYS_NO;
2183 	}
2184 	if (options->num_user_hostfiles == 0) {
2185 		options->user_hostfiles[options->num_user_hostfiles++] =
2186 		    xstrdup(_PATH_SSH_USER_HOSTFILE);
2187 		options->user_hostfiles[options->num_user_hostfiles++] =
2188 		    xstrdup(_PATH_SSH_USER_HOSTFILE2);
2189 	}
2190 	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
2191 		options->log_level = SYSLOG_LEVEL_INFO;
2192 	if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
2193 		options->log_facility = SYSLOG_FACILITY_USER;
2194 	if (options->no_host_authentication_for_localhost == - 1)
2195 		options->no_host_authentication_for_localhost = 0;
2196 	if (options->identities_only == -1)
2197 		options->identities_only = 0;
2198 	if (options->enable_ssh_keysign == -1)
2199 		options->enable_ssh_keysign = 0;
2200 	if (options->rekey_limit == -1)
2201 		options->rekey_limit = 0;
2202 	if (options->rekey_interval == -1)
2203 		options->rekey_interval = 0;
2204 	if (options->verify_host_key_dns == -1)
2205 		options->verify_host_key_dns = 0;
2206 	if (options->server_alive_interval == -1)
2207 		options->server_alive_interval = 0;
2208 	if (options->server_alive_count_max == -1)
2209 		options->server_alive_count_max = 3;
2210 	if (options->control_master == -1)
2211 		options->control_master = 0;
2212 	if (options->control_persist == -1) {
2213 		options->control_persist = 0;
2214 		options->control_persist_timeout = 0;
2215 	}
2216 	if (options->hash_known_hosts == -1)
2217 		options->hash_known_hosts = 0;
2218 	if (options->tun_open == -1)
2219 		options->tun_open = SSH_TUNMODE_NO;
2220 	if (options->tun_local == -1)
2221 		options->tun_local = SSH_TUNID_ANY;
2222 	if (options->tun_remote == -1)
2223 		options->tun_remote = SSH_TUNID_ANY;
2224 	if (options->permit_local_command == -1)
2225 		options->permit_local_command = 0;
2226 	if (options->visual_host_key == -1)
2227 		options->visual_host_key = 0;
2228 	if (options->ip_qos_interactive == -1)
2229 		options->ip_qos_interactive = IPTOS_DSCP_AF21;
2230 	if (options->ip_qos_bulk == -1)
2231 		options->ip_qos_bulk = IPTOS_DSCP_CS1;
2232 	if (options->request_tty == -1)
2233 		options->request_tty = REQUEST_TTY_AUTO;
2234 	if (options->proxy_use_fdpass == -1)
2235 		options->proxy_use_fdpass = 0;
2236 	if (options->canonicalize_max_dots == -1)
2237 		options->canonicalize_max_dots = 1;
2238 	if (options->canonicalize_fallback_local == -1)
2239 		options->canonicalize_fallback_local = 1;
2240 	if (options->canonicalize_hostname == -1)
2241 		options->canonicalize_hostname = SSH_CANONICALISE_NO;
2242 	if (options->fingerprint_hash == -1)
2243 		options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
2244 	if (options->sk_provider == NULL)
2245 		options->sk_provider = xstrdup("internal");
2246 
2247 	/* Expand KEX name lists */
2248 	all_cipher = cipher_alg_list(',', 0);
2249 	all_mac = mac_alg_list(',');
2250 	all_kex = kex_alg_list(',');
2251 	all_key = sshkey_alg_list(0, 0, 1, ',');
2252 	all_sig = sshkey_alg_list(0, 1, 1, ',');
2253 	/* remove unsupported algos from default lists */
2254 	def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher);
2255 	def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac);
2256 	def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex);
2257 	def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
2258 	def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig);
2259 #define ASSEMBLE(what, defaults, all) \
2260 	do { \
2261 		if ((r = kex_assemble_names(&options->what, \
2262 		    defaults, all)) != 0) \
2263 			fatal_fr(r, "%s", #what); \
2264 	} while (0)
2265 	ASSEMBLE(ciphers, def_cipher, all_cipher);
2266 	ASSEMBLE(macs, def_mac, all_mac);
2267 	ASSEMBLE(kex_algorithms, def_kex, all_kex);
2268 	ASSEMBLE(hostbased_key_types, def_key, all_key);
2269 	ASSEMBLE(pubkey_key_types, def_key, all_key);
2270 	ASSEMBLE(ca_sign_algorithms, def_sig, all_sig);
2271 #undef ASSEMBLE
2272 	free(all_cipher);
2273 	free(all_mac);
2274 	free(all_kex);
2275 	free(all_key);
2276 	free(all_sig);
2277 	free(def_cipher);
2278 	free(def_mac);
2279 	free(def_kex);
2280 	kex_default_pk_alg_filtered = def_key; /* save for later use */
2281 	free(def_sig);
2282 
2283 #define CLEAR_ON_NONE(v) \
2284 	do { \
2285 		if (option_clear_or_none(v)) { \
2286 			free(v); \
2287 			v = NULL; \
2288 		} \
2289 	} while(0)
2290 	CLEAR_ON_NONE(options->local_command);
2291 	CLEAR_ON_NONE(options->remote_command);
2292 	CLEAR_ON_NONE(options->proxy_command);
2293 	CLEAR_ON_NONE(options->control_path);
2294 	CLEAR_ON_NONE(options->revoked_host_keys);
2295 	CLEAR_ON_NONE(options->pkcs11_provider);
2296 	CLEAR_ON_NONE(options->sk_provider);
2297 	if (options->jump_host != NULL &&
2298 	    strcmp(options->jump_host, "none") == 0 &&
2299 	    options->jump_port == 0 && options->jump_user == NULL) {
2300 		free(options->jump_host);
2301 		options->jump_host = NULL;
2302 	}
2303 	/* options->identity_agent distinguishes NULL from 'none' */
2304 	/* options->user will be set in the main program if appropriate */
2305 	/* options->hostname will be set in the main program if appropriate */
2306 	/* options->host_key_alias should not be set by default */
2307 	/* options->preferred_authentications will be set in ssh */
2308 }
2309 
2310 struct fwdarg {
2311 	char *arg;
2312 	int ispath;
2313 };
2314 
2315 /*
2316  * parse_fwd_field
2317  * parses the next field in a port forwarding specification.
2318  * sets fwd to the parsed field and advances p past the colon
2319  * or sets it to NULL at end of string.
2320  * returns 0 on success, else non-zero.
2321  */
2322 static int
2323 parse_fwd_field(char **p, struct fwdarg *fwd)
2324 {
2325 	char *ep, *cp = *p;
2326 	int ispath = 0;
2327 
2328 	if (*cp == '\0') {
2329 		*p = NULL;
2330 		return -1;	/* end of string */
2331 	}
2332 
2333 	/*
2334 	 * A field escaped with square brackets is used literally.
2335 	 * XXX - allow ']' to be escaped via backslash?
2336 	 */
2337 	if (*cp == '[') {
2338 		/* find matching ']' */
2339 		for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
2340 			if (*ep == '/')
2341 				ispath = 1;
2342 		}
2343 		/* no matching ']' or not at end of field. */
2344 		if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
2345 			return -1;
2346 		/* NUL terminate the field and advance p past the colon */
2347 		*ep++ = '\0';
2348 		if (*ep != '\0')
2349 			*ep++ = '\0';
2350 		fwd->arg = cp + 1;
2351 		fwd->ispath = ispath;
2352 		*p = ep;
2353 		return 0;
2354 	}
2355 
2356 	for (cp = *p; *cp != '\0'; cp++) {
2357 		switch (*cp) {
2358 		case '\\':
2359 			memmove(cp, cp + 1, strlen(cp + 1) + 1);
2360 			if (*cp == '\0')
2361 				return -1;
2362 			break;
2363 		case '/':
2364 			ispath = 1;
2365 			break;
2366 		case ':':
2367 			*cp++ = '\0';
2368 			goto done;
2369 		}
2370 	}
2371 done:
2372 	fwd->arg = *p;
2373 	fwd->ispath = ispath;
2374 	*p = cp;
2375 	return 0;
2376 }
2377 
2378 /*
2379  * parse_forward
2380  * parses a string containing a port forwarding specification of the form:
2381  *   dynamicfwd == 0
2382  *	[listenhost:]listenport|listenpath:connecthost:connectport|connectpath
2383  *	listenpath:connectpath
2384  *   dynamicfwd == 1
2385  *	[listenhost:]listenport
2386  * returns number of arguments parsed or zero on error
2387  */
2388 int
2389 parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
2390 {
2391 	struct fwdarg fwdargs[4];
2392 	char *p, *cp;
2393 	int i, err;
2394 
2395 	memset(fwd, 0, sizeof(*fwd));
2396 	memset(fwdargs, 0, sizeof(fwdargs));
2397 
2398 	/*
2399 	 * We expand environment variables before checking if we think they're
2400 	 * paths so that if ${VAR} expands to a fully qualified path it is
2401 	 * treated as a path.
2402 	 */
2403 	cp = p = dollar_expand(&err, fwdspec);
2404 	if (p == NULL || err)
2405 		return 0;
2406 
2407 	/* skip leading spaces */
2408 	while (isspace((u_char)*cp))
2409 		cp++;
2410 
2411 	for (i = 0; i < 4; ++i) {
2412 		if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
2413 			break;
2414 	}
2415 
2416 	/* Check for trailing garbage */
2417 	if (cp != NULL && *cp != '\0') {
2418 		i = 0;	/* failure */
2419 	}
2420 
2421 	switch (i) {
2422 	case 1:
2423 		if (fwdargs[0].ispath) {
2424 			fwd->listen_path = xstrdup(fwdargs[0].arg);
2425 			fwd->listen_port = PORT_STREAMLOCAL;
2426 		} else {
2427 			fwd->listen_host = NULL;
2428 			fwd->listen_port = a2port(fwdargs[0].arg);
2429 		}
2430 		fwd->connect_host = xstrdup("socks");
2431 		break;
2432 
2433 	case 2:
2434 		if (fwdargs[0].ispath && fwdargs[1].ispath) {
2435 			fwd->listen_path = xstrdup(fwdargs[0].arg);
2436 			fwd->listen_port = PORT_STREAMLOCAL;
2437 			fwd->connect_path = xstrdup(fwdargs[1].arg);
2438 			fwd->connect_port = PORT_STREAMLOCAL;
2439 		} else if (fwdargs[1].ispath) {
2440 			fwd->listen_host = NULL;
2441 			fwd->listen_port = a2port(fwdargs[0].arg);
2442 			fwd->connect_path = xstrdup(fwdargs[1].arg);
2443 			fwd->connect_port = PORT_STREAMLOCAL;
2444 		} else {
2445 			fwd->listen_host = xstrdup(fwdargs[0].arg);
2446 			fwd->listen_port = a2port(fwdargs[1].arg);
2447 			fwd->connect_host = xstrdup("socks");
2448 		}
2449 		break;
2450 
2451 	case 3:
2452 		if (fwdargs[0].ispath) {
2453 			fwd->listen_path = xstrdup(fwdargs[0].arg);
2454 			fwd->listen_port = PORT_STREAMLOCAL;
2455 			fwd->connect_host = xstrdup(fwdargs[1].arg);
2456 			fwd->connect_port = a2port(fwdargs[2].arg);
2457 		} else if (fwdargs[2].ispath) {
2458 			fwd->listen_host = xstrdup(fwdargs[0].arg);
2459 			fwd->listen_port = a2port(fwdargs[1].arg);
2460 			fwd->connect_path = xstrdup(fwdargs[2].arg);
2461 			fwd->connect_port = PORT_STREAMLOCAL;
2462 		} else {
2463 			fwd->listen_host = NULL;
2464 			fwd->listen_port = a2port(fwdargs[0].arg);
2465 			fwd->connect_host = xstrdup(fwdargs[1].arg);
2466 			fwd->connect_port = a2port(fwdargs[2].arg);
2467 		}
2468 		break;
2469 
2470 	case 4:
2471 		fwd->listen_host = xstrdup(fwdargs[0].arg);
2472 		fwd->listen_port = a2port(fwdargs[1].arg);
2473 		fwd->connect_host = xstrdup(fwdargs[2].arg);
2474 		fwd->connect_port = a2port(fwdargs[3].arg);
2475 		break;
2476 	default:
2477 		i = 0; /* failure */
2478 	}
2479 
2480 	free(p);
2481 
2482 	if (dynamicfwd) {
2483 		if (!(i == 1 || i == 2))
2484 			goto fail_free;
2485 	} else {
2486 		if (!(i == 3 || i == 4)) {
2487 			if (fwd->connect_path == NULL &&
2488 			    fwd->listen_path == NULL)
2489 				goto fail_free;
2490 		}
2491 		if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
2492 			goto fail_free;
2493 	}
2494 
2495 	if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
2496 	    (!remotefwd && fwd->listen_port == 0))
2497 		goto fail_free;
2498 	if (fwd->connect_host != NULL &&
2499 	    strlen(fwd->connect_host) >= NI_MAXHOST)
2500 		goto fail_free;
2501 	/* XXX - if connecting to a remote socket, max sun len may not match this host */
2502 	if (fwd->connect_path != NULL &&
2503 	    strlen(fwd->connect_path) >= PATH_MAX_SUN)
2504 		goto fail_free;
2505 	if (fwd->listen_host != NULL &&
2506 	    strlen(fwd->listen_host) >= NI_MAXHOST)
2507 		goto fail_free;
2508 	if (fwd->listen_path != NULL &&
2509 	    strlen(fwd->listen_path) >= PATH_MAX_SUN)
2510 		goto fail_free;
2511 
2512 	return (i);
2513 
2514  fail_free:
2515 	free(fwd->connect_host);
2516 	fwd->connect_host = NULL;
2517 	free(fwd->connect_path);
2518 	fwd->connect_path = NULL;
2519 	free(fwd->listen_host);
2520 	fwd->listen_host = NULL;
2521 	free(fwd->listen_path);
2522 	fwd->listen_path = NULL;
2523 	return (0);
2524 }
2525 
2526 int
2527 parse_jump(const char *s, Options *o, int active)
2528 {
2529 	char *orig, *sdup, *cp;
2530 	char *host = NULL, *user = NULL;
2531 	int ret = -1, port = -1, first;
2532 
2533 	active &= o->proxy_command == NULL && o->jump_host == NULL;
2534 
2535 	orig = sdup = xstrdup(s);
2536 	first = active;
2537 	do {
2538 		if (strcasecmp(s, "none") == 0)
2539 			break;
2540 		if ((cp = strrchr(sdup, ',')) == NULL)
2541 			cp = sdup; /* last */
2542 		else
2543 			*cp++ = '\0';
2544 
2545 		if (first) {
2546 			/* First argument and configuration is active */
2547 			if (parse_ssh_uri(cp, &user, &host, &port) == -1 ||
2548 			    parse_user_host_port(cp, &user, &host, &port) != 0)
2549 				goto out;
2550 		} else {
2551 			/* Subsequent argument or inactive configuration */
2552 			if (parse_ssh_uri(cp, NULL, NULL, NULL) == -1 ||
2553 			    parse_user_host_port(cp, NULL, NULL, NULL) != 0)
2554 				goto out;
2555 		}
2556 		first = 0; /* only check syntax for subsequent hosts */
2557 	} while (cp != sdup);
2558 	/* success */
2559 	if (active) {
2560 		if (strcasecmp(s, "none") == 0) {
2561 			o->jump_host = xstrdup("none");
2562 			o->jump_port = 0;
2563 		} else {
2564 			o->jump_user = user;
2565 			o->jump_host = host;
2566 			o->jump_port = port;
2567 			o->proxy_command = xstrdup("none");
2568 			user = host = NULL;
2569 			if ((cp = strrchr(s, ',')) != NULL && cp != s) {
2570 				o->jump_extra = xstrdup(s);
2571 				o->jump_extra[cp - s] = '\0';
2572 			}
2573 		}
2574 	}
2575 	ret = 0;
2576  out:
2577 	free(orig);
2578 	free(user);
2579 	free(host);
2580 	return ret;
2581 }
2582 
2583 int
2584 parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp)
2585 {
2586 	char *path;
2587 	int r;
2588 
2589 	r = parse_uri("ssh", uri, userp, hostp, portp, &path);
2590 	if (r == 0 && path != NULL)
2591 		r = -1;		/* path not allowed */
2592 	return r;
2593 }
2594 
2595 /* XXX the following is a near-vebatim copy from servconf.c; refactor */
2596 static const char *
2597 fmt_multistate_int(int val, const struct multistate *m)
2598 {
2599 	u_int i;
2600 
2601 	for (i = 0; m[i].key != NULL; i++) {
2602 		if (m[i].value == val)
2603 			return m[i].key;
2604 	}
2605 	return "UNKNOWN";
2606 }
2607 
2608 static const char *
2609 fmt_intarg(OpCodes code, int val)
2610 {
2611 	if (val == -1)
2612 		return "unset";
2613 	switch (code) {
2614 	case oAddressFamily:
2615 		return fmt_multistate_int(val, multistate_addressfamily);
2616 	case oVerifyHostKeyDNS:
2617 	case oUpdateHostkeys:
2618 		return fmt_multistate_int(val, multistate_yesnoask);
2619 	case oStrictHostKeyChecking:
2620 		return fmt_multistate_int(val, multistate_strict_hostkey);
2621 	case oControlMaster:
2622 		return fmt_multistate_int(val, multistate_controlmaster);
2623 	case oTunnel:
2624 		return fmt_multistate_int(val, multistate_tunnel);
2625 	case oRequestTTY:
2626 		return fmt_multistate_int(val, multistate_requesttty);
2627 	case oCanonicalizeHostname:
2628 		return fmt_multistate_int(val, multistate_canonicalizehostname);
2629 	case oAddKeysToAgent:
2630 		return fmt_multistate_int(val, multistate_yesnoaskconfirm);
2631 	case oFingerprintHash:
2632 		return ssh_digest_alg_name(val);
2633 	default:
2634 		switch (val) {
2635 		case 0:
2636 			return "no";
2637 		case 1:
2638 			return "yes";
2639 		default:
2640 			return "UNKNOWN";
2641 		}
2642 	}
2643 }
2644 
2645 static const char *
2646 lookup_opcode_name(OpCodes code)
2647 {
2648 	u_int i;
2649 
2650 	for (i = 0; keywords[i].name != NULL; i++)
2651 		if (keywords[i].opcode == code)
2652 			return(keywords[i].name);
2653 	return "UNKNOWN";
2654 }
2655 
2656 static void
2657 dump_cfg_int(OpCodes code, int val)
2658 {
2659 	printf("%s %d\n", lookup_opcode_name(code), val);
2660 }
2661 
2662 static void
2663 dump_cfg_fmtint(OpCodes code, int val)
2664 {
2665 	printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
2666 }
2667 
2668 static void
2669 dump_cfg_string(OpCodes code, const char *val)
2670 {
2671 	if (val == NULL)
2672 		return;
2673 	printf("%s %s\n", lookup_opcode_name(code), val);
2674 }
2675 
2676 static void
2677 dump_cfg_strarray(OpCodes code, u_int count, char **vals)
2678 {
2679 	u_int i;
2680 
2681 	for (i = 0; i < count; i++)
2682 		printf("%s %s\n", lookup_opcode_name(code), vals[i]);
2683 }
2684 
2685 static void
2686 dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals)
2687 {
2688 	u_int i;
2689 
2690 	printf("%s", lookup_opcode_name(code));
2691 	for (i = 0; i < count; i++)
2692 		printf(" %s",  vals[i]);
2693 	printf("\n");
2694 }
2695 
2696 static void
2697 dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds)
2698 {
2699 	const struct Forward *fwd;
2700 	u_int i;
2701 
2702 	/* oDynamicForward */
2703 	for (i = 0; i < count; i++) {
2704 		fwd = &fwds[i];
2705 		if (code == oDynamicForward && fwd->connect_host != NULL &&
2706 		    strcmp(fwd->connect_host, "socks") != 0)
2707 			continue;
2708 		if (code == oLocalForward && fwd->connect_host != NULL &&
2709 		    strcmp(fwd->connect_host, "socks") == 0)
2710 			continue;
2711 		printf("%s", lookup_opcode_name(code));
2712 		if (fwd->listen_port == PORT_STREAMLOCAL)
2713 			printf(" %s", fwd->listen_path);
2714 		else if (fwd->listen_host == NULL)
2715 			printf(" %d", fwd->listen_port);
2716 		else {
2717 			printf(" [%s]:%d",
2718 			    fwd->listen_host, fwd->listen_port);
2719 		}
2720 		if (code != oDynamicForward) {
2721 			if (fwd->connect_port == PORT_STREAMLOCAL)
2722 				printf(" %s", fwd->connect_path);
2723 			else if (fwd->connect_host == NULL)
2724 				printf(" %d", fwd->connect_port);
2725 			else {
2726 				printf(" [%s]:%d",
2727 				    fwd->connect_host, fwd->connect_port);
2728 			}
2729 		}
2730 		printf("\n");
2731 	}
2732 }
2733 
2734 void
2735 dump_client_config(Options *o, const char *host)
2736 {
2737 	int i, r;
2738 	char buf[8], *all_key;
2739 
2740 	/*
2741 	 * Expand HostKeyAlgorithms name lists. This isn't handled in
2742 	 * fill_default_options() like the other algorithm lists because
2743 	 * the host key algorithms are by default dynamically chosen based
2744 	 * on the host's keys found in known_hosts.
2745 	 */
2746 	all_key = sshkey_alg_list(0, 0, 1, ',');
2747 	if ((r = kex_assemble_names(&o->hostkeyalgorithms, kex_default_pk_alg(),
2748 	    all_key)) != 0)
2749 		fatal_fr(r, "expand HostKeyAlgorithms");
2750 	free(all_key);
2751 
2752 	/* Most interesting options first: user, host, port */
2753 	dump_cfg_string(oUser, o->user);
2754 	dump_cfg_string(oHostname, host);
2755 	dump_cfg_int(oPort, o->port);
2756 
2757 	/* Flag options */
2758 	dump_cfg_fmtint(oAddressFamily, o->address_family);
2759 	dump_cfg_fmtint(oBatchMode, o->batch_mode);
2760 	dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local);
2761 	dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname);
2762 	dump_cfg_fmtint(oChallengeResponseAuthentication, o->challenge_response_authentication);
2763 	dump_cfg_fmtint(oCheckHostIP, o->check_host_ip);
2764 	dump_cfg_fmtint(oCompression, o->compression);
2765 	dump_cfg_fmtint(oControlMaster, o->control_master);
2766 	dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
2767 	dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings);
2768 	dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
2769 	dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash);
2770 	dump_cfg_fmtint(oForwardX11, o->forward_x11);
2771 	dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted);
2772 	dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports);
2773 #ifdef GSSAPI
2774 	dump_cfg_fmtint(oGssAuthentication, o->gss_authentication);
2775 	dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds);
2776 #endif /* GSSAPI */
2777 	dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);
2778 	dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);
2779 	dump_cfg_fmtint(oIdentitiesOnly, o->identities_only);
2780 	dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication);
2781 	dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost);
2782 	dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication);
2783 	dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command);
2784 	dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass);
2785 	dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
2786 	dump_cfg_fmtint(oRequestTTY, o->request_tty);
2787 	dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
2788 	dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
2789 	dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
2790 	dump_cfg_fmtint(oTunnel, o->tun_open);
2791 	dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns);
2792 	dump_cfg_fmtint(oVisualHostKey, o->visual_host_key);
2793 	dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys);
2794 
2795 	/* Integer options */
2796 	dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots);
2797 	dump_cfg_int(oConnectionAttempts, o->connection_attempts);
2798 	dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout);
2799 	dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
2800 	dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
2801 	dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
2802 
2803 	/* String options */
2804 	dump_cfg_string(oBindAddress, o->bind_address);
2805 	dump_cfg_string(oBindInterface, o->bind_interface);
2806 	dump_cfg_string(oCiphers, o->ciphers);
2807 	dump_cfg_string(oControlPath, o->control_path);
2808 	dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms);
2809 	dump_cfg_string(oHostKeyAlias, o->host_key_alias);
2810 	dump_cfg_string(oHostbasedKeyTypes, o->hostbased_key_types);
2811 	dump_cfg_string(oIdentityAgent, o->identity_agent);
2812 	dump_cfg_string(oIgnoreUnknown, o->ignored_unknown);
2813 	dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
2814 	dump_cfg_string(oKexAlgorithms, o->kex_algorithms);
2815 	dump_cfg_string(oCASignatureAlgorithms, o->ca_sign_algorithms);
2816 	dump_cfg_string(oLocalCommand, o->local_command);
2817 	dump_cfg_string(oRemoteCommand, o->remote_command);
2818 	dump_cfg_string(oLogLevel, log_level_name(o->log_level));
2819 	dump_cfg_string(oMacs, o->macs);
2820 #ifdef ENABLE_PKCS11
2821 	dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
2822 #endif
2823 	dump_cfg_string(oSecurityKeyProvider, o->sk_provider);
2824 	dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
2825 	dump_cfg_string(oPubkeyAcceptedKeyTypes, o->pubkey_key_types);
2826 	dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
2827 	dump_cfg_string(oXAuthLocation, o->xauth_location);
2828 
2829 	/* Forwards */
2830 	dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
2831 	dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards);
2832 	dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards);
2833 
2834 	/* String array options */
2835 	dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files);
2836 	dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains);
2837 	dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files);
2838 	dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles);
2839 	dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles);
2840 	dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env);
2841 	dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv);
2842 	dump_cfg_strarray_oneline(oLogVerbose,
2843 	    o->num_log_verbose, o->log_verbose);
2844 
2845 	/* Special cases */
2846 
2847 	/* AddKeysToAgent */
2848 	if (o->add_keys_to_agent_lifespan <= 0)
2849 		dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent);
2850 	else {
2851 		printf("addkeystoagent%s %d\n",
2852 		    o->add_keys_to_agent == 3 ? " confirm" : "",
2853 		    o->add_keys_to_agent_lifespan);
2854 	}
2855 
2856 	/* oForwardAgent */
2857 	if (o->forward_agent_sock_path == NULL)
2858 		dump_cfg_fmtint(oForwardAgent, o->forward_agent);
2859 	else
2860 		dump_cfg_string(oForwardAgent, o->forward_agent_sock_path);
2861 
2862 	/* oConnectTimeout */
2863 	if (o->connection_timeout == -1)
2864 		printf("connecttimeout none\n");
2865 	else
2866 		dump_cfg_int(oConnectTimeout, o->connection_timeout);
2867 
2868 	/* oTunnelDevice */
2869 	printf("tunneldevice");
2870 	if (o->tun_local == SSH_TUNID_ANY)
2871 		printf(" any");
2872 	else
2873 		printf(" %d", o->tun_local);
2874 	if (o->tun_remote == SSH_TUNID_ANY)
2875 		printf(":any");
2876 	else
2877 		printf(":%d", o->tun_remote);
2878 	printf("\n");
2879 
2880 	/* oCanonicalizePermittedCNAMEs */
2881 	if ( o->num_permitted_cnames > 0) {
2882 		printf("canonicalizePermittedcnames");
2883 		for (i = 0; i < o->num_permitted_cnames; i++) {
2884 			printf(" %s:%s", o->permitted_cnames[i].source_list,
2885 			    o->permitted_cnames[i].target_list);
2886 		}
2887 		printf("\n");
2888 	}
2889 
2890 	/* oControlPersist */
2891 	if (o->control_persist == 0 || o->control_persist_timeout == 0)
2892 		dump_cfg_fmtint(oControlPersist, o->control_persist);
2893 	else
2894 		dump_cfg_int(oControlPersist, o->control_persist_timeout);
2895 
2896 	/* oEscapeChar */
2897 	if (o->escape_char == SSH_ESCAPECHAR_NONE)
2898 		printf("escapechar none\n");
2899 	else {
2900 		vis(buf, o->escape_char, VIS_WHITE, 0);
2901 		printf("escapechar %s\n", buf);
2902 	}
2903 
2904 	/* oIPQoS */
2905 	printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
2906 	printf("%s\n", iptos2str(o->ip_qos_bulk));
2907 
2908 	/* oRekeyLimit */
2909 	printf("rekeylimit %llu %d\n",
2910 	    (unsigned long long)o->rekey_limit, o->rekey_interval);
2911 
2912 	/* oStreamLocalBindMask */
2913 	printf("streamlocalbindmask 0%o\n",
2914 	    o->fwd_opts.streamlocal_bind_mask);
2915 
2916 	/* oLogFacility */
2917 	printf("syslogfacility %s\n", log_facility_name(o->log_facility));
2918 
2919 	/* oProxyCommand / oProxyJump */
2920 	if (o->jump_host == NULL)
2921 		dump_cfg_string(oProxyCommand, o->proxy_command);
2922 	else {
2923 		/* Check for numeric addresses */
2924 		i = strchr(o->jump_host, ':') != NULL ||
2925 		    strspn(o->jump_host, "1234567890.") == strlen(o->jump_host);
2926 		snprintf(buf, sizeof(buf), "%d", o->jump_port);
2927 		printf("proxyjump %s%s%s%s%s%s%s%s%s\n",
2928 		    /* optional additional jump spec */
2929 		    o->jump_extra == NULL ? "" : o->jump_extra,
2930 		    o->jump_extra == NULL ? "" : ",",
2931 		    /* optional user */
2932 		    o->jump_user == NULL ? "" : o->jump_user,
2933 		    o->jump_user == NULL ? "" : "@",
2934 		    /* opening [ if hostname is numeric */
2935 		    i ? "[" : "",
2936 		    /* mandatory hostname */
2937 		    o->jump_host,
2938 		    /* closing ] if hostname is numeric */
2939 		    i ? "]" : "",
2940 		    /* optional port number */
2941 		    o->jump_port <= 0 ? "" : ":",
2942 		    o->jump_port <= 0 ? "" : buf);
2943 	}
2944 }
2945