xref: /freebsd/crypto/openssh/readconf.c (revision cf2b5f3b6d88690d9dee1824ed589d164bb62abc)
1511b41d2SMark Murray /*
2511b41d2SMark Murray  * Author: Tatu Ylonen <ylo@cs.hut.fi>
3511b41d2SMark Murray  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4511b41d2SMark Murray  *                    All rights reserved
5511b41d2SMark Murray  * Functions for reading the configuration files.
6511b41d2SMark Murray  *
7c2d3a559SKris Kennaway  * As far as I am concerned, the code I have written for this software
8c2d3a559SKris Kennaway  * can be used freely for any purpose.  Any derived versions of this
9c2d3a559SKris Kennaway  * software must be clearly marked as such, and if the derived work is
10c2d3a559SKris Kennaway  * incompatible with the protocol description in the RFC file, it must be
11c2d3a559SKris Kennaway  * called by a name other than "ssh" or "Secure Shell".
12511b41d2SMark Murray  */
13511b41d2SMark Murray 
14511b41d2SMark Murray #include "includes.h"
15cf2b5f3bSDag-Erling Smørgrav RCSID("$OpenBSD: readconf.c,v 1.121 2003/09/01 18:15:50 markus Exp $");
16975616f0SDag-Erling Smørgrav RCSID("$FreeBSD$");
17511b41d2SMark Murray 
18511b41d2SMark Murray #include "ssh.h"
19511b41d2SMark Murray #include "xmalloc.h"
20e8aafc91SKris Kennaway #include "compat.h"
21ca3176e7SBrian Feldman #include "cipher.h"
22ca3176e7SBrian Feldman #include "pathnames.h"
23ca3176e7SBrian Feldman #include "log.h"
24ca3176e7SBrian Feldman #include "readconf.h"
25ca3176e7SBrian Feldman #include "match.h"
26ca3176e7SBrian Feldman #include "misc.h"
27ca3176e7SBrian Feldman #include "kex.h"
28ca3176e7SBrian Feldman #include "mac.h"
29511b41d2SMark Murray 
30511b41d2SMark Murray /* Format of the configuration file:
31511b41d2SMark Murray 
32511b41d2SMark Murray    # Configuration data is parsed as follows:
33511b41d2SMark Murray    #  1. command line options
34511b41d2SMark Murray    #  2. user-specific file
35511b41d2SMark Murray    #  3. system-wide file
36511b41d2SMark Murray    # Any configuration value is only changed the first time it is set.
37511b41d2SMark Murray    # Thus, host-specific definitions should be at the beginning of the
38511b41d2SMark Murray    # configuration file, and defaults at the end.
39511b41d2SMark Murray 
40511b41d2SMark Murray    # Host-specific declarations.  These may override anything above.  A single
41511b41d2SMark Murray    # host may match multiple declarations; these are processed in the order
42511b41d2SMark Murray    # that they are given in.
43511b41d2SMark Murray 
44511b41d2SMark Murray    Host *.ngs.fi ngs.fi
4580628bacSDag-Erling Smørgrav      User foo
46511b41d2SMark Murray 
47511b41d2SMark Murray    Host fake.com
48511b41d2SMark Murray      HostName another.host.name.real.org
49511b41d2SMark Murray      User blaah
50511b41d2SMark Murray      Port 34289
51511b41d2SMark Murray      ForwardX11 no
52511b41d2SMark Murray      ForwardAgent no
53511b41d2SMark Murray 
54511b41d2SMark Murray    Host books.com
55511b41d2SMark Murray      RemoteForward 9999 shadows.cs.hut.fi:9999
56511b41d2SMark Murray      Cipher 3des
57511b41d2SMark Murray 
58511b41d2SMark Murray    Host fascist.blob.com
59511b41d2SMark Murray      Port 23123
60511b41d2SMark Murray      User tylonen
61511b41d2SMark Murray      PasswordAuthentication no
62511b41d2SMark Murray 
63511b41d2SMark Murray    Host puukko.hut.fi
64511b41d2SMark Murray      User t35124p
65511b41d2SMark Murray      ProxyCommand ssh-proxy %h %p
66511b41d2SMark Murray 
67511b41d2SMark Murray    Host *.fr
6880628bacSDag-Erling Smørgrav      PublicKeyAuthentication no
69511b41d2SMark Murray 
70511b41d2SMark Murray    Host *.su
71511b41d2SMark Murray      Cipher none
72511b41d2SMark Murray      PasswordAuthentication no
73511b41d2SMark Murray 
74511b41d2SMark Murray    # Defaults for various options
75511b41d2SMark Murray    Host *
76511b41d2SMark Murray      ForwardAgent no
77ca3176e7SBrian Feldman      ForwardX11 no
78511b41d2SMark Murray      PasswordAuthentication yes
79511b41d2SMark Murray      RSAAuthentication yes
80511b41d2SMark Murray      RhostsRSAAuthentication yes
81511b41d2SMark Murray      StrictHostKeyChecking yes
82511b41d2SMark Murray      KeepAlives no
83511b41d2SMark Murray      IdentityFile ~/.ssh/identity
84511b41d2SMark Murray      Port 22
85511b41d2SMark Murray      EscapeChar ~
86511b41d2SMark Murray 
87511b41d2SMark Murray */
88511b41d2SMark Murray 
89511b41d2SMark Murray /* Keyword tokens. */
90511b41d2SMark Murray 
91511b41d2SMark Murray typedef enum {
92511b41d2SMark Murray 	oBadOption,
93cf2b5f3bSDag-Erling Smørgrav 	oForwardAgent, oForwardX11, oGatewayPorts,
9480628bacSDag-Erling Smørgrav 	oPasswordAuthentication, oRSAAuthentication,
95ca3176e7SBrian Feldman 	oChallengeResponseAuthentication, oXAuthLocation,
96511b41d2SMark Murray 	oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
97511b41d2SMark Murray 	oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
98511b41d2SMark Murray 	oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
99511b41d2SMark Murray 	oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
100ca3176e7SBrian Feldman 	oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts,
101ca3176e7SBrian Feldman 	oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
102ca3176e7SBrian Feldman 	oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
103ca3176e7SBrian Feldman 	oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
104ca3176e7SBrian Feldman 	oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
105af12a3e7SDag-Erling Smørgrav 	oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
1069e2cbe04SDag-Erling Smørgrav 	oClearAllForwardings, oNoHostAuthenticationForLocalhost,
107cf2b5f3bSDag-Erling Smørgrav 	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
108cf2b5f3bSDag-Erling Smørgrav 	oAddressFamily, oGssAuthentication, oGssDelegateCreds,
109975616f0SDag-Erling Smørgrav 	oVersionAddendum,
110cf2b5f3bSDag-Erling Smørgrav 	oDeprecated, oUnsupported
111511b41d2SMark Murray } OpCodes;
112511b41d2SMark Murray 
113511b41d2SMark Murray /* Textual representations of the tokens. */
114511b41d2SMark Murray 
115511b41d2SMark Murray static struct {
116511b41d2SMark Murray 	const char *name;
117511b41d2SMark Murray 	OpCodes opcode;
118511b41d2SMark Murray } keywords[] = {
119511b41d2SMark Murray 	{ "forwardagent", oForwardAgent },
120511b41d2SMark Murray 	{ "forwardx11", oForwardX11 },
121c2d3a559SKris Kennaway 	{ "xauthlocation", oXAuthLocation },
122511b41d2SMark Murray 	{ "gatewayports", oGatewayPorts },
123511b41d2SMark Murray 	{ "useprivilegedport", oUsePrivilegedPort },
124cf2b5f3bSDag-Erling Smørgrav 	{ "rhostsauthentication", oDeprecated },
125511b41d2SMark Murray 	{ "passwordauthentication", oPasswordAuthentication },
12609958426SBrian Feldman 	{ "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
12709958426SBrian Feldman 	{ "kbdinteractivedevices", oKbdInteractiveDevices },
128511b41d2SMark Murray 	{ "rsaauthentication", oRSAAuthentication },
129ca3176e7SBrian Feldman 	{ "pubkeyauthentication", oPubkeyAuthentication },
130ca3176e7SBrian Feldman 	{ "dsaauthentication", oPubkeyAuthentication },		    /* alias */
131ca3176e7SBrian Feldman 	{ "rhostsrsaauthentication", oRhostsRSAAuthentication },
132ca3176e7SBrian Feldman 	{ "hostbasedauthentication", oHostbasedAuthentication },
133ca3176e7SBrian Feldman 	{ "challengeresponseauthentication", oChallengeResponseAuthentication },
134ca3176e7SBrian Feldman 	{ "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
135ca3176e7SBrian Feldman 	{ "tisauthentication", oChallengeResponseAuthentication },  /* alias */
136cf2b5f3bSDag-Erling Smørgrav 	{ "kerberosauthentication", oUnsupported },
137cf2b5f3bSDag-Erling Smørgrav 	{ "kerberostgtpassing", oUnsupported },
138cf2b5f3bSDag-Erling Smørgrav 	{ "afstokenpassing", oUnsupported },
139cf2b5f3bSDag-Erling Smørgrav #if defined(GSSAPI)
140cf2b5f3bSDag-Erling Smørgrav 	{ "gssapiauthentication", oGssAuthentication },
141cf2b5f3bSDag-Erling Smørgrav 	{ "gssapidelegatecredentials", oGssDelegateCreds },
142cf2b5f3bSDag-Erling Smørgrav #else
143cf2b5f3bSDag-Erling Smørgrav 	{ "gssapiauthentication", oUnsupported },
144cf2b5f3bSDag-Erling Smørgrav 	{ "gssapidelegatecredentials", oUnsupported },
145511b41d2SMark Murray #endif
14680628bacSDag-Erling Smørgrav 	{ "fallbacktorsh", oDeprecated },
14780628bacSDag-Erling Smørgrav 	{ "usersh", oDeprecated },
148511b41d2SMark Murray 	{ "identityfile", oIdentityFile },
149ca3176e7SBrian Feldman 	{ "identityfile2", oIdentityFile },			/* alias */
150511b41d2SMark Murray 	{ "hostname", oHostName },
151ca3176e7SBrian Feldman 	{ "hostkeyalias", oHostKeyAlias },
152511b41d2SMark Murray 	{ "proxycommand", oProxyCommand },
153511b41d2SMark Murray 	{ "port", oPort },
154511b41d2SMark Murray 	{ "cipher", oCipher },
155e8aafc91SKris Kennaway 	{ "ciphers", oCiphers },
156ca3176e7SBrian Feldman 	{ "macs", oMacs },
157e8aafc91SKris Kennaway 	{ "protocol", oProtocol },
158511b41d2SMark Murray 	{ "remoteforward", oRemoteForward },
159511b41d2SMark Murray 	{ "localforward", oLocalForward },
160511b41d2SMark Murray 	{ "user", oUser },
161511b41d2SMark Murray 	{ "host", oHost },
162511b41d2SMark Murray 	{ "escapechar", oEscapeChar },
163511b41d2SMark Murray 	{ "globalknownhostsfile", oGlobalKnownHostsFile },
164af12a3e7SDag-Erling Smørgrav 	{ "userknownhostsfile", oUserKnownHostsFile },		/* obsolete */
165e8aafc91SKris Kennaway 	{ "globalknownhostsfile2", oGlobalKnownHostsFile2 },
166af12a3e7SDag-Erling Smørgrav 	{ "userknownhostsfile2", oUserKnownHostsFile2 },	/* obsolete */
167511b41d2SMark Murray 	{ "connectionattempts", oConnectionAttempts },
168511b41d2SMark Murray 	{ "batchmode", oBatchMode },
169511b41d2SMark Murray 	{ "checkhostip", oCheckHostIP },
170511b41d2SMark Murray 	{ "stricthostkeychecking", oStrictHostKeyChecking },
171511b41d2SMark Murray 	{ "compression", oCompression },
172511b41d2SMark Murray 	{ "compressionlevel", oCompressionLevel },
173511b41d2SMark Murray 	{ "keepalive", oKeepAlives },
174511b41d2SMark Murray 	{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
175511b41d2SMark Murray 	{ "loglevel", oLogLevel },
176ca3176e7SBrian Feldman 	{ "dynamicforward", oDynamicForward },
177ca3176e7SBrian Feldman 	{ "preferredauthentications", oPreferredAuthentications },
178ca3176e7SBrian Feldman 	{ "hostkeyalgorithms", oHostKeyAlgorithms },
179af12a3e7SDag-Erling Smørgrav 	{ "bindaddress", oBindAddress },
180cf2b5f3bSDag-Erling Smørgrav #ifdef SMARTCARD
181af12a3e7SDag-Erling Smørgrav 	{ "smartcarddevice", oSmartcardDevice },
182cf2b5f3bSDag-Erling Smørgrav #else
183cf2b5f3bSDag-Erling Smørgrav 	{ "smartcarddevice", oUnsupported },
184cf2b5f3bSDag-Erling Smørgrav #endif
185af12a3e7SDag-Erling Smørgrav 	{ "clearallforwardings", oClearAllForwardings },
186e73e9afaSDag-Erling Smørgrav 	{ "enablesshkeysign", oEnableSSHKeysign },
187cf2b5f3bSDag-Erling Smørgrav #ifdef DNS
188cf2b5f3bSDag-Erling Smørgrav 	{ "verifyhostkeydns", oVerifyHostKeyDNS },
189cf2b5f3bSDag-Erling Smørgrav #else
190cf2b5f3bSDag-Erling Smørgrav 	{ "verifyhostkeydns", oUnsupported },
191cf2b5f3bSDag-Erling Smørgrav #endif
192af12a3e7SDag-Erling Smørgrav 	{ "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
193cf2b5f3bSDag-Erling Smørgrav 	{ "rekeylimit", oRekeyLimit },
194cf2b5f3bSDag-Erling Smørgrav 	{ "connecttimeout", oConnectTimeout },
195cf2b5f3bSDag-Erling Smørgrav 	{ "addressfamily", oAddressFamily },
196975616f0SDag-Erling Smørgrav 	{ "versionaddendum", oVersionAddendum },
197af12a3e7SDag-Erling Smørgrav 	{ NULL, oBadOption }
198511b41d2SMark Murray };
199511b41d2SMark Murray 
200511b41d2SMark Murray /*
201511b41d2SMark Murray  * Adds a local TCP/IP port forward to options.  Never returns if there is an
202511b41d2SMark Murray  * error.
203511b41d2SMark Murray  */
204511b41d2SMark Murray 
205511b41d2SMark Murray void
206511b41d2SMark Murray add_local_forward(Options *options, u_short port, const char *host,
207511b41d2SMark Murray 		  u_short host_port)
208511b41d2SMark Murray {
209511b41d2SMark Murray 	Forward *fwd;
210f388f5efSDag-Erling Smørgrav #ifndef NO_IPPORT_RESERVED_CONCEPT
211511b41d2SMark Murray 	extern uid_t original_real_uid;
212511b41d2SMark Murray 	if (port < IPPORT_RESERVED && original_real_uid != 0)
213ca3176e7SBrian Feldman 		fatal("Privileged ports can only be forwarded by root.");
214989dd127SDag-Erling Smørgrav #endif
215511b41d2SMark Murray 	if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
216511b41d2SMark Murray 		fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
217511b41d2SMark Murray 	fwd = &options->local_forwards[options->num_local_forwards++];
218511b41d2SMark Murray 	fwd->port = port;
219511b41d2SMark Murray 	fwd->host = xstrdup(host);
220511b41d2SMark Murray 	fwd->host_port = host_port;
221511b41d2SMark Murray }
222511b41d2SMark Murray 
223511b41d2SMark Murray /*
224511b41d2SMark Murray  * Adds a remote TCP/IP port forward to options.  Never returns if there is
225511b41d2SMark Murray  * an error.
226511b41d2SMark Murray  */
227511b41d2SMark Murray 
228511b41d2SMark Murray void
229511b41d2SMark Murray add_remote_forward(Options *options, u_short port, const char *host,
230511b41d2SMark Murray 		   u_short host_port)
231511b41d2SMark Murray {
232511b41d2SMark Murray 	Forward *fwd;
233511b41d2SMark Murray 	if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
234511b41d2SMark Murray 		fatal("Too many remote forwards (max %d).",
235511b41d2SMark Murray 		    SSH_MAX_FORWARDS_PER_DIRECTION);
236511b41d2SMark Murray 	fwd = &options->remote_forwards[options->num_remote_forwards++];
237511b41d2SMark Murray 	fwd->port = port;
238511b41d2SMark Murray 	fwd->host = xstrdup(host);
239511b41d2SMark Murray 	fwd->host_port = host_port;
240511b41d2SMark Murray }
241511b41d2SMark Murray 
242af12a3e7SDag-Erling Smørgrav static void
243af12a3e7SDag-Erling Smørgrav clear_forwardings(Options *options)
244af12a3e7SDag-Erling Smørgrav {
245af12a3e7SDag-Erling Smørgrav 	int i;
246af12a3e7SDag-Erling Smørgrav 
247af12a3e7SDag-Erling Smørgrav 	for (i = 0; i < options->num_local_forwards; i++)
248af12a3e7SDag-Erling Smørgrav 		xfree(options->local_forwards[i].host);
249af12a3e7SDag-Erling Smørgrav 	options->num_local_forwards = 0;
250af12a3e7SDag-Erling Smørgrav 	for (i = 0; i < options->num_remote_forwards; i++)
251af12a3e7SDag-Erling Smørgrav 		xfree(options->remote_forwards[i].host);
252af12a3e7SDag-Erling Smørgrav 	options->num_remote_forwards = 0;
253af12a3e7SDag-Erling Smørgrav }
254af12a3e7SDag-Erling Smørgrav 
255511b41d2SMark Murray /*
256ca3176e7SBrian Feldman  * Returns the number of the token pointed to by cp or oBadOption.
257511b41d2SMark Murray  */
258511b41d2SMark Murray 
259511b41d2SMark Murray static OpCodes
260511b41d2SMark Murray parse_token(const char *cp, const char *filename, int linenum)
261511b41d2SMark Murray {
262ca3176e7SBrian Feldman 	u_int i;
263511b41d2SMark Murray 
264511b41d2SMark Murray 	for (i = 0; keywords[i].name; i++)
265511b41d2SMark Murray 		if (strcasecmp(cp, keywords[i].name) == 0)
266511b41d2SMark Murray 			return keywords[i].opcode;
267511b41d2SMark Murray 
268ca3176e7SBrian Feldman 	error("%s: line %d: Bad configuration option: %s",
269511b41d2SMark Murray 	    filename, linenum, cp);
270511b41d2SMark Murray 	return oBadOption;
271511b41d2SMark Murray }
272511b41d2SMark Murray 
273511b41d2SMark Murray /*
274511b41d2SMark Murray  * Processes a single option line as used in the configuration files. This
275511b41d2SMark Murray  * only sets those values that have not already been set.
276511b41d2SMark Murray  */
277e73e9afaSDag-Erling Smørgrav #define WHITESPACE " \t\r\n"
278511b41d2SMark Murray 
279511b41d2SMark Murray int
280511b41d2SMark Murray process_config_line(Options *options, const char *host,
281511b41d2SMark Murray 		    char *line, const char *filename, int linenum,
282511b41d2SMark Murray 		    int *activep)
283511b41d2SMark Murray {
284e73e9afaSDag-Erling Smørgrav 	char buf[256], *s, **charptr, *endofnumber, *keyword, *arg;
285511b41d2SMark Murray 	int opcode, *intptr, value;
286e73e9afaSDag-Erling Smørgrav 	size_t len;
287511b41d2SMark Murray 	u_short fwd_port, fwd_host_port;
288af12a3e7SDag-Erling Smørgrav 	char sfwd_host_port[6];
289511b41d2SMark Murray 
290cf2b5f3bSDag-Erling Smørgrav 	/* Strip trailing whitespace */
291cf2b5f3bSDag-Erling Smørgrav 	for(len = strlen(line) - 1; len > 0; len--) {
292cf2b5f3bSDag-Erling Smørgrav 		if (strchr(WHITESPACE, line[len]) == NULL)
293cf2b5f3bSDag-Erling Smørgrav 			break;
294cf2b5f3bSDag-Erling Smørgrav 		line[len] = '\0';
295cf2b5f3bSDag-Erling Smørgrav 	}
296cf2b5f3bSDag-Erling Smørgrav 
297c2d3a559SKris Kennaway 	s = line;
298c2d3a559SKris Kennaway 	/* Get the keyword. (Each line is supposed to begin with a keyword). */
299c2d3a559SKris Kennaway 	keyword = strdelim(&s);
300c2d3a559SKris Kennaway 	/* Ignore leading whitespace. */
301c2d3a559SKris Kennaway 	if (*keyword == '\0')
302c2d3a559SKris Kennaway 		keyword = strdelim(&s);
303ca3176e7SBrian Feldman 	if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
304511b41d2SMark Murray 		return 0;
305511b41d2SMark Murray 
306c2d3a559SKris Kennaway 	opcode = parse_token(keyword, filename, linenum);
307511b41d2SMark Murray 
308511b41d2SMark Murray 	switch (opcode) {
309511b41d2SMark Murray 	case oBadOption:
310511b41d2SMark Murray 		/* don't panic, but count bad options */
311511b41d2SMark Murray 		return -1;
312511b41d2SMark Murray 		/* NOTREACHED */
313cf2b5f3bSDag-Erling Smørgrav 	case oConnectTimeout:
314cf2b5f3bSDag-Erling Smørgrav 		intptr = &options->connection_timeout;
315cf2b5f3bSDag-Erling Smørgrav /* parse_time: */
316cf2b5f3bSDag-Erling Smørgrav 		arg = strdelim(&s);
317cf2b5f3bSDag-Erling Smørgrav 		if (!arg || *arg == '\0')
318cf2b5f3bSDag-Erling Smørgrav 			fatal("%s line %d: missing time value.",
319cf2b5f3bSDag-Erling Smørgrav 			    filename, linenum);
320cf2b5f3bSDag-Erling Smørgrav 		if ((value = convtime(arg)) == -1)
321cf2b5f3bSDag-Erling Smørgrav 			fatal("%s line %d: invalid time value.",
322cf2b5f3bSDag-Erling Smørgrav 			    filename, linenum);
323cf2b5f3bSDag-Erling Smørgrav 		if (*intptr == -1)
324cf2b5f3bSDag-Erling Smørgrav 			*intptr = value;
325cf2b5f3bSDag-Erling Smørgrav 		break;
326cf2b5f3bSDag-Erling Smørgrav 
327511b41d2SMark Murray 	case oForwardAgent:
328511b41d2SMark Murray 		intptr = &options->forward_agent;
329511b41d2SMark Murray parse_flag:
330c2d3a559SKris Kennaway 		arg = strdelim(&s);
331c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
332511b41d2SMark Murray 			fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
333511b41d2SMark Murray 		value = 0;	/* To avoid compiler warning... */
334c2d3a559SKris Kennaway 		if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
335511b41d2SMark Murray 			value = 1;
336c2d3a559SKris Kennaway 		else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
337511b41d2SMark Murray 			value = 0;
338511b41d2SMark Murray 		else
339511b41d2SMark Murray 			fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
340511b41d2SMark Murray 		if (*activep && *intptr == -1)
341511b41d2SMark Murray 			*intptr = value;
342511b41d2SMark Murray 		break;
343511b41d2SMark Murray 
344511b41d2SMark Murray 	case oForwardX11:
345511b41d2SMark Murray 		intptr = &options->forward_x11;
346511b41d2SMark Murray 		goto parse_flag;
347511b41d2SMark Murray 
348511b41d2SMark Murray 	case oGatewayPorts:
349511b41d2SMark Murray 		intptr = &options->gateway_ports;
350511b41d2SMark Murray 		goto parse_flag;
351511b41d2SMark Murray 
352511b41d2SMark Murray 	case oUsePrivilegedPort:
353511b41d2SMark Murray 		intptr = &options->use_privileged_port;
354511b41d2SMark Murray 		goto parse_flag;
355511b41d2SMark Murray 
356511b41d2SMark Murray 	case oPasswordAuthentication:
357511b41d2SMark Murray 		intptr = &options->password_authentication;
358511b41d2SMark Murray 		goto parse_flag;
359511b41d2SMark Murray 
36009958426SBrian Feldman 	case oKbdInteractiveAuthentication:
36109958426SBrian Feldman 		intptr = &options->kbd_interactive_authentication;
36209958426SBrian Feldman 		goto parse_flag;
36309958426SBrian Feldman 
36409958426SBrian Feldman 	case oKbdInteractiveDevices:
36509958426SBrian Feldman 		charptr = &options->kbd_interactive_devices;
36609958426SBrian Feldman 		goto parse_string;
36709958426SBrian Feldman 
368ca3176e7SBrian Feldman 	case oPubkeyAuthentication:
369ca3176e7SBrian Feldman 		intptr = &options->pubkey_authentication;
370e8aafc91SKris Kennaway 		goto parse_flag;
371e8aafc91SKris Kennaway 
372511b41d2SMark Murray 	case oRSAAuthentication:
373511b41d2SMark Murray 		intptr = &options->rsa_authentication;
374511b41d2SMark Murray 		goto parse_flag;
375511b41d2SMark Murray 
376511b41d2SMark Murray 	case oRhostsRSAAuthentication:
377511b41d2SMark Murray 		intptr = &options->rhosts_rsa_authentication;
378511b41d2SMark Murray 		goto parse_flag;
379511b41d2SMark Murray 
380ca3176e7SBrian Feldman 	case oHostbasedAuthentication:
381ca3176e7SBrian Feldman 		intptr = &options->hostbased_authentication;
382511b41d2SMark Murray 		goto parse_flag;
383511b41d2SMark Murray 
384af12a3e7SDag-Erling Smørgrav 	case oChallengeResponseAuthentication:
385af12a3e7SDag-Erling Smørgrav 		intptr = &options->challenge_response_authentication;
386af12a3e7SDag-Erling Smørgrav 		goto parse_flag;
387cf2b5f3bSDag-Erling Smørgrav 
388cf2b5f3bSDag-Erling Smørgrav 	case oGssAuthentication:
389cf2b5f3bSDag-Erling Smørgrav 		intptr = &options->gss_authentication;
390511b41d2SMark Murray 		goto parse_flag;
391cf2b5f3bSDag-Erling Smørgrav 
392cf2b5f3bSDag-Erling Smørgrav 	case oGssDelegateCreds:
393cf2b5f3bSDag-Erling Smørgrav 		intptr = &options->gss_deleg_creds;
394ca3176e7SBrian Feldman 		goto parse_flag;
395cf2b5f3bSDag-Erling Smørgrav 
396511b41d2SMark Murray 	case oBatchMode:
397511b41d2SMark Murray 		intptr = &options->batch_mode;
398511b41d2SMark Murray 		goto parse_flag;
399511b41d2SMark Murray 
400511b41d2SMark Murray 	case oCheckHostIP:
401511b41d2SMark Murray 		intptr = &options->check_host_ip;
402511b41d2SMark Murray 		goto parse_flag;
403511b41d2SMark Murray 
404cf2b5f3bSDag-Erling Smørgrav 	case oVerifyHostKeyDNS:
405cf2b5f3bSDag-Erling Smørgrav 		intptr = &options->verify_host_key_dns;
406cf2b5f3bSDag-Erling Smørgrav 		goto parse_flag;
407cf2b5f3bSDag-Erling Smørgrav 
408511b41d2SMark Murray 	case oStrictHostKeyChecking:
409511b41d2SMark Murray 		intptr = &options->strict_host_key_checking;
410c2d3a559SKris Kennaway 		arg = strdelim(&s);
411c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
412ca3176e7SBrian Feldman 			fatal("%.200s line %d: Missing yes/no/ask argument.",
413511b41d2SMark Murray 			    filename, linenum);
414511b41d2SMark Murray 		value = 0;	/* To avoid compiler warning... */
415c2d3a559SKris Kennaway 		if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
416511b41d2SMark Murray 			value = 1;
417c2d3a559SKris Kennaway 		else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
418511b41d2SMark Murray 			value = 0;
419c2d3a559SKris Kennaway 		else if (strcmp(arg, "ask") == 0)
420511b41d2SMark Murray 			value = 2;
421511b41d2SMark Murray 		else
422511b41d2SMark Murray 			fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
423511b41d2SMark Murray 		if (*activep && *intptr == -1)
424511b41d2SMark Murray 			*intptr = value;
425511b41d2SMark Murray 		break;
426511b41d2SMark Murray 
427511b41d2SMark Murray 	case oCompression:
428511b41d2SMark Murray 		intptr = &options->compression;
429511b41d2SMark Murray 		goto parse_flag;
430511b41d2SMark Murray 
431511b41d2SMark Murray 	case oKeepAlives:
432511b41d2SMark Murray 		intptr = &options->keepalives;
433511b41d2SMark Murray 		goto parse_flag;
434511b41d2SMark Murray 
435af12a3e7SDag-Erling Smørgrav 	case oNoHostAuthenticationForLocalhost:
436af12a3e7SDag-Erling Smørgrav 		intptr = &options->no_host_authentication_for_localhost;
437af12a3e7SDag-Erling Smørgrav 		goto parse_flag;
438af12a3e7SDag-Erling Smørgrav 
439511b41d2SMark Murray 	case oNumberOfPasswordPrompts:
440511b41d2SMark Murray 		intptr = &options->number_of_password_prompts;
441511b41d2SMark Murray 		goto parse_int;
442511b41d2SMark Murray 
443511b41d2SMark Murray 	case oCompressionLevel:
444511b41d2SMark Murray 		intptr = &options->compression_level;
445511b41d2SMark Murray 		goto parse_int;
446511b41d2SMark Murray 
447cf2b5f3bSDag-Erling Smørgrav 	case oRekeyLimit:
448cf2b5f3bSDag-Erling Smørgrav 		intptr = &options->rekey_limit;
449cf2b5f3bSDag-Erling Smørgrav 		arg = strdelim(&s);
450cf2b5f3bSDag-Erling Smørgrav 		if (!arg || *arg == '\0')
451cf2b5f3bSDag-Erling Smørgrav 			fatal("%.200s line %d: Missing argument.", filename, linenum);
452cf2b5f3bSDag-Erling Smørgrav 		if (arg[0] < '0' || arg[0] > '9')
453cf2b5f3bSDag-Erling Smørgrav 			fatal("%.200s line %d: Bad number.", filename, linenum);
454cf2b5f3bSDag-Erling Smørgrav 		value = strtol(arg, &endofnumber, 10);
455cf2b5f3bSDag-Erling Smørgrav 		if (arg == endofnumber)
456cf2b5f3bSDag-Erling Smørgrav 			fatal("%.200s line %d: Bad number.", filename, linenum);
457cf2b5f3bSDag-Erling Smørgrav 		switch (toupper(*endofnumber)) {
458cf2b5f3bSDag-Erling Smørgrav 		case 'K':
459cf2b5f3bSDag-Erling Smørgrav 			value *= 1<<10;
460cf2b5f3bSDag-Erling Smørgrav 			break;
461cf2b5f3bSDag-Erling Smørgrav 		case 'M':
462cf2b5f3bSDag-Erling Smørgrav 			value *= 1<<20;
463cf2b5f3bSDag-Erling Smørgrav 			break;
464cf2b5f3bSDag-Erling Smørgrav 		case 'G':
465cf2b5f3bSDag-Erling Smørgrav 			value *= 1<<30;
466cf2b5f3bSDag-Erling Smørgrav 			break;
467cf2b5f3bSDag-Erling Smørgrav 		}
468cf2b5f3bSDag-Erling Smørgrav 		if (*activep && *intptr == -1)
469cf2b5f3bSDag-Erling Smørgrav 			*intptr = value;
470cf2b5f3bSDag-Erling Smørgrav 		break;
471cf2b5f3bSDag-Erling Smørgrav 
472511b41d2SMark Murray 	case oIdentityFile:
473c2d3a559SKris Kennaway 		arg = strdelim(&s);
474c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
475511b41d2SMark Murray 			fatal("%.200s line %d: Missing argument.", filename, linenum);
476511b41d2SMark Murray 		if (*activep) {
477ca3176e7SBrian Feldman 			intptr = &options->num_identity_files;
478e8aafc91SKris Kennaway 			if (*intptr >= SSH_MAX_IDENTITY_FILES)
479511b41d2SMark Murray 				fatal("%.200s line %d: Too many identity files specified (max %d).",
480511b41d2SMark Murray 				    filename, linenum, SSH_MAX_IDENTITY_FILES);
481ca3176e7SBrian Feldman 			charptr =  &options->identity_files[*intptr];
482c2d3a559SKris Kennaway 			*charptr = xstrdup(arg);
483e8aafc91SKris Kennaway 			*intptr = *intptr + 1;
484511b41d2SMark Murray 		}
485511b41d2SMark Murray 		break;
486511b41d2SMark Murray 
487c2d3a559SKris Kennaway 	case oXAuthLocation:
488c2d3a559SKris Kennaway 		charptr=&options->xauth_location;
489c2d3a559SKris Kennaway 		goto parse_string;
490c2d3a559SKris Kennaway 
491511b41d2SMark Murray 	case oUser:
492511b41d2SMark Murray 		charptr = &options->user;
493511b41d2SMark Murray parse_string:
494c2d3a559SKris Kennaway 		arg = strdelim(&s);
495c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
496511b41d2SMark Murray 			fatal("%.200s line %d: Missing argument.", filename, linenum);
497511b41d2SMark Murray 		if (*activep && *charptr == NULL)
498c2d3a559SKris Kennaway 			*charptr = xstrdup(arg);
499511b41d2SMark Murray 		break;
500511b41d2SMark Murray 
501511b41d2SMark Murray 	case oGlobalKnownHostsFile:
502511b41d2SMark Murray 		charptr = &options->system_hostfile;
503511b41d2SMark Murray 		goto parse_string;
504511b41d2SMark Murray 
505511b41d2SMark Murray 	case oUserKnownHostsFile:
506511b41d2SMark Murray 		charptr = &options->user_hostfile;
507511b41d2SMark Murray 		goto parse_string;
508511b41d2SMark Murray 
509e8aafc91SKris Kennaway 	case oGlobalKnownHostsFile2:
510e8aafc91SKris Kennaway 		charptr = &options->system_hostfile2;
511e8aafc91SKris Kennaway 		goto parse_string;
512e8aafc91SKris Kennaway 
513e8aafc91SKris Kennaway 	case oUserKnownHostsFile2:
514e8aafc91SKris Kennaway 		charptr = &options->user_hostfile2;
515e8aafc91SKris Kennaway 		goto parse_string;
516e8aafc91SKris Kennaway 
517511b41d2SMark Murray 	case oHostName:
518511b41d2SMark Murray 		charptr = &options->hostname;
519511b41d2SMark Murray 		goto parse_string;
520511b41d2SMark Murray 
521ca3176e7SBrian Feldman 	case oHostKeyAlias:
522ca3176e7SBrian Feldman 		charptr = &options->host_key_alias;
523ca3176e7SBrian Feldman 		goto parse_string;
524ca3176e7SBrian Feldman 
525ca3176e7SBrian Feldman 	case oPreferredAuthentications:
526ca3176e7SBrian Feldman 		charptr = &options->preferred_authentications;
527ca3176e7SBrian Feldman 		goto parse_string;
528ca3176e7SBrian Feldman 
529af12a3e7SDag-Erling Smørgrav 	case oBindAddress:
530af12a3e7SDag-Erling Smørgrav 		charptr = &options->bind_address;
531af12a3e7SDag-Erling Smørgrav 		goto parse_string;
532af12a3e7SDag-Erling Smørgrav 
533af12a3e7SDag-Erling Smørgrav 	case oSmartcardDevice:
534af12a3e7SDag-Erling Smørgrav 		charptr = &options->smartcard_device;
535af12a3e7SDag-Erling Smørgrav 		goto parse_string;
536af12a3e7SDag-Erling Smørgrav 
537511b41d2SMark Murray 	case oProxyCommand:
538cf2b5f3bSDag-Erling Smørgrav 		if (s == NULL)
539cf2b5f3bSDag-Erling Smørgrav 			fatal("%.200s line %d: Missing argument.", filename, linenum);
540511b41d2SMark Murray 		charptr = &options->proxy_command;
541e73e9afaSDag-Erling Smørgrav 		len = strspn(s, WHITESPACE "=");
542511b41d2SMark Murray 		if (*activep && *charptr == NULL)
543e73e9afaSDag-Erling Smørgrav 			*charptr = xstrdup(s + len);
544511b41d2SMark Murray 		return 0;
545511b41d2SMark Murray 
546511b41d2SMark Murray 	case oPort:
547511b41d2SMark Murray 		intptr = &options->port;
548511b41d2SMark Murray parse_int:
549c2d3a559SKris Kennaway 		arg = strdelim(&s);
550c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
551511b41d2SMark Murray 			fatal("%.200s line %d: Missing argument.", filename, linenum);
552c2d3a559SKris Kennaway 		if (arg[0] < '0' || arg[0] > '9')
553511b41d2SMark Murray 			fatal("%.200s line %d: Bad number.", filename, linenum);
554511b41d2SMark Murray 
555511b41d2SMark Murray 		/* Octal, decimal, or hex format? */
556c2d3a559SKris Kennaway 		value = strtol(arg, &endofnumber, 0);
557c2d3a559SKris Kennaway 		if (arg == endofnumber)
558511b41d2SMark Murray 			fatal("%.200s line %d: Bad number.", filename, linenum);
559511b41d2SMark Murray 		if (*activep && *intptr == -1)
560511b41d2SMark Murray 			*intptr = value;
561511b41d2SMark Murray 		break;
562511b41d2SMark Murray 
563511b41d2SMark Murray 	case oConnectionAttempts:
564511b41d2SMark Murray 		intptr = &options->connection_attempts;
565511b41d2SMark Murray 		goto parse_int;
566511b41d2SMark Murray 
567511b41d2SMark Murray 	case oCipher:
568511b41d2SMark Murray 		intptr = &options->cipher;
569c2d3a559SKris Kennaway 		arg = strdelim(&s);
570c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
571db1cb46cSKris Kennaway 			fatal("%.200s line %d: Missing argument.", filename, linenum);
572c2d3a559SKris Kennaway 		value = cipher_number(arg);
573511b41d2SMark Murray 		if (value == -1)
574511b41d2SMark Murray 			fatal("%.200s line %d: Bad cipher '%s'.",
575c2d3a559SKris Kennaway 			    filename, linenum, arg ? arg : "<NONE>");
576511b41d2SMark Murray 		if (*activep && *intptr == -1)
577511b41d2SMark Murray 			*intptr = value;
578511b41d2SMark Murray 		break;
579511b41d2SMark Murray 
580e8aafc91SKris Kennaway 	case oCiphers:
581c2d3a559SKris Kennaway 		arg = strdelim(&s);
582c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
583db1cb46cSKris Kennaway 			fatal("%.200s line %d: Missing argument.", filename, linenum);
584c2d3a559SKris Kennaway 		if (!ciphers_valid(arg))
585e8aafc91SKris Kennaway 			fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
586c2d3a559SKris Kennaway 			    filename, linenum, arg ? arg : "<NONE>");
587e8aafc91SKris Kennaway 		if (*activep && options->ciphers == NULL)
588c2d3a559SKris Kennaway 			options->ciphers = xstrdup(arg);
589e8aafc91SKris Kennaway 		break;
590e8aafc91SKris Kennaway 
591ca3176e7SBrian Feldman 	case oMacs:
592ca3176e7SBrian Feldman 		arg = strdelim(&s);
593ca3176e7SBrian Feldman 		if (!arg || *arg == '\0')
594ca3176e7SBrian Feldman 			fatal("%.200s line %d: Missing argument.", filename, linenum);
595ca3176e7SBrian Feldman 		if (!mac_valid(arg))
596ca3176e7SBrian Feldman 			fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
597ca3176e7SBrian Feldman 			    filename, linenum, arg ? arg : "<NONE>");
598ca3176e7SBrian Feldman 		if (*activep && options->macs == NULL)
599ca3176e7SBrian Feldman 			options->macs = xstrdup(arg);
600ca3176e7SBrian Feldman 		break;
601ca3176e7SBrian Feldman 
602ca3176e7SBrian Feldman 	case oHostKeyAlgorithms:
603ca3176e7SBrian Feldman 		arg = strdelim(&s);
604ca3176e7SBrian Feldman 		if (!arg || *arg == '\0')
605ca3176e7SBrian Feldman 			fatal("%.200s line %d: Missing argument.", filename, linenum);
606ca3176e7SBrian Feldman 		if (!key_names_valid2(arg))
607ca3176e7SBrian Feldman 			fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
608ca3176e7SBrian Feldman 			    filename, linenum, arg ? arg : "<NONE>");
609ca3176e7SBrian Feldman 		if (*activep && options->hostkeyalgorithms == NULL)
610ca3176e7SBrian Feldman 			options->hostkeyalgorithms = xstrdup(arg);
611ca3176e7SBrian Feldman 		break;
612ca3176e7SBrian Feldman 
613e8aafc91SKris Kennaway 	case oProtocol:
614e8aafc91SKris Kennaway 		intptr = &options->protocol;
615c2d3a559SKris Kennaway 		arg = strdelim(&s);
616c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
617db1cb46cSKris Kennaway 			fatal("%.200s line %d: Missing argument.", filename, linenum);
618c2d3a559SKris Kennaway 		value = proto_spec(arg);
619e8aafc91SKris Kennaway 		if (value == SSH_PROTO_UNKNOWN)
620e8aafc91SKris Kennaway 			fatal("%.200s line %d: Bad protocol spec '%s'.",
621c2d3a559SKris Kennaway 			    filename, linenum, arg ? arg : "<NONE>");
622e8aafc91SKris Kennaway 		if (*activep && *intptr == SSH_PROTO_UNKNOWN)
623e8aafc91SKris Kennaway 			*intptr = value;
624e8aafc91SKris Kennaway 		break;
625e8aafc91SKris Kennaway 
626511b41d2SMark Murray 	case oLogLevel:
627511b41d2SMark Murray 		intptr = (int *) &options->log_level;
628c2d3a559SKris Kennaway 		arg = strdelim(&s);
629c2d3a559SKris Kennaway 		value = log_level_number(arg);
630af12a3e7SDag-Erling Smørgrav 		if (value == SYSLOG_LEVEL_NOT_SET)
631ca3176e7SBrian Feldman 			fatal("%.200s line %d: unsupported log level '%s'",
632c2d3a559SKris Kennaway 			    filename, linenum, arg ? arg : "<NONE>");
633af12a3e7SDag-Erling Smørgrav 		if (*activep && (LogLevel) *intptr == SYSLOG_LEVEL_NOT_SET)
634511b41d2SMark Murray 			*intptr = (LogLevel) value;
635511b41d2SMark Murray 		break;
636511b41d2SMark Murray 
637af12a3e7SDag-Erling Smørgrav 	case oLocalForward:
638511b41d2SMark Murray 	case oRemoteForward:
639c2d3a559SKris Kennaway 		arg = strdelim(&s);
640c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
641af12a3e7SDag-Erling Smørgrav 			fatal("%.200s line %d: Missing port argument.",
642af12a3e7SDag-Erling Smørgrav 			    filename, linenum);
643af12a3e7SDag-Erling Smørgrav 		if ((fwd_port = a2port(arg)) == 0)
644af12a3e7SDag-Erling Smørgrav 			fatal("%.200s line %d: Bad listen port.",
645511b41d2SMark Murray 			    filename, linenum);
646c2d3a559SKris Kennaway 		arg = strdelim(&s);
647c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
648511b41d2SMark Murray 			fatal("%.200s line %d: Missing second argument.",
649511b41d2SMark Murray 			    filename, linenum);
650af12a3e7SDag-Erling Smørgrav 		if (sscanf(arg, "%255[^:]:%5[0-9]", buf, sfwd_host_port) != 2 &&
651af12a3e7SDag-Erling Smørgrav 		    sscanf(arg, "%255[^/]/%5[0-9]", buf, sfwd_host_port) != 2)
652af12a3e7SDag-Erling Smørgrav 			fatal("%.200s line %d: Bad forwarding specification.",
653511b41d2SMark Murray 			    filename, linenum);
654af12a3e7SDag-Erling Smørgrav 		if ((fwd_host_port = a2port(sfwd_host_port)) == 0)
655af12a3e7SDag-Erling Smørgrav 			fatal("%.200s line %d: Bad forwarding port.",
656511b41d2SMark Murray 			    filename, linenum);
657af12a3e7SDag-Erling Smørgrav 		if (*activep) {
658af12a3e7SDag-Erling Smørgrav 			if (opcode == oLocalForward)
659af12a3e7SDag-Erling Smørgrav 				add_local_forward(options, fwd_port, buf,
660af12a3e7SDag-Erling Smørgrav 				    fwd_host_port);
661af12a3e7SDag-Erling Smørgrav 			else if (opcode == oRemoteForward)
662af12a3e7SDag-Erling Smørgrav 				add_remote_forward(options, fwd_port, buf,
663af12a3e7SDag-Erling Smørgrav 				    fwd_host_port);
664af12a3e7SDag-Erling Smørgrav 		}
665511b41d2SMark Murray 		break;
666511b41d2SMark Murray 
667ca3176e7SBrian Feldman 	case oDynamicForward:
668ca3176e7SBrian Feldman 		arg = strdelim(&s);
669ca3176e7SBrian Feldman 		if (!arg || *arg == '\0')
670ca3176e7SBrian Feldman 			fatal("%.200s line %d: Missing port argument.",
671ca3176e7SBrian Feldman 			    filename, linenum);
672ca3176e7SBrian Feldman 		fwd_port = a2port(arg);
673ca3176e7SBrian Feldman 		if (fwd_port == 0)
674ca3176e7SBrian Feldman 			fatal("%.200s line %d: Badly formatted port number.",
675ca3176e7SBrian Feldman 			    filename, linenum);
676af12a3e7SDag-Erling Smørgrav 		if (*activep)
677cf2b5f3bSDag-Erling Smørgrav 			add_local_forward(options, fwd_port, "socks", 0);
678ca3176e7SBrian Feldman 		break;
679ca3176e7SBrian Feldman 
680af12a3e7SDag-Erling Smørgrav 	case oClearAllForwardings:
681af12a3e7SDag-Erling Smørgrav 		intptr = &options->clear_forwardings;
682af12a3e7SDag-Erling Smørgrav 		goto parse_flag;
683af12a3e7SDag-Erling Smørgrav 
684511b41d2SMark Murray 	case oHost:
685511b41d2SMark Murray 		*activep = 0;
686c2d3a559SKris Kennaway 		while ((arg = strdelim(&s)) != NULL && *arg != '\0')
687c2d3a559SKris Kennaway 			if (match_pattern(host, arg)) {
688c2d3a559SKris Kennaway 				debug("Applying options for %.100s", arg);
689511b41d2SMark Murray 				*activep = 1;
690511b41d2SMark Murray 				break;
691511b41d2SMark Murray 			}
692c2d3a559SKris Kennaway 		/* Avoid garbage check below, as strdelim is done. */
693511b41d2SMark Murray 		return 0;
694511b41d2SMark Murray 
695511b41d2SMark Murray 	case oEscapeChar:
696511b41d2SMark Murray 		intptr = &options->escape_char;
697c2d3a559SKris Kennaway 		arg = strdelim(&s);
698c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
699511b41d2SMark Murray 			fatal("%.200s line %d: Missing argument.", filename, linenum);
700c2d3a559SKris Kennaway 		if (arg[0] == '^' && arg[2] == 0 &&
701ca3176e7SBrian Feldman 		    (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
702ca3176e7SBrian Feldman 			value = (u_char) arg[1] & 31;
703c2d3a559SKris Kennaway 		else if (strlen(arg) == 1)
704ca3176e7SBrian Feldman 			value = (u_char) arg[0];
705c2d3a559SKris Kennaway 		else if (strcmp(arg, "none") == 0)
706af12a3e7SDag-Erling Smørgrav 			value = SSH_ESCAPECHAR_NONE;
707511b41d2SMark Murray 		else {
708511b41d2SMark Murray 			fatal("%.200s line %d: Bad escape character.",
709511b41d2SMark Murray 			    filename, linenum);
710511b41d2SMark Murray 			/* NOTREACHED */
711511b41d2SMark Murray 			value = 0;	/* Avoid compiler warning. */
712511b41d2SMark Murray 		}
713511b41d2SMark Murray 		if (*activep && *intptr == -1)
714511b41d2SMark Murray 			*intptr = value;
715511b41d2SMark Murray 		break;
716511b41d2SMark Murray 
717cf2b5f3bSDag-Erling Smørgrav 	case oAddressFamily:
718cf2b5f3bSDag-Erling Smørgrav 		arg = strdelim(&s);
719cf2b5f3bSDag-Erling Smørgrav 		intptr = &options->address_family;
720cf2b5f3bSDag-Erling Smørgrav 		if (strcasecmp(arg, "inet") == 0)
721cf2b5f3bSDag-Erling Smørgrav 			value = AF_INET;
722cf2b5f3bSDag-Erling Smørgrav 		else if (strcasecmp(arg, "inet6") == 0)
723cf2b5f3bSDag-Erling Smørgrav 			value = AF_INET6;
724cf2b5f3bSDag-Erling Smørgrav 		else if (strcasecmp(arg, "any") == 0)
725cf2b5f3bSDag-Erling Smørgrav 			value = AF_UNSPEC;
726cf2b5f3bSDag-Erling Smørgrav 		else
727cf2b5f3bSDag-Erling Smørgrav 			fatal("Unsupported AddressFamily \"%s\"", arg);
728cf2b5f3bSDag-Erling Smørgrav 		if (*activep && *intptr == -1)
729cf2b5f3bSDag-Erling Smørgrav 			*intptr = value;
730cf2b5f3bSDag-Erling Smørgrav 		break;
731cf2b5f3bSDag-Erling Smørgrav 
732e73e9afaSDag-Erling Smørgrav 	case oEnableSSHKeysign:
733e73e9afaSDag-Erling Smørgrav 		intptr = &options->enable_ssh_keysign;
734e73e9afaSDag-Erling Smørgrav 		goto parse_flag;
735e73e9afaSDag-Erling Smørgrav 
736975616f0SDag-Erling Smørgrav 	case oVersionAddendum:
737975616f0SDag-Erling Smørgrav 		ssh_version_set_addendum(strtok(s, "\n"));
738975616f0SDag-Erling Smørgrav 		do {
739975616f0SDag-Erling Smørgrav 			arg = strdelim(&s);
740975616f0SDag-Erling Smørgrav 		} while (arg != NULL && *arg != '\0');
741975616f0SDag-Erling Smørgrav 		break;
742975616f0SDag-Erling Smørgrav 
74380628bacSDag-Erling Smørgrav 	case oDeprecated:
74480628bacSDag-Erling Smørgrav 		debug("%s line %d: Deprecated option \"%s\"",
74580628bacSDag-Erling Smørgrav 		    filename, linenum, keyword);
74680628bacSDag-Erling Smørgrav 		return 0;
74780628bacSDag-Erling Smørgrav 
748cf2b5f3bSDag-Erling Smørgrav 	case oUnsupported:
749cf2b5f3bSDag-Erling Smørgrav 		error("%s line %d: Unsupported option \"%s\"",
750cf2b5f3bSDag-Erling Smørgrav 		    filename, linenum, keyword);
751cf2b5f3bSDag-Erling Smørgrav 		return 0;
752cf2b5f3bSDag-Erling Smørgrav 
753511b41d2SMark Murray 	default:
754511b41d2SMark Murray 		fatal("process_config_line: Unimplemented opcode %d", opcode);
755511b41d2SMark Murray 	}
756511b41d2SMark Murray 
757511b41d2SMark Murray 	/* Check that there is no garbage at end of line. */
758ca3176e7SBrian Feldman 	if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
759c2d3a559SKris Kennaway 		fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
760c2d3a559SKris Kennaway 		     filename, linenum, arg);
761c2d3a559SKris Kennaway 	}
762511b41d2SMark Murray 	return 0;
763511b41d2SMark Murray }
764511b41d2SMark Murray 
765511b41d2SMark Murray 
766511b41d2SMark Murray /*
767511b41d2SMark Murray  * Reads the config file and modifies the options accordingly.  Options
768511b41d2SMark Murray  * should already be initialized before this call.  This never returns if
769af12a3e7SDag-Erling Smørgrav  * there is an error.  If the file does not exist, this returns 0.
770511b41d2SMark Murray  */
771511b41d2SMark Murray 
772af12a3e7SDag-Erling Smørgrav int
773511b41d2SMark Murray read_config_file(const char *filename, const char *host, Options *options)
774511b41d2SMark Murray {
775511b41d2SMark Murray 	FILE *f;
776511b41d2SMark Murray 	char line[1024];
777511b41d2SMark Murray 	int active, linenum;
778511b41d2SMark Murray 	int bad_options = 0;
779511b41d2SMark Murray 
780511b41d2SMark Murray 	/* Open the file. */
781511b41d2SMark Murray 	f = fopen(filename, "r");
782511b41d2SMark Murray 	if (!f)
783af12a3e7SDag-Erling Smørgrav 		return 0;
784511b41d2SMark Murray 
785511b41d2SMark Murray 	debug("Reading configuration data %.200s", filename);
786511b41d2SMark Murray 
787511b41d2SMark Murray 	/*
788511b41d2SMark Murray 	 * Mark that we are now processing the options.  This flag is turned
789511b41d2SMark Murray 	 * on/off by Host specifications.
790511b41d2SMark Murray 	 */
791511b41d2SMark Murray 	active = 1;
792511b41d2SMark Murray 	linenum = 0;
793511b41d2SMark Murray 	while (fgets(line, sizeof(line), f)) {
794511b41d2SMark Murray 		/* Update line number counter. */
795511b41d2SMark Murray 		linenum++;
796511b41d2SMark Murray 		if (process_config_line(options, host, line, filename, linenum, &active) != 0)
797511b41d2SMark Murray 			bad_options++;
798511b41d2SMark Murray 	}
799511b41d2SMark Murray 	fclose(f);
800511b41d2SMark Murray 	if (bad_options > 0)
801ca3176e7SBrian Feldman 		fatal("%s: terminating, %d bad configuration options",
802511b41d2SMark Murray 		    filename, bad_options);
803af12a3e7SDag-Erling Smørgrav 	return 1;
804511b41d2SMark Murray }
805511b41d2SMark Murray 
806511b41d2SMark Murray /*
807511b41d2SMark Murray  * Initializes options to special values that indicate that they have not yet
808511b41d2SMark Murray  * been set.  Read_config_file will only set options with this value. Options
809511b41d2SMark Murray  * are processed in the following order: command line, user config file,
810511b41d2SMark Murray  * system config file.  Last, fill_default_options is called.
811511b41d2SMark Murray  */
812511b41d2SMark Murray 
813511b41d2SMark Murray void
814511b41d2SMark Murray initialize_options(Options * options)
815511b41d2SMark Murray {
816511b41d2SMark Murray 	memset(options, 'X', sizeof(*options));
817511b41d2SMark Murray 	options->forward_agent = -1;
818511b41d2SMark Murray 	options->forward_x11 = -1;
819c2d3a559SKris Kennaway 	options->xauth_location = NULL;
820511b41d2SMark Murray 	options->gateway_ports = -1;
821511b41d2SMark Murray 	options->use_privileged_port = -1;
822511b41d2SMark Murray 	options->rsa_authentication = -1;
823ca3176e7SBrian Feldman 	options->pubkey_authentication = -1;
824af12a3e7SDag-Erling Smørgrav 	options->challenge_response_authentication = -1;
825cf2b5f3bSDag-Erling Smørgrav 	options->gss_authentication = -1;
826cf2b5f3bSDag-Erling Smørgrav 	options->gss_deleg_creds = -1;
827511b41d2SMark Murray 	options->password_authentication = -1;
82809958426SBrian Feldman 	options->kbd_interactive_authentication = -1;
82909958426SBrian Feldman 	options->kbd_interactive_devices = NULL;
830511b41d2SMark Murray 	options->rhosts_rsa_authentication = -1;
831ca3176e7SBrian Feldman 	options->hostbased_authentication = -1;
832511b41d2SMark Murray 	options->batch_mode = -1;
833511b41d2SMark Murray 	options->check_host_ip = -1;
834511b41d2SMark Murray 	options->strict_host_key_checking = -1;
835511b41d2SMark Murray 	options->compression = -1;
836511b41d2SMark Murray 	options->keepalives = -1;
837511b41d2SMark Murray 	options->compression_level = -1;
838511b41d2SMark Murray 	options->port = -1;
839cf2b5f3bSDag-Erling Smørgrav 	options->address_family = -1;
840511b41d2SMark Murray 	options->connection_attempts = -1;
841cf2b5f3bSDag-Erling Smørgrav 	options->connection_timeout = -1;
842511b41d2SMark Murray 	options->number_of_password_prompts = -1;
843511b41d2SMark Murray 	options->cipher = -1;
844e8aafc91SKris Kennaway 	options->ciphers = NULL;
845ca3176e7SBrian Feldman 	options->macs = NULL;
846ca3176e7SBrian Feldman 	options->hostkeyalgorithms = NULL;
847e8aafc91SKris Kennaway 	options->protocol = SSH_PROTO_UNKNOWN;
848511b41d2SMark Murray 	options->num_identity_files = 0;
849511b41d2SMark Murray 	options->hostname = NULL;
850ca3176e7SBrian Feldman 	options->host_key_alias = NULL;
851511b41d2SMark Murray 	options->proxy_command = NULL;
852511b41d2SMark Murray 	options->user = NULL;
853511b41d2SMark Murray 	options->escape_char = -1;
854511b41d2SMark Murray 	options->system_hostfile = NULL;
855511b41d2SMark Murray 	options->user_hostfile = NULL;
856e8aafc91SKris Kennaway 	options->system_hostfile2 = NULL;
857e8aafc91SKris Kennaway 	options->user_hostfile2 = NULL;
858511b41d2SMark Murray 	options->num_local_forwards = 0;
859511b41d2SMark Murray 	options->num_remote_forwards = 0;
860af12a3e7SDag-Erling Smørgrav 	options->clear_forwardings = -1;
861af12a3e7SDag-Erling Smørgrav 	options->log_level = SYSLOG_LEVEL_NOT_SET;
862ca3176e7SBrian Feldman 	options->preferred_authentications = NULL;
863af12a3e7SDag-Erling Smørgrav 	options->bind_address = NULL;
864af12a3e7SDag-Erling Smørgrav 	options->smartcard_device = NULL;
865e73e9afaSDag-Erling Smørgrav 	options->enable_ssh_keysign = - 1;
866af12a3e7SDag-Erling Smørgrav 	options->no_host_authentication_for_localhost = - 1;
867cf2b5f3bSDag-Erling Smørgrav 	options->rekey_limit = - 1;
868cf2b5f3bSDag-Erling Smørgrav 	options->verify_host_key_dns = -1;
869511b41d2SMark Murray }
870511b41d2SMark Murray 
871511b41d2SMark Murray /*
872511b41d2SMark Murray  * Called after processing other sources of option data, this fills those
873511b41d2SMark Murray  * options for which no value has been specified with their default values.
874511b41d2SMark Murray  */
875511b41d2SMark Murray 
876511b41d2SMark Murray void
877511b41d2SMark Murray fill_default_options(Options * options)
878511b41d2SMark Murray {
879ca3176e7SBrian Feldman 	int len;
880ca3176e7SBrian Feldman 
881511b41d2SMark Murray 	if (options->forward_agent == -1)
882db1cb46cSKris Kennaway 		options->forward_agent = 0;
883511b41d2SMark Murray 	if (options->forward_x11 == -1)
8845dc73ebeSBrian Feldman 		options->forward_x11 = 0;
885c2d3a559SKris Kennaway 	if (options->xauth_location == NULL)
886af12a3e7SDag-Erling Smørgrav 		options->xauth_location = _PATH_XAUTH;
887511b41d2SMark Murray 	if (options->gateway_ports == -1)
888511b41d2SMark Murray 		options->gateway_ports = 0;
889511b41d2SMark Murray 	if (options->use_privileged_port == -1)
890ca3176e7SBrian Feldman 		options->use_privileged_port = 0;
891511b41d2SMark Murray 	if (options->rsa_authentication == -1)
892511b41d2SMark Murray 		options->rsa_authentication = 1;
893ca3176e7SBrian Feldman 	if (options->pubkey_authentication == -1)
894ca3176e7SBrian Feldman 		options->pubkey_authentication = 1;
895af12a3e7SDag-Erling Smørgrav 	if (options->challenge_response_authentication == -1)
896af12a3e7SDag-Erling Smørgrav 		options->challenge_response_authentication = 1;
897cf2b5f3bSDag-Erling Smørgrav 	if (options->gss_authentication == -1)
898cf2b5f3bSDag-Erling Smørgrav 		options->gss_authentication = 1;
899cf2b5f3bSDag-Erling Smørgrav 	if (options->gss_deleg_creds == -1)
900cf2b5f3bSDag-Erling Smørgrav 		options->gss_deleg_creds = 0;
901511b41d2SMark Murray 	if (options->password_authentication == -1)
902511b41d2SMark Murray 		options->password_authentication = 1;
90309958426SBrian Feldman 	if (options->kbd_interactive_authentication == -1)
904ca3176e7SBrian Feldman 		options->kbd_interactive_authentication = 1;
905511b41d2SMark Murray 	if (options->rhosts_rsa_authentication == -1)
90680628bacSDag-Erling Smørgrav 		options->rhosts_rsa_authentication = 0;
907ca3176e7SBrian Feldman 	if (options->hostbased_authentication == -1)
908ca3176e7SBrian Feldman 		options->hostbased_authentication = 0;
909511b41d2SMark Murray 	if (options->batch_mode == -1)
910511b41d2SMark Murray 		options->batch_mode = 0;
911511b41d2SMark Murray 	if (options->check_host_ip == -1)
912975616f0SDag-Erling Smørgrav 		options->check_host_ip = 0;
913511b41d2SMark Murray 	if (options->strict_host_key_checking == -1)
914511b41d2SMark Murray 		options->strict_host_key_checking = 2;	/* 2 is default */
915511b41d2SMark Murray 	if (options->compression == -1)
916511b41d2SMark Murray 		options->compression = 0;
917511b41d2SMark Murray 	if (options->keepalives == -1)
918511b41d2SMark Murray 		options->keepalives = 1;
919511b41d2SMark Murray 	if (options->compression_level == -1)
920511b41d2SMark Murray 		options->compression_level = 6;
921511b41d2SMark Murray 	if (options->port == -1)
922511b41d2SMark Murray 		options->port = 0;	/* Filled in ssh_connect. */
923cf2b5f3bSDag-Erling Smørgrav 	if (options->address_family == -1)
924cf2b5f3bSDag-Erling Smørgrav 		options->address_family = AF_UNSPEC;
925511b41d2SMark Murray 	if (options->connection_attempts == -1)
926af12a3e7SDag-Erling Smørgrav 		options->connection_attempts = 1;
927511b41d2SMark Murray 	if (options->number_of_password_prompts == -1)
928511b41d2SMark Murray 		options->number_of_password_prompts = 3;
929511b41d2SMark Murray 	/* Selected in ssh_login(). */
930511b41d2SMark Murray 	if (options->cipher == -1)
931511b41d2SMark Murray 		options->cipher = SSH_CIPHER_NOT_SET;
932e8aafc91SKris Kennaway 	/* options->ciphers, default set in myproposals.h */
933ca3176e7SBrian Feldman 	/* options->macs, default set in myproposals.h */
934ca3176e7SBrian Feldman 	/* options->hostkeyalgorithms, default set in myproposals.h */
935e8aafc91SKris Kennaway 	if (options->protocol == SSH_PROTO_UNKNOWN)
936ca3176e7SBrian Feldman 		options->protocol = SSH_PROTO_1|SSH_PROTO_2;
937511b41d2SMark Murray 	if (options->num_identity_files == 0) {
938ca3176e7SBrian Feldman 		if (options->protocol & SSH_PROTO_1) {
939ca3176e7SBrian Feldman 			len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1;
940ca3176e7SBrian Feldman 			options->identity_files[options->num_identity_files] =
941ca3176e7SBrian Feldman 			    xmalloc(len);
942ca3176e7SBrian Feldman 			snprintf(options->identity_files[options->num_identity_files++],
943ca3176e7SBrian Feldman 			    len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY);
944511b41d2SMark Murray 		}
945ca3176e7SBrian Feldman 		if (options->protocol & SSH_PROTO_2) {
946ca3176e7SBrian Feldman 			len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1;
947ca3176e7SBrian Feldman 			options->identity_files[options->num_identity_files] =
948ca3176e7SBrian Feldman 			    xmalloc(len);
949ca3176e7SBrian Feldman 			snprintf(options->identity_files[options->num_identity_files++],
950ca3176e7SBrian Feldman 			    len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA);
951ca3176e7SBrian Feldman 
952ca3176e7SBrian Feldman 			len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1;
953ca3176e7SBrian Feldman 			options->identity_files[options->num_identity_files] =
954ca3176e7SBrian Feldman 			    xmalloc(len);
955ca3176e7SBrian Feldman 			snprintf(options->identity_files[options->num_identity_files++],
956ca3176e7SBrian Feldman 			    len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA);
957ca3176e7SBrian Feldman 		}
958e8aafc91SKris Kennaway 	}
959511b41d2SMark Murray 	if (options->escape_char == -1)
960511b41d2SMark Murray 		options->escape_char = '~';
961511b41d2SMark Murray 	if (options->system_hostfile == NULL)
962ca3176e7SBrian Feldman 		options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE;
963511b41d2SMark Murray 	if (options->user_hostfile == NULL)
964ca3176e7SBrian Feldman 		options->user_hostfile = _PATH_SSH_USER_HOSTFILE;
965e8aafc91SKris Kennaway 	if (options->system_hostfile2 == NULL)
966ca3176e7SBrian Feldman 		options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2;
967e8aafc91SKris Kennaway 	if (options->user_hostfile2 == NULL)
968ca3176e7SBrian Feldman 		options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2;
969af12a3e7SDag-Erling Smørgrav 	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
970511b41d2SMark Murray 		options->log_level = SYSLOG_LEVEL_INFO;
971af12a3e7SDag-Erling Smørgrav 	if (options->clear_forwardings == 1)
972af12a3e7SDag-Erling Smørgrav 		clear_forwardings(options);
973af12a3e7SDag-Erling Smørgrav 	if (options->no_host_authentication_for_localhost == - 1)
974af12a3e7SDag-Erling Smørgrav 		options->no_host_authentication_for_localhost = 0;
975e73e9afaSDag-Erling Smørgrav 	if (options->enable_ssh_keysign == -1)
976e73e9afaSDag-Erling Smørgrav 		options->enable_ssh_keysign = 0;
977cf2b5f3bSDag-Erling Smørgrav 	if (options->rekey_limit == -1)
978cf2b5f3bSDag-Erling Smørgrav 		options->rekey_limit = 0;
979cf2b5f3bSDag-Erling Smørgrav 	if (options->verify_host_key_dns == -1)
980cf2b5f3bSDag-Erling Smørgrav 		options->verify_host_key_dns = 0;
981511b41d2SMark Murray 	/* options->proxy_command should not be set by default */
982511b41d2SMark Murray 	/* options->user will be set in the main program if appropriate */
983511b41d2SMark Murray 	/* options->hostname will be set in the main program if appropriate */
984ca3176e7SBrian Feldman 	/* options->host_key_alias should not be set by default */
985ca3176e7SBrian Feldman 	/* options->preferred_authentications will be set in ssh */
986511b41d2SMark Murray }
987