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