1/* $OpenBSD: readconf.c,v 1.386 2024/03/04 04:13:18 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
135static 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);
138static 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
145typedef 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, oObscureKeystrokeTiming, oChannelTimeout,
182	oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported
183} OpCodes;
184
185/* Textual representations of the tokens. */
186
187static 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	{ "obscurekeystroketiming", oObscureKeystrokeTiming },
331	{ "channeltimeout", oChannelTimeout },
332
333	{ NULL, oBadOption }
334};
335
336static const char *lookup_opcode_name(OpCodes code);
337
338const char *
339kex_default_pk_alg(void)
340{
341	static char *pkalgs;
342
343	if (pkalgs == NULL) {
344		char *all_key;
345
346		all_key = sshkey_alg_list(0, 0, 1, ',');
347		pkalgs = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
348		free(all_key);
349	}
350	return pkalgs;
351}
352
353char *
354ssh_connection_hash(const char *thishost, const char *host, const char *portstr,
355    const char *user, const char *jumphost)
356{
357	struct ssh_digest_ctx *md;
358	u_char conn_hash[SSH_DIGEST_MAX_LENGTH];
359
360	if ((md = ssh_digest_start(SSH_DIGEST_SHA1)) == NULL ||
361	    ssh_digest_update(md, thishost, strlen(thishost)) < 0 ||
362	    ssh_digest_update(md, host, strlen(host)) < 0 ||
363	    ssh_digest_update(md, portstr, strlen(portstr)) < 0 ||
364	    ssh_digest_update(md, user, strlen(user)) < 0 ||
365	    ssh_digest_update(md, jumphost, strlen(jumphost)) < 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
377void
378add_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
406void
407add_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
432static void
433clear_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
462void
463add_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
486void
487add_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
517int
518default_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 */
534static int
535execute_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 */
591static int
592check_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 */
651static int
652match_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, *jmphost;
769
770			if (gethostname(thishost, sizeof(thishost)) == -1)
771				fatal("gethostname: %s", strerror(errno));
772			jmphost = option_clear_or_none(options->jump_host) ?
773			    "" : options->jump_host;
774			strlcpy(shorthost, thishost, sizeof(shorthost));
775			shorthost[strcspn(thishost, ".")] = '\0';
776			snprintf(portstr, sizeof(portstr), "%d", port);
777			snprintf(uidstr, sizeof(uidstr), "%llu",
778			    (unsigned long long)pw->pw_uid);
779			conn_hash_hex = ssh_connection_hash(thishost, host,
780			    portstr, ruser, jmphost);
781			keyalias = options->host_key_alias ?
782			    options->host_key_alias : host;
783
784			cmd = percent_expand(arg,
785			    "C", conn_hash_hex,
786			    "L", shorthost,
787			    "d", pw->pw_dir,
788			    "h", host,
789			    "k", keyalias,
790			    "l", thishost,
791			    "n", original_host,
792			    "p", portstr,
793			    "r", ruser,
794			    "u", pw->pw_name,
795			    "i", uidstr,
796			    "j", jmphost,
797			    (char *)NULL);
798			free(conn_hash_hex);
799			if (result != 1) {
800				/* skip execution if prior predicate failed */
801				debug3("%.200s line %d: skipped exec "
802				    "\"%.100s\"", filename, linenum, cmd);
803				free(cmd);
804				continue;
805			}
806			r = execute_in_shell(cmd);
807			if (r == -1) {
808				fatal("%.200s line %d: match exec "
809				    "'%.100s' error", filename,
810				    linenum, cmd);
811			}
812			criteria = xstrdup(cmd);
813			free(cmd);
814			/* Force exit status to boolean */
815			r = r == 0;
816			if (r == (negate ? 1 : 0))
817				this_result = result = 0;
818		} else {
819			error("Unsupported Match attribute %s", attrib);
820			result = -1;
821			goto out;
822		}
823		debug3("%.200s line %d: %smatched '%s%s%.100s%s' ",
824		    filename, linenum, this_result ? "": "not ", oattrib,
825		    criteria == NULL ? "" : " \"",
826		    criteria == NULL ? "" : criteria,
827		    criteria == NULL ? "" : "\"");
828		free(criteria);
829	}
830	if (attributes == 0) {
831		error("One or more attributes required for Match");
832		result = -1;
833		goto out;
834	}
835 out:
836	if (result != -1)
837		debug2("match %sfound", result ? "" : "not ");
838	*condition = cp;
839	free(host);
840	return result;
841}
842
843/* Remove environment variable by pattern */
844static void
845rm_env(Options *options, const char *arg, const char *filename, int linenum)
846{
847	u_int i, j, onum_send_env = options->num_send_env;
848
849	/* Remove an environment variable */
850	for (i = 0; i < options->num_send_env; ) {
851		if (!match_pattern(options->send_env[i], arg + 1)) {
852			i++;
853			continue;
854		}
855		debug3("%s line %d: removing environment %s",
856		    filename, linenum, options->send_env[i]);
857		free(options->send_env[i]);
858		options->send_env[i] = NULL;
859		for (j = i; j < options->num_send_env - 1; j++) {
860			options->send_env[j] = options->send_env[j + 1];
861			options->send_env[j + 1] = NULL;
862		}
863		options->num_send_env--;
864		/* NB. don't increment i */
865	}
866	if (onum_send_env != options->num_send_env) {
867		options->send_env = xrecallocarray(options->send_env,
868		    onum_send_env, options->num_send_env,
869		    sizeof(*options->send_env));
870	}
871}
872
873/*
874 * Returns the number of the token pointed to by cp or oBadOption.
875 */
876static OpCodes
877parse_token(const char *cp, const char *filename, int linenum,
878    const char *ignored_unknown)
879{
880	int i;
881
882	for (i = 0; keywords[i].name; i++)
883		if (strcmp(cp, keywords[i].name) == 0)
884			return keywords[i].opcode;
885	if (ignored_unknown != NULL &&
886	    match_pattern_list(cp, ignored_unknown, 1) == 1)
887		return oIgnoredUnknownOption;
888	error("%s: line %d: Bad configuration option: %s",
889	    filename, linenum, cp);
890	return oBadOption;
891}
892
893static void
894free_canon_cnames(struct allowed_cname *cnames, u_int n)
895{
896	u_int i;
897
898	if (cnames == NULL || n == 0)
899		return;
900	for (i = 0; i < n; i++) {
901		free(cnames[i].source_list);
902		free(cnames[i].target_list);
903	}
904	free(cnames);
905}
906
907/* Multistate option parsing */
908struct multistate {
909	char *key;
910	int value;
911};
912static const struct multistate multistate_flag[] = {
913	{ "true",			1 },
914	{ "false",			0 },
915	{ "yes",			1 },
916	{ "no",				0 },
917	{ NULL, -1 }
918};
919static const struct multistate multistate_yesnoask[] = {
920	{ "true",			1 },
921	{ "false",			0 },
922	{ "yes",			1 },
923	{ "no",				0 },
924	{ "ask",			2 },
925	{ NULL, -1 }
926};
927static const struct multistate multistate_strict_hostkey[] = {
928	{ "true",			SSH_STRICT_HOSTKEY_YES },
929	{ "false",			SSH_STRICT_HOSTKEY_OFF },
930	{ "yes",			SSH_STRICT_HOSTKEY_YES },
931	{ "no",				SSH_STRICT_HOSTKEY_OFF },
932	{ "ask",			SSH_STRICT_HOSTKEY_ASK },
933	{ "off",			SSH_STRICT_HOSTKEY_OFF },
934	{ "accept-new",			SSH_STRICT_HOSTKEY_NEW },
935	{ NULL, -1 }
936};
937static const struct multistate multistate_yesnoaskconfirm[] = {
938	{ "true",			1 },
939	{ "false",			0 },
940	{ "yes",			1 },
941	{ "no",				0 },
942	{ "ask",			2 },
943	{ "confirm",			3 },
944	{ NULL, -1 }
945};
946static const struct multistate multistate_addressfamily[] = {
947	{ "inet",			AF_INET },
948	{ "inet6",			AF_INET6 },
949	{ "any",			AF_UNSPEC },
950	{ NULL, -1 }
951};
952static const struct multistate multistate_controlmaster[] = {
953	{ "true",			SSHCTL_MASTER_YES },
954	{ "yes",			SSHCTL_MASTER_YES },
955	{ "false",			SSHCTL_MASTER_NO },
956	{ "no",				SSHCTL_MASTER_NO },
957	{ "auto",			SSHCTL_MASTER_AUTO },
958	{ "ask",			SSHCTL_MASTER_ASK },
959	{ "autoask",			SSHCTL_MASTER_AUTO_ASK },
960	{ NULL, -1 }
961};
962static const struct multistate multistate_tunnel[] = {
963	{ "ethernet",			SSH_TUNMODE_ETHERNET },
964	{ "point-to-point",		SSH_TUNMODE_POINTOPOINT },
965	{ "true",			SSH_TUNMODE_DEFAULT },
966	{ "yes",			SSH_TUNMODE_DEFAULT },
967	{ "false",			SSH_TUNMODE_NO },
968	{ "no",				SSH_TUNMODE_NO },
969	{ NULL, -1 }
970};
971static const struct multistate multistate_requesttty[] = {
972	{ "true",			REQUEST_TTY_YES },
973	{ "yes",			REQUEST_TTY_YES },
974	{ "false",			REQUEST_TTY_NO },
975	{ "no",				REQUEST_TTY_NO },
976	{ "force",			REQUEST_TTY_FORCE },
977	{ "auto",			REQUEST_TTY_AUTO },
978	{ NULL, -1 }
979};
980static const struct multistate multistate_sessiontype[] = {
981	{ "none",			SESSION_TYPE_NONE },
982	{ "subsystem",			SESSION_TYPE_SUBSYSTEM },
983	{ "default",			SESSION_TYPE_DEFAULT },
984	{ NULL, -1 }
985};
986static const struct multistate multistate_canonicalizehostname[] = {
987	{ "true",			SSH_CANONICALISE_YES },
988	{ "false",			SSH_CANONICALISE_NO },
989	{ "yes",			SSH_CANONICALISE_YES },
990	{ "no",				SSH_CANONICALISE_NO },
991	{ "always",			SSH_CANONICALISE_ALWAYS },
992	{ NULL, -1 }
993};
994static const struct multistate multistate_pubkey_auth[] = {
995	{ "true",			SSH_PUBKEY_AUTH_ALL },
996	{ "false",			SSH_PUBKEY_AUTH_NO },
997	{ "yes",			SSH_PUBKEY_AUTH_ALL },
998	{ "no",				SSH_PUBKEY_AUTH_NO },
999	{ "unbound",			SSH_PUBKEY_AUTH_UNBOUND },
1000	{ "host-bound",			SSH_PUBKEY_AUTH_HBOUND },
1001	{ NULL, -1 }
1002};
1003static const struct multistate multistate_compression[] = {
1004#ifdef WITH_ZLIB
1005	{ "yes",			COMP_ZLIB },
1006#endif
1007	{ "no",				COMP_NONE },
1008	{ NULL, -1 }
1009};
1010
1011static int
1012parse_multistate_value(const char *arg, const char *filename, int linenum,
1013    const struct multistate *multistate_ptr)
1014{
1015	int i;
1016
1017	if (!arg || *arg == '\0') {
1018		error("%s line %d: missing argument.", filename, linenum);
1019		return -1;
1020	}
1021	for (i = 0; multistate_ptr[i].key != NULL; i++) {
1022		if (strcasecmp(arg, multistate_ptr[i].key) == 0)
1023			return multistate_ptr[i].value;
1024	}
1025	return -1;
1026}
1027
1028/*
1029 * Processes a single option line as used in the configuration files. This
1030 * only sets those values that have not already been set.
1031 */
1032int
1033process_config_line(Options *options, struct passwd *pw, const char *host,
1034    const char *original_host, char *line, const char *filename,
1035    int linenum, int *activep, int flags)
1036{
1037	return process_config_line_depth(options, pw, host, original_host,
1038	    line, filename, linenum, activep, flags, NULL, 0);
1039}
1040
1041#define WHITESPACE " \t\r\n"
1042static int
1043process_config_line_depth(Options *options, struct passwd *pw, const char *host,
1044    const char *original_host, char *line, const char *filename,
1045    int linenum, int *activep, int flags, int *want_final_pass, int depth)
1046{
1047	char *str, **charptr, *endofnumber, *keyword, *arg, *arg2, *p;
1048	char **cpptr, ***cppptr, fwdarg[256];
1049	u_int i, *uintptr, max_entries = 0;
1050	int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0;
1051	int remotefwd, dynamicfwd, ca_only = 0, found = 0;
1052	LogLevel *log_level_ptr;
1053	SyslogFacility *log_facility_ptr;
1054	long long val64;
1055	size_t len;
1056	struct Forward fwd;
1057	const struct multistate *multistate_ptr;
1058	glob_t gl;
1059	const char *errstr;
1060	char **oav = NULL, **av;
1061	int oac = 0, ac;
1062	int ret = -1;
1063	struct allowed_cname *cnames = NULL;
1064	u_int ncnames = 0;
1065	char **strs = NULL; /* string array arguments; freed implicitly */
1066	u_int nstrs = 0;
1067
1068	if (activep == NULL) { /* We are processing a command line directive */
1069		cmdline = 1;
1070		activep = &cmdline;
1071	}
1072
1073	/* Strip trailing whitespace. Allow \f (form feed) at EOL only */
1074	if ((len = strlen(line)) == 0)
1075		return 0;
1076	for (len--; len > 0; len--) {
1077		if (strchr(WHITESPACE "\f", line[len]) == NULL)
1078			break;
1079		line[len] = '\0';
1080	}
1081
1082	str = line;
1083	/* Get the keyword. (Each line is supposed to begin with a keyword). */
1084	if ((keyword = strdelim(&str)) == NULL)
1085		return 0;
1086	/* Ignore leading whitespace. */
1087	if (*keyword == '\0')
1088		keyword = strdelim(&str);
1089	if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
1090		return 0;
1091	/* Match lowercase keyword */
1092	lowercase(keyword);
1093
1094	/* Prepare to parse remainder of line */
1095	if (str != NULL)
1096		str += strspn(str, WHITESPACE);
1097	if (str == NULL || *str == '\0') {
1098		error("%s line %d: no argument after keyword \"%s\"",
1099		    filename, linenum, keyword);
1100		return -1;
1101	}
1102	opcode = parse_token(keyword, filename, linenum,
1103	    options->ignored_unknown);
1104	if (argv_split(str, &oac, &oav, 1) != 0) {
1105		error("%s line %d: invalid quotes", filename, linenum);
1106		return -1;
1107	}
1108	ac = oac;
1109	av = oav;
1110
1111	switch (opcode) {
1112	case oBadOption:
1113		/* don't panic, but count bad options */
1114		goto out;
1115	case oIgnore:
1116		argv_consume(&ac);
1117		break;
1118	case oIgnoredUnknownOption:
1119		debug("%s line %d: Ignored unknown option \"%s\"",
1120		    filename, linenum, keyword);
1121		argv_consume(&ac);
1122		break;
1123	case oConnectTimeout:
1124		intptr = &options->connection_timeout;
1125parse_time:
1126		arg = argv_next(&ac, &av);
1127		if (!arg || *arg == '\0') {
1128			error("%s line %d: missing time value.",
1129			    filename, linenum);
1130			goto out;
1131		}
1132		if (strcmp(arg, "none") == 0)
1133			value = -1;
1134		else if ((value = convtime(arg)) == -1) {
1135			error("%s line %d: invalid time value.",
1136			    filename, linenum);
1137			goto out;
1138		}
1139		if (*activep && *intptr == -1)
1140			*intptr = value;
1141		break;
1142
1143	case oForwardAgent:
1144		intptr = &options->forward_agent;
1145
1146		arg = argv_next(&ac, &av);
1147		if (!arg || *arg == '\0') {
1148			error("%s line %d: missing argument.",
1149			    filename, linenum);
1150			goto out;
1151		}
1152
1153		value = -1;
1154		multistate_ptr = multistate_flag;
1155		for (i = 0; multistate_ptr[i].key != NULL; i++) {
1156			if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
1157				value = multistate_ptr[i].value;
1158				break;
1159			}
1160		}
1161		if (value != -1) {
1162			if (*activep && *intptr == -1)
1163				*intptr = value;
1164			break;
1165		}
1166		/* ForwardAgent wasn't 'yes' or 'no', assume a path */
1167		if (*activep && *intptr == -1)
1168			*intptr = 1;
1169
1170		charptr = &options->forward_agent_sock_path;
1171		goto parse_agent_path;
1172
1173	case oForwardX11:
1174		intptr = &options->forward_x11;
1175 parse_flag:
1176		multistate_ptr = multistate_flag;
1177 parse_multistate:
1178		arg = argv_next(&ac, &av);
1179		if ((value = parse_multistate_value(arg, filename, linenum,
1180		    multistate_ptr)) == -1) {
1181			error("%s line %d: unsupported option \"%s\".",
1182			    filename, linenum, arg);
1183			goto out;
1184		}
1185		if (*activep && *intptr == -1)
1186			*intptr = value;
1187		break;
1188
1189	case oForwardX11Trusted:
1190		intptr = &options->forward_x11_trusted;
1191		goto parse_flag;
1192
1193	case oForwardX11Timeout:
1194		intptr = &options->forward_x11_timeout;
1195		goto parse_time;
1196
1197	case oGatewayPorts:
1198		intptr = &options->fwd_opts.gateway_ports;
1199		goto parse_flag;
1200
1201	case oExitOnForwardFailure:
1202		intptr = &options->exit_on_forward_failure;
1203		goto parse_flag;
1204
1205	case oPasswordAuthentication:
1206		intptr = &options->password_authentication;
1207		goto parse_flag;
1208
1209	case oKbdInteractiveAuthentication:
1210		intptr = &options->kbd_interactive_authentication;
1211		goto parse_flag;
1212
1213	case oKbdInteractiveDevices:
1214		charptr = &options->kbd_interactive_devices;
1215		goto parse_string;
1216
1217	case oPubkeyAuthentication:
1218		multistate_ptr = multistate_pubkey_auth;
1219		intptr = &options->pubkey_authentication;
1220		goto parse_multistate;
1221
1222	case oHostbasedAuthentication:
1223		intptr = &options->hostbased_authentication;
1224		goto parse_flag;
1225
1226	case oGssAuthentication:
1227		intptr = &options->gss_authentication;
1228		goto parse_flag;
1229
1230	case oGssDelegateCreds:
1231		intptr = &options->gss_deleg_creds;
1232		goto parse_flag;
1233
1234	case oBatchMode:
1235		intptr = &options->batch_mode;
1236		goto parse_flag;
1237
1238	case oCheckHostIP:
1239		intptr = &options->check_host_ip;
1240		goto parse_flag;
1241
1242	case oVerifyHostKeyDNS:
1243		intptr = &options->verify_host_key_dns;
1244		multistate_ptr = multistate_yesnoask;
1245		goto parse_multistate;
1246
1247	case oStrictHostKeyChecking:
1248		intptr = &options->strict_host_key_checking;
1249		multistate_ptr = multistate_strict_hostkey;
1250		goto parse_multistate;
1251
1252	case oCompression:
1253		intptr = &options->compression;
1254		multistate_ptr = multistate_compression;
1255		goto parse_multistate;
1256
1257	case oTCPKeepAlive:
1258		intptr = &options->tcp_keep_alive;
1259		goto parse_flag;
1260
1261	case oNoHostAuthenticationForLocalhost:
1262		intptr = &options->no_host_authentication_for_localhost;
1263		goto parse_flag;
1264
1265	case oNumberOfPasswordPrompts:
1266		intptr = &options->number_of_password_prompts;
1267		goto parse_int;
1268
1269	case oRekeyLimit:
1270		arg = argv_next(&ac, &av);
1271		if (!arg || *arg == '\0') {
1272			error("%.200s line %d: Missing argument.", filename,
1273			    linenum);
1274			goto out;
1275		}
1276		if (strcmp(arg, "default") == 0) {
1277			val64 = 0;
1278		} else {
1279			if (scan_scaled(arg, &val64) == -1) {
1280				error("%.200s line %d: Bad number '%s': %s",
1281				    filename, linenum, arg, strerror(errno));
1282				goto out;
1283			}
1284			if (val64 != 0 && val64 < 16) {
1285				error("%.200s line %d: RekeyLimit too small",
1286				    filename, linenum);
1287				goto out;
1288			}
1289		}
1290		if (*activep && options->rekey_limit == -1)
1291			options->rekey_limit = val64;
1292		if (ac != 0) { /* optional rekey interval present */
1293			if (strcmp(av[0], "none") == 0) {
1294				(void)argv_next(&ac, &av);	/* discard */
1295				break;
1296			}
1297			intptr = &options->rekey_interval;
1298			goto parse_time;
1299		}
1300		break;
1301
1302	case oIdentityFile:
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_identity_files;
1311			if (*intptr >= SSH_MAX_IDENTITY_FILES) {
1312				error("%.200s line %d: Too many identity files "
1313				    "specified (max %d).", filename, linenum,
1314				    SSH_MAX_IDENTITY_FILES);
1315				goto out;
1316			}
1317			add_identity_file(options, NULL,
1318			    arg, flags & SSHCONF_USERCONF);
1319		}
1320		break;
1321
1322	case oCertificateFile:
1323		arg = argv_next(&ac, &av);
1324		if (!arg || *arg == '\0') {
1325			error("%.200s line %d: Missing argument.",
1326			    filename, linenum);
1327			goto out;
1328		}
1329		if (*activep) {
1330			intptr = &options->num_certificate_files;
1331			if (*intptr >= SSH_MAX_CERTIFICATE_FILES) {
1332				error("%.200s line %d: Too many certificate "
1333				    "files specified (max %d).",
1334				    filename, linenum,
1335				    SSH_MAX_CERTIFICATE_FILES);
1336				goto out;
1337			}
1338			add_certificate_file(options, arg,
1339			    flags & SSHCONF_USERCONF);
1340		}
1341		break;
1342
1343	case oXAuthLocation:
1344		charptr=&options->xauth_location;
1345		goto parse_string;
1346
1347	case oUser:
1348		charptr = &options->user;
1349parse_string:
1350		arg = argv_next(&ac, &av);
1351		if (!arg || *arg == '\0') {
1352			error("%.200s line %d: Missing argument.",
1353			    filename, linenum);
1354			goto out;
1355		}
1356		if (*activep && *charptr == NULL)
1357			*charptr = xstrdup(arg);
1358		break;
1359
1360	case oGlobalKnownHostsFile:
1361		cpptr = (char **)&options->system_hostfiles;
1362		uintptr = &options->num_system_hostfiles;
1363		max_entries = SSH_MAX_HOSTS_FILES;
1364parse_char_array:
1365		i = 0;
1366		value = *uintptr == 0; /* was array empty when we started? */
1367		while ((arg = argv_next(&ac, &av)) != NULL) {
1368			if (*arg == '\0') {
1369				error("%s line %d: keyword %s empty argument",
1370				    filename, linenum, keyword);
1371				goto out;
1372			}
1373			/* Allow "none" only in first position */
1374			if (strcasecmp(arg, "none") == 0) {
1375				if (i > 0 || ac > 0) {
1376					error("%s line %d: keyword %s \"none\" "
1377					    "argument must appear alone.",
1378					    filename, linenum, keyword);
1379					goto out;
1380				}
1381			}
1382			i++;
1383			if (*activep && value) {
1384				if ((*uintptr) >= max_entries) {
1385					error("%s line %d: too many %s "
1386					    "entries.", filename, linenum,
1387					    keyword);
1388					goto out;
1389				}
1390				cpptr[(*uintptr)++] = xstrdup(arg);
1391			}
1392		}
1393		break;
1394
1395	case oUserKnownHostsFile:
1396		cpptr = (char **)&options->user_hostfiles;
1397		uintptr = &options->num_user_hostfiles;
1398		max_entries = SSH_MAX_HOSTS_FILES;
1399		goto parse_char_array;
1400
1401	case oHostname:
1402		charptr = &options->hostname;
1403		goto parse_string;
1404
1405	case oTag:
1406		charptr = &options->tag;
1407		goto parse_string;
1408
1409	case oHostKeyAlias:
1410		charptr = &options->host_key_alias;
1411		goto parse_string;
1412
1413	case oPreferredAuthentications:
1414		charptr = &options->preferred_authentications;
1415		goto parse_string;
1416
1417	case oBindAddress:
1418		charptr = &options->bind_address;
1419		goto parse_string;
1420
1421	case oBindInterface:
1422		charptr = &options->bind_interface;
1423		goto parse_string;
1424
1425	case oPKCS11Provider:
1426		charptr = &options->pkcs11_provider;
1427		goto parse_string;
1428
1429	case oSecurityKeyProvider:
1430		charptr = &options->sk_provider;
1431		goto parse_string;
1432
1433	case oKnownHostsCommand:
1434		charptr = &options->known_hosts_command;
1435		goto parse_command;
1436
1437	case oProxyCommand:
1438		charptr = &options->proxy_command;
1439		/* Ignore ProxyCommand if ProxyJump already specified */
1440		if (options->jump_host != NULL)
1441			charptr = &options->jump_host; /* Skip below */
1442parse_command:
1443		if (str == NULL) {
1444			error("%.200s line %d: Missing argument.",
1445			    filename, linenum);
1446			goto out;
1447		}
1448		len = strspn(str, WHITESPACE "=");
1449		if (*activep && *charptr == NULL)
1450			*charptr = xstrdup(str + len);
1451		argv_consume(&ac);
1452		break;
1453
1454	case oProxyJump:
1455		if (str == NULL) {
1456			error("%.200s line %d: Missing argument.",
1457			    filename, linenum);
1458			goto out;
1459		}
1460		len = strspn(str, WHITESPACE "=");
1461		/* XXX use argv? */
1462		if (parse_jump(str + len, options, *activep) == -1) {
1463			error("%.200s line %d: Invalid ProxyJump \"%s\"",
1464			    filename, linenum, str + len);
1465			goto out;
1466		}
1467		argv_consume(&ac);
1468		break;
1469
1470	case oPort:
1471		arg = argv_next(&ac, &av);
1472		if (!arg || *arg == '\0') {
1473			error("%.200s line %d: Missing argument.",
1474			    filename, linenum);
1475			goto out;
1476		}
1477		value = a2port(arg);
1478		if (value <= 0) {
1479			error("%.200s line %d: Bad port '%s'.",
1480			    filename, linenum, arg);
1481			goto out;
1482		}
1483		if (*activep && options->port == -1)
1484			options->port = value;
1485		break;
1486
1487	case oConnectionAttempts:
1488		intptr = &options->connection_attempts;
1489parse_int:
1490		arg = argv_next(&ac, &av);
1491		if ((errstr = atoi_err(arg, &value)) != NULL) {
1492			error("%s line %d: integer value %s.",
1493			    filename, linenum, errstr);
1494			goto out;
1495		}
1496		if (*activep && *intptr == -1)
1497			*intptr = value;
1498		break;
1499
1500	case oCiphers:
1501		arg = argv_next(&ac, &av);
1502		if (!arg || *arg == '\0') {
1503			error("%.200s line %d: Missing argument.",
1504			    filename, linenum);
1505			goto out;
1506		}
1507		if (*arg != '-' &&
1508		    !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)){
1509			error("%.200s line %d: Bad SSH2 cipher spec '%s'.",
1510			    filename, linenum, arg ? arg : "<NONE>");
1511			goto out;
1512		}
1513		if (*activep && options->ciphers == NULL)
1514			options->ciphers = xstrdup(arg);
1515		break;
1516
1517	case oMacs:
1518		arg = argv_next(&ac, &av);
1519		if (!arg || *arg == '\0') {
1520			error("%.200s line %d: Missing argument.",
1521			    filename, linenum);
1522			goto out;
1523		}
1524		if (*arg != '-' &&
1525		    !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) {
1526			error("%.200s line %d: Bad SSH2 MAC spec '%s'.",
1527			    filename, linenum, arg ? arg : "<NONE>");
1528			goto out;
1529		}
1530		if (*activep && options->macs == NULL)
1531			options->macs = xstrdup(arg);
1532		break;
1533
1534	case oKexAlgorithms:
1535		arg = argv_next(&ac, &av);
1536		if (!arg || *arg == '\0') {
1537			error("%.200s line %d: Missing argument.",
1538			    filename, linenum);
1539			goto out;
1540		}
1541		if (*arg != '-' &&
1542		    !kex_names_valid(*arg == '+' || *arg == '^' ?
1543		    arg + 1 : arg)) {
1544			error("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
1545			    filename, linenum, arg ? arg : "<NONE>");
1546			goto out;
1547		}
1548		if (*activep && options->kex_algorithms == NULL)
1549			options->kex_algorithms = xstrdup(arg);
1550		break;
1551
1552	case oHostKeyAlgorithms:
1553		charptr = &options->hostkeyalgorithms;
1554		ca_only = 0;
1555parse_pubkey_algos:
1556		arg = argv_next(&ac, &av);
1557		if (!arg || *arg == '\0') {
1558			error("%.200s line %d: Missing argument.",
1559			    filename, linenum);
1560			goto out;
1561		}
1562		if (*arg != '-' &&
1563		    !sshkey_names_valid2(*arg == '+' || *arg == '^' ?
1564		    arg + 1 : arg, 1, ca_only)) {
1565			error("%s line %d: Bad key types '%s'.",
1566			    filename, linenum, arg ? arg : "<NONE>");
1567			goto out;
1568		}
1569		if (*activep && *charptr == NULL)
1570			*charptr = xstrdup(arg);
1571		break;
1572
1573	case oCASignatureAlgorithms:
1574		charptr = &options->ca_sign_algorithms;
1575		ca_only = 1;
1576		goto parse_pubkey_algos;
1577
1578	case oLogLevel:
1579		log_level_ptr = &options->log_level;
1580		arg = argv_next(&ac, &av);
1581		value = log_level_number(arg);
1582		if (value == SYSLOG_LEVEL_NOT_SET) {
1583			error("%.200s line %d: unsupported log level '%s'",
1584			    filename, linenum, arg ? arg : "<NONE>");
1585			goto out;
1586		}
1587		if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
1588			*log_level_ptr = (LogLevel) value;
1589		break;
1590
1591	case oLogFacility:
1592		log_facility_ptr = &options->log_facility;
1593		arg = argv_next(&ac, &av);
1594		value = log_facility_number(arg);
1595		if (value == SYSLOG_FACILITY_NOT_SET) {
1596			error("%.200s line %d: unsupported log facility '%s'",
1597			    filename, linenum, arg ? arg : "<NONE>");
1598			goto out;
1599		}
1600		if (*log_facility_ptr == -1)
1601			*log_facility_ptr = (SyslogFacility) value;
1602		break;
1603
1604	case oLogVerbose:
1605		cppptr = &options->log_verbose;
1606		uintptr = &options->num_log_verbose;
1607		i = 0;
1608		while ((arg = argv_next(&ac, &av)) != NULL) {
1609			if (*arg == '\0') {
1610				error("%s line %d: keyword %s empty argument",
1611				    filename, linenum, keyword);
1612				goto out;
1613			}
1614			/* Allow "none" only in first position */
1615			if (strcasecmp(arg, "none") == 0) {
1616				if (i > 0 || ac > 0) {
1617					error("%s line %d: keyword %s \"none\" "
1618					    "argument must appear alone.",
1619					    filename, linenum, keyword);
1620					goto out;
1621				}
1622			}
1623			i++;
1624			if (*activep && *uintptr == 0) {
1625				*cppptr = xrecallocarray(*cppptr, *uintptr,
1626				    *uintptr + 1, sizeof(**cppptr));
1627				(*cppptr)[(*uintptr)++] = xstrdup(arg);
1628			}
1629		}
1630		break;
1631
1632	case oLocalForward:
1633	case oRemoteForward:
1634	case oDynamicForward:
1635		arg = argv_next(&ac, &av);
1636		if (!arg || *arg == '\0') {
1637			error("%.200s line %d: Missing argument.",
1638			    filename, linenum);
1639			goto out;
1640		}
1641
1642		remotefwd = (opcode == oRemoteForward);
1643		dynamicfwd = (opcode == oDynamicForward);
1644
1645		if (!dynamicfwd) {
1646			arg2 = argv_next(&ac, &av);
1647			if (arg2 == NULL || *arg2 == '\0') {
1648				if (remotefwd)
1649					dynamicfwd = 1;
1650				else {
1651					error("%.200s line %d: Missing target "
1652					    "argument.", filename, linenum);
1653					goto out;
1654				}
1655			} else {
1656				/* construct a string for parse_forward */
1657				snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg,
1658				    arg2);
1659			}
1660		}
1661		if (dynamicfwd)
1662			strlcpy(fwdarg, arg, sizeof(fwdarg));
1663
1664		if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0) {
1665			error("%.200s line %d: Bad forwarding specification.",
1666			    filename, linenum);
1667			goto out;
1668		}
1669
1670		if (*activep) {
1671			if (remotefwd) {
1672				add_remote_forward(options, &fwd);
1673			} else {
1674				add_local_forward(options, &fwd);
1675			}
1676		}
1677		break;
1678
1679	case oPermitRemoteOpen:
1680		uintptr = &options->num_permitted_remote_opens;
1681		cppptr = &options->permitted_remote_opens;
1682		found = *uintptr == 0;
1683		while ((arg = argv_next(&ac, &av)) != NULL) {
1684			arg2 = xstrdup(arg);
1685			/* Allow any/none only in first position */
1686			if (strcasecmp(arg, "none") == 0 ||
1687			    strcasecmp(arg, "any") == 0) {
1688				if (nstrs > 0 || ac > 0) {
1689					error("%s line %d: keyword %s \"%s\" "
1690					    "argument must appear alone.",
1691					    filename, linenum, keyword, arg);
1692					free(arg2);
1693					goto out;
1694				}
1695			} else {
1696				p = hpdelim(&arg);
1697				if (p == NULL) {
1698					fatal("%s line %d: missing host in %s",
1699					    filename, linenum,
1700					    lookup_opcode_name(opcode));
1701				}
1702				p = cleanhostname(p);
1703				/*
1704				 * don't want to use permitopen_port to avoid
1705				 * dependency on channels.[ch] here.
1706				 */
1707				if (arg == NULL || (strcmp(arg, "*") != 0 &&
1708				    a2port(arg) <= 0)) {
1709					fatal("%s line %d: bad port number "
1710					    "in %s", filename, linenum,
1711					    lookup_opcode_name(opcode));
1712				}
1713			}
1714			opt_array_append(filename, linenum,
1715			    lookup_opcode_name(opcode),
1716			    &strs, &nstrs, arg2);
1717			free(arg2);
1718		}
1719		if (nstrs == 0)
1720			fatal("%s line %d: missing %s specification",
1721			    filename, linenum, lookup_opcode_name(opcode));
1722		if (found && *activep) {
1723			*cppptr = strs;
1724			*uintptr = nstrs;
1725			strs = NULL; /* transferred */
1726			nstrs = 0;
1727		}
1728		break;
1729
1730	case oClearAllForwardings:
1731		intptr = &options->clear_forwardings;
1732		goto parse_flag;
1733
1734	case oHost:
1735		if (cmdline) {
1736			error("Host directive not supported as a command-line "
1737			    "option");
1738			goto out;
1739		}
1740		*activep = 0;
1741		arg2 = NULL;
1742		while ((arg = argv_next(&ac, &av)) != NULL) {
1743			if (*arg == '\0') {
1744				error("%s line %d: keyword %s empty argument",
1745				    filename, linenum, keyword);
1746				goto out;
1747			}
1748			if ((flags & SSHCONF_NEVERMATCH) != 0) {
1749				argv_consume(&ac);
1750				break;
1751			}
1752			negated = *arg == '!';
1753			if (negated)
1754				arg++;
1755			if (match_pattern(host, arg)) {
1756				if (negated) {
1757					debug("%.200s line %d: Skipping Host "
1758					    "block because of negated match "
1759					    "for %.100s", filename, linenum,
1760					    arg);
1761					*activep = 0;
1762					argv_consume(&ac);
1763					break;
1764				}
1765				if (!*activep)
1766					arg2 = arg; /* logged below */
1767				*activep = 1;
1768			}
1769		}
1770		if (*activep)
1771			debug("%.200s line %d: Applying options for %.100s",
1772			    filename, linenum, arg2);
1773		break;
1774
1775	case oMatch:
1776		if (cmdline) {
1777			error("Host directive not supported as a command-line "
1778			    "option");
1779			goto out;
1780		}
1781		value = match_cfg_line(options, &str, pw, host, original_host,
1782		    flags & SSHCONF_FINAL, want_final_pass,
1783		    filename, linenum);
1784		if (value < 0) {
1785			error("%.200s line %d: Bad Match condition", filename,
1786			    linenum);
1787			goto out;
1788		}
1789		*activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value;
1790		/*
1791		 * If match_cfg_line() didn't consume all its arguments then
1792		 * arrange for the extra arguments check below to fail.
1793		 */
1794
1795		if (str == NULL || *str == '\0')
1796			argv_consume(&ac);
1797		break;
1798
1799	case oEscapeChar:
1800		intptr = &options->escape_char;
1801		arg = argv_next(&ac, &av);
1802		if (!arg || *arg == '\0') {
1803			error("%.200s line %d: Missing argument.",
1804			    filename, linenum);
1805			goto out;
1806		}
1807		if (strcmp(arg, "none") == 0)
1808			value = SSH_ESCAPECHAR_NONE;
1809		else if (arg[1] == '\0')
1810			value = (u_char) arg[0];
1811		else if (arg[0] == '^' && arg[2] == 0 &&
1812		    (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
1813			value = (u_char) arg[1] & 31;
1814		else {
1815			error("%.200s line %d: Bad escape character.",
1816			    filename, linenum);
1817			goto out;
1818		}
1819		if (*activep && *intptr == -1)
1820			*intptr = value;
1821		break;
1822
1823	case oAddressFamily:
1824		intptr = &options->address_family;
1825		multistate_ptr = multistate_addressfamily;
1826		goto parse_multistate;
1827
1828	case oEnableSSHKeysign:
1829		intptr = &options->enable_ssh_keysign;
1830		goto parse_flag;
1831
1832	case oIdentitiesOnly:
1833		intptr = &options->identities_only;
1834		goto parse_flag;
1835
1836	case oServerAliveInterval:
1837		intptr = &options->server_alive_interval;
1838		goto parse_time;
1839
1840	case oServerAliveCountMax:
1841		intptr = &options->server_alive_count_max;
1842		goto parse_int;
1843
1844	case oSendEnv:
1845		/* XXX appends to list; doesn't respect first-match-wins */
1846		while ((arg = argv_next(&ac, &av)) != NULL) {
1847			if (*arg == '\0' || strchr(arg, '=') != NULL) {
1848				error("%s line %d: Invalid environment name.",
1849				    filename, linenum);
1850				goto out;
1851			}
1852			found = 1;
1853			if (!*activep)
1854				continue;
1855			if (*arg == '-') {
1856				/* Removing an env var */
1857				rm_env(options, arg, filename, linenum);
1858				continue;
1859			}
1860			opt_array_append(filename, linenum,
1861			    lookup_opcode_name(opcode),
1862			    &options->send_env, &options->num_send_env, arg);
1863		}
1864		if (!found) {
1865			fatal("%s line %d: no %s specified",
1866			    filename, linenum, keyword);
1867		}
1868		break;
1869
1870	case oSetEnv:
1871		found = options->num_setenv == 0;
1872		while ((arg = argv_next(&ac, &av)) != NULL) {
1873			if (strchr(arg, '=') == NULL) {
1874				error("%s line %d: Invalid SetEnv.",
1875				    filename, linenum);
1876				goto out;
1877			}
1878			if (lookup_setenv_in_list(arg, strs, nstrs) != NULL) {
1879				debug2("%s line %d: ignoring duplicate env "
1880				    "name \"%.64s\"", filename, linenum, arg);
1881				continue;
1882			}
1883			opt_array_append(filename, linenum,
1884			    lookup_opcode_name(opcode),
1885			    &strs, &nstrs, arg);
1886		}
1887		if (nstrs == 0) {
1888			fatal("%s line %d: no %s specified",
1889			    filename, linenum, keyword);
1890		}
1891		if (found && *activep) {
1892			options->setenv = strs;
1893			options->num_setenv = nstrs;
1894			strs = NULL; /* transferred */
1895			nstrs = 0;
1896		}
1897		break;
1898
1899	case oControlPath:
1900		charptr = &options->control_path;
1901		goto parse_string;
1902
1903	case oControlMaster:
1904		intptr = &options->control_master;
1905		multistate_ptr = multistate_controlmaster;
1906		goto parse_multistate;
1907
1908	case oControlPersist:
1909		/* no/false/yes/true, or a time spec */
1910		intptr = &options->control_persist;
1911		arg = argv_next(&ac, &av);
1912		if (!arg || *arg == '\0') {
1913			error("%.200s line %d: Missing ControlPersist"
1914			    " argument.", filename, linenum);
1915			goto out;
1916		}
1917		value = 0;
1918		value2 = 0;	/* timeout */
1919		if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
1920			value = 0;
1921		else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
1922			value = 1;
1923		else if ((value2 = convtime(arg)) >= 0)
1924			value = 1;
1925		else {
1926			error("%.200s line %d: Bad ControlPersist argument.",
1927			    filename, linenum);
1928			goto out;
1929		}
1930		if (*activep && *intptr == -1) {
1931			*intptr = value;
1932			options->control_persist_timeout = value2;
1933		}
1934		break;
1935
1936	case oHashKnownHosts:
1937		intptr = &options->hash_known_hosts;
1938		goto parse_flag;
1939
1940	case oTunnel:
1941		intptr = &options->tun_open;
1942		multistate_ptr = multistate_tunnel;
1943		goto parse_multistate;
1944
1945	case oTunnelDevice:
1946		arg = argv_next(&ac, &av);
1947		if (!arg || *arg == '\0') {
1948			error("%.200s line %d: Missing argument.",
1949			    filename, linenum);
1950			goto out;
1951		}
1952		value = a2tun(arg, &value2);
1953		if (value == SSH_TUNID_ERR) {
1954			error("%.200s line %d: Bad tun device.",
1955			    filename, linenum);
1956			goto out;
1957		}
1958		if (*activep && options->tun_local == -1) {
1959			options->tun_local = value;
1960			options->tun_remote = value2;
1961		}
1962		break;
1963
1964	case oLocalCommand:
1965		charptr = &options->local_command;
1966		goto parse_command;
1967
1968	case oPermitLocalCommand:
1969		intptr = &options->permit_local_command;
1970		goto parse_flag;
1971
1972	case oRemoteCommand:
1973		charptr = &options->remote_command;
1974		goto parse_command;
1975
1976	case oVisualHostKey:
1977		intptr = &options->visual_host_key;
1978		goto parse_flag;
1979
1980	case oInclude:
1981		if (cmdline) {
1982			error("Include directive not supported as a "
1983			    "command-line option");
1984			goto out;
1985		}
1986		value = 0;
1987		while ((arg = argv_next(&ac, &av)) != NULL) {
1988			if (*arg == '\0') {
1989				error("%s line %d: keyword %s empty argument",
1990				    filename, linenum, keyword);
1991				goto out;
1992			}
1993			/*
1994			 * Ensure all paths are anchored. User configuration
1995			 * files may begin with '~/' but system configurations
1996			 * must not. If the path is relative, then treat it
1997			 * as living in ~/.ssh for user configurations or
1998			 * /etc/ssh for system ones.
1999			 */
2000			if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0) {
2001				error("%.200s line %d: bad include path %s.",
2002				    filename, linenum, arg);
2003				goto out;
2004			}
2005			if (!path_absolute(arg) && *arg != '~') {
2006				xasprintf(&arg2, "%s/%s",
2007				    (flags & SSHCONF_USERCONF) ?
2008				    "~/" _PATH_SSH_USER_DIR : SSHDIR, arg);
2009			} else
2010				arg2 = xstrdup(arg);
2011			memset(&gl, 0, sizeof(gl));
2012			r = glob(arg2, GLOB_TILDE, NULL, &gl);
2013			if (r == GLOB_NOMATCH) {
2014				debug("%.200s line %d: include %s matched no "
2015				    "files",filename, linenum, arg2);
2016				free(arg2);
2017				continue;
2018			} else if (r != 0) {
2019				error("%.200s line %d: glob failed for %s.",
2020				    filename, linenum, arg2);
2021				goto out;
2022			}
2023			free(arg2);
2024			oactive = *activep;
2025			for (i = 0; i < gl.gl_pathc; i++) {
2026				debug3("%.200s line %d: Including file %s "
2027				    "depth %d%s", filename, linenum,
2028				    gl.gl_pathv[i], depth,
2029				    oactive ? "" : " (parse only)");
2030				r = read_config_file_depth(gl.gl_pathv[i],
2031				    pw, host, original_host, options,
2032				    flags | SSHCONF_CHECKPERM |
2033				    (oactive ? 0 : SSHCONF_NEVERMATCH),
2034				    activep, want_final_pass, depth + 1);
2035				if (r != 1 && errno != ENOENT) {
2036					error("Can't open user config file "
2037					    "%.100s: %.100s", gl.gl_pathv[i],
2038					    strerror(errno));
2039					globfree(&gl);
2040					goto out;
2041				}
2042				/*
2043				 * don't let Match in includes clobber the
2044				 * containing file's Match state.
2045				 */
2046				*activep = oactive;
2047				if (r != 1)
2048					value = -1;
2049			}
2050			globfree(&gl);
2051		}
2052		if (value != 0)
2053			ret = value;
2054		break;
2055
2056	case oIPQoS:
2057		arg = argv_next(&ac, &av);
2058		if ((value = parse_ipqos(arg)) == -1) {
2059			error("%s line %d: Bad IPQoS value: %s",
2060			    filename, linenum, arg);
2061			goto out;
2062		}
2063		arg = argv_next(&ac, &av);
2064		if (arg == NULL)
2065			value2 = value;
2066		else if ((value2 = parse_ipqos(arg)) == -1) {
2067			error("%s line %d: Bad IPQoS value: %s",
2068			    filename, linenum, arg);
2069			goto out;
2070		}
2071		if (*activep && options->ip_qos_interactive == -1) {
2072			options->ip_qos_interactive = value;
2073			options->ip_qos_bulk = value2;
2074		}
2075		break;
2076
2077	case oRequestTTY:
2078		intptr = &options->request_tty;
2079		multistate_ptr = multistate_requesttty;
2080		goto parse_multistate;
2081
2082	case oSessionType:
2083		intptr = &options->session_type;
2084		multistate_ptr = multistate_sessiontype;
2085		goto parse_multistate;
2086
2087	case oStdinNull:
2088		intptr = &options->stdin_null;
2089		goto parse_flag;
2090
2091	case oForkAfterAuthentication:
2092		intptr = &options->fork_after_authentication;
2093		goto parse_flag;
2094
2095	case oIgnoreUnknown:
2096		charptr = &options->ignored_unknown;
2097		goto parse_string;
2098
2099	case oProxyUseFdpass:
2100		intptr = &options->proxy_use_fdpass;
2101		goto parse_flag;
2102
2103	case oCanonicalDomains:
2104		found = options->num_canonical_domains == 0;
2105		while ((arg = argv_next(&ac, &av)) != NULL) {
2106			/* Allow "none" only in first position */
2107			if (strcasecmp(arg, "none") == 0) {
2108				if (nstrs > 0 || ac > 0) {
2109					error("%s line %d: keyword %s \"none\" "
2110					    "argument must appear alone.",
2111					    filename, linenum, keyword);
2112					goto out;
2113				}
2114			}
2115			if (!valid_domain(arg, 1, &errstr)) {
2116				error("%s line %d: %s", filename, linenum,
2117				    errstr);
2118				goto out;
2119			}
2120			opt_array_append(filename, linenum, keyword,
2121			    &strs, &nstrs, arg);
2122		}
2123		if (nstrs == 0) {
2124			fatal("%s line %d: no %s specified",
2125			    filename, linenum, keyword);
2126		}
2127		if (found && *activep) {
2128			options->canonical_domains = strs;
2129			options->num_canonical_domains = nstrs;
2130			strs = NULL; /* transferred */
2131			nstrs = 0;
2132		}
2133		break;
2134
2135	case oCanonicalizePermittedCNAMEs:
2136		found = options->num_permitted_cnames == 0;
2137		while ((arg = argv_next(&ac, &av)) != NULL) {
2138			/*
2139			 * Either 'none' (only in first position), '*' for
2140			 * everything or 'list:list'
2141			 */
2142			if (strcasecmp(arg, "none") == 0) {
2143				if (ncnames > 0 || ac > 0) {
2144					error("%s line %d: keyword %s \"none\" "
2145					    "argument must appear alone.",
2146					    filename, linenum, keyword);
2147					goto out;
2148				}
2149				arg2 = "";
2150			} else if (strcmp(arg, "*") == 0) {
2151				arg2 = arg;
2152			} else {
2153				lowercase(arg);
2154				if ((arg2 = strchr(arg, ':')) == NULL ||
2155				    arg2[1] == '\0') {
2156					error("%s line %d: "
2157					    "Invalid permitted CNAME \"%s\"",
2158					    filename, linenum, arg);
2159					goto out;
2160				}
2161				*arg2 = '\0';
2162				arg2++;
2163			}
2164			cnames = xrecallocarray(cnames, ncnames, ncnames + 1,
2165			    sizeof(*cnames));
2166			cnames[ncnames].source_list = xstrdup(arg);
2167			cnames[ncnames].target_list = xstrdup(arg2);
2168			ncnames++;
2169		}
2170		if (ncnames == 0) {
2171			fatal("%s line %d: no %s specified",
2172			    filename, linenum, keyword);
2173		}
2174		if (found && *activep) {
2175			options->permitted_cnames = cnames;
2176			options->num_permitted_cnames = ncnames;
2177			cnames = NULL; /* transferred */
2178			ncnames = 0;
2179		}
2180		/* un-transferred cnames is cleaned up before exit */
2181		break;
2182
2183	case oCanonicalizeHostname:
2184		intptr = &options->canonicalize_hostname;
2185		multistate_ptr = multistate_canonicalizehostname;
2186		goto parse_multistate;
2187
2188	case oCanonicalizeMaxDots:
2189		intptr = &options->canonicalize_max_dots;
2190		goto parse_int;
2191
2192	case oCanonicalizeFallbackLocal:
2193		intptr = &options->canonicalize_fallback_local;
2194		goto parse_flag;
2195
2196	case oStreamLocalBindMask:
2197		arg = argv_next(&ac, &av);
2198		if (!arg || *arg == '\0') {
2199			error("%.200s line %d: Missing StreamLocalBindMask "
2200			    "argument.", filename, linenum);
2201			goto out;
2202		}
2203		/* Parse mode in octal format */
2204		value = strtol(arg, &endofnumber, 8);
2205		if (arg == endofnumber || value < 0 || value > 0777) {
2206			error("%.200s line %d: Bad mask.", filename, linenum);
2207			goto out;
2208		}
2209		options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
2210		break;
2211
2212	case oStreamLocalBindUnlink:
2213		intptr = &options->fwd_opts.streamlocal_bind_unlink;
2214		goto parse_flag;
2215
2216	case oRevokedHostKeys:
2217		charptr = &options->revoked_host_keys;
2218		goto parse_string;
2219
2220	case oFingerprintHash:
2221		intptr = &options->fingerprint_hash;
2222		arg = argv_next(&ac, &av);
2223		if (!arg || *arg == '\0') {
2224			error("%.200s line %d: Missing argument.",
2225			    filename, linenum);
2226			goto out;
2227		}
2228		if ((value = ssh_digest_alg_by_name(arg)) == -1) {
2229			error("%.200s line %d: Invalid hash algorithm \"%s\".",
2230			    filename, linenum, arg);
2231			goto out;
2232		}
2233		if (*activep && *intptr == -1)
2234			*intptr = value;
2235		break;
2236
2237	case oUpdateHostkeys:
2238		intptr = &options->update_hostkeys;
2239		multistate_ptr = multistate_yesnoask;
2240		goto parse_multistate;
2241
2242	case oHostbasedAcceptedAlgorithms:
2243		charptr = &options->hostbased_accepted_algos;
2244		ca_only = 0;
2245		goto parse_pubkey_algos;
2246
2247	case oPubkeyAcceptedAlgorithms:
2248		charptr = &options->pubkey_accepted_algos;
2249		ca_only = 0;
2250		goto parse_pubkey_algos;
2251
2252	case oAddKeysToAgent:
2253		arg = argv_next(&ac, &av);
2254		arg2 = argv_next(&ac, &av);
2255		value = parse_multistate_value(arg, filename, linenum,
2256		    multistate_yesnoaskconfirm);
2257		value2 = 0; /* unlimited lifespan by default */
2258		if (value == 3 && arg2 != NULL) {
2259			/* allow "AddKeysToAgent confirm 5m" */
2260			if ((value2 = convtime(arg2)) == -1) {
2261				error("%s line %d: invalid time value.",
2262				    filename, linenum);
2263				goto out;
2264			}
2265		} else if (value == -1 && arg2 == NULL) {
2266			if ((value2 = convtime(arg)) == -1) {
2267				error("%s line %d: unsupported option",
2268				    filename, linenum);
2269				goto out;
2270			}
2271			value = 1; /* yes */
2272		} else if (value == -1 || arg2 != NULL) {
2273			error("%s line %d: unsupported option",
2274			    filename, linenum);
2275			goto out;
2276		}
2277		if (*activep && options->add_keys_to_agent == -1) {
2278			options->add_keys_to_agent = value;
2279			options->add_keys_to_agent_lifespan = value2;
2280		}
2281		break;
2282
2283	case oIdentityAgent:
2284		charptr = &options->identity_agent;
2285		arg = argv_next(&ac, &av);
2286		if (!arg || *arg == '\0') {
2287			error("%.200s line %d: Missing argument.",
2288			    filename, linenum);
2289			goto out;
2290		}
2291  parse_agent_path:
2292		/* Extra validation if the string represents an env var. */
2293		if ((arg2 = dollar_expand(&r, arg)) == NULL || r) {
2294			error("%.200s line %d: Invalid environment expansion "
2295			    "%s.", filename, linenum, arg);
2296			goto out;
2297		}
2298		free(arg2);
2299		/* check for legacy environment format */
2300		if (arg[0] == '$' && arg[1] != '{' &&
2301		    !valid_env_name(arg + 1)) {
2302			error("%.200s line %d: Invalid environment name %s.",
2303			    filename, linenum, arg);
2304			goto out;
2305		}
2306		if (*activep && *charptr == NULL)
2307			*charptr = xstrdup(arg);
2308		break;
2309
2310	case oEnableEscapeCommandline:
2311		intptr = &options->enable_escape_commandline;
2312		goto parse_flag;
2313
2314	case oRequiredRSASize:
2315		intptr = &options->required_rsa_size;
2316		goto parse_int;
2317
2318	case oObscureKeystrokeTiming:
2319		value = -1;
2320		while ((arg = argv_next(&ac, &av)) != NULL) {
2321			if (value != -1) {
2322				error("%s line %d: invalid arguments",
2323				    filename, linenum);
2324				goto out;
2325			}
2326			if (strcmp(arg, "yes") == 0 ||
2327			    strcmp(arg, "true") == 0)
2328				value = SSH_KEYSTROKE_DEFAULT_INTERVAL_MS;
2329			else if (strcmp(arg, "no") == 0 ||
2330			    strcmp(arg, "false") == 0)
2331				value = 0;
2332			else if (strncmp(arg, "interval:", 9) == 0) {
2333				if ((errstr = atoi_err(arg + 9,
2334				    &value)) != NULL) {
2335					error("%s line %d: integer value %s.",
2336					    filename, linenum, errstr);
2337					goto out;
2338				}
2339				if (value <= 0 || value > 1000) {
2340					error("%s line %d: value out of range.",
2341					    filename, linenum);
2342					goto out;
2343				}
2344			} else {
2345				error("%s line %d: unsupported argument \"%s\"",
2346				    filename, linenum, arg);
2347				goto out;
2348			}
2349		}
2350		if (value == -1) {
2351			error("%s line %d: missing argument",
2352			    filename, linenum);
2353			goto out;
2354		}
2355		intptr = &options->obscure_keystroke_timing_interval;
2356		if (*activep && *intptr == -1)
2357			*intptr = value;
2358		break;
2359
2360	case oChannelTimeout:
2361		found = options->num_channel_timeouts == 0;
2362		while ((arg = argv_next(&ac, &av)) != NULL) {
2363			/* Allow "none" only in first position */
2364			if (strcasecmp(arg, "none") == 0) {
2365				if (nstrs > 0 || ac > 0) {
2366					error("%s line %d: keyword %s \"none\" "
2367					    "argument must appear alone.",
2368					    filename, linenum, keyword);
2369					goto out;
2370				}
2371			} else if (parse_pattern_interval(arg,
2372			    NULL, NULL) != 0) {
2373				fatal("%s line %d: invalid channel timeout %s",
2374				    filename, linenum, arg);
2375			}
2376			opt_array_append(filename, linenum, keyword,
2377			    &strs, &nstrs, arg);
2378		}
2379		if (nstrs == 0) {
2380			fatal("%s line %d: no %s specified",
2381			    filename, linenum, keyword);
2382		}
2383		if (found && *activep) {
2384			options->channel_timeouts = strs;
2385			options->num_channel_timeouts = nstrs;
2386			strs = NULL; /* transferred */
2387			nstrs = 0;
2388		}
2389		break;
2390
2391	case oDeprecated:
2392		debug("%s line %d: Deprecated option \"%s\"",
2393		    filename, linenum, keyword);
2394		argv_consume(&ac);
2395		break;
2396
2397	case oUnsupported:
2398		error("%s line %d: Unsupported option \"%s\"",
2399		    filename, linenum, keyword);
2400		argv_consume(&ac);
2401		break;
2402
2403	default:
2404		error("%s line %d: Unimplemented opcode %d",
2405		    filename, linenum, opcode);
2406		goto out;
2407	}
2408
2409	/* Check that there is no garbage at end of line. */
2410	if (ac > 0) {
2411		error("%.200s line %d: keyword %s extra arguments "
2412		    "at end of line", filename, linenum, keyword);
2413		goto out;
2414	}
2415
2416	/* success */
2417	ret = 0;
2418 out:
2419	free_canon_cnames(cnames, ncnames);
2420	opt_array_free2(strs, NULL, nstrs);
2421	argv_free(oav, oac);
2422	return ret;
2423}
2424
2425/*
2426 * Reads the config file and modifies the options accordingly.  Options
2427 * should already be initialized before this call.  This never returns if
2428 * there is an error.  If the file does not exist, this returns 0.
2429 */
2430int
2431read_config_file(const char *filename, struct passwd *pw, const char *host,
2432    const char *original_host, Options *options, int flags,
2433    int *want_final_pass)
2434{
2435	int active = 1;
2436
2437	return read_config_file_depth(filename, pw, host, original_host,
2438	    options, flags, &active, want_final_pass, 0);
2439}
2440
2441#define READCONF_MAX_DEPTH	16
2442static int
2443read_config_file_depth(const char *filename, struct passwd *pw,
2444    const char *host, const char *original_host, Options *options,
2445    int flags, int *activep, int *want_final_pass, int depth)
2446{
2447	FILE *f;
2448	char *line = NULL;
2449	size_t linesize = 0;
2450	int linenum;
2451	int bad_options = 0;
2452
2453	if (depth < 0 || depth > READCONF_MAX_DEPTH)
2454		fatal("Too many recursive configuration includes");
2455
2456	if ((f = fopen(filename, "r")) == NULL)
2457		return 0;
2458
2459	if (flags & SSHCONF_CHECKPERM) {
2460		struct stat sb;
2461
2462		if (fstat(fileno(f), &sb) == -1)
2463			fatal("fstat %s: %s", filename, strerror(errno));
2464		if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
2465		    (sb.st_mode & 022) != 0))
2466			fatal("Bad owner or permissions on %s", filename);
2467	}
2468
2469	debug("Reading configuration data %.200s", filename);
2470
2471	/*
2472	 * Mark that we are now processing the options.  This flag is turned
2473	 * on/off by Host specifications.
2474	 */
2475	linenum = 0;
2476	while (getline(&line, &linesize, f) != -1) {
2477		/* Update line number counter. */
2478		linenum++;
2479		/*
2480		 * Trim out comments and strip whitespace.
2481		 * NB - preserve newlines, they are needed to reproduce
2482		 * line numbers later for error messages.
2483		 */
2484		if (process_config_line_depth(options, pw, host, original_host,
2485		    line, filename, linenum, activep, flags, want_final_pass,
2486		    depth) != 0)
2487			bad_options++;
2488	}
2489	free(line);
2490	fclose(f);
2491	if (bad_options > 0)
2492		fatal("%s: terminating, %d bad configuration options",
2493		    filename, bad_options);
2494	return 1;
2495}
2496
2497/* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
2498int
2499option_clear_or_none(const char *o)
2500{
2501	return o == NULL || strcasecmp(o, "none") == 0;
2502}
2503
2504/*
2505 * Returns 1 if CanonicalizePermittedCNAMEs have been specified, 0 otherwise.
2506 * Allowed to be called on non-final configuration.
2507 */
2508int
2509config_has_permitted_cnames(Options *options)
2510{
2511	if (options->num_permitted_cnames == 1 &&
2512	    strcasecmp(options->permitted_cnames[0].source_list, "none") == 0 &&
2513	    strcmp(options->permitted_cnames[0].target_list, "") == 0)
2514		return 0;
2515	return options->num_permitted_cnames > 0;
2516}
2517
2518/*
2519 * Initializes options to special values that indicate that they have not yet
2520 * been set.  Read_config_file will only set options with this value. Options
2521 * are processed in the following order: command line, user config file,
2522 * system config file.  Last, fill_default_options is called.
2523 */
2524
2525void
2526initialize_options(Options * options)
2527{
2528	memset(options, 'X', sizeof(*options));
2529	options->host_arg = NULL;
2530	options->forward_agent = -1;
2531	options->forward_agent_sock_path = NULL;
2532	options->forward_x11 = -1;
2533	options->forward_x11_trusted = -1;
2534	options->forward_x11_timeout = -1;
2535	options->stdio_forward_host = NULL;
2536	options->stdio_forward_port = 0;
2537	options->clear_forwardings = -1;
2538	options->exit_on_forward_failure = -1;
2539	options->xauth_location = NULL;
2540	options->fwd_opts.gateway_ports = -1;
2541	options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
2542	options->fwd_opts.streamlocal_bind_unlink = -1;
2543	options->pubkey_authentication = -1;
2544	options->gss_authentication = -1;
2545	options->gss_deleg_creds = -1;
2546	options->password_authentication = -1;
2547	options->kbd_interactive_authentication = -1;
2548	options->kbd_interactive_devices = NULL;
2549	options->hostbased_authentication = -1;
2550	options->batch_mode = -1;
2551	options->check_host_ip = -1;
2552	options->strict_host_key_checking = -1;
2553	options->compression = -1;
2554	options->tcp_keep_alive = -1;
2555	options->port = -1;
2556	options->address_family = -1;
2557	options->connection_attempts = -1;
2558	options->connection_timeout = -1;
2559	options->number_of_password_prompts = -1;
2560	options->ciphers = NULL;
2561	options->macs = NULL;
2562	options->kex_algorithms = NULL;
2563	options->hostkeyalgorithms = NULL;
2564	options->ca_sign_algorithms = NULL;
2565	options->num_identity_files = 0;
2566	memset(options->identity_keys, 0, sizeof(options->identity_keys));
2567	options->num_certificate_files = 0;
2568	memset(options->certificates, 0, sizeof(options->certificates));
2569	options->hostname = NULL;
2570	options->host_key_alias = NULL;
2571	options->proxy_command = NULL;
2572	options->jump_user = NULL;
2573	options->jump_host = NULL;
2574	options->jump_port = -1;
2575	options->jump_extra = NULL;
2576	options->user = NULL;
2577	options->escape_char = -1;
2578	options->num_system_hostfiles = 0;
2579	options->num_user_hostfiles = 0;
2580	options->local_forwards = NULL;
2581	options->num_local_forwards = 0;
2582	options->remote_forwards = NULL;
2583	options->num_remote_forwards = 0;
2584	options->permitted_remote_opens = NULL;
2585	options->num_permitted_remote_opens = 0;
2586	options->log_facility = SYSLOG_FACILITY_NOT_SET;
2587	options->log_level = SYSLOG_LEVEL_NOT_SET;
2588	options->num_log_verbose = 0;
2589	options->log_verbose = NULL;
2590	options->preferred_authentications = NULL;
2591	options->bind_address = NULL;
2592	options->bind_interface = NULL;
2593	options->pkcs11_provider = NULL;
2594	options->sk_provider = NULL;
2595	options->enable_ssh_keysign = - 1;
2596	options->no_host_authentication_for_localhost = - 1;
2597	options->identities_only = - 1;
2598	options->rekey_limit = - 1;
2599	options->rekey_interval = -1;
2600	options->verify_host_key_dns = -1;
2601	options->server_alive_interval = -1;
2602	options->server_alive_count_max = -1;
2603	options->send_env = NULL;
2604	options->num_send_env = 0;
2605	options->setenv = NULL;
2606	options->num_setenv = 0;
2607	options->control_path = NULL;
2608	options->control_master = -1;
2609	options->control_persist = -1;
2610	options->control_persist_timeout = 0;
2611	options->hash_known_hosts = -1;
2612	options->tun_open = -1;
2613	options->tun_local = -1;
2614	options->tun_remote = -1;
2615	options->local_command = NULL;
2616	options->permit_local_command = -1;
2617	options->remote_command = NULL;
2618	options->add_keys_to_agent = -1;
2619	options->add_keys_to_agent_lifespan = -1;
2620	options->identity_agent = NULL;
2621	options->visual_host_key = -1;
2622	options->ip_qos_interactive = -1;
2623	options->ip_qos_bulk = -1;
2624	options->request_tty = -1;
2625	options->session_type = -1;
2626	options->stdin_null = -1;
2627	options->fork_after_authentication = -1;
2628	options->proxy_use_fdpass = -1;
2629	options->ignored_unknown = NULL;
2630	options->num_canonical_domains = 0;
2631	options->num_permitted_cnames = 0;
2632	options->canonicalize_max_dots = -1;
2633	options->canonicalize_fallback_local = -1;
2634	options->canonicalize_hostname = -1;
2635	options->revoked_host_keys = NULL;
2636	options->fingerprint_hash = -1;
2637	options->update_hostkeys = -1;
2638	options->hostbased_accepted_algos = NULL;
2639	options->pubkey_accepted_algos = NULL;
2640	options->known_hosts_command = NULL;
2641	options->required_rsa_size = -1;
2642	options->enable_escape_commandline = -1;
2643	options->obscure_keystroke_timing_interval = -1;
2644	options->tag = NULL;
2645	options->channel_timeouts = NULL;
2646	options->num_channel_timeouts = 0;
2647}
2648
2649/*
2650 * A petite version of fill_default_options() that just fills the options
2651 * needed for hostname canonicalization to proceed.
2652 */
2653void
2654fill_default_options_for_canonicalization(Options *options)
2655{
2656	if (options->canonicalize_max_dots == -1)
2657		options->canonicalize_max_dots = 1;
2658	if (options->canonicalize_fallback_local == -1)
2659		options->canonicalize_fallback_local = 1;
2660	if (options->canonicalize_hostname == -1)
2661		options->canonicalize_hostname = SSH_CANONICALISE_NO;
2662}
2663
2664/*
2665 * Called after processing other sources of option data, this fills those
2666 * options for which no value has been specified with their default values.
2667 */
2668int
2669fill_default_options(Options * options)
2670{
2671	char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig;
2672	char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig;
2673	int ret = 0, r;
2674
2675	if (options->forward_agent == -1)
2676		options->forward_agent = 0;
2677	if (options->forward_x11 == -1)
2678		options->forward_x11 = 0;
2679	if (options->forward_x11_trusted == -1)
2680		options->forward_x11_trusted = 0;
2681	if (options->forward_x11_timeout == -1)
2682		options->forward_x11_timeout = 1200;
2683	/*
2684	 * stdio forwarding (-W) changes the default for these but we defer
2685	 * setting the values so they can be overridden.
2686	 */
2687	if (options->exit_on_forward_failure == -1)
2688		options->exit_on_forward_failure =
2689		    options->stdio_forward_host != NULL ? 1 : 0;
2690	if (options->clear_forwardings == -1)
2691		options->clear_forwardings =
2692		    options->stdio_forward_host != NULL ? 1 : 0;
2693	if (options->clear_forwardings == 1)
2694		clear_forwardings(options);
2695
2696	if (options->xauth_location == NULL)
2697		options->xauth_location = xstrdup(_PATH_XAUTH);
2698	if (options->fwd_opts.gateway_ports == -1)
2699		options->fwd_opts.gateway_ports = 0;
2700	if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
2701		options->fwd_opts.streamlocal_bind_mask = 0177;
2702	if (options->fwd_opts.streamlocal_bind_unlink == -1)
2703		options->fwd_opts.streamlocal_bind_unlink = 0;
2704	if (options->pubkey_authentication == -1)
2705		options->pubkey_authentication = SSH_PUBKEY_AUTH_ALL;
2706	if (options->gss_authentication == -1)
2707		options->gss_authentication = 0;
2708	if (options->gss_deleg_creds == -1)
2709		options->gss_deleg_creds = 0;
2710	if (options->password_authentication == -1)
2711		options->password_authentication = 1;
2712	if (options->kbd_interactive_authentication == -1)
2713		options->kbd_interactive_authentication = 1;
2714	if (options->hostbased_authentication == -1)
2715		options->hostbased_authentication = 0;
2716	if (options->batch_mode == -1)
2717		options->batch_mode = 0;
2718	if (options->check_host_ip == -1)
2719		options->check_host_ip = 0;
2720	if (options->strict_host_key_checking == -1)
2721		options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK;
2722	if (options->compression == -1)
2723		options->compression = 0;
2724	if (options->tcp_keep_alive == -1)
2725		options->tcp_keep_alive = 1;
2726	if (options->port == -1)
2727		options->port = 0;	/* Filled in ssh_connect. */
2728	if (options->address_family == -1)
2729		options->address_family = AF_UNSPEC;
2730	if (options->connection_attempts == -1)
2731		options->connection_attempts = 1;
2732	if (options->number_of_password_prompts == -1)
2733		options->number_of_password_prompts = 3;
2734	/* options->hostkeyalgorithms, default set in myproposals.h */
2735	if (options->add_keys_to_agent == -1) {
2736		options->add_keys_to_agent = 0;
2737		options->add_keys_to_agent_lifespan = 0;
2738	}
2739	if (options->num_identity_files == 0) {
2740		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0);
2741#ifdef OPENSSL_HAS_ECC
2742		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0);
2743		add_identity_file(options, "~/",
2744		    _PATH_SSH_CLIENT_ID_ECDSA_SK, 0);
2745#endif
2746		add_identity_file(options, "~/",
2747		    _PATH_SSH_CLIENT_ID_ED25519, 0);
2748		add_identity_file(options, "~/",
2749		    _PATH_SSH_CLIENT_ID_ED25519_SK, 0);
2750		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0);
2751#ifdef WITH_DSA
2752		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0);
2753#endif
2754	}
2755	if (options->escape_char == -1)
2756		options->escape_char = '~';
2757	if (options->num_system_hostfiles == 0) {
2758		options->system_hostfiles[options->num_system_hostfiles++] =
2759		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
2760		options->system_hostfiles[options->num_system_hostfiles++] =
2761		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
2762	}
2763	if (options->update_hostkeys == -1) {
2764		if (options->verify_host_key_dns <= 0 &&
2765		    (options->num_user_hostfiles == 0 ||
2766		    (options->num_user_hostfiles == 1 && strcmp(options->
2767		    user_hostfiles[0], _PATH_SSH_USER_HOSTFILE) == 0)))
2768			options->update_hostkeys = SSH_UPDATE_HOSTKEYS_YES;
2769		else
2770			options->update_hostkeys = SSH_UPDATE_HOSTKEYS_NO;
2771	}
2772	if (options->num_user_hostfiles == 0) {
2773		options->user_hostfiles[options->num_user_hostfiles++] =
2774		    xstrdup(_PATH_SSH_USER_HOSTFILE);
2775		options->user_hostfiles[options->num_user_hostfiles++] =
2776		    xstrdup(_PATH_SSH_USER_HOSTFILE2);
2777	}
2778	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
2779		options->log_level = SYSLOG_LEVEL_INFO;
2780	if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
2781		options->log_facility = SYSLOG_FACILITY_USER;
2782	if (options->no_host_authentication_for_localhost == - 1)
2783		options->no_host_authentication_for_localhost = 0;
2784	if (options->identities_only == -1)
2785		options->identities_only = 0;
2786	if (options->enable_ssh_keysign == -1)
2787		options->enable_ssh_keysign = 0;
2788	if (options->rekey_limit == -1)
2789		options->rekey_limit = 0;
2790	if (options->rekey_interval == -1)
2791		options->rekey_interval = 0;
2792	if (options->verify_host_key_dns == -1)
2793		options->verify_host_key_dns = 0;
2794	if (options->server_alive_interval == -1)
2795		options->server_alive_interval = 0;
2796	if (options->server_alive_count_max == -1)
2797		options->server_alive_count_max = 3;
2798	if (options->control_master == -1)
2799		options->control_master = 0;
2800	if (options->control_persist == -1) {
2801		options->control_persist = 0;
2802		options->control_persist_timeout = 0;
2803	}
2804	if (options->hash_known_hosts == -1)
2805		options->hash_known_hosts = 0;
2806	if (options->tun_open == -1)
2807		options->tun_open = SSH_TUNMODE_NO;
2808	if (options->tun_local == -1)
2809		options->tun_local = SSH_TUNID_ANY;
2810	if (options->tun_remote == -1)
2811		options->tun_remote = SSH_TUNID_ANY;
2812	if (options->permit_local_command == -1)
2813		options->permit_local_command = 0;
2814	if (options->visual_host_key == -1)
2815		options->visual_host_key = 0;
2816	if (options->ip_qos_interactive == -1)
2817		options->ip_qos_interactive = IPTOS_DSCP_AF21;
2818	if (options->ip_qos_bulk == -1)
2819		options->ip_qos_bulk = IPTOS_DSCP_CS1;
2820	if (options->request_tty == -1)
2821		options->request_tty = REQUEST_TTY_AUTO;
2822	if (options->session_type == -1)
2823		options->session_type = SESSION_TYPE_DEFAULT;
2824	if (options->stdin_null == -1)
2825		options->stdin_null = 0;
2826	if (options->fork_after_authentication == -1)
2827		options->fork_after_authentication = 0;
2828	if (options->proxy_use_fdpass == -1)
2829		options->proxy_use_fdpass = 0;
2830	if (options->canonicalize_max_dots == -1)
2831		options->canonicalize_max_dots = 1;
2832	if (options->canonicalize_fallback_local == -1)
2833		options->canonicalize_fallback_local = 1;
2834	if (options->canonicalize_hostname == -1)
2835		options->canonicalize_hostname = SSH_CANONICALISE_NO;
2836	if (options->fingerprint_hash == -1)
2837		options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
2838#ifdef ENABLE_SK_INTERNAL
2839	if (options->sk_provider == NULL)
2840		options->sk_provider = xstrdup("internal");
2841#else
2842	if (options->sk_provider == NULL)
2843		options->sk_provider = xstrdup("$SSH_SK_PROVIDER");
2844#endif
2845	if (options->required_rsa_size == -1)
2846		options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
2847	if (options->enable_escape_commandline == -1)
2848		options->enable_escape_commandline = 0;
2849	if (options->obscure_keystroke_timing_interval == -1) {
2850		options->obscure_keystroke_timing_interval =
2851		    SSH_KEYSTROKE_DEFAULT_INTERVAL_MS;
2852	}
2853
2854	/* Expand KEX name lists */
2855	all_cipher = cipher_alg_list(',', 0);
2856	all_mac = mac_alg_list(',');
2857	all_kex = kex_alg_list(',');
2858	all_key = sshkey_alg_list(0, 0, 1, ',');
2859	all_sig = sshkey_alg_list(0, 1, 1, ',');
2860	/* remove unsupported algos from default lists */
2861	def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher);
2862	def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac);
2863	def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex);
2864	def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
2865	def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig);
2866#define ASSEMBLE(what, defaults, all) \
2867	do { \
2868		if ((r = kex_assemble_names(&options->what, \
2869		    defaults, all)) != 0) { \
2870			error_fr(r, "%s", #what); \
2871			goto fail; \
2872		} \
2873	} while (0)
2874	ASSEMBLE(ciphers, def_cipher, all_cipher);
2875	ASSEMBLE(macs, def_mac, all_mac);
2876	ASSEMBLE(kex_algorithms, def_kex, all_kex);
2877	ASSEMBLE(hostbased_accepted_algos, def_key, all_key);
2878	ASSEMBLE(pubkey_accepted_algos, def_key, all_key);
2879	ASSEMBLE(ca_sign_algorithms, def_sig, all_sig);
2880#undef ASSEMBLE
2881
2882#define CLEAR_ON_NONE(v) \
2883	do { \
2884		if (option_clear_or_none(v)) { \
2885			free(v); \
2886			v = NULL; \
2887		} \
2888	} while(0)
2889#define CLEAR_ON_NONE_ARRAY(v, nv, none) \
2890	do { \
2891		if (options->nv == 1 && \
2892		    strcasecmp(options->v[0], none) == 0) { \
2893			free(options->v[0]); \
2894			free(options->v); \
2895			options->v = NULL; \
2896			options->nv = 0; \
2897		} \
2898	} while (0)
2899	CLEAR_ON_NONE(options->local_command);
2900	CLEAR_ON_NONE(options->remote_command);
2901	CLEAR_ON_NONE(options->proxy_command);
2902	CLEAR_ON_NONE(options->control_path);
2903	CLEAR_ON_NONE(options->revoked_host_keys);
2904	CLEAR_ON_NONE(options->pkcs11_provider);
2905	CLEAR_ON_NONE(options->sk_provider);
2906	CLEAR_ON_NONE(options->known_hosts_command);
2907	CLEAR_ON_NONE_ARRAY(channel_timeouts, num_channel_timeouts, "none");
2908#undef CLEAR_ON_NONE
2909#undef CLEAR_ON_NONE_ARRAY
2910	if (options->jump_host != NULL &&
2911	    strcmp(options->jump_host, "none") == 0 &&
2912	    options->jump_port == 0 && options->jump_user == NULL) {
2913		free(options->jump_host);
2914		options->jump_host = NULL;
2915	}
2916	if (options->num_permitted_cnames == 1 &&
2917	    !config_has_permitted_cnames(options)) {
2918		/* clean up CanonicalizePermittedCNAMEs=none */
2919		free(options->permitted_cnames[0].source_list);
2920		free(options->permitted_cnames[0].target_list);
2921		memset(options->permitted_cnames, '\0',
2922		    sizeof(*options->permitted_cnames));
2923		options->num_permitted_cnames = 0;
2924	}
2925	/* options->identity_agent distinguishes NULL from 'none' */
2926	/* options->user will be set in the main program if appropriate */
2927	/* options->hostname will be set in the main program if appropriate */
2928	/* options->host_key_alias should not be set by default */
2929	/* options->preferred_authentications will be set in ssh */
2930
2931	/* success */
2932	ret = 0;
2933 fail:
2934	free(all_cipher);
2935	free(all_mac);
2936	free(all_kex);
2937	free(all_key);
2938	free(all_sig);
2939	free(def_cipher);
2940	free(def_mac);
2941	free(def_kex);
2942	free(def_key);
2943	free(def_sig);
2944	return ret;
2945}
2946
2947void
2948free_options(Options *o)
2949{
2950	int i;
2951
2952	if (o == NULL)
2953		return;
2954
2955#define FREE_ARRAY(type, n, a) \
2956	do { \
2957		type _i; \
2958		for (_i = 0; _i < (n); _i++) \
2959			free((a)[_i]); \
2960	} while (0)
2961
2962	free(o->forward_agent_sock_path);
2963	free(o->xauth_location);
2964	FREE_ARRAY(u_int, o->num_log_verbose, o->log_verbose);
2965	free(o->log_verbose);
2966	free(o->ciphers);
2967	free(o->macs);
2968	free(o->hostkeyalgorithms);
2969	free(o->kex_algorithms);
2970	free(o->ca_sign_algorithms);
2971	free(o->hostname);
2972	free(o->host_key_alias);
2973	free(o->proxy_command);
2974	free(o->user);
2975	FREE_ARRAY(u_int, o->num_system_hostfiles, o->system_hostfiles);
2976	FREE_ARRAY(u_int, o->num_user_hostfiles, o->user_hostfiles);
2977	free(o->preferred_authentications);
2978	free(o->bind_address);
2979	free(o->bind_interface);
2980	free(o->pkcs11_provider);
2981	free(o->sk_provider);
2982	for (i = 0; i < o->num_identity_files; i++) {
2983		free(o->identity_files[i]);
2984		sshkey_free(o->identity_keys[i]);
2985	}
2986	for (i = 0; i < o->num_certificate_files; i++) {
2987		free(o->certificate_files[i]);
2988		sshkey_free(o->certificates[i]);
2989	}
2990	free(o->identity_agent);
2991	for (i = 0; i < o->num_local_forwards; i++) {
2992		free(o->local_forwards[i].listen_host);
2993		free(o->local_forwards[i].listen_path);
2994		free(o->local_forwards[i].connect_host);
2995		free(o->local_forwards[i].connect_path);
2996	}
2997	free(o->local_forwards);
2998	for (i = 0; i < o->num_remote_forwards; i++) {
2999		free(o->remote_forwards[i].listen_host);
3000		free(o->remote_forwards[i].listen_path);
3001		free(o->remote_forwards[i].connect_host);
3002		free(o->remote_forwards[i].connect_path);
3003	}
3004	free(o->remote_forwards);
3005	free(o->stdio_forward_host);
3006	FREE_ARRAY(u_int, o->num_send_env, o->send_env);
3007	free(o->send_env);
3008	FREE_ARRAY(u_int, o->num_setenv, o->setenv);
3009	free(o->setenv);
3010	free(o->control_path);
3011	free(o->local_command);
3012	free(o->remote_command);
3013	FREE_ARRAY(int, o->num_canonical_domains, o->canonical_domains);
3014	for (i = 0; i < o->num_permitted_cnames; i++) {
3015		free(o->permitted_cnames[i].source_list);
3016		free(o->permitted_cnames[i].target_list);
3017	}
3018	free(o->revoked_host_keys);
3019	free(o->hostbased_accepted_algos);
3020	free(o->pubkey_accepted_algos);
3021	free(o->jump_user);
3022	free(o->jump_host);
3023	free(o->jump_extra);
3024	free(o->ignored_unknown);
3025	explicit_bzero(o, sizeof(*o));
3026#undef FREE_ARRAY
3027}
3028
3029struct fwdarg {
3030	char *arg;
3031	int ispath;
3032};
3033
3034/*
3035 * parse_fwd_field
3036 * parses the next field in a port forwarding specification.
3037 * sets fwd to the parsed field and advances p past the colon
3038 * or sets it to NULL at end of string.
3039 * returns 0 on success, else non-zero.
3040 */
3041static int
3042parse_fwd_field(char **p, struct fwdarg *fwd)
3043{
3044	char *ep, *cp = *p;
3045	int ispath = 0;
3046
3047	if (*cp == '\0') {
3048		*p = NULL;
3049		return -1;	/* end of string */
3050	}
3051
3052	/*
3053	 * A field escaped with square brackets is used literally.
3054	 * XXX - allow ']' to be escaped via backslash?
3055	 */
3056	if (*cp == '[') {
3057		/* find matching ']' */
3058		for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
3059			if (*ep == '/')
3060				ispath = 1;
3061		}
3062		/* no matching ']' or not at end of field. */
3063		if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
3064			return -1;
3065		/* NUL terminate the field and advance p past the colon */
3066		*ep++ = '\0';
3067		if (*ep != '\0')
3068			*ep++ = '\0';
3069		fwd->arg = cp + 1;
3070		fwd->ispath = ispath;
3071		*p = ep;
3072		return 0;
3073	}
3074
3075	for (cp = *p; *cp != '\0'; cp++) {
3076		switch (*cp) {
3077		case '\\':
3078			memmove(cp, cp + 1, strlen(cp + 1) + 1);
3079			if (*cp == '\0')
3080				return -1;
3081			break;
3082		case '/':
3083			ispath = 1;
3084			break;
3085		case ':':
3086			*cp++ = '\0';
3087			goto done;
3088		}
3089	}
3090done:
3091	fwd->arg = *p;
3092	fwd->ispath = ispath;
3093	*p = cp;
3094	return 0;
3095}
3096
3097/*
3098 * parse_forward
3099 * parses a string containing a port forwarding specification of the form:
3100 *   dynamicfwd == 0
3101 *	[listenhost:]listenport|listenpath:connecthost:connectport|connectpath
3102 *	listenpath:connectpath
3103 *   dynamicfwd == 1
3104 *	[listenhost:]listenport
3105 * returns number of arguments parsed or zero on error
3106 */
3107int
3108parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
3109{
3110	struct fwdarg fwdargs[4];
3111	char *p, *cp;
3112	int i, err;
3113
3114	memset(fwd, 0, sizeof(*fwd));
3115	memset(fwdargs, 0, sizeof(fwdargs));
3116
3117	/*
3118	 * We expand environment variables before checking if we think they're
3119	 * paths so that if ${VAR} expands to a fully qualified path it is
3120	 * treated as a path.
3121	 */
3122	cp = p = dollar_expand(&err, fwdspec);
3123	if (p == NULL || err)
3124		return 0;
3125
3126	/* skip leading spaces */
3127	while (isspace((u_char)*cp))
3128		cp++;
3129
3130	for (i = 0; i < 4; ++i) {
3131		if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
3132			break;
3133	}
3134
3135	/* Check for trailing garbage */
3136	if (cp != NULL && *cp != '\0') {
3137		i = 0;	/* failure */
3138	}
3139
3140	switch (i) {
3141	case 1:
3142		if (fwdargs[0].ispath) {
3143			fwd->listen_path = xstrdup(fwdargs[0].arg);
3144			fwd->listen_port = PORT_STREAMLOCAL;
3145		} else {
3146			fwd->listen_host = NULL;
3147			fwd->listen_port = a2port(fwdargs[0].arg);
3148		}
3149		fwd->connect_host = xstrdup("socks");
3150		break;
3151
3152	case 2:
3153		if (fwdargs[0].ispath && fwdargs[1].ispath) {
3154			fwd->listen_path = xstrdup(fwdargs[0].arg);
3155			fwd->listen_port = PORT_STREAMLOCAL;
3156			fwd->connect_path = xstrdup(fwdargs[1].arg);
3157			fwd->connect_port = PORT_STREAMLOCAL;
3158		} else if (fwdargs[1].ispath) {
3159			fwd->listen_host = NULL;
3160			fwd->listen_port = a2port(fwdargs[0].arg);
3161			fwd->connect_path = xstrdup(fwdargs[1].arg);
3162			fwd->connect_port = PORT_STREAMLOCAL;
3163		} else {
3164			fwd->listen_host = xstrdup(fwdargs[0].arg);
3165			fwd->listen_port = a2port(fwdargs[1].arg);
3166			fwd->connect_host = xstrdup("socks");
3167		}
3168		break;
3169
3170	case 3:
3171		if (fwdargs[0].ispath) {
3172			fwd->listen_path = xstrdup(fwdargs[0].arg);
3173			fwd->listen_port = PORT_STREAMLOCAL;
3174			fwd->connect_host = xstrdup(fwdargs[1].arg);
3175			fwd->connect_port = a2port(fwdargs[2].arg);
3176		} else if (fwdargs[2].ispath) {
3177			fwd->listen_host = xstrdup(fwdargs[0].arg);
3178			fwd->listen_port = a2port(fwdargs[1].arg);
3179			fwd->connect_path = xstrdup(fwdargs[2].arg);
3180			fwd->connect_port = PORT_STREAMLOCAL;
3181		} else {
3182			fwd->listen_host = NULL;
3183			fwd->listen_port = a2port(fwdargs[0].arg);
3184			fwd->connect_host = xstrdup(fwdargs[1].arg);
3185			fwd->connect_port = a2port(fwdargs[2].arg);
3186		}
3187		break;
3188
3189	case 4:
3190		fwd->listen_host = xstrdup(fwdargs[0].arg);
3191		fwd->listen_port = a2port(fwdargs[1].arg);
3192		fwd->connect_host = xstrdup(fwdargs[2].arg);
3193		fwd->connect_port = a2port(fwdargs[3].arg);
3194		break;
3195	default:
3196		i = 0; /* failure */
3197	}
3198
3199	free(p);
3200
3201	if (dynamicfwd) {
3202		if (!(i == 1 || i == 2))
3203			goto fail_free;
3204	} else {
3205		if (!(i == 3 || i == 4)) {
3206			if (fwd->connect_path == NULL &&
3207			    fwd->listen_path == NULL)
3208				goto fail_free;
3209		}
3210		if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
3211			goto fail_free;
3212	}
3213
3214	if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
3215	    (!remotefwd && fwd->listen_port == 0))
3216		goto fail_free;
3217	if (fwd->connect_host != NULL &&
3218	    strlen(fwd->connect_host) >= NI_MAXHOST)
3219		goto fail_free;
3220	/*
3221	 * XXX - if connecting to a remote socket, max sun len may not
3222	 * match this host
3223	 */
3224	if (fwd->connect_path != NULL &&
3225	    strlen(fwd->connect_path) >= PATH_MAX_SUN)
3226		goto fail_free;
3227	if (fwd->listen_host != NULL &&
3228	    strlen(fwd->listen_host) >= NI_MAXHOST)
3229		goto fail_free;
3230	if (fwd->listen_path != NULL &&
3231	    strlen(fwd->listen_path) >= PATH_MAX_SUN)
3232		goto fail_free;
3233
3234	return (i);
3235
3236 fail_free:
3237	free(fwd->connect_host);
3238	fwd->connect_host = NULL;
3239	free(fwd->connect_path);
3240	fwd->connect_path = NULL;
3241	free(fwd->listen_host);
3242	fwd->listen_host = NULL;
3243	free(fwd->listen_path);
3244	fwd->listen_path = NULL;
3245	return (0);
3246}
3247
3248int
3249parse_jump(const char *s, Options *o, int active)
3250{
3251	char *orig, *sdup, *cp;
3252	char *host = NULL, *user = NULL;
3253	int r, ret = -1, port = -1, first;
3254
3255	active &= o->proxy_command == NULL && o->jump_host == NULL;
3256
3257	orig = sdup = xstrdup(s);
3258
3259	/* Remove comment and trailing whitespace */
3260	if ((cp = strchr(orig, '#')) != NULL)
3261		*cp = '\0';
3262	rtrim(orig);
3263
3264	first = active;
3265	do {
3266		if (strcasecmp(s, "none") == 0)
3267			break;
3268		if ((cp = strrchr(sdup, ',')) == NULL)
3269			cp = sdup; /* last */
3270		else
3271			*cp++ = '\0';
3272
3273		if (first) {
3274			/* First argument and configuration is active */
3275			r = parse_ssh_uri(cp, &user, &host, &port);
3276			if (r == -1 || (r == 1 &&
3277			    parse_user_host_port(cp, &user, &host, &port) != 0))
3278				goto out;
3279		} else {
3280			/* Subsequent argument or inactive configuration */
3281			r = parse_ssh_uri(cp, NULL, NULL, NULL);
3282			if (r == -1 || (r == 1 &&
3283			    parse_user_host_port(cp, NULL, NULL, NULL) != 0))
3284				goto out;
3285		}
3286		first = 0; /* only check syntax for subsequent hosts */
3287	} while (cp != sdup);
3288	/* success */
3289	if (active) {
3290		if (strcasecmp(s, "none") == 0) {
3291			o->jump_host = xstrdup("none");
3292			o->jump_port = 0;
3293		} else {
3294			o->jump_user = user;
3295			o->jump_host = host;
3296			o->jump_port = port;
3297			o->proxy_command = xstrdup("none");
3298			user = host = NULL;
3299			if ((cp = strrchr(s, ',')) != NULL && cp != s) {
3300				o->jump_extra = xstrdup(s);
3301				o->jump_extra[cp - s] = '\0';
3302			}
3303		}
3304	}
3305	ret = 0;
3306 out:
3307	free(orig);
3308	free(user);
3309	free(host);
3310	return ret;
3311}
3312
3313int
3314parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp)
3315{
3316	char *user = NULL, *host = NULL, *path = NULL;
3317	int r, port;
3318
3319	r = parse_uri("ssh", uri, &user, &host, &port, &path);
3320	if (r == 0 && path != NULL)
3321		r = -1;		/* path not allowed */
3322	if (r == 0) {
3323		if (userp != NULL) {
3324			*userp = user;
3325			user = NULL;
3326		}
3327		if (hostp != NULL) {
3328			*hostp = host;
3329			host = NULL;
3330		}
3331		if (portp != NULL)
3332			*portp = port;
3333	}
3334	free(user);
3335	free(host);
3336	free(path);
3337	return r;
3338}
3339
3340/* XXX the following is a near-vebatim copy from servconf.c; refactor */
3341static const char *
3342fmt_multistate_int(int val, const struct multistate *m)
3343{
3344	u_int i;
3345
3346	for (i = 0; m[i].key != NULL; i++) {
3347		if (m[i].value == val)
3348			return m[i].key;
3349	}
3350	return "UNKNOWN";
3351}
3352
3353static const char *
3354fmt_intarg(OpCodes code, int val)
3355{
3356	if (val == -1)
3357		return "unset";
3358	switch (code) {
3359	case oAddressFamily:
3360		return fmt_multistate_int(val, multistate_addressfamily);
3361	case oVerifyHostKeyDNS:
3362	case oUpdateHostkeys:
3363		return fmt_multistate_int(val, multistate_yesnoask);
3364	case oStrictHostKeyChecking:
3365		return fmt_multistate_int(val, multistate_strict_hostkey);
3366	case oControlMaster:
3367		return fmt_multistate_int(val, multistate_controlmaster);
3368	case oTunnel:
3369		return fmt_multistate_int(val, multistate_tunnel);
3370	case oRequestTTY:
3371		return fmt_multistate_int(val, multistate_requesttty);
3372	case oSessionType:
3373		return fmt_multistate_int(val, multistate_sessiontype);
3374	case oCanonicalizeHostname:
3375		return fmt_multistate_int(val, multistate_canonicalizehostname);
3376	case oAddKeysToAgent:
3377		return fmt_multistate_int(val, multistate_yesnoaskconfirm);
3378	case oPubkeyAuthentication:
3379		return fmt_multistate_int(val, multistate_pubkey_auth);
3380	case oFingerprintHash:
3381		return ssh_digest_alg_name(val);
3382	default:
3383		switch (val) {
3384		case 0:
3385			return "no";
3386		case 1:
3387			return "yes";
3388		default:
3389			return "UNKNOWN";
3390		}
3391	}
3392}
3393
3394static const char *
3395lookup_opcode_name(OpCodes code)
3396{
3397	u_int i;
3398
3399	for (i = 0; keywords[i].name != NULL; i++)
3400		if (keywords[i].opcode == code)
3401			return(keywords[i].name);
3402	return "UNKNOWN";
3403}
3404
3405static void
3406dump_cfg_int(OpCodes code, int val)
3407{
3408	if (code == oObscureKeystrokeTiming) {
3409		if (val == 0) {
3410			printf("%s no\n", lookup_opcode_name(code));
3411			return;
3412		} else if (val == SSH_KEYSTROKE_DEFAULT_INTERVAL_MS) {
3413			printf("%s yes\n", lookup_opcode_name(code));
3414			return;
3415		}
3416		/* FALLTHROUGH */
3417	}
3418	printf("%s %d\n", lookup_opcode_name(code), val);
3419}
3420
3421static void
3422dump_cfg_fmtint(OpCodes code, int val)
3423{
3424	printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
3425}
3426
3427static void
3428dump_cfg_string(OpCodes code, const char *val)
3429{
3430	if (val == NULL)
3431		return;
3432	printf("%s %s\n", lookup_opcode_name(code), val);
3433}
3434
3435static void
3436dump_cfg_strarray(OpCodes code, u_int count, char **vals)
3437{
3438	u_int i;
3439
3440	for (i = 0; i < count; i++)
3441		printf("%s %s\n", lookup_opcode_name(code), vals[i]);
3442}
3443
3444static void
3445dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals)
3446{
3447	u_int i;
3448
3449	printf("%s", lookup_opcode_name(code));
3450	if (count == 0)
3451		printf(" none");
3452	for (i = 0; i < count; i++)
3453		printf(" %s",  vals[i]);
3454	printf("\n");
3455}
3456
3457static void
3458dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds)
3459{
3460	const struct Forward *fwd;
3461	u_int i;
3462
3463	/* oDynamicForward */
3464	for (i = 0; i < count; i++) {
3465		fwd = &fwds[i];
3466		if (code == oDynamicForward && fwd->connect_host != NULL &&
3467		    strcmp(fwd->connect_host, "socks") != 0)
3468			continue;
3469		if (code == oLocalForward && fwd->connect_host != NULL &&
3470		    strcmp(fwd->connect_host, "socks") == 0)
3471			continue;
3472		printf("%s", lookup_opcode_name(code));
3473		if (fwd->listen_port == PORT_STREAMLOCAL)
3474			printf(" %s", fwd->listen_path);
3475		else if (fwd->listen_host == NULL)
3476			printf(" %d", fwd->listen_port);
3477		else {
3478			printf(" [%s]:%d",
3479			    fwd->listen_host, fwd->listen_port);
3480		}
3481		if (code != oDynamicForward) {
3482			if (fwd->connect_port == PORT_STREAMLOCAL)
3483				printf(" %s", fwd->connect_path);
3484			else if (fwd->connect_host == NULL)
3485				printf(" %d", fwd->connect_port);
3486			else {
3487				printf(" [%s]:%d",
3488				    fwd->connect_host, fwd->connect_port);
3489			}
3490		}
3491		printf("\n");
3492	}
3493}
3494
3495void
3496dump_client_config(Options *o, const char *host)
3497{
3498	int i, r;
3499	char buf[8], *all_key;
3500
3501	/*
3502	 * Expand HostKeyAlgorithms name lists. This isn't handled in
3503	 * fill_default_options() like the other algorithm lists because
3504	 * the host key algorithms are by default dynamically chosen based
3505	 * on the host's keys found in known_hosts.
3506	 */
3507	all_key = sshkey_alg_list(0, 0, 1, ',');
3508	if ((r = kex_assemble_names(&o->hostkeyalgorithms, kex_default_pk_alg(),
3509	    all_key)) != 0)
3510		fatal_fr(r, "expand HostKeyAlgorithms");
3511	free(all_key);
3512
3513	/* Most interesting options first: user, host, port */
3514	dump_cfg_string(oHost, o->host_arg);
3515	dump_cfg_string(oUser, o->user);
3516	dump_cfg_string(oHostname, host);
3517	dump_cfg_int(oPort, o->port);
3518
3519	/* Flag options */
3520	dump_cfg_fmtint(oAddressFamily, o->address_family);
3521	dump_cfg_fmtint(oBatchMode, o->batch_mode);
3522	dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local);
3523	dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname);
3524	dump_cfg_fmtint(oCheckHostIP, o->check_host_ip);
3525	dump_cfg_fmtint(oCompression, o->compression);
3526	dump_cfg_fmtint(oControlMaster, o->control_master);
3527	dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
3528	dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings);
3529	dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
3530	dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash);
3531	dump_cfg_fmtint(oForwardX11, o->forward_x11);
3532	dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted);
3533	dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports);
3534#ifdef GSSAPI
3535	dump_cfg_fmtint(oGssAuthentication, o->gss_authentication);
3536	dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds);
3537#endif /* GSSAPI */
3538	dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);
3539	dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);
3540	dump_cfg_fmtint(oIdentitiesOnly, o->identities_only);
3541	dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication);
3542	dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost);
3543	dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication);
3544	dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command);
3545	dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass);
3546	dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
3547	dump_cfg_fmtint(oRequestTTY, o->request_tty);
3548	dump_cfg_fmtint(oSessionType, o->session_type);
3549	dump_cfg_fmtint(oStdinNull, o->stdin_null);
3550	dump_cfg_fmtint(oForkAfterAuthentication, o->fork_after_authentication);
3551	dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
3552	dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
3553	dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
3554	dump_cfg_fmtint(oTunnel, o->tun_open);
3555	dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns);
3556	dump_cfg_fmtint(oVisualHostKey, o->visual_host_key);
3557	dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys);
3558	dump_cfg_fmtint(oEnableEscapeCommandline, o->enable_escape_commandline);
3559
3560	/* Integer options */
3561	dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots);
3562	dump_cfg_int(oConnectionAttempts, o->connection_attempts);
3563	dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout);
3564	dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
3565	dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
3566	dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
3567	dump_cfg_int(oRequiredRSASize, o->required_rsa_size);
3568	dump_cfg_int(oObscureKeystrokeTiming,
3569	    o->obscure_keystroke_timing_interval);
3570
3571	/* String options */
3572	dump_cfg_string(oBindAddress, o->bind_address);
3573	dump_cfg_string(oBindInterface, o->bind_interface);
3574	dump_cfg_string(oCiphers, o->ciphers);
3575	dump_cfg_string(oControlPath, o->control_path);
3576	dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms);
3577	dump_cfg_string(oHostKeyAlias, o->host_key_alias);
3578	dump_cfg_string(oHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos);
3579	dump_cfg_string(oIdentityAgent, o->identity_agent);
3580	dump_cfg_string(oIgnoreUnknown, o->ignored_unknown);
3581	dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
3582	dump_cfg_string(oKexAlgorithms, o->kex_algorithms);
3583	dump_cfg_string(oCASignatureAlgorithms, o->ca_sign_algorithms);
3584	dump_cfg_string(oLocalCommand, o->local_command);
3585	dump_cfg_string(oRemoteCommand, o->remote_command);
3586	dump_cfg_string(oLogLevel, log_level_name(o->log_level));
3587	dump_cfg_string(oMacs, o->macs);
3588#ifdef ENABLE_PKCS11
3589	dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
3590#endif
3591	dump_cfg_string(oSecurityKeyProvider, o->sk_provider);
3592	dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
3593	dump_cfg_string(oPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos);
3594	dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
3595	dump_cfg_string(oXAuthLocation, o->xauth_location);
3596	dump_cfg_string(oKnownHostsCommand, o->known_hosts_command);
3597	dump_cfg_string(oTag, o->tag);
3598
3599	/* Forwards */
3600	dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
3601	dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards);
3602	dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards);
3603
3604	/* String array options */
3605	dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files);
3606	dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains);
3607	dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files);
3608	dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles);
3609	dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles);
3610	dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env);
3611	dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv);
3612	dump_cfg_strarray_oneline(oLogVerbose,
3613	    o->num_log_verbose, o->log_verbose);
3614	dump_cfg_strarray_oneline(oChannelTimeout,
3615	    o->num_channel_timeouts, o->channel_timeouts);
3616
3617	/* Special cases */
3618
3619	/* PermitRemoteOpen */
3620	if (o->num_permitted_remote_opens == 0)
3621		printf("%s any\n", lookup_opcode_name(oPermitRemoteOpen));
3622	else
3623		dump_cfg_strarray_oneline(oPermitRemoteOpen,
3624		    o->num_permitted_remote_opens, o->permitted_remote_opens);
3625
3626	/* AddKeysToAgent */
3627	if (o->add_keys_to_agent_lifespan <= 0)
3628		dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent);
3629	else {
3630		printf("addkeystoagent%s %d\n",
3631		    o->add_keys_to_agent == 3 ? " confirm" : "",
3632		    o->add_keys_to_agent_lifespan);
3633	}
3634
3635	/* oForwardAgent */
3636	if (o->forward_agent_sock_path == NULL)
3637		dump_cfg_fmtint(oForwardAgent, o->forward_agent);
3638	else
3639		dump_cfg_string(oForwardAgent, o->forward_agent_sock_path);
3640
3641	/* oConnectTimeout */
3642	if (o->connection_timeout == -1)
3643		printf("connecttimeout none\n");
3644	else
3645		dump_cfg_int(oConnectTimeout, o->connection_timeout);
3646
3647	/* oTunnelDevice */
3648	printf("tunneldevice");
3649	if (o->tun_local == SSH_TUNID_ANY)
3650		printf(" any");
3651	else
3652		printf(" %d", o->tun_local);
3653	if (o->tun_remote == SSH_TUNID_ANY)
3654		printf(":any");
3655	else
3656		printf(":%d", o->tun_remote);
3657	printf("\n");
3658
3659	/* oCanonicalizePermittedCNAMEs */
3660	printf("canonicalizePermittedcnames");
3661	if (o->num_permitted_cnames == 0)
3662		printf(" none");
3663	for (i = 0; i < o->num_permitted_cnames; i++) {
3664		printf(" %s:%s", o->permitted_cnames[i].source_list,
3665		    o->permitted_cnames[i].target_list);
3666	}
3667	printf("\n");
3668
3669	/* oControlPersist */
3670	if (o->control_persist == 0 || o->control_persist_timeout == 0)
3671		dump_cfg_fmtint(oControlPersist, o->control_persist);
3672	else
3673		dump_cfg_int(oControlPersist, o->control_persist_timeout);
3674
3675	/* oEscapeChar */
3676	if (o->escape_char == SSH_ESCAPECHAR_NONE)
3677		printf("escapechar none\n");
3678	else {
3679		vis(buf, o->escape_char, VIS_WHITE, 0);
3680		printf("escapechar %s\n", buf);
3681	}
3682
3683	/* oIPQoS */
3684	printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
3685	printf("%s\n", iptos2str(o->ip_qos_bulk));
3686
3687	/* oRekeyLimit */
3688	printf("rekeylimit %llu %d\n",
3689	    (unsigned long long)o->rekey_limit, o->rekey_interval);
3690
3691	/* oStreamLocalBindMask */
3692	printf("streamlocalbindmask 0%o\n",
3693	    o->fwd_opts.streamlocal_bind_mask);
3694
3695	/* oLogFacility */
3696	printf("syslogfacility %s\n", log_facility_name(o->log_facility));
3697
3698	/* oProxyCommand / oProxyJump */
3699	if (o->jump_host == NULL)
3700		dump_cfg_string(oProxyCommand, o->proxy_command);
3701	else {
3702		/* Check for numeric addresses */
3703		i = strchr(o->jump_host, ':') != NULL ||
3704		    strspn(o->jump_host, "1234567890.") == strlen(o->jump_host);
3705		snprintf(buf, sizeof(buf), "%d", o->jump_port);
3706		printf("proxyjump %s%s%s%s%s%s%s%s%s\n",
3707		    /* optional additional jump spec */
3708		    o->jump_extra == NULL ? "" : o->jump_extra,
3709		    o->jump_extra == NULL ? "" : ",",
3710		    /* optional user */
3711		    o->jump_user == NULL ? "" : o->jump_user,
3712		    o->jump_user == NULL ? "" : "@",
3713		    /* opening [ if hostname is numeric */
3714		    i ? "[" : "",
3715		    /* mandatory hostname */
3716		    o->jump_host,
3717		    /* closing ] if hostname is numeric */
3718		    i ? "]" : "",
3719		    /* optional port number */
3720		    o->jump_port <= 0 ? "" : ":",
3721		    o->jump_port <= 0 ? "" : buf);
3722	}
3723}
3724