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