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