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