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