xref: /freebsd/crypto/openssh/readconf.c (revision b74df5b26fa43e05a034a6ce662dcf286a1ffdd9)
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"
15b74df5b2SDag-Erling Smørgrav RCSID("$OpenBSD: readconf.c,v 1.145 2005/12/08 18:34:11 reyk 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 
74b74df5b2SDag-Erling Smørgrav    Host vpn.fake.com
75b74df5b2SDag-Erling Smørgrav      Tunnel yes
76b74df5b2SDag-Erling Smørgrav      TunnelDevice 3
77b74df5b2SDag-Erling Smørgrav 
78511b41d2SMark Murray    # Defaults for various options
79511b41d2SMark Murray    Host *
80511b41d2SMark Murray      ForwardAgent no
81ca3176e7SBrian Feldman      ForwardX11 no
82511b41d2SMark Murray      PasswordAuthentication yes
83511b41d2SMark Murray      RSAAuthentication yes
84511b41d2SMark Murray      RhostsRSAAuthentication yes
85511b41d2SMark Murray      StrictHostKeyChecking yes
861ec0d754SDag-Erling Smørgrav      TcpKeepAlive no
87511b41d2SMark Murray      IdentityFile ~/.ssh/identity
88511b41d2SMark Murray      Port 22
89511b41d2SMark Murray      EscapeChar ~
90511b41d2SMark Murray 
91511b41d2SMark Murray */
92511b41d2SMark Murray 
93511b41d2SMark Murray /* Keyword tokens. */
94511b41d2SMark Murray 
95511b41d2SMark Murray typedef enum {
96511b41d2SMark Murray 	oBadOption,
971ec0d754SDag-Erling Smørgrav 	oForwardAgent, oForwardX11, oForwardX11Trusted, oGatewayPorts,
9880628bacSDag-Erling Smørgrav 	oPasswordAuthentication, oRSAAuthentication,
99ca3176e7SBrian Feldman 	oChallengeResponseAuthentication, oXAuthLocation,
100511b41d2SMark Murray 	oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
101511b41d2SMark Murray 	oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
102511b41d2SMark Murray 	oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
103511b41d2SMark Murray 	oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
1041ec0d754SDag-Erling Smørgrav 	oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
105ca3176e7SBrian Feldman 	oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
106ca3176e7SBrian Feldman 	oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
107ca3176e7SBrian Feldman 	oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
108ca3176e7SBrian Feldman 	oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
109af12a3e7SDag-Erling Smørgrav 	oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
1109e2cbe04SDag-Erling Smørgrav 	oClearAllForwardings, oNoHostAuthenticationForLocalhost,
111cf2b5f3bSDag-Erling Smørgrav 	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
112cf2b5f3bSDag-Erling Smørgrav 	oAddressFamily, oGssAuthentication, oGssDelegateCreds,
1135962c0e9SDag-Erling Smørgrav 	oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
114aa49c926SDag-Erling Smørgrav 	oSendEnv, oControlPath, oControlMaster, oHashKnownHosts,
115b74df5b2SDag-Erling Smørgrav 	oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
116cfa59440SDag-Erling Smørgrav 	oVersionAddendum,
117cf2b5f3bSDag-Erling Smørgrav 	oDeprecated, oUnsupported
118511b41d2SMark Murray } OpCodes;
119511b41d2SMark Murray 
120511b41d2SMark Murray /* Textual representations of the tokens. */
121511b41d2SMark Murray 
122511b41d2SMark Murray static struct {
123511b41d2SMark Murray 	const char *name;
124511b41d2SMark Murray 	OpCodes opcode;
125511b41d2SMark Murray } keywords[] = {
126511b41d2SMark Murray 	{ "forwardagent", oForwardAgent },
127511b41d2SMark Murray 	{ "forwardx11", oForwardX11 },
1281ec0d754SDag-Erling Smørgrav 	{ "forwardx11trusted", oForwardX11Trusted },
129c2d3a559SKris Kennaway 	{ "xauthlocation", oXAuthLocation },
130511b41d2SMark Murray 	{ "gatewayports", oGatewayPorts },
131511b41d2SMark Murray 	{ "useprivilegedport", oUsePrivilegedPort },
132cf2b5f3bSDag-Erling Smørgrav 	{ "rhostsauthentication", oDeprecated },
133511b41d2SMark Murray 	{ "passwordauthentication", oPasswordAuthentication },
13409958426SBrian Feldman 	{ "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
13509958426SBrian Feldman 	{ "kbdinteractivedevices", oKbdInteractiveDevices },
136511b41d2SMark Murray 	{ "rsaauthentication", oRSAAuthentication },
137ca3176e7SBrian Feldman 	{ "pubkeyauthentication", oPubkeyAuthentication },
138ca3176e7SBrian Feldman 	{ "dsaauthentication", oPubkeyAuthentication },		    /* alias */
139ca3176e7SBrian Feldman 	{ "rhostsrsaauthentication", oRhostsRSAAuthentication },
140ca3176e7SBrian Feldman 	{ "hostbasedauthentication", oHostbasedAuthentication },
141ca3176e7SBrian Feldman 	{ "challengeresponseauthentication", oChallengeResponseAuthentication },
142ca3176e7SBrian Feldman 	{ "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
143ca3176e7SBrian Feldman 	{ "tisauthentication", oChallengeResponseAuthentication },  /* alias */
144cf2b5f3bSDag-Erling Smørgrav 	{ "kerberosauthentication", oUnsupported },
145cf2b5f3bSDag-Erling Smørgrav 	{ "kerberostgtpassing", oUnsupported },
146cf2b5f3bSDag-Erling Smørgrav 	{ "afstokenpassing", oUnsupported },
147cf2b5f3bSDag-Erling Smørgrav #if defined(GSSAPI)
148cf2b5f3bSDag-Erling Smørgrav 	{ "gssapiauthentication", oGssAuthentication },
149cf2b5f3bSDag-Erling Smørgrav 	{ "gssapidelegatecredentials", oGssDelegateCreds },
150cf2b5f3bSDag-Erling Smørgrav #else
151cf2b5f3bSDag-Erling Smørgrav 	{ "gssapiauthentication", oUnsupported },
152cf2b5f3bSDag-Erling Smørgrav 	{ "gssapidelegatecredentials", oUnsupported },
153511b41d2SMark Murray #endif
15480628bacSDag-Erling Smørgrav 	{ "fallbacktorsh", oDeprecated },
15580628bacSDag-Erling Smørgrav 	{ "usersh", oDeprecated },
156511b41d2SMark Murray 	{ "identityfile", oIdentityFile },
157ca3176e7SBrian Feldman 	{ "identityfile2", oIdentityFile },			/* alias */
1585962c0e9SDag-Erling Smørgrav 	{ "identitiesonly", oIdentitiesOnly },
159511b41d2SMark Murray 	{ "hostname", oHostName },
160ca3176e7SBrian Feldman 	{ "hostkeyalias", oHostKeyAlias },
161511b41d2SMark Murray 	{ "proxycommand", oProxyCommand },
162511b41d2SMark Murray 	{ "port", oPort },
163511b41d2SMark Murray 	{ "cipher", oCipher },
164e8aafc91SKris Kennaway 	{ "ciphers", oCiphers },
165ca3176e7SBrian Feldman 	{ "macs", oMacs },
166e8aafc91SKris Kennaway 	{ "protocol", oProtocol },
167511b41d2SMark Murray 	{ "remoteforward", oRemoteForward },
168511b41d2SMark Murray 	{ "localforward", oLocalForward },
169511b41d2SMark Murray 	{ "user", oUser },
170511b41d2SMark Murray 	{ "host", oHost },
171511b41d2SMark Murray 	{ "escapechar", oEscapeChar },
172511b41d2SMark Murray 	{ "globalknownhostsfile", oGlobalKnownHostsFile },
173af12a3e7SDag-Erling Smørgrav 	{ "userknownhostsfile", oUserKnownHostsFile },		/* obsolete */
174e8aafc91SKris Kennaway 	{ "globalknownhostsfile2", oGlobalKnownHostsFile2 },
175af12a3e7SDag-Erling Smørgrav 	{ "userknownhostsfile2", oUserKnownHostsFile2 },	/* obsolete */
176511b41d2SMark Murray 	{ "connectionattempts", oConnectionAttempts },
177511b41d2SMark Murray 	{ "batchmode", oBatchMode },
178511b41d2SMark Murray 	{ "checkhostip", oCheckHostIP },
179511b41d2SMark Murray 	{ "stricthostkeychecking", oStrictHostKeyChecking },
180511b41d2SMark Murray 	{ "compression", oCompression },
181511b41d2SMark Murray 	{ "compressionlevel", oCompressionLevel },
1821ec0d754SDag-Erling Smørgrav 	{ "tcpkeepalive", oTCPKeepAlive },
1831ec0d754SDag-Erling Smørgrav 	{ "keepalive", oTCPKeepAlive },				/* obsolete */
184511b41d2SMark Murray 	{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
185511b41d2SMark Murray 	{ "loglevel", oLogLevel },
186ca3176e7SBrian Feldman 	{ "dynamicforward", oDynamicForward },
187ca3176e7SBrian Feldman 	{ "preferredauthentications", oPreferredAuthentications },
188ca3176e7SBrian Feldman 	{ "hostkeyalgorithms", oHostKeyAlgorithms },
189af12a3e7SDag-Erling Smørgrav 	{ "bindaddress", oBindAddress },
190cf2b5f3bSDag-Erling Smørgrav #ifdef SMARTCARD
191af12a3e7SDag-Erling Smørgrav 	{ "smartcarddevice", oSmartcardDevice },
192cf2b5f3bSDag-Erling Smørgrav #else
193cf2b5f3bSDag-Erling Smørgrav 	{ "smartcarddevice", oUnsupported },
194cf2b5f3bSDag-Erling Smørgrav #endif
195af12a3e7SDag-Erling Smørgrav 	{ "clearallforwardings", oClearAllForwardings },
196e73e9afaSDag-Erling Smørgrav 	{ "enablesshkeysign", oEnableSSHKeysign },
197cf2b5f3bSDag-Erling Smørgrav 	{ "verifyhostkeydns", oVerifyHostKeyDNS },
198af12a3e7SDag-Erling Smørgrav 	{ "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
199cf2b5f3bSDag-Erling Smørgrav 	{ "rekeylimit", oRekeyLimit },
200cf2b5f3bSDag-Erling Smørgrav 	{ "connecttimeout", oConnectTimeout },
201cf2b5f3bSDag-Erling Smørgrav 	{ "addressfamily", oAddressFamily },
2021ec0d754SDag-Erling Smørgrav 	{ "serveraliveinterval", oServerAliveInterval },
2031ec0d754SDag-Erling Smørgrav 	{ "serveralivecountmax", oServerAliveCountMax },
20421e764dfSDag-Erling Smørgrav 	{ "sendenv", oSendEnv },
20521e764dfSDag-Erling Smørgrav 	{ "controlpath", oControlPath },
20621e764dfSDag-Erling Smørgrav 	{ "controlmaster", oControlMaster },
207aa49c926SDag-Erling Smørgrav 	{ "hashknownhosts", oHashKnownHosts },
208b74df5b2SDag-Erling Smørgrav 	{ "tunnel", oTunnel },
209b74df5b2SDag-Erling Smørgrav 	{ "tunneldevice", oTunnelDevice },
210b74df5b2SDag-Erling Smørgrav 	{ "localcommand", oLocalCommand },
211b74df5b2SDag-Erling Smørgrav 	{ "permitlocalcommand", oPermitLocalCommand },
212975616f0SDag-Erling Smørgrav 	{ "versionaddendum", oVersionAddendum },
213af12a3e7SDag-Erling Smørgrav 	{ NULL, oBadOption }
214511b41d2SMark Murray };
215511b41d2SMark Murray 
216511b41d2SMark Murray /*
217511b41d2SMark Murray  * Adds a local TCP/IP port forward to options.  Never returns if there is an
218511b41d2SMark Murray  * error.
219511b41d2SMark Murray  */
220511b41d2SMark Murray 
221511b41d2SMark Murray void
222aa49c926SDag-Erling Smørgrav add_local_forward(Options *options, const Forward *newfwd)
223511b41d2SMark Murray {
224511b41d2SMark Murray 	Forward *fwd;
225f388f5efSDag-Erling Smørgrav #ifndef NO_IPPORT_RESERVED_CONCEPT
226511b41d2SMark Murray 	extern uid_t original_real_uid;
227aa49c926SDag-Erling Smørgrav 	if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0)
228ca3176e7SBrian Feldman 		fatal("Privileged ports can only be forwarded by root.");
229989dd127SDag-Erling Smørgrav #endif
230511b41d2SMark Murray 	if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
231511b41d2SMark Murray 		fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
232511b41d2SMark Murray 	fwd = &options->local_forwards[options->num_local_forwards++];
233aa49c926SDag-Erling Smørgrav 
234aa49c926SDag-Erling Smørgrav 	fwd->listen_host = (newfwd->listen_host == NULL) ?
235aa49c926SDag-Erling Smørgrav 	    NULL : xstrdup(newfwd->listen_host);
236aa49c926SDag-Erling Smørgrav 	fwd->listen_port = newfwd->listen_port;
237aa49c926SDag-Erling Smørgrav 	fwd->connect_host = xstrdup(newfwd->connect_host);
238aa49c926SDag-Erling Smørgrav 	fwd->connect_port = newfwd->connect_port;
239511b41d2SMark Murray }
240511b41d2SMark Murray 
241511b41d2SMark Murray /*
242511b41d2SMark Murray  * Adds a remote TCP/IP port forward to options.  Never returns if there is
243511b41d2SMark Murray  * an error.
244511b41d2SMark Murray  */
245511b41d2SMark Murray 
246511b41d2SMark Murray void
247aa49c926SDag-Erling Smørgrav add_remote_forward(Options *options, const Forward *newfwd)
248511b41d2SMark Murray {
249511b41d2SMark Murray 	Forward *fwd;
250511b41d2SMark Murray 	if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
251511b41d2SMark Murray 		fatal("Too many remote forwards (max %d).",
252511b41d2SMark Murray 		    SSH_MAX_FORWARDS_PER_DIRECTION);
253511b41d2SMark Murray 	fwd = &options->remote_forwards[options->num_remote_forwards++];
254aa49c926SDag-Erling Smørgrav 
255aa49c926SDag-Erling Smørgrav 	fwd->listen_host = (newfwd->listen_host == NULL) ?
256aa49c926SDag-Erling Smørgrav 	    NULL : xstrdup(newfwd->listen_host);
257aa49c926SDag-Erling Smørgrav 	fwd->listen_port = newfwd->listen_port;
258aa49c926SDag-Erling Smørgrav 	fwd->connect_host = xstrdup(newfwd->connect_host);
259aa49c926SDag-Erling Smørgrav 	fwd->connect_port = newfwd->connect_port;
260511b41d2SMark Murray }
261511b41d2SMark Murray 
262af12a3e7SDag-Erling Smørgrav static void
263af12a3e7SDag-Erling Smørgrav clear_forwardings(Options *options)
264af12a3e7SDag-Erling Smørgrav {
265af12a3e7SDag-Erling Smørgrav 	int i;
266af12a3e7SDag-Erling Smørgrav 
267aa49c926SDag-Erling Smørgrav 	for (i = 0; i < options->num_local_forwards; i++) {
268aa49c926SDag-Erling Smørgrav 		if (options->local_forwards[i].listen_host != NULL)
269aa49c926SDag-Erling Smørgrav 			xfree(options->local_forwards[i].listen_host);
270aa49c926SDag-Erling Smørgrav 		xfree(options->local_forwards[i].connect_host);
271aa49c926SDag-Erling Smørgrav 	}
272af12a3e7SDag-Erling Smørgrav 	options->num_local_forwards = 0;
273aa49c926SDag-Erling Smørgrav 	for (i = 0; i < options->num_remote_forwards; i++) {
274aa49c926SDag-Erling Smørgrav 		if (options->remote_forwards[i].listen_host != NULL)
275aa49c926SDag-Erling Smørgrav 			xfree(options->remote_forwards[i].listen_host);
276aa49c926SDag-Erling Smørgrav 		xfree(options->remote_forwards[i].connect_host);
277aa49c926SDag-Erling Smørgrav 	}
278af12a3e7SDag-Erling Smørgrav 	options->num_remote_forwards = 0;
279b74df5b2SDag-Erling Smørgrav 	options->tun_open = SSH_TUNMODE_NO;
280af12a3e7SDag-Erling Smørgrav }
281af12a3e7SDag-Erling Smørgrav 
282511b41d2SMark Murray /*
283ca3176e7SBrian Feldman  * Returns the number of the token pointed to by cp or oBadOption.
284511b41d2SMark Murray  */
285511b41d2SMark Murray 
286511b41d2SMark Murray static OpCodes
287511b41d2SMark Murray parse_token(const char *cp, const char *filename, int linenum)
288511b41d2SMark Murray {
289ca3176e7SBrian Feldman 	u_int i;
290511b41d2SMark Murray 
291511b41d2SMark Murray 	for (i = 0; keywords[i].name; i++)
292511b41d2SMark Murray 		if (strcasecmp(cp, keywords[i].name) == 0)
293511b41d2SMark Murray 			return keywords[i].opcode;
294511b41d2SMark Murray 
295ca3176e7SBrian Feldman 	error("%s: line %d: Bad configuration option: %s",
296511b41d2SMark Murray 	    filename, linenum, cp);
297511b41d2SMark Murray 	return oBadOption;
298511b41d2SMark Murray }
299511b41d2SMark Murray 
300511b41d2SMark Murray /*
301511b41d2SMark Murray  * Processes a single option line as used in the configuration files. This
302511b41d2SMark Murray  * only sets those values that have not already been set.
303511b41d2SMark Murray  */
304e73e9afaSDag-Erling Smørgrav #define WHITESPACE " \t\r\n"
305511b41d2SMark Murray 
306511b41d2SMark Murray int
307511b41d2SMark Murray process_config_line(Options *options, const char *host,
308511b41d2SMark Murray 		    char *line, const char *filename, int linenum,
309511b41d2SMark Murray 		    int *activep)
310511b41d2SMark Murray {
311aa49c926SDag-Erling Smørgrav 	char *s, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256];
312b74df5b2SDag-Erling Smørgrav 	int opcode, *intptr, value, value2;
313e73e9afaSDag-Erling Smørgrav 	size_t len;
314aa49c926SDag-Erling Smørgrav 	Forward fwd;
315511b41d2SMark Murray 
316cf2b5f3bSDag-Erling Smørgrav 	/* Strip trailing whitespace */
317cf2b5f3bSDag-Erling Smørgrav 	for (len = strlen(line) - 1; len > 0; len--) {
318cf2b5f3bSDag-Erling Smørgrav 		if (strchr(WHITESPACE, line[len]) == NULL)
319cf2b5f3bSDag-Erling Smørgrav 			break;
320cf2b5f3bSDag-Erling Smørgrav 		line[len] = '\0';
321cf2b5f3bSDag-Erling Smørgrav 	}
322cf2b5f3bSDag-Erling Smørgrav 
323c2d3a559SKris Kennaway 	s = line;
324c2d3a559SKris Kennaway 	/* Get the keyword. (Each line is supposed to begin with a keyword). */
325c2d3a559SKris Kennaway 	keyword = strdelim(&s);
326c2d3a559SKris Kennaway 	/* Ignore leading whitespace. */
327c2d3a559SKris Kennaway 	if (*keyword == '\0')
328c2d3a559SKris Kennaway 		keyword = strdelim(&s);
329ca3176e7SBrian Feldman 	if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
330511b41d2SMark Murray 		return 0;
331511b41d2SMark Murray 
332c2d3a559SKris Kennaway 	opcode = parse_token(keyword, filename, linenum);
333511b41d2SMark Murray 
334511b41d2SMark Murray 	switch (opcode) {
335511b41d2SMark Murray 	case oBadOption:
336511b41d2SMark Murray 		/* don't panic, but count bad options */
337511b41d2SMark Murray 		return -1;
338511b41d2SMark Murray 		/* NOTREACHED */
339cf2b5f3bSDag-Erling Smørgrav 	case oConnectTimeout:
340cf2b5f3bSDag-Erling Smørgrav 		intptr = &options->connection_timeout;
3411ec0d754SDag-Erling Smørgrav parse_time:
342cf2b5f3bSDag-Erling Smørgrav 		arg = strdelim(&s);
343cf2b5f3bSDag-Erling Smørgrav 		if (!arg || *arg == '\0')
344cf2b5f3bSDag-Erling Smørgrav 			fatal("%s line %d: missing time value.",
345cf2b5f3bSDag-Erling Smørgrav 			    filename, linenum);
346cf2b5f3bSDag-Erling Smørgrav 		if ((value = convtime(arg)) == -1)
347cf2b5f3bSDag-Erling Smørgrav 			fatal("%s line %d: invalid time value.",
348cf2b5f3bSDag-Erling Smørgrav 			    filename, linenum);
349cf2b5f3bSDag-Erling Smørgrav 		if (*intptr == -1)
350cf2b5f3bSDag-Erling Smørgrav 			*intptr = value;
351cf2b5f3bSDag-Erling Smørgrav 		break;
352cf2b5f3bSDag-Erling Smørgrav 
353511b41d2SMark Murray 	case oForwardAgent:
354511b41d2SMark Murray 		intptr = &options->forward_agent;
355511b41d2SMark Murray parse_flag:
356c2d3a559SKris Kennaway 		arg = strdelim(&s);
357c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
358511b41d2SMark Murray 			fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
359511b41d2SMark Murray 		value = 0;	/* To avoid compiler warning... */
360c2d3a559SKris Kennaway 		if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
361511b41d2SMark Murray 			value = 1;
362c2d3a559SKris Kennaway 		else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
363511b41d2SMark Murray 			value = 0;
364511b41d2SMark Murray 		else
365511b41d2SMark Murray 			fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
366511b41d2SMark Murray 		if (*activep && *intptr == -1)
367511b41d2SMark Murray 			*intptr = value;
368511b41d2SMark Murray 		break;
369511b41d2SMark Murray 
370511b41d2SMark Murray 	case oForwardX11:
371511b41d2SMark Murray 		intptr = &options->forward_x11;
372511b41d2SMark Murray 		goto parse_flag;
373511b41d2SMark Murray 
3741ec0d754SDag-Erling Smørgrav 	case oForwardX11Trusted:
3751ec0d754SDag-Erling Smørgrav 		intptr = &options->forward_x11_trusted;
3761ec0d754SDag-Erling Smørgrav 		goto parse_flag;
3771ec0d754SDag-Erling Smørgrav 
378511b41d2SMark Murray 	case oGatewayPorts:
379511b41d2SMark Murray 		intptr = &options->gateway_ports;
380511b41d2SMark Murray 		goto parse_flag;
381511b41d2SMark Murray 
382511b41d2SMark Murray 	case oUsePrivilegedPort:
383511b41d2SMark Murray 		intptr = &options->use_privileged_port;
384511b41d2SMark Murray 		goto parse_flag;
385511b41d2SMark Murray 
386511b41d2SMark Murray 	case oPasswordAuthentication:
387511b41d2SMark Murray 		intptr = &options->password_authentication;
388511b41d2SMark Murray 		goto parse_flag;
389511b41d2SMark Murray 
39009958426SBrian Feldman 	case oKbdInteractiveAuthentication:
39109958426SBrian Feldman 		intptr = &options->kbd_interactive_authentication;
39209958426SBrian Feldman 		goto parse_flag;
39309958426SBrian Feldman 
39409958426SBrian Feldman 	case oKbdInteractiveDevices:
39509958426SBrian Feldman 		charptr = &options->kbd_interactive_devices;
39609958426SBrian Feldman 		goto parse_string;
39709958426SBrian Feldman 
398ca3176e7SBrian Feldman 	case oPubkeyAuthentication:
399ca3176e7SBrian Feldman 		intptr = &options->pubkey_authentication;
400e8aafc91SKris Kennaway 		goto parse_flag;
401e8aafc91SKris Kennaway 
402511b41d2SMark Murray 	case oRSAAuthentication:
403511b41d2SMark Murray 		intptr = &options->rsa_authentication;
404511b41d2SMark Murray 		goto parse_flag;
405511b41d2SMark Murray 
406511b41d2SMark Murray 	case oRhostsRSAAuthentication:
407511b41d2SMark Murray 		intptr = &options->rhosts_rsa_authentication;
408511b41d2SMark Murray 		goto parse_flag;
409511b41d2SMark Murray 
410ca3176e7SBrian Feldman 	case oHostbasedAuthentication:
411ca3176e7SBrian Feldman 		intptr = &options->hostbased_authentication;
412511b41d2SMark Murray 		goto parse_flag;
413511b41d2SMark Murray 
414af12a3e7SDag-Erling Smørgrav 	case oChallengeResponseAuthentication:
415af12a3e7SDag-Erling Smørgrav 		intptr = &options->challenge_response_authentication;
416af12a3e7SDag-Erling Smørgrav 		goto parse_flag;
417cf2b5f3bSDag-Erling Smørgrav 
418cf2b5f3bSDag-Erling Smørgrav 	case oGssAuthentication:
419cf2b5f3bSDag-Erling Smørgrav 		intptr = &options->gss_authentication;
420511b41d2SMark Murray 		goto parse_flag;
421cf2b5f3bSDag-Erling Smørgrav 
422cf2b5f3bSDag-Erling Smørgrav 	case oGssDelegateCreds:
423cf2b5f3bSDag-Erling Smørgrav 		intptr = &options->gss_deleg_creds;
424ca3176e7SBrian Feldman 		goto parse_flag;
425cf2b5f3bSDag-Erling Smørgrav 
426511b41d2SMark Murray 	case oBatchMode:
427511b41d2SMark Murray 		intptr = &options->batch_mode;
428511b41d2SMark Murray 		goto parse_flag;
429511b41d2SMark Murray 
430511b41d2SMark Murray 	case oCheckHostIP:
431511b41d2SMark Murray 		intptr = &options->check_host_ip;
432511b41d2SMark Murray 		goto parse_flag;
433511b41d2SMark Murray 
434cf2b5f3bSDag-Erling Smørgrav 	case oVerifyHostKeyDNS:
435cf2b5f3bSDag-Erling Smørgrav 		intptr = &options->verify_host_key_dns;
4361ec0d754SDag-Erling Smørgrav 		goto parse_yesnoask;
437cf2b5f3bSDag-Erling Smørgrav 
438511b41d2SMark Murray 	case oStrictHostKeyChecking:
439511b41d2SMark Murray 		intptr = &options->strict_host_key_checking;
4401ec0d754SDag-Erling Smørgrav parse_yesnoask:
441c2d3a559SKris Kennaway 		arg = strdelim(&s);
442c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
443ca3176e7SBrian Feldman 			fatal("%.200s line %d: Missing yes/no/ask argument.",
444511b41d2SMark Murray 			    filename, linenum);
445511b41d2SMark Murray 		value = 0;	/* To avoid compiler warning... */
446c2d3a559SKris Kennaway 		if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
447511b41d2SMark Murray 			value = 1;
448c2d3a559SKris Kennaway 		else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
449511b41d2SMark Murray 			value = 0;
450c2d3a559SKris Kennaway 		else if (strcmp(arg, "ask") == 0)
451511b41d2SMark Murray 			value = 2;
452511b41d2SMark Murray 		else
453511b41d2SMark Murray 			fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
454511b41d2SMark Murray 		if (*activep && *intptr == -1)
455511b41d2SMark Murray 			*intptr = value;
456511b41d2SMark Murray 		break;
457511b41d2SMark Murray 
458511b41d2SMark Murray 	case oCompression:
459511b41d2SMark Murray 		intptr = &options->compression;
460511b41d2SMark Murray 		goto parse_flag;
461511b41d2SMark Murray 
4621ec0d754SDag-Erling Smørgrav 	case oTCPKeepAlive:
4631ec0d754SDag-Erling Smørgrav 		intptr = &options->tcp_keep_alive;
464511b41d2SMark Murray 		goto parse_flag;
465511b41d2SMark Murray 
466af12a3e7SDag-Erling Smørgrav 	case oNoHostAuthenticationForLocalhost:
467af12a3e7SDag-Erling Smørgrav 		intptr = &options->no_host_authentication_for_localhost;
468af12a3e7SDag-Erling Smørgrav 		goto parse_flag;
469af12a3e7SDag-Erling Smørgrav 
470511b41d2SMark Murray 	case oNumberOfPasswordPrompts:
471511b41d2SMark Murray 		intptr = &options->number_of_password_prompts;
472511b41d2SMark Murray 		goto parse_int;
473511b41d2SMark Murray 
474511b41d2SMark Murray 	case oCompressionLevel:
475511b41d2SMark Murray 		intptr = &options->compression_level;
476511b41d2SMark Murray 		goto parse_int;
477511b41d2SMark Murray 
478cf2b5f3bSDag-Erling Smørgrav 	case oRekeyLimit:
479cf2b5f3bSDag-Erling Smørgrav 		intptr = &options->rekey_limit;
480cf2b5f3bSDag-Erling Smørgrav 		arg = strdelim(&s);
481cf2b5f3bSDag-Erling Smørgrav 		if (!arg || *arg == '\0')
482cf2b5f3bSDag-Erling Smørgrav 			fatal("%.200s line %d: Missing argument.", filename, linenum);
483cf2b5f3bSDag-Erling Smørgrav 		if (arg[0] < '0' || arg[0] > '9')
484cf2b5f3bSDag-Erling Smørgrav 			fatal("%.200s line %d: Bad number.", filename, linenum);
485cf2b5f3bSDag-Erling Smørgrav 		value = strtol(arg, &endofnumber, 10);
486cf2b5f3bSDag-Erling Smørgrav 		if (arg == endofnumber)
487cf2b5f3bSDag-Erling Smørgrav 			fatal("%.200s line %d: Bad number.", filename, linenum);
488cf2b5f3bSDag-Erling Smørgrav 		switch (toupper(*endofnumber)) {
489cf2b5f3bSDag-Erling Smørgrav 		case 'K':
490cf2b5f3bSDag-Erling Smørgrav 			value *= 1<<10;
491cf2b5f3bSDag-Erling Smørgrav 			break;
492cf2b5f3bSDag-Erling Smørgrav 		case 'M':
493cf2b5f3bSDag-Erling Smørgrav 			value *= 1<<20;
494cf2b5f3bSDag-Erling Smørgrav 			break;
495cf2b5f3bSDag-Erling Smørgrav 		case 'G':
496cf2b5f3bSDag-Erling Smørgrav 			value *= 1<<30;
497cf2b5f3bSDag-Erling Smørgrav 			break;
498cf2b5f3bSDag-Erling Smørgrav 		}
499cf2b5f3bSDag-Erling Smørgrav 		if (*activep && *intptr == -1)
500cf2b5f3bSDag-Erling Smørgrav 			*intptr = value;
501cf2b5f3bSDag-Erling Smørgrav 		break;
502cf2b5f3bSDag-Erling Smørgrav 
503511b41d2SMark Murray 	case oIdentityFile:
504c2d3a559SKris Kennaway 		arg = strdelim(&s);
505c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
506511b41d2SMark Murray 			fatal("%.200s line %d: Missing argument.", filename, linenum);
507511b41d2SMark Murray 		if (*activep) {
508ca3176e7SBrian Feldman 			intptr = &options->num_identity_files;
509e8aafc91SKris Kennaway 			if (*intptr >= SSH_MAX_IDENTITY_FILES)
510511b41d2SMark Murray 				fatal("%.200s line %d: Too many identity files specified (max %d).",
511511b41d2SMark Murray 				    filename, linenum, SSH_MAX_IDENTITY_FILES);
512ca3176e7SBrian Feldman 			charptr =  &options->identity_files[*intptr];
513c2d3a559SKris Kennaway 			*charptr = xstrdup(arg);
514e8aafc91SKris Kennaway 			*intptr = *intptr + 1;
515511b41d2SMark Murray 		}
516511b41d2SMark Murray 		break;
517511b41d2SMark Murray 
518c2d3a559SKris Kennaway 	case oXAuthLocation:
519c2d3a559SKris Kennaway 		charptr=&options->xauth_location;
520c2d3a559SKris Kennaway 		goto parse_string;
521c2d3a559SKris Kennaway 
522511b41d2SMark Murray 	case oUser:
523511b41d2SMark Murray 		charptr = &options->user;
524511b41d2SMark Murray parse_string:
525c2d3a559SKris Kennaway 		arg = strdelim(&s);
526c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
527511b41d2SMark Murray 			fatal("%.200s line %d: Missing argument.", filename, linenum);
528511b41d2SMark Murray 		if (*activep && *charptr == NULL)
529c2d3a559SKris Kennaway 			*charptr = xstrdup(arg);
530511b41d2SMark Murray 		break;
531511b41d2SMark Murray 
532511b41d2SMark Murray 	case oGlobalKnownHostsFile:
533511b41d2SMark Murray 		charptr = &options->system_hostfile;
534511b41d2SMark Murray 		goto parse_string;
535511b41d2SMark Murray 
536511b41d2SMark Murray 	case oUserKnownHostsFile:
537511b41d2SMark Murray 		charptr = &options->user_hostfile;
538511b41d2SMark Murray 		goto parse_string;
539511b41d2SMark Murray 
540e8aafc91SKris Kennaway 	case oGlobalKnownHostsFile2:
541e8aafc91SKris Kennaway 		charptr = &options->system_hostfile2;
542e8aafc91SKris Kennaway 		goto parse_string;
543e8aafc91SKris Kennaway 
544e8aafc91SKris Kennaway 	case oUserKnownHostsFile2:
545e8aafc91SKris Kennaway 		charptr = &options->user_hostfile2;
546e8aafc91SKris Kennaway 		goto parse_string;
547e8aafc91SKris Kennaway 
548511b41d2SMark Murray 	case oHostName:
549511b41d2SMark Murray 		charptr = &options->hostname;
550511b41d2SMark Murray 		goto parse_string;
551511b41d2SMark Murray 
552ca3176e7SBrian Feldman 	case oHostKeyAlias:
553ca3176e7SBrian Feldman 		charptr = &options->host_key_alias;
554ca3176e7SBrian Feldman 		goto parse_string;
555ca3176e7SBrian Feldman 
556ca3176e7SBrian Feldman 	case oPreferredAuthentications:
557ca3176e7SBrian Feldman 		charptr = &options->preferred_authentications;
558ca3176e7SBrian Feldman 		goto parse_string;
559ca3176e7SBrian Feldman 
560af12a3e7SDag-Erling Smørgrav 	case oBindAddress:
561af12a3e7SDag-Erling Smørgrav 		charptr = &options->bind_address;
562af12a3e7SDag-Erling Smørgrav 		goto parse_string;
563af12a3e7SDag-Erling Smørgrav 
564af12a3e7SDag-Erling Smørgrav 	case oSmartcardDevice:
565af12a3e7SDag-Erling Smørgrav 		charptr = &options->smartcard_device;
566af12a3e7SDag-Erling Smørgrav 		goto parse_string;
567af12a3e7SDag-Erling Smørgrav 
568511b41d2SMark Murray 	case oProxyCommand:
569b74df5b2SDag-Erling Smørgrav 		charptr = &options->proxy_command;
570b74df5b2SDag-Erling Smørgrav parse_command:
571cf2b5f3bSDag-Erling Smørgrav 		if (s == NULL)
572cf2b5f3bSDag-Erling Smørgrav 			fatal("%.200s line %d: Missing argument.", filename, linenum);
573e73e9afaSDag-Erling Smørgrav 		len = strspn(s, WHITESPACE "=");
574511b41d2SMark Murray 		if (*activep && *charptr == NULL)
575e73e9afaSDag-Erling Smørgrav 			*charptr = xstrdup(s + len);
576511b41d2SMark Murray 		return 0;
577511b41d2SMark Murray 
578511b41d2SMark Murray 	case oPort:
579511b41d2SMark Murray 		intptr = &options->port;
580511b41d2SMark Murray parse_int:
581c2d3a559SKris Kennaway 		arg = strdelim(&s);
582c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
583511b41d2SMark Murray 			fatal("%.200s line %d: Missing argument.", filename, linenum);
584c2d3a559SKris Kennaway 		if (arg[0] < '0' || arg[0] > '9')
585511b41d2SMark Murray 			fatal("%.200s line %d: Bad number.", filename, linenum);
586511b41d2SMark Murray 
587511b41d2SMark Murray 		/* Octal, decimal, or hex format? */
588c2d3a559SKris Kennaway 		value = strtol(arg, &endofnumber, 0);
589c2d3a559SKris Kennaway 		if (arg == endofnumber)
590511b41d2SMark Murray 			fatal("%.200s line %d: Bad number.", filename, linenum);
591511b41d2SMark Murray 		if (*activep && *intptr == -1)
592511b41d2SMark Murray 			*intptr = value;
593511b41d2SMark Murray 		break;
594511b41d2SMark Murray 
595511b41d2SMark Murray 	case oConnectionAttempts:
596511b41d2SMark Murray 		intptr = &options->connection_attempts;
597511b41d2SMark Murray 		goto parse_int;
598511b41d2SMark Murray 
599511b41d2SMark Murray 	case oCipher:
600511b41d2SMark Murray 		intptr = &options->cipher;
601c2d3a559SKris Kennaway 		arg = strdelim(&s);
602c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
603db1cb46cSKris Kennaway 			fatal("%.200s line %d: Missing argument.", filename, linenum);
604c2d3a559SKris Kennaway 		value = cipher_number(arg);
605511b41d2SMark Murray 		if (value == -1)
606511b41d2SMark Murray 			fatal("%.200s line %d: Bad cipher '%s'.",
607c2d3a559SKris Kennaway 			    filename, linenum, arg ? arg : "<NONE>");
608511b41d2SMark Murray 		if (*activep && *intptr == -1)
609511b41d2SMark Murray 			*intptr = value;
610511b41d2SMark Murray 		break;
611511b41d2SMark Murray 
612e8aafc91SKris Kennaway 	case oCiphers:
613c2d3a559SKris Kennaway 		arg = strdelim(&s);
614c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
615db1cb46cSKris Kennaway 			fatal("%.200s line %d: Missing argument.", filename, linenum);
616c2d3a559SKris Kennaway 		if (!ciphers_valid(arg))
617e8aafc91SKris Kennaway 			fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
618c2d3a559SKris Kennaway 			    filename, linenum, arg ? arg : "<NONE>");
619e8aafc91SKris Kennaway 		if (*activep && options->ciphers == NULL)
620c2d3a559SKris Kennaway 			options->ciphers = xstrdup(arg);
621e8aafc91SKris Kennaway 		break;
622e8aafc91SKris Kennaway 
623ca3176e7SBrian Feldman 	case oMacs:
624ca3176e7SBrian Feldman 		arg = strdelim(&s);
625ca3176e7SBrian Feldman 		if (!arg || *arg == '\0')
626ca3176e7SBrian Feldman 			fatal("%.200s line %d: Missing argument.", filename, linenum);
627ca3176e7SBrian Feldman 		if (!mac_valid(arg))
628ca3176e7SBrian Feldman 			fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
629ca3176e7SBrian Feldman 			    filename, linenum, arg ? arg : "<NONE>");
630ca3176e7SBrian Feldman 		if (*activep && options->macs == NULL)
631ca3176e7SBrian Feldman 			options->macs = xstrdup(arg);
632ca3176e7SBrian Feldman 		break;
633ca3176e7SBrian Feldman 
634ca3176e7SBrian Feldman 	case oHostKeyAlgorithms:
635ca3176e7SBrian Feldman 		arg = strdelim(&s);
636ca3176e7SBrian Feldman 		if (!arg || *arg == '\0')
637ca3176e7SBrian Feldman 			fatal("%.200s line %d: Missing argument.", filename, linenum);
638ca3176e7SBrian Feldman 		if (!key_names_valid2(arg))
639ca3176e7SBrian Feldman 			fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
640ca3176e7SBrian Feldman 			    filename, linenum, arg ? arg : "<NONE>");
641ca3176e7SBrian Feldman 		if (*activep && options->hostkeyalgorithms == NULL)
642ca3176e7SBrian Feldman 			options->hostkeyalgorithms = xstrdup(arg);
643ca3176e7SBrian Feldman 		break;
644ca3176e7SBrian Feldman 
645e8aafc91SKris Kennaway 	case oProtocol:
646e8aafc91SKris Kennaway 		intptr = &options->protocol;
647c2d3a559SKris Kennaway 		arg = strdelim(&s);
648c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
649db1cb46cSKris Kennaway 			fatal("%.200s line %d: Missing argument.", filename, linenum);
650c2d3a559SKris Kennaway 		value = proto_spec(arg);
651e8aafc91SKris Kennaway 		if (value == SSH_PROTO_UNKNOWN)
652e8aafc91SKris Kennaway 			fatal("%.200s line %d: Bad protocol spec '%s'.",
653c2d3a559SKris Kennaway 			    filename, linenum, arg ? arg : "<NONE>");
654e8aafc91SKris Kennaway 		if (*activep && *intptr == SSH_PROTO_UNKNOWN)
655e8aafc91SKris Kennaway 			*intptr = value;
656e8aafc91SKris Kennaway 		break;
657e8aafc91SKris Kennaway 
658511b41d2SMark Murray 	case oLogLevel:
659511b41d2SMark Murray 		intptr = (int *) &options->log_level;
660c2d3a559SKris Kennaway 		arg = strdelim(&s);
661c2d3a559SKris Kennaway 		value = log_level_number(arg);
662af12a3e7SDag-Erling Smørgrav 		if (value == SYSLOG_LEVEL_NOT_SET)
663ca3176e7SBrian Feldman 			fatal("%.200s line %d: unsupported log level '%s'",
664c2d3a559SKris Kennaway 			    filename, linenum, arg ? arg : "<NONE>");
665af12a3e7SDag-Erling Smørgrav 		if (*activep && (LogLevel) *intptr == SYSLOG_LEVEL_NOT_SET)
666511b41d2SMark Murray 			*intptr = (LogLevel) value;
667511b41d2SMark Murray 		break;
668511b41d2SMark Murray 
669af12a3e7SDag-Erling Smørgrav 	case oLocalForward:
670511b41d2SMark Murray 	case oRemoteForward:
671c2d3a559SKris Kennaway 		arg = strdelim(&s);
672aa49c926SDag-Erling Smørgrav 		if (arg == NULL || *arg == '\0')
673af12a3e7SDag-Erling Smørgrav 			fatal("%.200s line %d: Missing port argument.",
674af12a3e7SDag-Erling Smørgrav 			    filename, linenum);
675aa49c926SDag-Erling Smørgrav 		arg2 = strdelim(&s);
676aa49c926SDag-Erling Smørgrav 		if (arg2 == NULL || *arg2 == '\0')
677aa49c926SDag-Erling Smørgrav 			fatal("%.200s line %d: Missing target argument.",
678511b41d2SMark Murray 			    filename, linenum);
679aa49c926SDag-Erling Smørgrav 
680aa49c926SDag-Erling Smørgrav 		/* construct a string for parse_forward */
681aa49c926SDag-Erling Smørgrav 		snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
682aa49c926SDag-Erling Smørgrav 
683aa49c926SDag-Erling Smørgrav 		if (parse_forward(&fwd, fwdarg) == 0)
684af12a3e7SDag-Erling Smørgrav 			fatal("%.200s line %d: Bad forwarding specification.",
685511b41d2SMark Murray 			    filename, linenum);
686aa49c926SDag-Erling Smørgrav 
687af12a3e7SDag-Erling Smørgrav 		if (*activep) {
688af12a3e7SDag-Erling Smørgrav 			if (opcode == oLocalForward)
689aa49c926SDag-Erling Smørgrav 				add_local_forward(options, &fwd);
690af12a3e7SDag-Erling Smørgrav 			else if (opcode == oRemoteForward)
691aa49c926SDag-Erling Smørgrav 				add_remote_forward(options, &fwd);
692af12a3e7SDag-Erling Smørgrav 		}
693511b41d2SMark Murray 		break;
694511b41d2SMark Murray 
695ca3176e7SBrian Feldman 	case oDynamicForward:
696ca3176e7SBrian Feldman 		arg = strdelim(&s);
697ca3176e7SBrian Feldman 		if (!arg || *arg == '\0')
698ca3176e7SBrian Feldman 			fatal("%.200s line %d: Missing port argument.",
699ca3176e7SBrian Feldman 			    filename, linenum);
700aa49c926SDag-Erling Smørgrav 		memset(&fwd, '\0', sizeof(fwd));
701aa49c926SDag-Erling Smørgrav 		fwd.connect_host = "socks";
702aa49c926SDag-Erling Smørgrav 		fwd.listen_host = hpdelim(&arg);
703aa49c926SDag-Erling Smørgrav 		if (fwd.listen_host == NULL ||
704aa49c926SDag-Erling Smørgrav 		    strlen(fwd.listen_host) >= NI_MAXHOST)
705aa49c926SDag-Erling Smørgrav 			fatal("%.200s line %d: Bad forwarding specification.",
706aa49c926SDag-Erling Smørgrav 			    filename, linenum);
707aa49c926SDag-Erling Smørgrav 		if (arg) {
708aa49c926SDag-Erling Smørgrav 			fwd.listen_port = a2port(arg);
709aa49c926SDag-Erling Smørgrav 			fwd.listen_host = cleanhostname(fwd.listen_host);
710aa49c926SDag-Erling Smørgrav 		} else {
711aa49c926SDag-Erling Smørgrav 			fwd.listen_port = a2port(fwd.listen_host);
712d4ecd108SDag-Erling Smørgrav 			fwd.listen_host = NULL;
713aa49c926SDag-Erling Smørgrav 		}
714aa49c926SDag-Erling Smørgrav 		if (fwd.listen_port == 0)
715ca3176e7SBrian Feldman 			fatal("%.200s line %d: Badly formatted port number.",
716ca3176e7SBrian Feldman 			    filename, linenum);
717af12a3e7SDag-Erling Smørgrav 		if (*activep)
718aa49c926SDag-Erling Smørgrav 			add_local_forward(options, &fwd);
719ca3176e7SBrian Feldman 		break;
720ca3176e7SBrian Feldman 
721af12a3e7SDag-Erling Smørgrav 	case oClearAllForwardings:
722af12a3e7SDag-Erling Smørgrav 		intptr = &options->clear_forwardings;
723af12a3e7SDag-Erling Smørgrav 		goto parse_flag;
724af12a3e7SDag-Erling Smørgrav 
725511b41d2SMark Murray 	case oHost:
726511b41d2SMark Murray 		*activep = 0;
727c2d3a559SKris Kennaway 		while ((arg = strdelim(&s)) != NULL && *arg != '\0')
728c2d3a559SKris Kennaway 			if (match_pattern(host, arg)) {
729c2d3a559SKris Kennaway 				debug("Applying options for %.100s", arg);
730511b41d2SMark Murray 				*activep = 1;
731511b41d2SMark Murray 				break;
732511b41d2SMark Murray 			}
733c2d3a559SKris Kennaway 		/* Avoid garbage check below, as strdelim is done. */
734511b41d2SMark Murray 		return 0;
735511b41d2SMark Murray 
736511b41d2SMark Murray 	case oEscapeChar:
737511b41d2SMark Murray 		intptr = &options->escape_char;
738c2d3a559SKris Kennaway 		arg = strdelim(&s);
739c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
740511b41d2SMark Murray 			fatal("%.200s line %d: Missing argument.", filename, linenum);
741c2d3a559SKris Kennaway 		if (arg[0] == '^' && arg[2] == 0 &&
742ca3176e7SBrian Feldman 		    (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
743ca3176e7SBrian Feldman 			value = (u_char) arg[1] & 31;
744c2d3a559SKris Kennaway 		else if (strlen(arg) == 1)
745ca3176e7SBrian Feldman 			value = (u_char) arg[0];
746c2d3a559SKris Kennaway 		else if (strcmp(arg, "none") == 0)
747af12a3e7SDag-Erling Smørgrav 			value = SSH_ESCAPECHAR_NONE;
748511b41d2SMark Murray 		else {
749511b41d2SMark Murray 			fatal("%.200s line %d: Bad escape character.",
750511b41d2SMark Murray 			    filename, linenum);
751511b41d2SMark Murray 			/* NOTREACHED */
752511b41d2SMark Murray 			value = 0;	/* Avoid compiler warning. */
753511b41d2SMark Murray 		}
754511b41d2SMark Murray 		if (*activep && *intptr == -1)
755511b41d2SMark Murray 			*intptr = value;
756511b41d2SMark Murray 		break;
757511b41d2SMark Murray 
758cf2b5f3bSDag-Erling Smørgrav 	case oAddressFamily:
759cf2b5f3bSDag-Erling Smørgrav 		arg = strdelim(&s);
760d4ecd108SDag-Erling Smørgrav 		if (!arg || *arg == '\0')
761d4ecd108SDag-Erling Smørgrav 			fatal("%s line %d: missing address family.",
762d4ecd108SDag-Erling Smørgrav 			    filename, linenum);
763cf2b5f3bSDag-Erling Smørgrav 		intptr = &options->address_family;
764cf2b5f3bSDag-Erling Smørgrav 		if (strcasecmp(arg, "inet") == 0)
765cf2b5f3bSDag-Erling Smørgrav 			value = AF_INET;
766cf2b5f3bSDag-Erling Smørgrav 		else if (strcasecmp(arg, "inet6") == 0)
767cf2b5f3bSDag-Erling Smørgrav 			value = AF_INET6;
768cf2b5f3bSDag-Erling Smørgrav 		else if (strcasecmp(arg, "any") == 0)
769cf2b5f3bSDag-Erling Smørgrav 			value = AF_UNSPEC;
770cf2b5f3bSDag-Erling Smørgrav 		else
771cf2b5f3bSDag-Erling Smørgrav 			fatal("Unsupported AddressFamily \"%s\"", arg);
772cf2b5f3bSDag-Erling Smørgrav 		if (*activep && *intptr == -1)
773cf2b5f3bSDag-Erling Smørgrav 			*intptr = value;
774cf2b5f3bSDag-Erling Smørgrav 		break;
775cf2b5f3bSDag-Erling Smørgrav 
776e73e9afaSDag-Erling Smørgrav 	case oEnableSSHKeysign:
777e73e9afaSDag-Erling Smørgrav 		intptr = &options->enable_ssh_keysign;
778e73e9afaSDag-Erling Smørgrav 		goto parse_flag;
779e73e9afaSDag-Erling Smørgrav 
7805962c0e9SDag-Erling Smørgrav 	case oIdentitiesOnly:
7815962c0e9SDag-Erling Smørgrav 		intptr = &options->identities_only;
7825962c0e9SDag-Erling Smørgrav 		goto parse_flag;
7835962c0e9SDag-Erling Smørgrav 
7841ec0d754SDag-Erling Smørgrav 	case oServerAliveInterval:
7851ec0d754SDag-Erling Smørgrav 		intptr = &options->server_alive_interval;
7861ec0d754SDag-Erling Smørgrav 		goto parse_time;
7871ec0d754SDag-Erling Smørgrav 
7881ec0d754SDag-Erling Smørgrav 	case oServerAliveCountMax:
7891ec0d754SDag-Erling Smørgrav 		intptr = &options->server_alive_count_max;
7901ec0d754SDag-Erling Smørgrav 		goto parse_int;
7911ec0d754SDag-Erling Smørgrav 
79221e764dfSDag-Erling Smørgrav 	case oSendEnv:
79321e764dfSDag-Erling Smørgrav 		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
79421e764dfSDag-Erling Smørgrav 			if (strchr(arg, '=') != NULL)
79521e764dfSDag-Erling Smørgrav 				fatal("%s line %d: Invalid environment name.",
79621e764dfSDag-Erling Smørgrav 				    filename, linenum);
797aa49c926SDag-Erling Smørgrav 			if (!*activep)
798aa49c926SDag-Erling Smørgrav 				continue;
79921e764dfSDag-Erling Smørgrav 			if (options->num_send_env >= MAX_SEND_ENV)
80021e764dfSDag-Erling Smørgrav 				fatal("%s line %d: too many send env.",
80121e764dfSDag-Erling Smørgrav 				    filename, linenum);
80221e764dfSDag-Erling Smørgrav 			options->send_env[options->num_send_env++] =
80321e764dfSDag-Erling Smørgrav 			    xstrdup(arg);
80421e764dfSDag-Erling Smørgrav 		}
80521e764dfSDag-Erling Smørgrav 		break;
80621e764dfSDag-Erling Smørgrav 
80721e764dfSDag-Erling Smørgrav 	case oControlPath:
80821e764dfSDag-Erling Smørgrav 		charptr = &options->control_path;
80921e764dfSDag-Erling Smørgrav 		goto parse_string;
81021e764dfSDag-Erling Smørgrav 
81121e764dfSDag-Erling Smørgrav 	case oControlMaster:
81221e764dfSDag-Erling Smørgrav 		intptr = &options->control_master;
813d4ecd108SDag-Erling Smørgrav 		arg = strdelim(&s);
814d4ecd108SDag-Erling Smørgrav 		if (!arg || *arg == '\0')
815d4ecd108SDag-Erling Smørgrav 			fatal("%.200s line %d: Missing ControlMaster argument.",
816d4ecd108SDag-Erling Smørgrav 			    filename, linenum);
817d4ecd108SDag-Erling Smørgrav 		value = 0;	/* To avoid compiler warning... */
818d4ecd108SDag-Erling Smørgrav 		if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
819d4ecd108SDag-Erling Smørgrav 			value = SSHCTL_MASTER_YES;
820d4ecd108SDag-Erling Smørgrav 		else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
821d4ecd108SDag-Erling Smørgrav 			value = SSHCTL_MASTER_NO;
822d4ecd108SDag-Erling Smørgrav 		else if (strcmp(arg, "auto") == 0)
823d4ecd108SDag-Erling Smørgrav 			value = SSHCTL_MASTER_AUTO;
824d4ecd108SDag-Erling Smørgrav 		else if (strcmp(arg, "ask") == 0)
825d4ecd108SDag-Erling Smørgrav 			value = SSHCTL_MASTER_ASK;
826d4ecd108SDag-Erling Smørgrav 		else if (strcmp(arg, "autoask") == 0)
827d4ecd108SDag-Erling Smørgrav 			value = SSHCTL_MASTER_AUTO_ASK;
828d4ecd108SDag-Erling Smørgrav 		else
829d4ecd108SDag-Erling Smørgrav 			fatal("%.200s line %d: Bad ControlMaster argument.",
830d4ecd108SDag-Erling Smørgrav 			    filename, linenum);
831d4ecd108SDag-Erling Smørgrav 		if (*activep && *intptr == -1)
832d4ecd108SDag-Erling Smørgrav 			*intptr = value;
833d4ecd108SDag-Erling Smørgrav 		break;
83421e764dfSDag-Erling Smørgrav 
835aa49c926SDag-Erling Smørgrav 	case oHashKnownHosts:
836aa49c926SDag-Erling Smørgrav 		intptr = &options->hash_known_hosts;
837aa49c926SDag-Erling Smørgrav 		goto parse_flag;
838aa49c926SDag-Erling Smørgrav 
839b74df5b2SDag-Erling Smørgrav 	case oTunnel:
840b74df5b2SDag-Erling Smørgrav 		intptr = &options->tun_open;
841b74df5b2SDag-Erling Smørgrav 		arg = strdelim(&s);
842b74df5b2SDag-Erling Smørgrav 		if (!arg || *arg == '\0')
843b74df5b2SDag-Erling Smørgrav 			fatal("%s line %d: Missing yes/point-to-point/"
844b74df5b2SDag-Erling Smørgrav 			    "ethernet/no argument.", filename, linenum);
845b74df5b2SDag-Erling Smørgrav 		value = 0;	/* silence compiler */
846b74df5b2SDag-Erling Smørgrav 		if (strcasecmp(arg, "ethernet") == 0)
847b74df5b2SDag-Erling Smørgrav 			value = SSH_TUNMODE_ETHERNET;
848b74df5b2SDag-Erling Smørgrav 		else if (strcasecmp(arg, "point-to-point") == 0)
849b74df5b2SDag-Erling Smørgrav 			value = SSH_TUNMODE_POINTOPOINT;
850b74df5b2SDag-Erling Smørgrav 		else if (strcasecmp(arg, "yes") == 0)
851b74df5b2SDag-Erling Smørgrav 			value = SSH_TUNMODE_DEFAULT;
852b74df5b2SDag-Erling Smørgrav 		else if (strcasecmp(arg, "no") == 0)
853b74df5b2SDag-Erling Smørgrav 			value = SSH_TUNMODE_NO;
854b74df5b2SDag-Erling Smørgrav 		else
855b74df5b2SDag-Erling Smørgrav 			fatal("%s line %d: Bad yes/point-to-point/ethernet/"
856b74df5b2SDag-Erling Smørgrav 			    "no argument: %s", filename, linenum, arg);
857b74df5b2SDag-Erling Smørgrav 		if (*activep)
858b74df5b2SDag-Erling Smørgrav 			*intptr = value;
859b74df5b2SDag-Erling Smørgrav 		break;
860b74df5b2SDag-Erling Smørgrav 
861b74df5b2SDag-Erling Smørgrav 	case oTunnelDevice:
862b74df5b2SDag-Erling Smørgrav 		arg = strdelim(&s);
863b74df5b2SDag-Erling Smørgrav 		if (!arg || *arg == '\0')
864b74df5b2SDag-Erling Smørgrav 			fatal("%.200s line %d: Missing argument.", filename, linenum);
865b74df5b2SDag-Erling Smørgrav 		value = a2tun(arg, &value2);
866b74df5b2SDag-Erling Smørgrav 		if (value == SSH_TUNID_ERR)
867b74df5b2SDag-Erling Smørgrav 			fatal("%.200s line %d: Bad tun device.", filename, linenum);
868b74df5b2SDag-Erling Smørgrav 		if (*activep) {
869b74df5b2SDag-Erling Smørgrav 			options->tun_local = value;
870b74df5b2SDag-Erling Smørgrav 			options->tun_remote = value2;
871b74df5b2SDag-Erling Smørgrav 		}
872b74df5b2SDag-Erling Smørgrav 		break;
873b74df5b2SDag-Erling Smørgrav 
874b74df5b2SDag-Erling Smørgrav 	case oLocalCommand:
875b74df5b2SDag-Erling Smørgrav 		charptr = &options->local_command;
876b74df5b2SDag-Erling Smørgrav 		goto parse_command;
877b74df5b2SDag-Erling Smørgrav 
878b74df5b2SDag-Erling Smørgrav 	case oPermitLocalCommand:
879b74df5b2SDag-Erling Smørgrav 		intptr = &options->permit_local_command;
880b74df5b2SDag-Erling Smørgrav 		goto parse_flag;
881b74df5b2SDag-Erling Smørgrav 
882975616f0SDag-Erling Smørgrav 	case oVersionAddendum:
883975616f0SDag-Erling Smørgrav 		ssh_version_set_addendum(strtok(s, "\n"));
884975616f0SDag-Erling Smørgrav 		do {
885975616f0SDag-Erling Smørgrav 			arg = strdelim(&s);
886975616f0SDag-Erling Smørgrav 		} while (arg != NULL && *arg != '\0');
887975616f0SDag-Erling Smørgrav 		break;
888975616f0SDag-Erling Smørgrav 
88980628bacSDag-Erling Smørgrav 	case oDeprecated:
89080628bacSDag-Erling Smørgrav 		debug("%s line %d: Deprecated option \"%s\"",
89180628bacSDag-Erling Smørgrav 		    filename, linenum, keyword);
89280628bacSDag-Erling Smørgrav 		return 0;
89380628bacSDag-Erling Smørgrav 
894cf2b5f3bSDag-Erling Smørgrav 	case oUnsupported:
895cf2b5f3bSDag-Erling Smørgrav 		error("%s line %d: Unsupported option \"%s\"",
896cf2b5f3bSDag-Erling Smørgrav 		    filename, linenum, keyword);
897cf2b5f3bSDag-Erling Smørgrav 		return 0;
898cf2b5f3bSDag-Erling Smørgrav 
899511b41d2SMark Murray 	default:
900511b41d2SMark Murray 		fatal("process_config_line: Unimplemented opcode %d", opcode);
901511b41d2SMark Murray 	}
902511b41d2SMark Murray 
903511b41d2SMark Murray 	/* Check that there is no garbage at end of line. */
904ca3176e7SBrian Feldman 	if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
905c2d3a559SKris Kennaway 		fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
906c2d3a559SKris Kennaway 		    filename, linenum, arg);
907c2d3a559SKris Kennaway 	}
908511b41d2SMark Murray 	return 0;
909511b41d2SMark Murray }
910511b41d2SMark Murray 
911511b41d2SMark Murray 
912511b41d2SMark Murray /*
913511b41d2SMark Murray  * Reads the config file and modifies the options accordingly.  Options
914511b41d2SMark Murray  * should already be initialized before this call.  This never returns if
915af12a3e7SDag-Erling Smørgrav  * there is an error.  If the file does not exist, this returns 0.
916511b41d2SMark Murray  */
917511b41d2SMark Murray 
918af12a3e7SDag-Erling Smørgrav int
91921e764dfSDag-Erling Smørgrav read_config_file(const char *filename, const char *host, Options *options,
92021e764dfSDag-Erling Smørgrav     int checkperm)
921511b41d2SMark Murray {
922511b41d2SMark Murray 	FILE *f;
923511b41d2SMark Murray 	char line[1024];
924511b41d2SMark Murray 	int active, linenum;
925511b41d2SMark Murray 	int bad_options = 0;
926511b41d2SMark Murray 
927511b41d2SMark Murray 	/* Open the file. */
92821e764dfSDag-Erling Smørgrav 	if ((f = fopen(filename, "r")) == NULL)
929af12a3e7SDag-Erling Smørgrav 		return 0;
930511b41d2SMark Murray 
93121e764dfSDag-Erling Smørgrav 	if (checkperm) {
93221e764dfSDag-Erling Smørgrav 		struct stat sb;
93321e764dfSDag-Erling Smørgrav 
93421e764dfSDag-Erling Smørgrav 		if (fstat(fileno(f), &sb) == -1)
93521e764dfSDag-Erling Smørgrav 			fatal("fstat %s: %s", filename, strerror(errno));
93621e764dfSDag-Erling Smørgrav 		if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
93721e764dfSDag-Erling Smørgrav 		    (sb.st_mode & 022) != 0))
93821e764dfSDag-Erling Smørgrav 			fatal("Bad owner or permissions on %s", filename);
93921e764dfSDag-Erling Smørgrav 	}
94021e764dfSDag-Erling Smørgrav 
941511b41d2SMark Murray 	debug("Reading configuration data %.200s", filename);
942511b41d2SMark Murray 
943511b41d2SMark Murray 	/*
944511b41d2SMark Murray 	 * Mark that we are now processing the options.  This flag is turned
945511b41d2SMark Murray 	 * on/off by Host specifications.
946511b41d2SMark Murray 	 */
947511b41d2SMark Murray 	active = 1;
948511b41d2SMark Murray 	linenum = 0;
949511b41d2SMark Murray 	while (fgets(line, sizeof(line), f)) {
950511b41d2SMark Murray 		/* Update line number counter. */
951511b41d2SMark Murray 		linenum++;
952511b41d2SMark Murray 		if (process_config_line(options, host, line, filename, linenum, &active) != 0)
953511b41d2SMark Murray 			bad_options++;
954511b41d2SMark Murray 	}
955511b41d2SMark Murray 	fclose(f);
956511b41d2SMark Murray 	if (bad_options > 0)
957ca3176e7SBrian Feldman 		fatal("%s: terminating, %d bad configuration options",
958511b41d2SMark Murray 		    filename, bad_options);
959af12a3e7SDag-Erling Smørgrav 	return 1;
960511b41d2SMark Murray }
961511b41d2SMark Murray 
962511b41d2SMark Murray /*
963511b41d2SMark Murray  * Initializes options to special values that indicate that they have not yet
964511b41d2SMark Murray  * been set.  Read_config_file will only set options with this value. Options
965511b41d2SMark Murray  * are processed in the following order: command line, user config file,
966511b41d2SMark Murray  * system config file.  Last, fill_default_options is called.
967511b41d2SMark Murray  */
968511b41d2SMark Murray 
969511b41d2SMark Murray void
970511b41d2SMark Murray initialize_options(Options * options)
971511b41d2SMark Murray {
972511b41d2SMark Murray 	memset(options, 'X', sizeof(*options));
973511b41d2SMark Murray 	options->forward_agent = -1;
974511b41d2SMark Murray 	options->forward_x11 = -1;
9751ec0d754SDag-Erling Smørgrav 	options->forward_x11_trusted = -1;
976c2d3a559SKris Kennaway 	options->xauth_location = NULL;
977511b41d2SMark Murray 	options->gateway_ports = -1;
978511b41d2SMark Murray 	options->use_privileged_port = -1;
979511b41d2SMark Murray 	options->rsa_authentication = -1;
980ca3176e7SBrian Feldman 	options->pubkey_authentication = -1;
981af12a3e7SDag-Erling Smørgrav 	options->challenge_response_authentication = -1;
982cf2b5f3bSDag-Erling Smørgrav 	options->gss_authentication = -1;
983cf2b5f3bSDag-Erling Smørgrav 	options->gss_deleg_creds = -1;
984511b41d2SMark Murray 	options->password_authentication = -1;
98509958426SBrian Feldman 	options->kbd_interactive_authentication = -1;
98609958426SBrian Feldman 	options->kbd_interactive_devices = NULL;
987511b41d2SMark Murray 	options->rhosts_rsa_authentication = -1;
988ca3176e7SBrian Feldman 	options->hostbased_authentication = -1;
989511b41d2SMark Murray 	options->batch_mode = -1;
990511b41d2SMark Murray 	options->check_host_ip = -1;
991511b41d2SMark Murray 	options->strict_host_key_checking = -1;
992511b41d2SMark Murray 	options->compression = -1;
9931ec0d754SDag-Erling Smørgrav 	options->tcp_keep_alive = -1;
994511b41d2SMark Murray 	options->compression_level = -1;
995511b41d2SMark Murray 	options->port = -1;
996cf2b5f3bSDag-Erling Smørgrav 	options->address_family = -1;
997511b41d2SMark Murray 	options->connection_attempts = -1;
998cf2b5f3bSDag-Erling Smørgrav 	options->connection_timeout = -1;
999511b41d2SMark Murray 	options->number_of_password_prompts = -1;
1000511b41d2SMark Murray 	options->cipher = -1;
1001e8aafc91SKris Kennaway 	options->ciphers = NULL;
1002ca3176e7SBrian Feldman 	options->macs = NULL;
1003ca3176e7SBrian Feldman 	options->hostkeyalgorithms = NULL;
1004e8aafc91SKris Kennaway 	options->protocol = SSH_PROTO_UNKNOWN;
1005511b41d2SMark Murray 	options->num_identity_files = 0;
1006511b41d2SMark Murray 	options->hostname = NULL;
1007ca3176e7SBrian Feldman 	options->host_key_alias = NULL;
1008511b41d2SMark Murray 	options->proxy_command = NULL;
1009511b41d2SMark Murray 	options->user = NULL;
1010511b41d2SMark Murray 	options->escape_char = -1;
1011511b41d2SMark Murray 	options->system_hostfile = NULL;
1012511b41d2SMark Murray 	options->user_hostfile = NULL;
1013e8aafc91SKris Kennaway 	options->system_hostfile2 = NULL;
1014e8aafc91SKris Kennaway 	options->user_hostfile2 = NULL;
1015511b41d2SMark Murray 	options->num_local_forwards = 0;
1016511b41d2SMark Murray 	options->num_remote_forwards = 0;
1017af12a3e7SDag-Erling Smørgrav 	options->clear_forwardings = -1;
1018af12a3e7SDag-Erling Smørgrav 	options->log_level = SYSLOG_LEVEL_NOT_SET;
1019ca3176e7SBrian Feldman 	options->preferred_authentications = NULL;
1020af12a3e7SDag-Erling Smørgrav 	options->bind_address = NULL;
1021af12a3e7SDag-Erling Smørgrav 	options->smartcard_device = NULL;
1022e73e9afaSDag-Erling Smørgrav 	options->enable_ssh_keysign = - 1;
1023af12a3e7SDag-Erling Smørgrav 	options->no_host_authentication_for_localhost = - 1;
10245962c0e9SDag-Erling Smørgrav 	options->identities_only = - 1;
1025cf2b5f3bSDag-Erling Smørgrav 	options->rekey_limit = - 1;
1026cf2b5f3bSDag-Erling Smørgrav 	options->verify_host_key_dns = -1;
10271ec0d754SDag-Erling Smørgrav 	options->server_alive_interval = -1;
10281ec0d754SDag-Erling Smørgrav 	options->server_alive_count_max = -1;
102921e764dfSDag-Erling Smørgrav 	options->num_send_env = 0;
103021e764dfSDag-Erling Smørgrav 	options->control_path = NULL;
103121e764dfSDag-Erling Smørgrav 	options->control_master = -1;
1032aa49c926SDag-Erling Smørgrav 	options->hash_known_hosts = -1;
1033b74df5b2SDag-Erling Smørgrav 	options->tun_open = -1;
1034b74df5b2SDag-Erling Smørgrav 	options->tun_local = -1;
1035b74df5b2SDag-Erling Smørgrav 	options->tun_remote = -1;
1036b74df5b2SDag-Erling Smørgrav 	options->local_command = NULL;
1037b74df5b2SDag-Erling Smørgrav 	options->permit_local_command = -1;
1038511b41d2SMark Murray }
1039511b41d2SMark Murray 
1040511b41d2SMark Murray /*
1041511b41d2SMark Murray  * Called after processing other sources of option data, this fills those
1042511b41d2SMark Murray  * options for which no value has been specified with their default values.
1043511b41d2SMark Murray  */
1044511b41d2SMark Murray 
1045511b41d2SMark Murray void
1046511b41d2SMark Murray fill_default_options(Options * options)
1047511b41d2SMark Murray {
1048ca3176e7SBrian Feldman 	int len;
1049ca3176e7SBrian Feldman 
1050511b41d2SMark Murray 	if (options->forward_agent == -1)
1051db1cb46cSKris Kennaway 		options->forward_agent = 0;
1052511b41d2SMark Murray 	if (options->forward_x11 == -1)
10535dc73ebeSBrian Feldman 		options->forward_x11 = 0;
10541ec0d754SDag-Erling Smørgrav 	if (options->forward_x11_trusted == -1)
10551ec0d754SDag-Erling Smørgrav 		options->forward_x11_trusted = 0;
1056c2d3a559SKris Kennaway 	if (options->xauth_location == NULL)
1057af12a3e7SDag-Erling Smørgrav 		options->xauth_location = _PATH_XAUTH;
1058511b41d2SMark Murray 	if (options->gateway_ports == -1)
1059511b41d2SMark Murray 		options->gateway_ports = 0;
1060511b41d2SMark Murray 	if (options->use_privileged_port == -1)
1061ca3176e7SBrian Feldman 		options->use_privileged_port = 0;
1062511b41d2SMark Murray 	if (options->rsa_authentication == -1)
1063511b41d2SMark Murray 		options->rsa_authentication = 1;
1064ca3176e7SBrian Feldman 	if (options->pubkey_authentication == -1)
1065ca3176e7SBrian Feldman 		options->pubkey_authentication = 1;
1066af12a3e7SDag-Erling Smørgrav 	if (options->challenge_response_authentication == -1)
1067af12a3e7SDag-Erling Smørgrav 		options->challenge_response_authentication = 1;
1068cf2b5f3bSDag-Erling Smørgrav 	if (options->gss_authentication == -1)
10691ec0d754SDag-Erling Smørgrav 		options->gss_authentication = 0;
1070cf2b5f3bSDag-Erling Smørgrav 	if (options->gss_deleg_creds == -1)
1071cf2b5f3bSDag-Erling Smørgrav 		options->gss_deleg_creds = 0;
1072511b41d2SMark Murray 	if (options->password_authentication == -1)
1073511b41d2SMark Murray 		options->password_authentication = 1;
107409958426SBrian Feldman 	if (options->kbd_interactive_authentication == -1)
1075ca3176e7SBrian Feldman 		options->kbd_interactive_authentication = 1;
1076511b41d2SMark Murray 	if (options->rhosts_rsa_authentication == -1)
107780628bacSDag-Erling Smørgrav 		options->rhosts_rsa_authentication = 0;
1078ca3176e7SBrian Feldman 	if (options->hostbased_authentication == -1)
1079ca3176e7SBrian Feldman 		options->hostbased_authentication = 0;
1080511b41d2SMark Murray 	if (options->batch_mode == -1)
1081511b41d2SMark Murray 		options->batch_mode = 0;
1082511b41d2SMark Murray 	if (options->check_host_ip == -1)
1083975616f0SDag-Erling Smørgrav 		options->check_host_ip = 0;
1084511b41d2SMark Murray 	if (options->strict_host_key_checking == -1)
1085511b41d2SMark Murray 		options->strict_host_key_checking = 2;	/* 2 is default */
1086511b41d2SMark Murray 	if (options->compression == -1)
1087511b41d2SMark Murray 		options->compression = 0;
10881ec0d754SDag-Erling Smørgrav 	if (options->tcp_keep_alive == -1)
10891ec0d754SDag-Erling Smørgrav 		options->tcp_keep_alive = 1;
1090511b41d2SMark Murray 	if (options->compression_level == -1)
1091511b41d2SMark Murray 		options->compression_level = 6;
1092511b41d2SMark Murray 	if (options->port == -1)
1093511b41d2SMark Murray 		options->port = 0;	/* Filled in ssh_connect. */
1094cf2b5f3bSDag-Erling Smørgrav 	if (options->address_family == -1)
1095cf2b5f3bSDag-Erling Smørgrav 		options->address_family = AF_UNSPEC;
1096511b41d2SMark Murray 	if (options->connection_attempts == -1)
1097af12a3e7SDag-Erling Smørgrav 		options->connection_attempts = 1;
1098511b41d2SMark Murray 	if (options->number_of_password_prompts == -1)
1099511b41d2SMark Murray 		options->number_of_password_prompts = 3;
1100511b41d2SMark Murray 	/* Selected in ssh_login(). */
1101511b41d2SMark Murray 	if (options->cipher == -1)
1102511b41d2SMark Murray 		options->cipher = SSH_CIPHER_NOT_SET;
1103e8aafc91SKris Kennaway 	/* options->ciphers, default set in myproposals.h */
1104ca3176e7SBrian Feldman 	/* options->macs, default set in myproposals.h */
1105ca3176e7SBrian Feldman 	/* options->hostkeyalgorithms, default set in myproposals.h */
1106e8aafc91SKris Kennaway 	if (options->protocol == SSH_PROTO_UNKNOWN)
1107ca3176e7SBrian Feldman 		options->protocol = SSH_PROTO_1|SSH_PROTO_2;
1108511b41d2SMark Murray 	if (options->num_identity_files == 0) {
1109ca3176e7SBrian Feldman 		if (options->protocol & SSH_PROTO_1) {
1110ca3176e7SBrian Feldman 			len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1;
1111ca3176e7SBrian Feldman 			options->identity_files[options->num_identity_files] =
1112ca3176e7SBrian Feldman 			    xmalloc(len);
1113ca3176e7SBrian Feldman 			snprintf(options->identity_files[options->num_identity_files++],
1114ca3176e7SBrian Feldman 			    len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY);
1115511b41d2SMark Murray 		}
1116ca3176e7SBrian Feldman 		if (options->protocol & SSH_PROTO_2) {
1117ca3176e7SBrian Feldman 			len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1;
1118ca3176e7SBrian Feldman 			options->identity_files[options->num_identity_files] =
1119ca3176e7SBrian Feldman 			    xmalloc(len);
1120ca3176e7SBrian Feldman 			snprintf(options->identity_files[options->num_identity_files++],
1121ca3176e7SBrian Feldman 			    len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA);
1122ca3176e7SBrian Feldman 
1123ca3176e7SBrian Feldman 			len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1;
1124ca3176e7SBrian Feldman 			options->identity_files[options->num_identity_files] =
1125ca3176e7SBrian Feldman 			    xmalloc(len);
1126ca3176e7SBrian Feldman 			snprintf(options->identity_files[options->num_identity_files++],
1127ca3176e7SBrian Feldman 			    len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA);
1128ca3176e7SBrian Feldman 		}
1129e8aafc91SKris Kennaway 	}
1130511b41d2SMark Murray 	if (options->escape_char == -1)
1131511b41d2SMark Murray 		options->escape_char = '~';
1132511b41d2SMark Murray 	if (options->system_hostfile == NULL)
1133ca3176e7SBrian Feldman 		options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE;
1134511b41d2SMark Murray 	if (options->user_hostfile == NULL)
1135ca3176e7SBrian Feldman 		options->user_hostfile = _PATH_SSH_USER_HOSTFILE;
1136e8aafc91SKris Kennaway 	if (options->system_hostfile2 == NULL)
1137ca3176e7SBrian Feldman 		options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2;
1138e8aafc91SKris Kennaway 	if (options->user_hostfile2 == NULL)
1139ca3176e7SBrian Feldman 		options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2;
1140af12a3e7SDag-Erling Smørgrav 	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
1141511b41d2SMark Murray 		options->log_level = SYSLOG_LEVEL_INFO;
1142af12a3e7SDag-Erling Smørgrav 	if (options->clear_forwardings == 1)
1143af12a3e7SDag-Erling Smørgrav 		clear_forwardings(options);
1144af12a3e7SDag-Erling Smørgrav 	if (options->no_host_authentication_for_localhost == - 1)
1145af12a3e7SDag-Erling Smørgrav 		options->no_host_authentication_for_localhost = 0;
11465962c0e9SDag-Erling Smørgrav 	if (options->identities_only == -1)
11475962c0e9SDag-Erling Smørgrav 		options->identities_only = 0;
1148e73e9afaSDag-Erling Smørgrav 	if (options->enable_ssh_keysign == -1)
1149e73e9afaSDag-Erling Smørgrav 		options->enable_ssh_keysign = 0;
1150cf2b5f3bSDag-Erling Smørgrav 	if (options->rekey_limit == -1)
1151cf2b5f3bSDag-Erling Smørgrav 		options->rekey_limit = 0;
1152cf2b5f3bSDag-Erling Smørgrav 	if (options->verify_host_key_dns == -1)
1153cf2b5f3bSDag-Erling Smørgrav 		options->verify_host_key_dns = 0;
11541ec0d754SDag-Erling Smørgrav 	if (options->server_alive_interval == -1)
11551ec0d754SDag-Erling Smørgrav 		options->server_alive_interval = 0;
11561ec0d754SDag-Erling Smørgrav 	if (options->server_alive_count_max == -1)
11571ec0d754SDag-Erling Smørgrav 		options->server_alive_count_max = 3;
115821e764dfSDag-Erling Smørgrav 	if (options->control_master == -1)
115921e764dfSDag-Erling Smørgrav 		options->control_master = 0;
1160aa49c926SDag-Erling Smørgrav 	if (options->hash_known_hosts == -1)
1161aa49c926SDag-Erling Smørgrav 		options->hash_known_hosts = 0;
1162b74df5b2SDag-Erling Smørgrav 	if (options->tun_open == -1)
1163b74df5b2SDag-Erling Smørgrav 		options->tun_open = SSH_TUNMODE_NO;
1164b74df5b2SDag-Erling Smørgrav 	if (options->tun_local == -1)
1165b74df5b2SDag-Erling Smørgrav 		options->tun_local = SSH_TUNID_ANY;
1166b74df5b2SDag-Erling Smørgrav 	if (options->tun_remote == -1)
1167b74df5b2SDag-Erling Smørgrav 		options->tun_remote = SSH_TUNID_ANY;
1168b74df5b2SDag-Erling Smørgrav 	if (options->permit_local_command == -1)
1169b74df5b2SDag-Erling Smørgrav 		options->permit_local_command = 0;
1170b74df5b2SDag-Erling Smørgrav 	/* options->local_command should not be set by default */
1171511b41d2SMark Murray 	/* options->proxy_command should not be set by default */
1172511b41d2SMark Murray 	/* options->user will be set in the main program if appropriate */
1173511b41d2SMark Murray 	/* options->hostname will be set in the main program if appropriate */
1174ca3176e7SBrian Feldman 	/* options->host_key_alias should not be set by default */
1175ca3176e7SBrian Feldman 	/* options->preferred_authentications will be set in ssh */
1176511b41d2SMark Murray }
1177aa49c926SDag-Erling Smørgrav 
1178aa49c926SDag-Erling Smørgrav /*
1179aa49c926SDag-Erling Smørgrav  * parse_forward
1180aa49c926SDag-Erling Smørgrav  * parses a string containing a port forwarding specification of the form:
1181aa49c926SDag-Erling Smørgrav  *	[listenhost:]listenport:connecthost:connectport
1182aa49c926SDag-Erling Smørgrav  * returns number of arguments parsed or zero on error
1183aa49c926SDag-Erling Smørgrav  */
1184aa49c926SDag-Erling Smørgrav int
1185aa49c926SDag-Erling Smørgrav parse_forward(Forward *fwd, const char *fwdspec)
1186aa49c926SDag-Erling Smørgrav {
1187aa49c926SDag-Erling Smørgrav 	int i;
1188aa49c926SDag-Erling Smørgrav 	char *p, *cp, *fwdarg[4];
1189aa49c926SDag-Erling Smørgrav 
1190aa49c926SDag-Erling Smørgrav 	memset(fwd, '\0', sizeof(*fwd));
1191aa49c926SDag-Erling Smørgrav 
1192aa49c926SDag-Erling Smørgrav 	cp = p = xstrdup(fwdspec);
1193aa49c926SDag-Erling Smørgrav 
1194aa49c926SDag-Erling Smørgrav 	/* skip leading spaces */
1195aa49c926SDag-Erling Smørgrav 	while (*cp && isspace(*cp))
1196aa49c926SDag-Erling Smørgrav 		cp++;
1197aa49c926SDag-Erling Smørgrav 
1198aa49c926SDag-Erling Smørgrav 	for (i = 0; i < 4; ++i)
1199aa49c926SDag-Erling Smørgrav 		if ((fwdarg[i] = hpdelim(&cp)) == NULL)
1200aa49c926SDag-Erling Smørgrav 			break;
1201aa49c926SDag-Erling Smørgrav 
1202aa49c926SDag-Erling Smørgrav 	/* Check for trailing garbage in 4-arg case*/
1203aa49c926SDag-Erling Smørgrav 	if (cp != NULL)
1204aa49c926SDag-Erling Smørgrav 		i = 0;	/* failure */
1205aa49c926SDag-Erling Smørgrav 
1206aa49c926SDag-Erling Smørgrav 	switch (i) {
1207aa49c926SDag-Erling Smørgrav 	case 3:
1208aa49c926SDag-Erling Smørgrav 		fwd->listen_host = NULL;
1209aa49c926SDag-Erling Smørgrav 		fwd->listen_port = a2port(fwdarg[0]);
1210aa49c926SDag-Erling Smørgrav 		fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
1211aa49c926SDag-Erling Smørgrav 		fwd->connect_port = a2port(fwdarg[2]);
1212aa49c926SDag-Erling Smørgrav 		break;
1213aa49c926SDag-Erling Smørgrav 
1214aa49c926SDag-Erling Smørgrav 	case 4:
1215aa49c926SDag-Erling Smørgrav 		fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
1216aa49c926SDag-Erling Smørgrav 		fwd->listen_port = a2port(fwdarg[1]);
1217aa49c926SDag-Erling Smørgrav 		fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
1218aa49c926SDag-Erling Smørgrav 		fwd->connect_port = a2port(fwdarg[3]);
1219aa49c926SDag-Erling Smørgrav 		break;
1220aa49c926SDag-Erling Smørgrav 	default:
1221aa49c926SDag-Erling Smørgrav 		i = 0; /* failure */
1222aa49c926SDag-Erling Smørgrav 	}
1223aa49c926SDag-Erling Smørgrav 
1224aa49c926SDag-Erling Smørgrav 	xfree(p);
1225aa49c926SDag-Erling Smørgrav 
1226aa49c926SDag-Erling Smørgrav 	if (fwd->listen_port == 0 && fwd->connect_port == 0)
1227aa49c926SDag-Erling Smørgrav 		goto fail_free;
1228aa49c926SDag-Erling Smørgrav 
1229aa49c926SDag-Erling Smørgrav 	if (fwd->connect_host != NULL &&
1230aa49c926SDag-Erling Smørgrav 	    strlen(fwd->connect_host) >= NI_MAXHOST)
1231aa49c926SDag-Erling Smørgrav 		goto fail_free;
1232aa49c926SDag-Erling Smørgrav 
1233aa49c926SDag-Erling Smørgrav 	return (i);
1234aa49c926SDag-Erling Smørgrav 
1235aa49c926SDag-Erling Smørgrav  fail_free:
1236aa49c926SDag-Erling Smørgrav 	if (fwd->connect_host != NULL)
1237aa49c926SDag-Erling Smørgrav 		xfree(fwd->connect_host);
1238aa49c926SDag-Erling Smørgrav 	if (fwd->listen_host != NULL)
1239aa49c926SDag-Erling Smørgrav 		xfree(fwd->listen_host);
1240aa49c926SDag-Erling Smørgrav 	return (0);
1241aa49c926SDag-Erling Smørgrav }
1242