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