xref: /freebsd/crypto/openssh/readconf.c (revision e4a9863fb76a1f6b16ecbcbd31e88f4ad9a9565e)
1*e4a9863fSDag-Erling Smørgrav /* $OpenBSD: readconf.c,v 1.204 2013/06/10 19:19:44 dtucker Exp $ */
289986192SBrooks Davis /* $FreeBSD$ */
3511b41d2SMark Murray /*
4511b41d2SMark Murray  * Author: Tatu Ylonen <ylo@cs.hut.fi>
5511b41d2SMark Murray  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
6511b41d2SMark Murray  *                    All rights reserved
7511b41d2SMark Murray  * Functions for reading the configuration files.
8511b41d2SMark Murray  *
9c2d3a559SKris Kennaway  * As far as I am concerned, the code I have written for this software
10c2d3a559SKris Kennaway  * can be used freely for any purpose.  Any derived versions of this
11c2d3a559SKris Kennaway  * software must be clearly marked as such, and if the derived work is
12c2d3a559SKris Kennaway  * incompatible with the protocol description in the RFC file, it must be
13c2d3a559SKris Kennaway  * called by a name other than "ssh" or "Secure Shell".
14511b41d2SMark Murray  */
15511b41d2SMark Murray 
16511b41d2SMark Murray #include "includes.h"
17333ee039SDag-Erling Smørgrav __RCSID("$FreeBSD$");
18511b41d2SMark Murray 
19333ee039SDag-Erling Smørgrav #include <sys/types.h>
20333ee039SDag-Erling Smørgrav #include <sys/stat.h>
21333ee039SDag-Erling Smørgrav #include <sys/socket.h>
2203f6c5cdSDag-Erling Smørgrav #include <sys/sysctl.h>
23333ee039SDag-Erling Smørgrav 
24333ee039SDag-Erling Smørgrav #include <netinet/in.h>
254a421b63SDag-Erling Smørgrav #include <netinet/in_systm.h>
264a421b63SDag-Erling Smørgrav #include <netinet/ip.h>
27333ee039SDag-Erling Smørgrav 
28333ee039SDag-Erling Smørgrav #include <ctype.h>
29333ee039SDag-Erling Smørgrav #include <errno.h>
30333ee039SDag-Erling Smørgrav #include <netdb.h>
31333ee039SDag-Erling Smørgrav #include <signal.h>
32333ee039SDag-Erling Smørgrav #include <stdarg.h>
33333ee039SDag-Erling Smørgrav #include <stdio.h>
34333ee039SDag-Erling Smørgrav #include <string.h>
35333ee039SDag-Erling Smørgrav #include <unistd.h>
36*e4a9863fSDag-Erling Smørgrav #ifdef HAVE_UTIL_H
37*e4a9863fSDag-Erling Smørgrav #include <util.h>
38*e4a9863fSDag-Erling Smørgrav #endif
39333ee039SDag-Erling Smørgrav 
40511b41d2SMark Murray #include "xmalloc.h"
41333ee039SDag-Erling Smørgrav #include "ssh.h"
42e8aafc91SKris Kennaway #include "compat.h"
43ca3176e7SBrian Feldman #include "cipher.h"
44ca3176e7SBrian Feldman #include "pathnames.h"
45ca3176e7SBrian Feldman #include "log.h"
46333ee039SDag-Erling Smørgrav #include "key.h"
47ca3176e7SBrian Feldman #include "readconf.h"
48ca3176e7SBrian Feldman #include "match.h"
49ca3176e7SBrian Feldman #include "misc.h"
50333ee039SDag-Erling Smørgrav #include "buffer.h"
51ca3176e7SBrian Feldman #include "kex.h"
52ca3176e7SBrian Feldman #include "mac.h"
53cce7d346SDag-Erling Smørgrav #include "version.h"
54511b41d2SMark Murray 
55511b41d2SMark Murray /* Format of the configuration file:
56511b41d2SMark Murray 
57511b41d2SMark Murray    # Configuration data is parsed as follows:
58511b41d2SMark Murray    #  1. command line options
59511b41d2SMark Murray    #  2. user-specific file
60511b41d2SMark Murray    #  3. system-wide file
61511b41d2SMark Murray    # Any configuration value is only changed the first time it is set.
62511b41d2SMark Murray    # Thus, host-specific definitions should be at the beginning of the
63511b41d2SMark Murray    # configuration file, and defaults at the end.
64511b41d2SMark Murray 
65511b41d2SMark Murray    # Host-specific declarations.  These may override anything above.  A single
66511b41d2SMark Murray    # host may match multiple declarations; these are processed in the order
67511b41d2SMark Murray    # that they are given in.
68511b41d2SMark Murray 
69511b41d2SMark Murray    Host *.ngs.fi ngs.fi
7080628bacSDag-Erling Smørgrav      User foo
71511b41d2SMark Murray 
72511b41d2SMark Murray    Host fake.com
73511b41d2SMark Murray      HostName another.host.name.real.org
74511b41d2SMark Murray      User blaah
75511b41d2SMark Murray      Port 34289
76511b41d2SMark Murray      ForwardX11 no
77511b41d2SMark Murray      ForwardAgent no
78511b41d2SMark Murray 
79511b41d2SMark Murray    Host books.com
80511b41d2SMark Murray      RemoteForward 9999 shadows.cs.hut.fi:9999
81511b41d2SMark Murray      Cipher 3des
82511b41d2SMark Murray 
83511b41d2SMark Murray    Host fascist.blob.com
84511b41d2SMark Murray      Port 23123
85511b41d2SMark Murray      User tylonen
86511b41d2SMark Murray      PasswordAuthentication no
87511b41d2SMark Murray 
88511b41d2SMark Murray    Host puukko.hut.fi
89511b41d2SMark Murray      User t35124p
90511b41d2SMark Murray      ProxyCommand ssh-proxy %h %p
91511b41d2SMark Murray 
92511b41d2SMark Murray    Host *.fr
9380628bacSDag-Erling Smørgrav      PublicKeyAuthentication no
94511b41d2SMark Murray 
95511b41d2SMark Murray    Host *.su
96511b41d2SMark Murray      Cipher none
97511b41d2SMark Murray      PasswordAuthentication no
98511b41d2SMark Murray 
99b74df5b2SDag-Erling Smørgrav    Host vpn.fake.com
100b74df5b2SDag-Erling Smørgrav      Tunnel yes
101b74df5b2SDag-Erling Smørgrav      TunnelDevice 3
102b74df5b2SDag-Erling Smørgrav 
103511b41d2SMark Murray    # Defaults for various options
104511b41d2SMark Murray    Host *
105511b41d2SMark Murray      ForwardAgent no
106ca3176e7SBrian Feldman      ForwardX11 no
107511b41d2SMark Murray      PasswordAuthentication yes
108511b41d2SMark Murray      RSAAuthentication yes
109511b41d2SMark Murray      RhostsRSAAuthentication yes
110511b41d2SMark Murray      StrictHostKeyChecking yes
1111ec0d754SDag-Erling Smørgrav      TcpKeepAlive no
112511b41d2SMark Murray      IdentityFile ~/.ssh/identity
113511b41d2SMark Murray      Port 22
114511b41d2SMark Murray      EscapeChar ~
115511b41d2SMark Murray 
116511b41d2SMark Murray */
117511b41d2SMark Murray 
118511b41d2SMark Murray /* Keyword tokens. */
119511b41d2SMark Murray 
120511b41d2SMark Murray typedef enum {
121511b41d2SMark Murray 	oBadOption,
122e2f6069cSDag-Erling Smørgrav 	oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
123e2f6069cSDag-Erling Smørgrav 	oGatewayPorts, oExitOnForwardFailure,
12480628bacSDag-Erling Smørgrav 	oPasswordAuthentication, oRSAAuthentication,
125ca3176e7SBrian Feldman 	oChallengeResponseAuthentication, oXAuthLocation,
126511b41d2SMark Murray 	oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
127511b41d2SMark Murray 	oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
128511b41d2SMark Murray 	oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
129511b41d2SMark Murray 	oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
1301ec0d754SDag-Erling Smørgrav 	oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
131ca3176e7SBrian Feldman 	oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
132ca3176e7SBrian Feldman 	oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
133ca3176e7SBrian Feldman 	oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
134ca3176e7SBrian Feldman 	oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
135b15c8340SDag-Erling Smørgrav 	oHostKeyAlgorithms, oBindAddress, oPKCS11Provider,
1369e2cbe04SDag-Erling Smørgrav 	oClearAllForwardings, oNoHostAuthenticationForLocalhost,
137cf2b5f3bSDag-Erling Smørgrav 	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
138cf2b5f3bSDag-Erling Smørgrav 	oAddressFamily, oGssAuthentication, oGssDelegateCreds,
1395962c0e9SDag-Erling Smørgrav 	oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
140e2f6069cSDag-Erling Smørgrav 	oSendEnv, oControlPath, oControlMaster, oControlPersist,
141e2f6069cSDag-Erling Smørgrav 	oHashKnownHosts,
142b74df5b2SDag-Erling Smørgrav 	oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
1437aee6ffeSDag-Erling Smørgrav 	oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication,
144*e4a9863fSDag-Erling Smørgrav 	oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown,
145*e4a9863fSDag-Erling Smørgrav 	oIgnoredUnknownOption,
14689986192SBrooks Davis 	oHPNDisabled, oHPNBufferSize, oTcpRcvBufPoll, oTcpRcvBuf,
14789986192SBrooks Davis #ifdef NONE_CIPHER_ENABLED
14889986192SBrooks Davis 	oNoneEnabled, oNoneSwitch,
14989986192SBrooks Davis #endif
150*e4a9863fSDag-Erling Smørgrav 	oVersionAddendum, oDeprecated, oUnsupported
151511b41d2SMark Murray } OpCodes;
152511b41d2SMark Murray 
153511b41d2SMark Murray /* Textual representations of the tokens. */
154511b41d2SMark Murray 
155511b41d2SMark Murray static struct {
156511b41d2SMark Murray 	const char *name;
157511b41d2SMark Murray 	OpCodes opcode;
158511b41d2SMark Murray } keywords[] = {
159511b41d2SMark Murray 	{ "forwardagent", oForwardAgent },
160511b41d2SMark Murray 	{ "forwardx11", oForwardX11 },
1611ec0d754SDag-Erling Smørgrav 	{ "forwardx11trusted", oForwardX11Trusted },
162e2f6069cSDag-Erling Smørgrav 	{ "forwardx11timeout", oForwardX11Timeout },
163333ee039SDag-Erling Smørgrav 	{ "exitonforwardfailure", oExitOnForwardFailure },
164c2d3a559SKris Kennaway 	{ "xauthlocation", oXAuthLocation },
165511b41d2SMark Murray 	{ "gatewayports", oGatewayPorts },
166511b41d2SMark Murray 	{ "useprivilegedport", oUsePrivilegedPort },
167cf2b5f3bSDag-Erling Smørgrav 	{ "rhostsauthentication", oDeprecated },
168511b41d2SMark Murray 	{ "passwordauthentication", oPasswordAuthentication },
16909958426SBrian Feldman 	{ "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
17009958426SBrian Feldman 	{ "kbdinteractivedevices", oKbdInteractiveDevices },
171511b41d2SMark Murray 	{ "rsaauthentication", oRSAAuthentication },
172ca3176e7SBrian Feldman 	{ "pubkeyauthentication", oPubkeyAuthentication },
173ca3176e7SBrian Feldman 	{ "dsaauthentication", oPubkeyAuthentication },		    /* alias */
174ca3176e7SBrian Feldman 	{ "rhostsrsaauthentication", oRhostsRSAAuthentication },
175ca3176e7SBrian Feldman 	{ "hostbasedauthentication", oHostbasedAuthentication },
176ca3176e7SBrian Feldman 	{ "challengeresponseauthentication", oChallengeResponseAuthentication },
177ca3176e7SBrian Feldman 	{ "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
178ca3176e7SBrian Feldman 	{ "tisauthentication", oChallengeResponseAuthentication },  /* alias */
179cf2b5f3bSDag-Erling Smørgrav 	{ "kerberosauthentication", oUnsupported },
180cf2b5f3bSDag-Erling Smørgrav 	{ "kerberostgtpassing", oUnsupported },
181cf2b5f3bSDag-Erling Smørgrav 	{ "afstokenpassing", oUnsupported },
182cf2b5f3bSDag-Erling Smørgrav #if defined(GSSAPI)
183cf2b5f3bSDag-Erling Smørgrav 	{ "gssapiauthentication", oGssAuthentication },
184cf2b5f3bSDag-Erling Smørgrav 	{ "gssapidelegatecredentials", oGssDelegateCreds },
185cf2b5f3bSDag-Erling Smørgrav #else
186cf2b5f3bSDag-Erling Smørgrav 	{ "gssapiauthentication", oUnsupported },
187cf2b5f3bSDag-Erling Smørgrav 	{ "gssapidelegatecredentials", oUnsupported },
188511b41d2SMark Murray #endif
18980628bacSDag-Erling Smørgrav 	{ "fallbacktorsh", oDeprecated },
19080628bacSDag-Erling Smørgrav 	{ "usersh", oDeprecated },
191511b41d2SMark Murray 	{ "identityfile", oIdentityFile },
192cce7d346SDag-Erling Smørgrav 	{ "identityfile2", oIdentityFile },			/* obsolete */
1935962c0e9SDag-Erling Smørgrav 	{ "identitiesonly", oIdentitiesOnly },
194511b41d2SMark Murray 	{ "hostname", oHostName },
195ca3176e7SBrian Feldman 	{ "hostkeyalias", oHostKeyAlias },
196511b41d2SMark Murray 	{ "proxycommand", oProxyCommand },
197511b41d2SMark Murray 	{ "port", oPort },
198511b41d2SMark Murray 	{ "cipher", oCipher },
199e8aafc91SKris Kennaway 	{ "ciphers", oCiphers },
200ca3176e7SBrian Feldman 	{ "macs", oMacs },
201e8aafc91SKris Kennaway 	{ "protocol", oProtocol },
202511b41d2SMark Murray 	{ "remoteforward", oRemoteForward },
203511b41d2SMark Murray 	{ "localforward", oLocalForward },
204511b41d2SMark Murray 	{ "user", oUser },
205511b41d2SMark Murray 	{ "host", oHost },
206511b41d2SMark Murray 	{ "escapechar", oEscapeChar },
207511b41d2SMark Murray 	{ "globalknownhostsfile", oGlobalKnownHostsFile },
208e146993eSDag-Erling Smørgrav 	{ "globalknownhostsfile2", oDeprecated },
209cce7d346SDag-Erling Smørgrav 	{ "userknownhostsfile", oUserKnownHostsFile },
210e146993eSDag-Erling Smørgrav 	{ "userknownhostsfile2", oDeprecated },
211511b41d2SMark Murray 	{ "connectionattempts", oConnectionAttempts },
212511b41d2SMark Murray 	{ "batchmode", oBatchMode },
213511b41d2SMark Murray 	{ "checkhostip", oCheckHostIP },
214511b41d2SMark Murray 	{ "stricthostkeychecking", oStrictHostKeyChecking },
215511b41d2SMark Murray 	{ "compression", oCompression },
216511b41d2SMark Murray 	{ "compressionlevel", oCompressionLevel },
2171ec0d754SDag-Erling Smørgrav 	{ "tcpkeepalive", oTCPKeepAlive },
2181ec0d754SDag-Erling Smørgrav 	{ "keepalive", oTCPKeepAlive },				/* obsolete */
219511b41d2SMark Murray 	{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
220511b41d2SMark Murray 	{ "loglevel", oLogLevel },
221ca3176e7SBrian Feldman 	{ "dynamicforward", oDynamicForward },
222ca3176e7SBrian Feldman 	{ "preferredauthentications", oPreferredAuthentications },
223ca3176e7SBrian Feldman 	{ "hostkeyalgorithms", oHostKeyAlgorithms },
224af12a3e7SDag-Erling Smørgrav 	{ "bindaddress", oBindAddress },
225b15c8340SDag-Erling Smørgrav #ifdef ENABLE_PKCS11
226b15c8340SDag-Erling Smørgrav 	{ "smartcarddevice", oPKCS11Provider },
227b15c8340SDag-Erling Smørgrav 	{ "pkcs11provider", oPKCS11Provider },
228cf2b5f3bSDag-Erling Smørgrav #else
229cf2b5f3bSDag-Erling Smørgrav 	{ "smartcarddevice", oUnsupported },
230b15c8340SDag-Erling Smørgrav 	{ "pkcs11provider", oUnsupported },
231cf2b5f3bSDag-Erling Smørgrav #endif
232af12a3e7SDag-Erling Smørgrav 	{ "clearallforwardings", oClearAllForwardings },
233e73e9afaSDag-Erling Smørgrav 	{ "enablesshkeysign", oEnableSSHKeysign },
234cf2b5f3bSDag-Erling Smørgrav 	{ "verifyhostkeydns", oVerifyHostKeyDNS },
235af12a3e7SDag-Erling Smørgrav 	{ "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
236cf2b5f3bSDag-Erling Smørgrav 	{ "rekeylimit", oRekeyLimit },
237cf2b5f3bSDag-Erling Smørgrav 	{ "connecttimeout", oConnectTimeout },
238cf2b5f3bSDag-Erling Smørgrav 	{ "addressfamily", oAddressFamily },
2391ec0d754SDag-Erling Smørgrav 	{ "serveraliveinterval", oServerAliveInterval },
2401ec0d754SDag-Erling Smørgrav 	{ "serveralivecountmax", oServerAliveCountMax },
24121e764dfSDag-Erling Smørgrav 	{ "sendenv", oSendEnv },
24221e764dfSDag-Erling Smørgrav 	{ "controlpath", oControlPath },
24321e764dfSDag-Erling Smørgrav 	{ "controlmaster", oControlMaster },
244e2f6069cSDag-Erling Smørgrav 	{ "controlpersist", oControlPersist },
245aa49c926SDag-Erling Smørgrav 	{ "hashknownhosts", oHashKnownHosts },
246b74df5b2SDag-Erling Smørgrav 	{ "tunnel", oTunnel },
247b74df5b2SDag-Erling Smørgrav 	{ "tunneldevice", oTunnelDevice },
248b74df5b2SDag-Erling Smørgrav 	{ "localcommand", oLocalCommand },
249b74df5b2SDag-Erling Smørgrav 	{ "permitlocalcommand", oPermitLocalCommand },
250d4af9e69SDag-Erling Smørgrav 	{ "visualhostkey", oVisualHostKey },
2517aee6ffeSDag-Erling Smørgrav 	{ "useroaming", oUseRoaming },
252cce7d346SDag-Erling Smørgrav #ifdef JPAKE
253cce7d346SDag-Erling Smørgrav 	{ "zeroknowledgepasswordauthentication",
254cce7d346SDag-Erling Smørgrav 	    oZeroKnowledgePasswordAuthentication },
255cce7d346SDag-Erling Smørgrav #else
256cce7d346SDag-Erling Smørgrav 	{ "zeroknowledgepasswordauthentication", oUnsupported },
257cce7d346SDag-Erling Smørgrav #endif
2584a421b63SDag-Erling Smørgrav 	{ "kexalgorithms", oKexAlgorithms },
2594a421b63SDag-Erling Smørgrav 	{ "ipqos", oIPQoS },
260e146993eSDag-Erling Smørgrav 	{ "requesttty", oRequestTTY },
261*e4a9863fSDag-Erling Smørgrav 	{ "ignoreunknown", oIgnoreUnknown },
26289986192SBrooks Davis 	{ "hpndisabled", oHPNDisabled },
26389986192SBrooks Davis 	{ "hpnbuffersize", oHPNBufferSize },
26489986192SBrooks Davis 	{ "tcprcvbufpoll", oTcpRcvBufPoll },
26589986192SBrooks Davis 	{ "tcprcvbuf", oTcpRcvBuf },
26689986192SBrooks Davis #ifdef	NONE_CIPHER_ENABLED
26789986192SBrooks Davis 	{ "noneenabled", oNoneEnabled },
26889986192SBrooks Davis 	{ "noneswitch", oNoneSwitch },
26989986192SBrooks Davis #endif
270975616f0SDag-Erling Smørgrav 	{ "versionaddendum", oVersionAddendum },
27135762f59SEd Schouten 
272af12a3e7SDag-Erling Smørgrav 	{ NULL, oBadOption }
273511b41d2SMark Murray };
274511b41d2SMark Murray 
275511b41d2SMark Murray /*
276511b41d2SMark Murray  * Adds a local TCP/IP port forward to options.  Never returns if there is an
277511b41d2SMark Murray  * error.
278511b41d2SMark Murray  */
279511b41d2SMark Murray 
280511b41d2SMark Murray void
281aa49c926SDag-Erling Smørgrav add_local_forward(Options *options, const Forward *newfwd)
282511b41d2SMark Murray {
283511b41d2SMark Murray 	Forward *fwd;
284f388f5efSDag-Erling Smørgrav #ifndef NO_IPPORT_RESERVED_CONCEPT
285511b41d2SMark Murray 	extern uid_t original_real_uid;
28603f6c5cdSDag-Erling Smørgrav 	int ipport_reserved;
28703f6c5cdSDag-Erling Smørgrav #ifdef __FreeBSD__
28803f6c5cdSDag-Erling Smørgrav 	size_t len_ipport_reserved = sizeof(ipport_reserved);
28903f6c5cdSDag-Erling Smørgrav 
29003f6c5cdSDag-Erling Smørgrav 	if (sysctlbyname("net.inet.ip.portrange.reservedhigh",
29103f6c5cdSDag-Erling Smørgrav 	    &ipport_reserved, &len_ipport_reserved, NULL, 0) != 0)
29203f6c5cdSDag-Erling Smørgrav 		ipport_reserved = IPPORT_RESERVED;
29303f6c5cdSDag-Erling Smørgrav 	else
29403f6c5cdSDag-Erling Smørgrav 		ipport_reserved++;
29503f6c5cdSDag-Erling Smørgrav #else
29603f6c5cdSDag-Erling Smørgrav 	ipport_reserved = IPPORT_RESERVED;
29703f6c5cdSDag-Erling Smørgrav #endif
29803f6c5cdSDag-Erling Smørgrav 	if (newfwd->listen_port < ipport_reserved && original_real_uid != 0)
299ca3176e7SBrian Feldman 		fatal("Privileged ports can only be forwarded by root.");
300989dd127SDag-Erling Smørgrav #endif
301e2f6069cSDag-Erling Smørgrav 	options->local_forwards = xrealloc(options->local_forwards,
302e2f6069cSDag-Erling Smørgrav 	    options->num_local_forwards + 1,
303e2f6069cSDag-Erling Smørgrav 	    sizeof(*options->local_forwards));
304511b41d2SMark Murray 	fwd = &options->local_forwards[options->num_local_forwards++];
305aa49c926SDag-Erling Smørgrav 
306cce7d346SDag-Erling Smørgrav 	fwd->listen_host = newfwd->listen_host;
307aa49c926SDag-Erling Smørgrav 	fwd->listen_port = newfwd->listen_port;
308cce7d346SDag-Erling Smørgrav 	fwd->connect_host = newfwd->connect_host;
309aa49c926SDag-Erling Smørgrav 	fwd->connect_port = newfwd->connect_port;
310511b41d2SMark Murray }
311511b41d2SMark Murray 
312511b41d2SMark Murray /*
313511b41d2SMark Murray  * Adds a remote TCP/IP port forward to options.  Never returns if there is
314511b41d2SMark Murray  * an error.
315511b41d2SMark Murray  */
316511b41d2SMark Murray 
317511b41d2SMark Murray void
318aa49c926SDag-Erling Smørgrav add_remote_forward(Options *options, const Forward *newfwd)
319511b41d2SMark Murray {
320511b41d2SMark Murray 	Forward *fwd;
321e2f6069cSDag-Erling Smørgrav 
322e2f6069cSDag-Erling Smørgrav 	options->remote_forwards = xrealloc(options->remote_forwards,
323e2f6069cSDag-Erling Smørgrav 	    options->num_remote_forwards + 1,
324e2f6069cSDag-Erling Smørgrav 	    sizeof(*options->remote_forwards));
325511b41d2SMark Murray 	fwd = &options->remote_forwards[options->num_remote_forwards++];
326aa49c926SDag-Erling Smørgrav 
327cce7d346SDag-Erling Smørgrav 	fwd->listen_host = newfwd->listen_host;
328aa49c926SDag-Erling Smørgrav 	fwd->listen_port = newfwd->listen_port;
329cce7d346SDag-Erling Smørgrav 	fwd->connect_host = newfwd->connect_host;
330aa49c926SDag-Erling Smørgrav 	fwd->connect_port = newfwd->connect_port;
331462c32cbSDag-Erling Smørgrav 	fwd->handle = newfwd->handle;
332e2f6069cSDag-Erling Smørgrav 	fwd->allocated_port = 0;
333511b41d2SMark Murray }
334511b41d2SMark Murray 
335af12a3e7SDag-Erling Smørgrav static void
336af12a3e7SDag-Erling Smørgrav clear_forwardings(Options *options)
337af12a3e7SDag-Erling Smørgrav {
338af12a3e7SDag-Erling Smørgrav 	int i;
339af12a3e7SDag-Erling Smørgrav 
340aa49c926SDag-Erling Smørgrav 	for (i = 0; i < options->num_local_forwards; i++) {
341*e4a9863fSDag-Erling Smørgrav 		free(options->local_forwards[i].listen_host);
342*e4a9863fSDag-Erling Smørgrav 		free(options->local_forwards[i].connect_host);
343aa49c926SDag-Erling Smørgrav 	}
344e2f6069cSDag-Erling Smørgrav 	if (options->num_local_forwards > 0) {
345*e4a9863fSDag-Erling Smørgrav 		free(options->local_forwards);
346e2f6069cSDag-Erling Smørgrav 		options->local_forwards = NULL;
347e2f6069cSDag-Erling Smørgrav 	}
348af12a3e7SDag-Erling Smørgrav 	options->num_local_forwards = 0;
349aa49c926SDag-Erling Smørgrav 	for (i = 0; i < options->num_remote_forwards; i++) {
350*e4a9863fSDag-Erling Smørgrav 		free(options->remote_forwards[i].listen_host);
351*e4a9863fSDag-Erling Smørgrav 		free(options->remote_forwards[i].connect_host);
352aa49c926SDag-Erling Smørgrav 	}
353e2f6069cSDag-Erling Smørgrav 	if (options->num_remote_forwards > 0) {
354*e4a9863fSDag-Erling Smørgrav 		free(options->remote_forwards);
355e2f6069cSDag-Erling Smørgrav 		options->remote_forwards = NULL;
356e2f6069cSDag-Erling Smørgrav 	}
357af12a3e7SDag-Erling Smørgrav 	options->num_remote_forwards = 0;
358b74df5b2SDag-Erling Smørgrav 	options->tun_open = SSH_TUNMODE_NO;
359af12a3e7SDag-Erling Smørgrav }
360af12a3e7SDag-Erling Smørgrav 
361fa67e83cSDag-Erling Smørgrav void
362fa67e83cSDag-Erling Smørgrav add_identity_file(Options *options, const char *dir, const char *filename,
363fa67e83cSDag-Erling Smørgrav     int userprovided)
364fa67e83cSDag-Erling Smørgrav {
365fa67e83cSDag-Erling Smørgrav 	char *path;
366fa67e83cSDag-Erling Smørgrav 
367fa67e83cSDag-Erling Smørgrav 	if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
368fa67e83cSDag-Erling Smørgrav 		fatal("Too many identity files specified (max %d)",
369fa67e83cSDag-Erling Smørgrav 		    SSH_MAX_IDENTITY_FILES);
370fa67e83cSDag-Erling Smørgrav 
371fa67e83cSDag-Erling Smørgrav 	if (dir == NULL) /* no dir, filename is absolute */
372fa67e83cSDag-Erling Smørgrav 		path = xstrdup(filename);
373fa67e83cSDag-Erling Smørgrav 	else
374fa67e83cSDag-Erling Smørgrav 		(void)xasprintf(&path, "%.100s%.100s", dir, filename);
375fa67e83cSDag-Erling Smørgrav 
376fa67e83cSDag-Erling Smørgrav 	options->identity_file_userprovided[options->num_identity_files] =
377fa67e83cSDag-Erling Smørgrav 	    userprovided;
378fa67e83cSDag-Erling Smørgrav 	options->identity_files[options->num_identity_files++] = path;
379fa67e83cSDag-Erling Smørgrav }
380fa67e83cSDag-Erling Smørgrav 
381511b41d2SMark Murray /*
382ca3176e7SBrian Feldman  * Returns the number of the token pointed to by cp or oBadOption.
383511b41d2SMark Murray  */
384511b41d2SMark Murray 
385511b41d2SMark Murray static OpCodes
386*e4a9863fSDag-Erling Smørgrav parse_token(const char *cp, const char *filename, int linenum,
387*e4a9863fSDag-Erling Smørgrav     const char *ignored_unknown)
388511b41d2SMark Murray {
389*e4a9863fSDag-Erling Smørgrav 	int i;
390511b41d2SMark Murray 
391511b41d2SMark Murray 	for (i = 0; keywords[i].name; i++)
392*e4a9863fSDag-Erling Smørgrav 		if (strcmp(cp, keywords[i].name) == 0)
393511b41d2SMark Murray 			return keywords[i].opcode;
394*e4a9863fSDag-Erling Smørgrav 	if (ignored_unknown != NULL && match_pattern_list(cp, ignored_unknown,
395*e4a9863fSDag-Erling Smørgrav 	    strlen(ignored_unknown), 1) == 1)
396*e4a9863fSDag-Erling Smørgrav 		return oIgnoredUnknownOption;
397ca3176e7SBrian Feldman 	error("%s: line %d: Bad configuration option: %s",
398511b41d2SMark Murray 	    filename, linenum, cp);
399511b41d2SMark Murray 	return oBadOption;
400511b41d2SMark Murray }
401511b41d2SMark Murray 
402511b41d2SMark Murray /*
403511b41d2SMark Murray  * Processes a single option line as used in the configuration files. This
404511b41d2SMark Murray  * only sets those values that have not already been set.
405511b41d2SMark Murray  */
406e73e9afaSDag-Erling Smørgrav #define WHITESPACE " \t\r\n"
407511b41d2SMark Murray 
408511b41d2SMark Murray int
409511b41d2SMark Murray process_config_line(Options *options, const char *host,
410511b41d2SMark Murray 		    char *line, const char *filename, int linenum,
41173370613SDag-Erling Smørgrav 		    int *activep, int userconfig)
412511b41d2SMark Murray {
413e146993eSDag-Erling Smørgrav 	char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;
414e146993eSDag-Erling Smørgrav 	char **cpptr, fwdarg[256];
415*e4a9863fSDag-Erling Smørgrav 	u_int i, *uintptr, max_entries = 0;
416*e4a9863fSDag-Erling Smørgrav 	int negated, opcode, *intptr, value, value2;
417d4af9e69SDag-Erling Smørgrav 	LogLevel *log_level_ptr;
418*e4a9863fSDag-Erling Smørgrav 	long long val64;
419e73e9afaSDag-Erling Smørgrav 	size_t len;
420aa49c926SDag-Erling Smørgrav 	Forward fwd;
421511b41d2SMark Murray 
422cf2b5f3bSDag-Erling Smørgrav 	/* Strip trailing whitespace */
423cf2b5f3bSDag-Erling Smørgrav 	for (len = strlen(line) - 1; len > 0; len--) {
424cf2b5f3bSDag-Erling Smørgrav 		if (strchr(WHITESPACE, line[len]) == NULL)
425cf2b5f3bSDag-Erling Smørgrav 			break;
426cf2b5f3bSDag-Erling Smørgrav 		line[len] = '\0';
427cf2b5f3bSDag-Erling Smørgrav 	}
428cf2b5f3bSDag-Erling Smørgrav 
429c2d3a559SKris Kennaway 	s = line;
430c2d3a559SKris Kennaway 	/* Get the keyword. (Each line is supposed to begin with a keyword). */
431333ee039SDag-Erling Smørgrav 	if ((keyword = strdelim(&s)) == NULL)
432333ee039SDag-Erling Smørgrav 		return 0;
433c2d3a559SKris Kennaway 	/* Ignore leading whitespace. */
434c2d3a559SKris Kennaway 	if (*keyword == '\0')
435c2d3a559SKris Kennaway 		keyword = strdelim(&s);
436ca3176e7SBrian Feldman 	if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
437511b41d2SMark Murray 		return 0;
438*e4a9863fSDag-Erling Smørgrav 	/* Match lowercase keyword */
439*e4a9863fSDag-Erling Smørgrav 	for (i = 0; i < strlen(keyword); i++)
440*e4a9863fSDag-Erling Smørgrav 		keyword[i] = tolower(keyword[i]);
441511b41d2SMark Murray 
442*e4a9863fSDag-Erling Smørgrav 	opcode = parse_token(keyword, filename, linenum,
443*e4a9863fSDag-Erling Smørgrav 	    options->ignored_unknown);
444511b41d2SMark Murray 
445511b41d2SMark Murray 	switch (opcode) {
446511b41d2SMark Murray 	case oBadOption:
447511b41d2SMark Murray 		/* don't panic, but count bad options */
448511b41d2SMark Murray 		return -1;
449511b41d2SMark Murray 		/* NOTREACHED */
450*e4a9863fSDag-Erling Smørgrav 	case oIgnoredUnknownOption:
451*e4a9863fSDag-Erling Smørgrav 		debug("%s line %d: Ignored unknown option \"%s\"",
452*e4a9863fSDag-Erling Smørgrav 		    filename, linenum, keyword);
453*e4a9863fSDag-Erling Smørgrav 		return 0;
454cf2b5f3bSDag-Erling Smørgrav 	case oConnectTimeout:
455cf2b5f3bSDag-Erling Smørgrav 		intptr = &options->connection_timeout;
4561ec0d754SDag-Erling Smørgrav parse_time:
457cf2b5f3bSDag-Erling Smørgrav 		arg = strdelim(&s);
458cf2b5f3bSDag-Erling Smørgrav 		if (!arg || *arg == '\0')
459cf2b5f3bSDag-Erling Smørgrav 			fatal("%s line %d: missing time value.",
460cf2b5f3bSDag-Erling Smørgrav 			    filename, linenum);
461cf2b5f3bSDag-Erling Smørgrav 		if ((value = convtime(arg)) == -1)
462cf2b5f3bSDag-Erling Smørgrav 			fatal("%s line %d: invalid time value.",
463cf2b5f3bSDag-Erling Smørgrav 			    filename, linenum);
464d4af9e69SDag-Erling Smørgrav 		if (*activep && *intptr == -1)
465cf2b5f3bSDag-Erling Smørgrav 			*intptr = value;
466cf2b5f3bSDag-Erling Smørgrav 		break;
467cf2b5f3bSDag-Erling Smørgrav 
468511b41d2SMark Murray 	case oForwardAgent:
469511b41d2SMark Murray 		intptr = &options->forward_agent;
470511b41d2SMark Murray parse_flag:
471c2d3a559SKris Kennaway 		arg = strdelim(&s);
472c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
473511b41d2SMark Murray 			fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
474511b41d2SMark Murray 		value = 0;	/* To avoid compiler warning... */
475c2d3a559SKris Kennaway 		if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
476511b41d2SMark Murray 			value = 1;
477c2d3a559SKris Kennaway 		else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
478511b41d2SMark Murray 			value = 0;
479511b41d2SMark Murray 		else
480511b41d2SMark Murray 			fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
481511b41d2SMark Murray 		if (*activep && *intptr == -1)
482511b41d2SMark Murray 			*intptr = value;
483511b41d2SMark Murray 		break;
484511b41d2SMark Murray 
485511b41d2SMark Murray 	case oForwardX11:
486511b41d2SMark Murray 		intptr = &options->forward_x11;
487511b41d2SMark Murray 		goto parse_flag;
488511b41d2SMark Murray 
4891ec0d754SDag-Erling Smørgrav 	case oForwardX11Trusted:
4901ec0d754SDag-Erling Smørgrav 		intptr = &options->forward_x11_trusted;
4911ec0d754SDag-Erling Smørgrav 		goto parse_flag;
4921ec0d754SDag-Erling Smørgrav 
493e2f6069cSDag-Erling Smørgrav 	case oForwardX11Timeout:
494e2f6069cSDag-Erling Smørgrav 		intptr = &options->forward_x11_timeout;
495e2f6069cSDag-Erling Smørgrav 		goto parse_time;
496e2f6069cSDag-Erling Smørgrav 
497511b41d2SMark Murray 	case oGatewayPorts:
498511b41d2SMark Murray 		intptr = &options->gateway_ports;
499511b41d2SMark Murray 		goto parse_flag;
500511b41d2SMark Murray 
501333ee039SDag-Erling Smørgrav 	case oExitOnForwardFailure:
502333ee039SDag-Erling Smørgrav 		intptr = &options->exit_on_forward_failure;
503333ee039SDag-Erling Smørgrav 		goto parse_flag;
504333ee039SDag-Erling Smørgrav 
505511b41d2SMark Murray 	case oUsePrivilegedPort:
506511b41d2SMark Murray 		intptr = &options->use_privileged_port;
507511b41d2SMark Murray 		goto parse_flag;
508511b41d2SMark Murray 
509511b41d2SMark Murray 	case oPasswordAuthentication:
510511b41d2SMark Murray 		intptr = &options->password_authentication;
511511b41d2SMark Murray 		goto parse_flag;
512511b41d2SMark Murray 
513cce7d346SDag-Erling Smørgrav 	case oZeroKnowledgePasswordAuthentication:
514cce7d346SDag-Erling Smørgrav 		intptr = &options->zero_knowledge_password_authentication;
515cce7d346SDag-Erling Smørgrav 		goto parse_flag;
516cce7d346SDag-Erling Smørgrav 
51709958426SBrian Feldman 	case oKbdInteractiveAuthentication:
51809958426SBrian Feldman 		intptr = &options->kbd_interactive_authentication;
51909958426SBrian Feldman 		goto parse_flag;
52009958426SBrian Feldman 
52109958426SBrian Feldman 	case oKbdInteractiveDevices:
52209958426SBrian Feldman 		charptr = &options->kbd_interactive_devices;
52309958426SBrian Feldman 		goto parse_string;
52409958426SBrian Feldman 
525ca3176e7SBrian Feldman 	case oPubkeyAuthentication:
526ca3176e7SBrian Feldman 		intptr = &options->pubkey_authentication;
527e8aafc91SKris Kennaway 		goto parse_flag;
528e8aafc91SKris Kennaway 
529511b41d2SMark Murray 	case oRSAAuthentication:
530511b41d2SMark Murray 		intptr = &options->rsa_authentication;
531511b41d2SMark Murray 		goto parse_flag;
532511b41d2SMark Murray 
533511b41d2SMark Murray 	case oRhostsRSAAuthentication:
534511b41d2SMark Murray 		intptr = &options->rhosts_rsa_authentication;
535511b41d2SMark Murray 		goto parse_flag;
536511b41d2SMark Murray 
537ca3176e7SBrian Feldman 	case oHostbasedAuthentication:
538ca3176e7SBrian Feldman 		intptr = &options->hostbased_authentication;
539511b41d2SMark Murray 		goto parse_flag;
540511b41d2SMark Murray 
541af12a3e7SDag-Erling Smørgrav 	case oChallengeResponseAuthentication:
542af12a3e7SDag-Erling Smørgrav 		intptr = &options->challenge_response_authentication;
543af12a3e7SDag-Erling Smørgrav 		goto parse_flag;
544cf2b5f3bSDag-Erling Smørgrav 
545cf2b5f3bSDag-Erling Smørgrav 	case oGssAuthentication:
546cf2b5f3bSDag-Erling Smørgrav 		intptr = &options->gss_authentication;
547511b41d2SMark Murray 		goto parse_flag;
548cf2b5f3bSDag-Erling Smørgrav 
549cf2b5f3bSDag-Erling Smørgrav 	case oGssDelegateCreds:
550cf2b5f3bSDag-Erling Smørgrav 		intptr = &options->gss_deleg_creds;
551ca3176e7SBrian Feldman 		goto parse_flag;
552cf2b5f3bSDag-Erling Smørgrav 
553511b41d2SMark Murray 	case oBatchMode:
554511b41d2SMark Murray 		intptr = &options->batch_mode;
555511b41d2SMark Murray 		goto parse_flag;
556511b41d2SMark Murray 
557511b41d2SMark Murray 	case oCheckHostIP:
558511b41d2SMark Murray 		intptr = &options->check_host_ip;
559511b41d2SMark Murray 		goto parse_flag;
560511b41d2SMark Murray 
561cf2b5f3bSDag-Erling Smørgrav 	case oVerifyHostKeyDNS:
562cf2b5f3bSDag-Erling Smørgrav 		intptr = &options->verify_host_key_dns;
5631ec0d754SDag-Erling Smørgrav 		goto parse_yesnoask;
564cf2b5f3bSDag-Erling Smørgrav 
565511b41d2SMark Murray 	case oStrictHostKeyChecking:
566511b41d2SMark Murray 		intptr = &options->strict_host_key_checking;
5671ec0d754SDag-Erling Smørgrav parse_yesnoask:
568c2d3a559SKris Kennaway 		arg = strdelim(&s);
569c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
570ca3176e7SBrian Feldman 			fatal("%.200s line %d: Missing yes/no/ask argument.",
571511b41d2SMark Murray 			    filename, linenum);
572511b41d2SMark Murray 		value = 0;	/* To avoid compiler warning... */
573c2d3a559SKris Kennaway 		if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
574511b41d2SMark Murray 			value = 1;
575c2d3a559SKris Kennaway 		else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
576511b41d2SMark Murray 			value = 0;
577c2d3a559SKris Kennaway 		else if (strcmp(arg, "ask") == 0)
578511b41d2SMark Murray 			value = 2;
579511b41d2SMark Murray 		else
580511b41d2SMark Murray 			fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
581511b41d2SMark Murray 		if (*activep && *intptr == -1)
582511b41d2SMark Murray 			*intptr = value;
583511b41d2SMark Murray 		break;
584511b41d2SMark Murray 
585511b41d2SMark Murray 	case oCompression:
586511b41d2SMark Murray 		intptr = &options->compression;
587511b41d2SMark Murray 		goto parse_flag;
588511b41d2SMark Murray 
5891ec0d754SDag-Erling Smørgrav 	case oTCPKeepAlive:
5901ec0d754SDag-Erling Smørgrav 		intptr = &options->tcp_keep_alive;
591511b41d2SMark Murray 		goto parse_flag;
592511b41d2SMark Murray 
593af12a3e7SDag-Erling Smørgrav 	case oNoHostAuthenticationForLocalhost:
594af12a3e7SDag-Erling Smørgrav 		intptr = &options->no_host_authentication_for_localhost;
595af12a3e7SDag-Erling Smørgrav 		goto parse_flag;
596af12a3e7SDag-Erling Smørgrav 
597511b41d2SMark Murray 	case oNumberOfPasswordPrompts:
598511b41d2SMark Murray 		intptr = &options->number_of_password_prompts;
599511b41d2SMark Murray 		goto parse_int;
600511b41d2SMark Murray 
601511b41d2SMark Murray 	case oCompressionLevel:
602511b41d2SMark Murray 		intptr = &options->compression_level;
603511b41d2SMark Murray 		goto parse_int;
604511b41d2SMark Murray 
605cf2b5f3bSDag-Erling Smørgrav 	case oRekeyLimit:
606cf2b5f3bSDag-Erling Smørgrav 		arg = strdelim(&s);
607cf2b5f3bSDag-Erling Smørgrav 		if (!arg || *arg == '\0')
608*e4a9863fSDag-Erling Smørgrav 			fatal("%.200s line %d: Missing argument.", filename,
609*e4a9863fSDag-Erling Smørgrav 			    linenum);
610*e4a9863fSDag-Erling Smørgrav 		if (strcmp(arg, "default") == 0) {
611*e4a9863fSDag-Erling Smørgrav 			val64 = 0;
612*e4a9863fSDag-Erling Smørgrav 		} else {
613*e4a9863fSDag-Erling Smørgrav 			if (scan_scaled(arg, &val64) == -1)
614*e4a9863fSDag-Erling Smørgrav 				fatal("%.200s line %d: Bad number '%s': %s",
615*e4a9863fSDag-Erling Smørgrav 				    filename, linenum, arg, strerror(errno));
616*e4a9863fSDag-Erling Smørgrav 			/* check for too-large or too-small limits */
617*e4a9863fSDag-Erling Smørgrav 			if (val64 > UINT_MAX)
618333ee039SDag-Erling Smørgrav 				fatal("%.200s line %d: RekeyLimit too large",
619333ee039SDag-Erling Smørgrav 				    filename, linenum);
620*e4a9863fSDag-Erling Smørgrav 			if (val64 != 0 && val64 < 16)
621333ee039SDag-Erling Smørgrav 				fatal("%.200s line %d: RekeyLimit too small",
622333ee039SDag-Erling Smørgrav 				    filename, linenum);
623*e4a9863fSDag-Erling Smørgrav 		}
624d4af9e69SDag-Erling Smørgrav 		if (*activep && options->rekey_limit == -1)
625d4af9e69SDag-Erling Smørgrav 			options->rekey_limit = (u_int32_t)val64;
626*e4a9863fSDag-Erling Smørgrav 		if (s != NULL) { /* optional rekey interval present */
627*e4a9863fSDag-Erling Smørgrav 			if (strcmp(s, "none") == 0) {
628*e4a9863fSDag-Erling Smørgrav 				(void)strdelim(&s);	/* discard */
629*e4a9863fSDag-Erling Smørgrav 				break;
630*e4a9863fSDag-Erling Smørgrav 			}
631*e4a9863fSDag-Erling Smørgrav 			intptr = &options->rekey_interval;
632*e4a9863fSDag-Erling Smørgrav 			goto parse_time;
633*e4a9863fSDag-Erling Smørgrav 		}
634cf2b5f3bSDag-Erling Smørgrav 		break;
635cf2b5f3bSDag-Erling Smørgrav 
636511b41d2SMark Murray 	case oIdentityFile:
637c2d3a559SKris Kennaway 		arg = strdelim(&s);
638c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
639511b41d2SMark Murray 			fatal("%.200s line %d: Missing argument.", filename, linenum);
640511b41d2SMark Murray 		if (*activep) {
641ca3176e7SBrian Feldman 			intptr = &options->num_identity_files;
642e8aafc91SKris Kennaway 			if (*intptr >= SSH_MAX_IDENTITY_FILES)
643511b41d2SMark Murray 				fatal("%.200s line %d: Too many identity files specified (max %d).",
644511b41d2SMark Murray 				    filename, linenum, SSH_MAX_IDENTITY_FILES);
64573370613SDag-Erling Smørgrav 			add_identity_file(options, NULL, arg, userconfig);
646511b41d2SMark Murray 		}
647511b41d2SMark Murray 		break;
648511b41d2SMark Murray 
649c2d3a559SKris Kennaway 	case oXAuthLocation:
650c2d3a559SKris Kennaway 		charptr=&options->xauth_location;
651c2d3a559SKris Kennaway 		goto parse_string;
652c2d3a559SKris Kennaway 
653511b41d2SMark Murray 	case oUser:
654511b41d2SMark Murray 		charptr = &options->user;
655511b41d2SMark Murray parse_string:
656c2d3a559SKris Kennaway 		arg = strdelim(&s);
657c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
658e146993eSDag-Erling Smørgrav 			fatal("%.200s line %d: Missing argument.",
659e146993eSDag-Erling Smørgrav 			    filename, linenum);
660511b41d2SMark Murray 		if (*activep && *charptr == NULL)
661c2d3a559SKris Kennaway 			*charptr = xstrdup(arg);
662511b41d2SMark Murray 		break;
663511b41d2SMark Murray 
664511b41d2SMark Murray 	case oGlobalKnownHostsFile:
665e146993eSDag-Erling Smørgrav 		cpptr = (char **)&options->system_hostfiles;
666e146993eSDag-Erling Smørgrav 		uintptr = &options->num_system_hostfiles;
667e146993eSDag-Erling Smørgrav 		max_entries = SSH_MAX_HOSTS_FILES;
668e146993eSDag-Erling Smørgrav parse_char_array:
669e146993eSDag-Erling Smørgrav 		if (*activep && *uintptr == 0) {
670e146993eSDag-Erling Smørgrav 			while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
671e146993eSDag-Erling Smørgrav 				if ((*uintptr) >= max_entries)
672e146993eSDag-Erling Smørgrav 					fatal("%s line %d: "
673e146993eSDag-Erling Smørgrav 					    "too many authorized keys files.",
674e146993eSDag-Erling Smørgrav 					    filename, linenum);
675e146993eSDag-Erling Smørgrav 				cpptr[(*uintptr)++] = xstrdup(arg);
676e146993eSDag-Erling Smørgrav 			}
677e146993eSDag-Erling Smørgrav 		}
678e146993eSDag-Erling Smørgrav 		return 0;
679511b41d2SMark Murray 
680511b41d2SMark Murray 	case oUserKnownHostsFile:
681e146993eSDag-Erling Smørgrav 		cpptr = (char **)&options->user_hostfiles;
682e146993eSDag-Erling Smørgrav 		uintptr = &options->num_user_hostfiles;
683e146993eSDag-Erling Smørgrav 		max_entries = SSH_MAX_HOSTS_FILES;
684e146993eSDag-Erling Smørgrav 		goto parse_char_array;
685e8aafc91SKris Kennaway 
686511b41d2SMark Murray 	case oHostName:
687511b41d2SMark Murray 		charptr = &options->hostname;
688511b41d2SMark Murray 		goto parse_string;
689511b41d2SMark Murray 
690ca3176e7SBrian Feldman 	case oHostKeyAlias:
691ca3176e7SBrian Feldman 		charptr = &options->host_key_alias;
692ca3176e7SBrian Feldman 		goto parse_string;
693ca3176e7SBrian Feldman 
694ca3176e7SBrian Feldman 	case oPreferredAuthentications:
695ca3176e7SBrian Feldman 		charptr = &options->preferred_authentications;
696ca3176e7SBrian Feldman 		goto parse_string;
697ca3176e7SBrian Feldman 
698af12a3e7SDag-Erling Smørgrav 	case oBindAddress:
699af12a3e7SDag-Erling Smørgrav 		charptr = &options->bind_address;
700af12a3e7SDag-Erling Smørgrav 		goto parse_string;
701af12a3e7SDag-Erling Smørgrav 
702b15c8340SDag-Erling Smørgrav 	case oPKCS11Provider:
703b15c8340SDag-Erling Smørgrav 		charptr = &options->pkcs11_provider;
704af12a3e7SDag-Erling Smørgrav 		goto parse_string;
705af12a3e7SDag-Erling Smørgrav 
706511b41d2SMark Murray 	case oProxyCommand:
707b74df5b2SDag-Erling Smørgrav 		charptr = &options->proxy_command;
708b74df5b2SDag-Erling Smørgrav parse_command:
709cf2b5f3bSDag-Erling Smørgrav 		if (s == NULL)
710cf2b5f3bSDag-Erling Smørgrav 			fatal("%.200s line %d: Missing argument.", filename, linenum);
711e73e9afaSDag-Erling Smørgrav 		len = strspn(s, WHITESPACE "=");
712511b41d2SMark Murray 		if (*activep && *charptr == NULL)
713e73e9afaSDag-Erling Smørgrav 			*charptr = xstrdup(s + len);
714511b41d2SMark Murray 		return 0;
715511b41d2SMark Murray 
716511b41d2SMark Murray 	case oPort:
717511b41d2SMark Murray 		intptr = &options->port;
718511b41d2SMark Murray parse_int:
719c2d3a559SKris Kennaway 		arg = strdelim(&s);
720c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
721511b41d2SMark Murray 			fatal("%.200s line %d: Missing argument.", filename, linenum);
722c2d3a559SKris Kennaway 		if (arg[0] < '0' || arg[0] > '9')
723511b41d2SMark Murray 			fatal("%.200s line %d: Bad number.", filename, linenum);
724511b41d2SMark Murray 
725511b41d2SMark Murray 		/* Octal, decimal, or hex format? */
726c2d3a559SKris Kennaway 		value = strtol(arg, &endofnumber, 0);
727c2d3a559SKris Kennaway 		if (arg == endofnumber)
728511b41d2SMark Murray 			fatal("%.200s line %d: Bad number.", filename, linenum);
729511b41d2SMark Murray 		if (*activep && *intptr == -1)
730511b41d2SMark Murray 			*intptr = value;
731511b41d2SMark Murray 		break;
732511b41d2SMark Murray 
733511b41d2SMark Murray 	case oConnectionAttempts:
734511b41d2SMark Murray 		intptr = &options->connection_attempts;
735511b41d2SMark Murray 		goto parse_int;
736511b41d2SMark Murray 
737511b41d2SMark Murray 	case oCipher:
738511b41d2SMark Murray 		intptr = &options->cipher;
739c2d3a559SKris Kennaway 		arg = strdelim(&s);
740c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
741db1cb46cSKris Kennaway 			fatal("%.200s line %d: Missing argument.", filename, linenum);
742c2d3a559SKris Kennaway 		value = cipher_number(arg);
743511b41d2SMark Murray 		if (value == -1)
744511b41d2SMark Murray 			fatal("%.200s line %d: Bad cipher '%s'.",
745c2d3a559SKris Kennaway 			    filename, linenum, arg ? arg : "<NONE>");
746511b41d2SMark Murray 		if (*activep && *intptr == -1)
747511b41d2SMark Murray 			*intptr = value;
748511b41d2SMark Murray 		break;
749511b41d2SMark Murray 
750e8aafc91SKris Kennaway 	case oCiphers:
751c2d3a559SKris Kennaway 		arg = strdelim(&s);
752c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
753db1cb46cSKris Kennaway 			fatal("%.200s line %d: Missing argument.", filename, linenum);
754c2d3a559SKris Kennaway 		if (!ciphers_valid(arg))
755e8aafc91SKris Kennaway 			fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
756c2d3a559SKris Kennaway 			    filename, linenum, arg ? arg : "<NONE>");
757e8aafc91SKris Kennaway 		if (*activep && options->ciphers == NULL)
758c2d3a559SKris Kennaway 			options->ciphers = xstrdup(arg);
759e8aafc91SKris Kennaway 		break;
760e8aafc91SKris Kennaway 
761ca3176e7SBrian Feldman 	case oMacs:
762ca3176e7SBrian Feldman 		arg = strdelim(&s);
763ca3176e7SBrian Feldman 		if (!arg || *arg == '\0')
764ca3176e7SBrian Feldman 			fatal("%.200s line %d: Missing argument.", filename, linenum);
765ca3176e7SBrian Feldman 		if (!mac_valid(arg))
766ca3176e7SBrian Feldman 			fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
767ca3176e7SBrian Feldman 			    filename, linenum, arg ? arg : "<NONE>");
768ca3176e7SBrian Feldman 		if (*activep && options->macs == NULL)
769ca3176e7SBrian Feldman 			options->macs = xstrdup(arg);
770ca3176e7SBrian Feldman 		break;
771ca3176e7SBrian Feldman 
7724a421b63SDag-Erling Smørgrav 	case oKexAlgorithms:
7734a421b63SDag-Erling Smørgrav 		arg = strdelim(&s);
7744a421b63SDag-Erling Smørgrav 		if (!arg || *arg == '\0')
7754a421b63SDag-Erling Smørgrav 			fatal("%.200s line %d: Missing argument.",
7764a421b63SDag-Erling Smørgrav 			    filename, linenum);
7774a421b63SDag-Erling Smørgrav 		if (!kex_names_valid(arg))
7784a421b63SDag-Erling Smørgrav 			fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
7794a421b63SDag-Erling Smørgrav 			    filename, linenum, arg ? arg : "<NONE>");
7804a421b63SDag-Erling Smørgrav 		if (*activep && options->kex_algorithms == NULL)
7814a421b63SDag-Erling Smørgrav 			options->kex_algorithms = xstrdup(arg);
7824a421b63SDag-Erling Smørgrav 		break;
7834a421b63SDag-Erling Smørgrav 
784ca3176e7SBrian Feldman 	case oHostKeyAlgorithms:
785ca3176e7SBrian Feldman 		arg = strdelim(&s);
786ca3176e7SBrian Feldman 		if (!arg || *arg == '\0')
787ca3176e7SBrian Feldman 			fatal("%.200s line %d: Missing argument.", filename, linenum);
788ca3176e7SBrian Feldman 		if (!key_names_valid2(arg))
789ca3176e7SBrian Feldman 			fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
790ca3176e7SBrian Feldman 			    filename, linenum, arg ? arg : "<NONE>");
791ca3176e7SBrian Feldman 		if (*activep && options->hostkeyalgorithms == NULL)
792ca3176e7SBrian Feldman 			options->hostkeyalgorithms = xstrdup(arg);
793ca3176e7SBrian Feldman 		break;
794ca3176e7SBrian Feldman 
795e8aafc91SKris Kennaway 	case oProtocol:
796e8aafc91SKris Kennaway 		intptr = &options->protocol;
797c2d3a559SKris Kennaway 		arg = strdelim(&s);
798c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
799db1cb46cSKris Kennaway 			fatal("%.200s line %d: Missing argument.", filename, linenum);
800c2d3a559SKris Kennaway 		value = proto_spec(arg);
801e8aafc91SKris Kennaway 		if (value == SSH_PROTO_UNKNOWN)
802e8aafc91SKris Kennaway 			fatal("%.200s line %d: Bad protocol spec '%s'.",
803c2d3a559SKris Kennaway 			    filename, linenum, arg ? arg : "<NONE>");
804e8aafc91SKris Kennaway 		if (*activep && *intptr == SSH_PROTO_UNKNOWN)
805e8aafc91SKris Kennaway 			*intptr = value;
806e8aafc91SKris Kennaway 		break;
807e8aafc91SKris Kennaway 
808511b41d2SMark Murray 	case oLogLevel:
809d4af9e69SDag-Erling Smørgrav 		log_level_ptr = &options->log_level;
810c2d3a559SKris Kennaway 		arg = strdelim(&s);
811c2d3a559SKris Kennaway 		value = log_level_number(arg);
812af12a3e7SDag-Erling Smørgrav 		if (value == SYSLOG_LEVEL_NOT_SET)
813ca3176e7SBrian Feldman 			fatal("%.200s line %d: unsupported log level '%s'",
814c2d3a559SKris Kennaway 			    filename, linenum, arg ? arg : "<NONE>");
815d4af9e69SDag-Erling Smørgrav 		if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
816d4af9e69SDag-Erling Smørgrav 			*log_level_ptr = (LogLevel) value;
817511b41d2SMark Murray 		break;
818511b41d2SMark Murray 
819af12a3e7SDag-Erling Smørgrav 	case oLocalForward:
820511b41d2SMark Murray 	case oRemoteForward:
821cce7d346SDag-Erling Smørgrav 	case oDynamicForward:
822c2d3a559SKris Kennaway 		arg = strdelim(&s);
823aa49c926SDag-Erling Smørgrav 		if (arg == NULL || *arg == '\0')
824af12a3e7SDag-Erling Smørgrav 			fatal("%.200s line %d: Missing port argument.",
825af12a3e7SDag-Erling Smørgrav 			    filename, linenum);
826cce7d346SDag-Erling Smørgrav 
827cce7d346SDag-Erling Smørgrav 		if (opcode == oLocalForward ||
828cce7d346SDag-Erling Smørgrav 		    opcode == oRemoteForward) {
829aa49c926SDag-Erling Smørgrav 			arg2 = strdelim(&s);
830aa49c926SDag-Erling Smørgrav 			if (arg2 == NULL || *arg2 == '\0')
831aa49c926SDag-Erling Smørgrav 				fatal("%.200s line %d: Missing target argument.",
832511b41d2SMark Murray 				    filename, linenum);
833aa49c926SDag-Erling Smørgrav 
834aa49c926SDag-Erling Smørgrav 			/* construct a string for parse_forward */
835aa49c926SDag-Erling Smørgrav 			snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
836cce7d346SDag-Erling Smørgrav 		} else if (opcode == oDynamicForward) {
837cce7d346SDag-Erling Smørgrav 			strlcpy(fwdarg, arg, sizeof(fwdarg));
838cce7d346SDag-Erling Smørgrav 		}
839aa49c926SDag-Erling Smørgrav 
840cce7d346SDag-Erling Smørgrav 		if (parse_forward(&fwd, fwdarg,
841cce7d346SDag-Erling Smørgrav 		    opcode == oDynamicForward ? 1 : 0,
842cce7d346SDag-Erling Smørgrav 		    opcode == oRemoteForward ? 1 : 0) == 0)
843af12a3e7SDag-Erling Smørgrav 			fatal("%.200s line %d: Bad forwarding specification.",
844511b41d2SMark Murray 			    filename, linenum);
845aa49c926SDag-Erling Smørgrav 
846af12a3e7SDag-Erling Smørgrav 		if (*activep) {
847cce7d346SDag-Erling Smørgrav 			if (opcode == oLocalForward ||
848cce7d346SDag-Erling Smørgrav 			    opcode == oDynamicForward)
849aa49c926SDag-Erling Smørgrav 				add_local_forward(options, &fwd);
850af12a3e7SDag-Erling Smørgrav 			else if (opcode == oRemoteForward)
851aa49c926SDag-Erling Smørgrav 				add_remote_forward(options, &fwd);
852af12a3e7SDag-Erling Smørgrav 		}
853511b41d2SMark Murray 		break;
854511b41d2SMark Murray 
855af12a3e7SDag-Erling Smørgrav 	case oClearAllForwardings:
856af12a3e7SDag-Erling Smørgrav 		intptr = &options->clear_forwardings;
857af12a3e7SDag-Erling Smørgrav 		goto parse_flag;
858af12a3e7SDag-Erling Smørgrav 
859511b41d2SMark Murray 	case oHost:
860511b41d2SMark Murray 		*activep = 0;
861e146993eSDag-Erling Smørgrav 		arg2 = NULL;
862e146993eSDag-Erling Smørgrav 		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
863e146993eSDag-Erling Smørgrav 			negated = *arg == '!';
864e146993eSDag-Erling Smørgrav 			if (negated)
865e146993eSDag-Erling Smørgrav 				arg++;
866c2d3a559SKris Kennaway 			if (match_pattern(host, arg)) {
867e146993eSDag-Erling Smørgrav 				if (negated) {
868e146993eSDag-Erling Smørgrav 					debug("%.200s line %d: Skipping Host "
869e146993eSDag-Erling Smørgrav 					    "block because of negated match "
870e146993eSDag-Erling Smørgrav 					    "for %.100s", filename, linenum,
871e146993eSDag-Erling Smørgrav 					    arg);
872e146993eSDag-Erling Smørgrav 					*activep = 0;
873511b41d2SMark Murray 					break;
874511b41d2SMark Murray 				}
875e146993eSDag-Erling Smørgrav 				if (!*activep)
876e146993eSDag-Erling Smørgrav 					arg2 = arg; /* logged below */
877e146993eSDag-Erling Smørgrav 				*activep = 1;
878e146993eSDag-Erling Smørgrav 			}
879e146993eSDag-Erling Smørgrav 		}
880e146993eSDag-Erling Smørgrav 		if (*activep)
881e146993eSDag-Erling Smørgrav 			debug("%.200s line %d: Applying options for %.100s",
882e146993eSDag-Erling Smørgrav 			    filename, linenum, arg2);
883c2d3a559SKris Kennaway 		/* Avoid garbage check below, as strdelim is done. */
884511b41d2SMark Murray 		return 0;
885511b41d2SMark Murray 
886511b41d2SMark Murray 	case oEscapeChar:
887511b41d2SMark Murray 		intptr = &options->escape_char;
888c2d3a559SKris Kennaway 		arg = strdelim(&s);
889c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
890511b41d2SMark Murray 			fatal("%.200s line %d: Missing argument.", filename, linenum);
891c2d3a559SKris Kennaway 		if (arg[0] == '^' && arg[2] == 0 &&
892ca3176e7SBrian Feldman 		    (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
893ca3176e7SBrian Feldman 			value = (u_char) arg[1] & 31;
894c2d3a559SKris Kennaway 		else if (strlen(arg) == 1)
895ca3176e7SBrian Feldman 			value = (u_char) arg[0];
896c2d3a559SKris Kennaway 		else if (strcmp(arg, "none") == 0)
897af12a3e7SDag-Erling Smørgrav 			value = SSH_ESCAPECHAR_NONE;
898511b41d2SMark Murray 		else {
899511b41d2SMark Murray 			fatal("%.200s line %d: Bad escape character.",
900511b41d2SMark Murray 			    filename, linenum);
901511b41d2SMark Murray 			/* NOTREACHED */
902511b41d2SMark Murray 			value = 0;	/* Avoid compiler warning. */
903511b41d2SMark Murray 		}
904511b41d2SMark Murray 		if (*activep && *intptr == -1)
905511b41d2SMark Murray 			*intptr = value;
906511b41d2SMark Murray 		break;
907511b41d2SMark Murray 
908cf2b5f3bSDag-Erling Smørgrav 	case oAddressFamily:
909cf2b5f3bSDag-Erling Smørgrav 		arg = strdelim(&s);
910d4ecd108SDag-Erling Smørgrav 		if (!arg || *arg == '\0')
911d4ecd108SDag-Erling Smørgrav 			fatal("%s line %d: missing address family.",
912d4ecd108SDag-Erling Smørgrav 			    filename, linenum);
913cf2b5f3bSDag-Erling Smørgrav 		intptr = &options->address_family;
914cf2b5f3bSDag-Erling Smørgrav 		if (strcasecmp(arg, "inet") == 0)
915cf2b5f3bSDag-Erling Smørgrav 			value = AF_INET;
916cf2b5f3bSDag-Erling Smørgrav 		else if (strcasecmp(arg, "inet6") == 0)
917cf2b5f3bSDag-Erling Smørgrav 			value = AF_INET6;
918cf2b5f3bSDag-Erling Smørgrav 		else if (strcasecmp(arg, "any") == 0)
919cf2b5f3bSDag-Erling Smørgrav 			value = AF_UNSPEC;
920cf2b5f3bSDag-Erling Smørgrav 		else
921cf2b5f3bSDag-Erling Smørgrav 			fatal("Unsupported AddressFamily \"%s\"", arg);
922cf2b5f3bSDag-Erling Smørgrav 		if (*activep && *intptr == -1)
923cf2b5f3bSDag-Erling Smørgrav 			*intptr = value;
924cf2b5f3bSDag-Erling Smørgrav 		break;
925cf2b5f3bSDag-Erling Smørgrav 
926e73e9afaSDag-Erling Smørgrav 	case oEnableSSHKeysign:
927e73e9afaSDag-Erling Smørgrav 		intptr = &options->enable_ssh_keysign;
928e73e9afaSDag-Erling Smørgrav 		goto parse_flag;
929e73e9afaSDag-Erling Smørgrav 
9305962c0e9SDag-Erling Smørgrav 	case oIdentitiesOnly:
9315962c0e9SDag-Erling Smørgrav 		intptr = &options->identities_only;
9325962c0e9SDag-Erling Smørgrav 		goto parse_flag;
9335962c0e9SDag-Erling Smørgrav 
9341ec0d754SDag-Erling Smørgrav 	case oServerAliveInterval:
9351ec0d754SDag-Erling Smørgrav 		intptr = &options->server_alive_interval;
9361ec0d754SDag-Erling Smørgrav 		goto parse_time;
9371ec0d754SDag-Erling Smørgrav 
9381ec0d754SDag-Erling Smørgrav 	case oServerAliveCountMax:
9391ec0d754SDag-Erling Smørgrav 		intptr = &options->server_alive_count_max;
9401ec0d754SDag-Erling Smørgrav 		goto parse_int;
9411ec0d754SDag-Erling Smørgrav 
94221e764dfSDag-Erling Smørgrav 	case oSendEnv:
94321e764dfSDag-Erling Smørgrav 		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
94421e764dfSDag-Erling Smørgrav 			if (strchr(arg, '=') != NULL)
94521e764dfSDag-Erling Smørgrav 				fatal("%s line %d: Invalid environment name.",
94621e764dfSDag-Erling Smørgrav 				    filename, linenum);
947aa49c926SDag-Erling Smørgrav 			if (!*activep)
948aa49c926SDag-Erling Smørgrav 				continue;
94921e764dfSDag-Erling Smørgrav 			if (options->num_send_env >= MAX_SEND_ENV)
95021e764dfSDag-Erling Smørgrav 				fatal("%s line %d: too many send env.",
95121e764dfSDag-Erling Smørgrav 				    filename, linenum);
95221e764dfSDag-Erling Smørgrav 			options->send_env[options->num_send_env++] =
95321e764dfSDag-Erling Smørgrav 			    xstrdup(arg);
95421e764dfSDag-Erling Smørgrav 		}
95521e764dfSDag-Erling Smørgrav 		break;
95621e764dfSDag-Erling Smørgrav 
95721e764dfSDag-Erling Smørgrav 	case oControlPath:
95821e764dfSDag-Erling Smørgrav 		charptr = &options->control_path;
95921e764dfSDag-Erling Smørgrav 		goto parse_string;
96021e764dfSDag-Erling Smørgrav 
96121e764dfSDag-Erling Smørgrav 	case oControlMaster:
96221e764dfSDag-Erling Smørgrav 		intptr = &options->control_master;
963d4ecd108SDag-Erling Smørgrav 		arg = strdelim(&s);
964d4ecd108SDag-Erling Smørgrav 		if (!arg || *arg == '\0')
965d4ecd108SDag-Erling Smørgrav 			fatal("%.200s line %d: Missing ControlMaster argument.",
966d4ecd108SDag-Erling Smørgrav 			    filename, linenum);
967d4ecd108SDag-Erling Smørgrav 		value = 0;	/* To avoid compiler warning... */
968d4ecd108SDag-Erling Smørgrav 		if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
969d4ecd108SDag-Erling Smørgrav 			value = SSHCTL_MASTER_YES;
970d4ecd108SDag-Erling Smørgrav 		else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
971d4ecd108SDag-Erling Smørgrav 			value = SSHCTL_MASTER_NO;
972d4ecd108SDag-Erling Smørgrav 		else if (strcmp(arg, "auto") == 0)
973d4ecd108SDag-Erling Smørgrav 			value = SSHCTL_MASTER_AUTO;
974d4ecd108SDag-Erling Smørgrav 		else if (strcmp(arg, "ask") == 0)
975d4ecd108SDag-Erling Smørgrav 			value = SSHCTL_MASTER_ASK;
976d4ecd108SDag-Erling Smørgrav 		else if (strcmp(arg, "autoask") == 0)
977d4ecd108SDag-Erling Smørgrav 			value = SSHCTL_MASTER_AUTO_ASK;
978d4ecd108SDag-Erling Smørgrav 		else
979d4ecd108SDag-Erling Smørgrav 			fatal("%.200s line %d: Bad ControlMaster argument.",
980d4ecd108SDag-Erling Smørgrav 			    filename, linenum);
981d4ecd108SDag-Erling Smørgrav 		if (*activep && *intptr == -1)
982d4ecd108SDag-Erling Smørgrav 			*intptr = value;
983d4ecd108SDag-Erling Smørgrav 		break;
98421e764dfSDag-Erling Smørgrav 
985e2f6069cSDag-Erling Smørgrav 	case oControlPersist:
986e2f6069cSDag-Erling Smørgrav 		/* no/false/yes/true, or a time spec */
987e2f6069cSDag-Erling Smørgrav 		intptr = &options->control_persist;
988e2f6069cSDag-Erling Smørgrav 		arg = strdelim(&s);
989e2f6069cSDag-Erling Smørgrav 		if (!arg || *arg == '\0')
990e2f6069cSDag-Erling Smørgrav 			fatal("%.200s line %d: Missing ControlPersist"
991e2f6069cSDag-Erling Smørgrav 			    " argument.", filename, linenum);
992e2f6069cSDag-Erling Smørgrav 		value = 0;
993e2f6069cSDag-Erling Smørgrav 		value2 = 0;	/* timeout */
994e2f6069cSDag-Erling Smørgrav 		if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
995e2f6069cSDag-Erling Smørgrav 			value = 0;
996e2f6069cSDag-Erling Smørgrav 		else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
997e2f6069cSDag-Erling Smørgrav 			value = 1;
998e2f6069cSDag-Erling Smørgrav 		else if ((value2 = convtime(arg)) >= 0)
999e2f6069cSDag-Erling Smørgrav 			value = 1;
1000e2f6069cSDag-Erling Smørgrav 		else
1001e2f6069cSDag-Erling Smørgrav 			fatal("%.200s line %d: Bad ControlPersist argument.",
1002e2f6069cSDag-Erling Smørgrav 			    filename, linenum);
1003e2f6069cSDag-Erling Smørgrav 		if (*activep && *intptr == -1) {
1004e2f6069cSDag-Erling Smørgrav 			*intptr = value;
1005e2f6069cSDag-Erling Smørgrav 			options->control_persist_timeout = value2;
1006e2f6069cSDag-Erling Smørgrav 		}
1007e2f6069cSDag-Erling Smørgrav 		break;
1008e2f6069cSDag-Erling Smørgrav 
1009aa49c926SDag-Erling Smørgrav 	case oHashKnownHosts:
1010aa49c926SDag-Erling Smørgrav 		intptr = &options->hash_known_hosts;
1011aa49c926SDag-Erling Smørgrav 		goto parse_flag;
1012aa49c926SDag-Erling Smørgrav 
1013b74df5b2SDag-Erling Smørgrav 	case oTunnel:
1014b74df5b2SDag-Erling Smørgrav 		intptr = &options->tun_open;
1015b74df5b2SDag-Erling Smørgrav 		arg = strdelim(&s);
1016b74df5b2SDag-Erling Smørgrav 		if (!arg || *arg == '\0')
1017b74df5b2SDag-Erling Smørgrav 			fatal("%s line %d: Missing yes/point-to-point/"
1018b74df5b2SDag-Erling Smørgrav 			    "ethernet/no argument.", filename, linenum);
1019b74df5b2SDag-Erling Smørgrav 		value = 0;	/* silence compiler */
1020b74df5b2SDag-Erling Smørgrav 		if (strcasecmp(arg, "ethernet") == 0)
1021b74df5b2SDag-Erling Smørgrav 			value = SSH_TUNMODE_ETHERNET;
1022b74df5b2SDag-Erling Smørgrav 		else if (strcasecmp(arg, "point-to-point") == 0)
1023b74df5b2SDag-Erling Smørgrav 			value = SSH_TUNMODE_POINTOPOINT;
1024b74df5b2SDag-Erling Smørgrav 		else if (strcasecmp(arg, "yes") == 0)
1025b74df5b2SDag-Erling Smørgrav 			value = SSH_TUNMODE_DEFAULT;
1026b74df5b2SDag-Erling Smørgrav 		else if (strcasecmp(arg, "no") == 0)
1027b74df5b2SDag-Erling Smørgrav 			value = SSH_TUNMODE_NO;
1028b74df5b2SDag-Erling Smørgrav 		else
1029b74df5b2SDag-Erling Smørgrav 			fatal("%s line %d: Bad yes/point-to-point/ethernet/"
1030b74df5b2SDag-Erling Smørgrav 			    "no argument: %s", filename, linenum, arg);
1031b74df5b2SDag-Erling Smørgrav 		if (*activep)
1032b74df5b2SDag-Erling Smørgrav 			*intptr = value;
1033b74df5b2SDag-Erling Smørgrav 		break;
1034b74df5b2SDag-Erling Smørgrav 
1035b74df5b2SDag-Erling Smørgrav 	case oTunnelDevice:
1036b74df5b2SDag-Erling Smørgrav 		arg = strdelim(&s);
1037b74df5b2SDag-Erling Smørgrav 		if (!arg || *arg == '\0')
1038b74df5b2SDag-Erling Smørgrav 			fatal("%.200s line %d: Missing argument.", filename, linenum);
1039b74df5b2SDag-Erling Smørgrav 		value = a2tun(arg, &value2);
1040b74df5b2SDag-Erling Smørgrav 		if (value == SSH_TUNID_ERR)
1041b74df5b2SDag-Erling Smørgrav 			fatal("%.200s line %d: Bad tun device.", filename, linenum);
1042b74df5b2SDag-Erling Smørgrav 		if (*activep) {
1043b74df5b2SDag-Erling Smørgrav 			options->tun_local = value;
1044b74df5b2SDag-Erling Smørgrav 			options->tun_remote = value2;
1045b74df5b2SDag-Erling Smørgrav 		}
1046b74df5b2SDag-Erling Smørgrav 		break;
1047b74df5b2SDag-Erling Smørgrav 
1048b74df5b2SDag-Erling Smørgrav 	case oLocalCommand:
1049b74df5b2SDag-Erling Smørgrav 		charptr = &options->local_command;
1050b74df5b2SDag-Erling Smørgrav 		goto parse_command;
1051b74df5b2SDag-Erling Smørgrav 
1052b74df5b2SDag-Erling Smørgrav 	case oPermitLocalCommand:
1053b74df5b2SDag-Erling Smørgrav 		intptr = &options->permit_local_command;
1054b74df5b2SDag-Erling Smørgrav 		goto parse_flag;
1055b74df5b2SDag-Erling Smørgrav 
1056d4af9e69SDag-Erling Smørgrav 	case oVisualHostKey:
1057d4af9e69SDag-Erling Smørgrav 		intptr = &options->visual_host_key;
1058d4af9e69SDag-Erling Smørgrav 		goto parse_flag;
1059d4af9e69SDag-Erling Smørgrav 
10604a421b63SDag-Erling Smørgrav 	case oIPQoS:
10614a421b63SDag-Erling Smørgrav 		arg = strdelim(&s);
10624a421b63SDag-Erling Smørgrav 		if ((value = parse_ipqos(arg)) == -1)
10634a421b63SDag-Erling Smørgrav 			fatal("%s line %d: Bad IPQoS value: %s",
10644a421b63SDag-Erling Smørgrav 			    filename, linenum, arg);
10654a421b63SDag-Erling Smørgrav 		arg = strdelim(&s);
10664a421b63SDag-Erling Smørgrav 		if (arg == NULL)
10674a421b63SDag-Erling Smørgrav 			value2 = value;
10684a421b63SDag-Erling Smørgrav 		else if ((value2 = parse_ipqos(arg)) == -1)
10694a421b63SDag-Erling Smørgrav 			fatal("%s line %d: Bad IPQoS value: %s",
10704a421b63SDag-Erling Smørgrav 			    filename, linenum, arg);
10714a421b63SDag-Erling Smørgrav 		if (*activep) {
10724a421b63SDag-Erling Smørgrav 			options->ip_qos_interactive = value;
10734a421b63SDag-Erling Smørgrav 			options->ip_qos_bulk = value2;
10744a421b63SDag-Erling Smørgrav 		}
10754a421b63SDag-Erling Smørgrav 		break;
10764a421b63SDag-Erling Smørgrav 
10777aee6ffeSDag-Erling Smørgrav 	case oUseRoaming:
10787aee6ffeSDag-Erling Smørgrav 		intptr = &options->use_roaming;
10797aee6ffeSDag-Erling Smørgrav 		goto parse_flag;
10807aee6ffeSDag-Erling Smørgrav 
1081e146993eSDag-Erling Smørgrav 	case oRequestTTY:
1082975616f0SDag-Erling Smørgrav 		arg = strdelim(&s);
1083e146993eSDag-Erling Smørgrav 		if (!arg || *arg == '\0')
1084e146993eSDag-Erling Smørgrav 			fatal("%s line %d: missing argument.",
1085e146993eSDag-Erling Smørgrav 			    filename, linenum);
1086e146993eSDag-Erling Smørgrav 		intptr = &options->request_tty;
1087e146993eSDag-Erling Smørgrav 		if (strcasecmp(arg, "yes") == 0)
1088e146993eSDag-Erling Smørgrav 			value = REQUEST_TTY_YES;
1089e146993eSDag-Erling Smørgrav 		else if (strcasecmp(arg, "no") == 0)
1090e146993eSDag-Erling Smørgrav 			value = REQUEST_TTY_NO;
1091e146993eSDag-Erling Smørgrav 		else if (strcasecmp(arg, "force") == 0)
1092e146993eSDag-Erling Smørgrav 			value = REQUEST_TTY_FORCE;
1093e146993eSDag-Erling Smørgrav 		else if (strcasecmp(arg, "auto") == 0)
1094e146993eSDag-Erling Smørgrav 			value = REQUEST_TTY_AUTO;
1095e146993eSDag-Erling Smørgrav 		else
1096e146993eSDag-Erling Smørgrav 			fatal("Unsupported RequestTTY \"%s\"", arg);
1097e146993eSDag-Erling Smørgrav 		if (*activep && *intptr == -1)
1098e146993eSDag-Erling Smørgrav 			*intptr = value;
1099975616f0SDag-Erling Smørgrav 		break;
1100975616f0SDag-Erling Smørgrav 
110189986192SBrooks Davis 	case oHPNDisabled:
110289986192SBrooks Davis 		intptr = &options->hpn_disabled;
110389986192SBrooks Davis 		goto parse_flag;
110489986192SBrooks Davis 
110589986192SBrooks Davis 	case oHPNBufferSize:
110689986192SBrooks Davis 		intptr = &options->hpn_buffer_size;
110789986192SBrooks Davis 		goto parse_int;
110889986192SBrooks Davis 
110989986192SBrooks Davis 	case oTcpRcvBufPoll:
111089986192SBrooks Davis 		intptr = &options->tcp_rcv_buf_poll;
111189986192SBrooks Davis 		goto parse_flag;
111289986192SBrooks Davis 
111389986192SBrooks Davis 	case oTcpRcvBuf:
111489986192SBrooks Davis 		intptr = &options->tcp_rcv_buf;
111589986192SBrooks Davis 		goto parse_int;
111689986192SBrooks Davis 
111789986192SBrooks Davis #ifdef	NONE_CIPHER_ENABLED
111889986192SBrooks Davis 	case oNoneEnabled:
111989986192SBrooks Davis 		intptr = &options->none_enabled;
112089986192SBrooks Davis 		goto parse_flag;
112189986192SBrooks Davis 
112289986192SBrooks Davis 	/*
112389986192SBrooks Davis 	 * We check to see if the command comes from the command line or not.
112489986192SBrooks Davis 	 * If it does then enable it otherwise fail.  NONE must never be a
112589986192SBrooks Davis 	 * default configuration.
112689986192SBrooks Davis 	 */
112789986192SBrooks Davis 	case oNoneSwitch:
112889986192SBrooks Davis 		if (strcmp(filename,"command-line") == 0) {
112989986192SBrooks Davis 			intptr = &options->none_switch;
113089986192SBrooks Davis 			goto parse_flag;
113189986192SBrooks Davis 		} else {
113289986192SBrooks Davis 			debug("NoneSwitch directive found in %.200s.",
113389986192SBrooks Davis 			    filename);
113489986192SBrooks Davis 			error("NoneSwitch is found in %.200s.\n"
113589986192SBrooks Davis 			    "You may only use this configuration option "
113689986192SBrooks Davis 			    "from the command line", filename);
113789986192SBrooks Davis 			error("Continuing...");
113889986192SBrooks Davis 			return 0;
113989986192SBrooks Davis 		}
114089986192SBrooks Davis #endif
114189986192SBrooks Davis 
1142e146993eSDag-Erling Smørgrav 	case oVersionAddendum:
1143462c32cbSDag-Erling Smørgrav 		if (s == NULL)
1144462c32cbSDag-Erling Smørgrav 			fatal("%.200s line %d: Missing argument.", filename,
1145462c32cbSDag-Erling Smørgrav 			    linenum);
1146462c32cbSDag-Erling Smørgrav 		len = strspn(s, WHITESPACE);
1147462c32cbSDag-Erling Smørgrav 		if (*activep && options->version_addendum == NULL) {
1148462c32cbSDag-Erling Smørgrav 			if (strcasecmp(s + len, "none") == 0)
1149462c32cbSDag-Erling Smørgrav 				options->version_addendum = xstrdup("");
1150462c32cbSDag-Erling Smørgrav 			else if (strchr(s + len, '\r') != NULL)
1151462c32cbSDag-Erling Smørgrav 				fatal("%.200s line %d: Invalid argument",
1152462c32cbSDag-Erling Smørgrav 				    filename, linenum);
1153462c32cbSDag-Erling Smørgrav 			else
1154462c32cbSDag-Erling Smørgrav 				options->version_addendum = xstrdup(s + len);
1155462c32cbSDag-Erling Smørgrav 		}
1156462c32cbSDag-Erling Smørgrav 		return 0;
1157e146993eSDag-Erling Smørgrav 
1158*e4a9863fSDag-Erling Smørgrav 	case oIgnoreUnknown:
1159*e4a9863fSDag-Erling Smørgrav 		charptr = &options->ignored_unknown;
1160*e4a9863fSDag-Erling Smørgrav 		goto parse_string;
1161*e4a9863fSDag-Erling Smørgrav 
116280628bacSDag-Erling Smørgrav 	case oDeprecated:
116380628bacSDag-Erling Smørgrav 		debug("%s line %d: Deprecated option \"%s\"",
116480628bacSDag-Erling Smørgrav 		    filename, linenum, keyword);
116580628bacSDag-Erling Smørgrav 		return 0;
116680628bacSDag-Erling Smørgrav 
1167cf2b5f3bSDag-Erling Smørgrav 	case oUnsupported:
1168cf2b5f3bSDag-Erling Smørgrav 		error("%s line %d: Unsupported option \"%s\"",
1169cf2b5f3bSDag-Erling Smørgrav 		    filename, linenum, keyword);
1170cf2b5f3bSDag-Erling Smørgrav 		return 0;
1171cf2b5f3bSDag-Erling Smørgrav 
1172511b41d2SMark Murray 	default:
1173511b41d2SMark Murray 		fatal("process_config_line: Unimplemented opcode %d", opcode);
1174511b41d2SMark Murray 	}
1175511b41d2SMark Murray 
1176511b41d2SMark Murray 	/* Check that there is no garbage at end of line. */
1177ca3176e7SBrian Feldman 	if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1178c2d3a559SKris Kennaway 		fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
1179c2d3a559SKris Kennaway 		    filename, linenum, arg);
1180c2d3a559SKris Kennaway 	}
1181511b41d2SMark Murray 	return 0;
1182511b41d2SMark Murray }
1183511b41d2SMark Murray 
1184511b41d2SMark Murray 
1185511b41d2SMark Murray /*
1186511b41d2SMark Murray  * Reads the config file and modifies the options accordingly.  Options
1187511b41d2SMark Murray  * should already be initialized before this call.  This never returns if
1188af12a3e7SDag-Erling Smørgrav  * there is an error.  If the file does not exist, this returns 0.
1189511b41d2SMark Murray  */
1190511b41d2SMark Murray 
1191af12a3e7SDag-Erling Smørgrav int
119221e764dfSDag-Erling Smørgrav read_config_file(const char *filename, const char *host, Options *options,
119373370613SDag-Erling Smørgrav     int flags)
1194511b41d2SMark Murray {
1195511b41d2SMark Murray 	FILE *f;
1196511b41d2SMark Murray 	char line[1024];
1197511b41d2SMark Murray 	int active, linenum;
1198511b41d2SMark Murray 	int bad_options = 0;
1199511b41d2SMark Murray 
120021e764dfSDag-Erling Smørgrav 	if ((f = fopen(filename, "r")) == NULL)
1201af12a3e7SDag-Erling Smørgrav 		return 0;
1202511b41d2SMark Murray 
120373370613SDag-Erling Smørgrav 	if (flags & SSHCONF_CHECKPERM) {
120421e764dfSDag-Erling Smørgrav 		struct stat sb;
120521e764dfSDag-Erling Smørgrav 
120621e764dfSDag-Erling Smørgrav 		if (fstat(fileno(f), &sb) == -1)
120721e764dfSDag-Erling Smørgrav 			fatal("fstat %s: %s", filename, strerror(errno));
120821e764dfSDag-Erling Smørgrav 		if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
120921e764dfSDag-Erling Smørgrav 		    (sb.st_mode & 022) != 0))
121021e764dfSDag-Erling Smørgrav 			fatal("Bad owner or permissions on %s", filename);
121121e764dfSDag-Erling Smørgrav 	}
121221e764dfSDag-Erling Smørgrav 
1213511b41d2SMark Murray 	debug("Reading configuration data %.200s", filename);
1214511b41d2SMark Murray 
1215511b41d2SMark Murray 	/*
1216511b41d2SMark Murray 	 * Mark that we are now processing the options.  This flag is turned
1217511b41d2SMark Murray 	 * on/off by Host specifications.
1218511b41d2SMark Murray 	 */
1219511b41d2SMark Murray 	active = 1;
1220511b41d2SMark Murray 	linenum = 0;
1221511b41d2SMark Murray 	while (fgets(line, sizeof(line), f)) {
1222511b41d2SMark Murray 		/* Update line number counter. */
1223511b41d2SMark Murray 		linenum++;
122473370613SDag-Erling Smørgrav 		if (process_config_line(options, host, line, filename, linenum,
122573370613SDag-Erling Smørgrav 		    &active, flags & SSHCONF_USERCONF) != 0)
1226511b41d2SMark Murray 			bad_options++;
1227511b41d2SMark Murray 	}
1228511b41d2SMark Murray 	fclose(f);
1229511b41d2SMark Murray 	if (bad_options > 0)
1230ca3176e7SBrian Feldman 		fatal("%s: terminating, %d bad configuration options",
1231511b41d2SMark Murray 		    filename, bad_options);
1232af12a3e7SDag-Erling Smørgrav 	return 1;
1233511b41d2SMark Murray }
1234511b41d2SMark Murray 
1235511b41d2SMark Murray /*
1236511b41d2SMark Murray  * Initializes options to special values that indicate that they have not yet
1237511b41d2SMark Murray  * been set.  Read_config_file will only set options with this value. Options
1238511b41d2SMark Murray  * are processed in the following order: command line, user config file,
1239511b41d2SMark Murray  * system config file.  Last, fill_default_options is called.
1240511b41d2SMark Murray  */
1241511b41d2SMark Murray 
1242511b41d2SMark Murray void
1243511b41d2SMark Murray initialize_options(Options * options)
1244511b41d2SMark Murray {
1245511b41d2SMark Murray 	memset(options, 'X', sizeof(*options));
1246511b41d2SMark Murray 	options->forward_agent = -1;
1247511b41d2SMark Murray 	options->forward_x11 = -1;
12481ec0d754SDag-Erling Smørgrav 	options->forward_x11_trusted = -1;
1249e2f6069cSDag-Erling Smørgrav 	options->forward_x11_timeout = -1;
1250333ee039SDag-Erling Smørgrav 	options->exit_on_forward_failure = -1;
1251c2d3a559SKris Kennaway 	options->xauth_location = NULL;
1252511b41d2SMark Murray 	options->gateway_ports = -1;
1253511b41d2SMark Murray 	options->use_privileged_port = -1;
1254511b41d2SMark Murray 	options->rsa_authentication = -1;
1255ca3176e7SBrian Feldman 	options->pubkey_authentication = -1;
1256af12a3e7SDag-Erling Smørgrav 	options->challenge_response_authentication = -1;
1257cf2b5f3bSDag-Erling Smørgrav 	options->gss_authentication = -1;
1258cf2b5f3bSDag-Erling Smørgrav 	options->gss_deleg_creds = -1;
1259511b41d2SMark Murray 	options->password_authentication = -1;
126009958426SBrian Feldman 	options->kbd_interactive_authentication = -1;
126109958426SBrian Feldman 	options->kbd_interactive_devices = NULL;
1262511b41d2SMark Murray 	options->rhosts_rsa_authentication = -1;
1263ca3176e7SBrian Feldman 	options->hostbased_authentication = -1;
1264511b41d2SMark Murray 	options->batch_mode = -1;
1265511b41d2SMark Murray 	options->check_host_ip = -1;
1266511b41d2SMark Murray 	options->strict_host_key_checking = -1;
1267511b41d2SMark Murray 	options->compression = -1;
12681ec0d754SDag-Erling Smørgrav 	options->tcp_keep_alive = -1;
1269511b41d2SMark Murray 	options->compression_level = -1;
1270511b41d2SMark Murray 	options->port = -1;
1271cf2b5f3bSDag-Erling Smørgrav 	options->address_family = -1;
1272511b41d2SMark Murray 	options->connection_attempts = -1;
1273cf2b5f3bSDag-Erling Smørgrav 	options->connection_timeout = -1;
1274511b41d2SMark Murray 	options->number_of_password_prompts = -1;
1275511b41d2SMark Murray 	options->cipher = -1;
1276e8aafc91SKris Kennaway 	options->ciphers = NULL;
1277ca3176e7SBrian Feldman 	options->macs = NULL;
12784a421b63SDag-Erling Smørgrav 	options->kex_algorithms = NULL;
1279ca3176e7SBrian Feldman 	options->hostkeyalgorithms = NULL;
1280e8aafc91SKris Kennaway 	options->protocol = SSH_PROTO_UNKNOWN;
1281511b41d2SMark Murray 	options->num_identity_files = 0;
1282511b41d2SMark Murray 	options->hostname = NULL;
1283ca3176e7SBrian Feldman 	options->host_key_alias = NULL;
1284511b41d2SMark Murray 	options->proxy_command = NULL;
1285511b41d2SMark Murray 	options->user = NULL;
1286511b41d2SMark Murray 	options->escape_char = -1;
1287e146993eSDag-Erling Smørgrav 	options->num_system_hostfiles = 0;
1288e146993eSDag-Erling Smørgrav 	options->num_user_hostfiles = 0;
1289e2f6069cSDag-Erling Smørgrav 	options->local_forwards = NULL;
1290511b41d2SMark Murray 	options->num_local_forwards = 0;
1291e2f6069cSDag-Erling Smørgrav 	options->remote_forwards = NULL;
1292511b41d2SMark Murray 	options->num_remote_forwards = 0;
1293af12a3e7SDag-Erling Smørgrav 	options->clear_forwardings = -1;
1294af12a3e7SDag-Erling Smørgrav 	options->log_level = SYSLOG_LEVEL_NOT_SET;
1295ca3176e7SBrian Feldman 	options->preferred_authentications = NULL;
1296af12a3e7SDag-Erling Smørgrav 	options->bind_address = NULL;
1297b15c8340SDag-Erling Smørgrav 	options->pkcs11_provider = NULL;
1298e73e9afaSDag-Erling Smørgrav 	options->enable_ssh_keysign = - 1;
1299af12a3e7SDag-Erling Smørgrav 	options->no_host_authentication_for_localhost = - 1;
13005962c0e9SDag-Erling Smørgrav 	options->identities_only = - 1;
1301cf2b5f3bSDag-Erling Smørgrav 	options->rekey_limit = - 1;
1302*e4a9863fSDag-Erling Smørgrav 	options->rekey_interval = -1;
1303cf2b5f3bSDag-Erling Smørgrav 	options->verify_host_key_dns = -1;
13041ec0d754SDag-Erling Smørgrav 	options->server_alive_interval = -1;
13051ec0d754SDag-Erling Smørgrav 	options->server_alive_count_max = -1;
130621e764dfSDag-Erling Smørgrav 	options->num_send_env = 0;
130721e764dfSDag-Erling Smørgrav 	options->control_path = NULL;
130821e764dfSDag-Erling Smørgrav 	options->control_master = -1;
1309e2f6069cSDag-Erling Smørgrav 	options->control_persist = -1;
1310e2f6069cSDag-Erling Smørgrav 	options->control_persist_timeout = 0;
1311aa49c926SDag-Erling Smørgrav 	options->hash_known_hosts = -1;
1312b74df5b2SDag-Erling Smørgrav 	options->tun_open = -1;
1313b74df5b2SDag-Erling Smørgrav 	options->tun_local = -1;
1314b74df5b2SDag-Erling Smørgrav 	options->tun_remote = -1;
1315b74df5b2SDag-Erling Smørgrav 	options->local_command = NULL;
1316b74df5b2SDag-Erling Smørgrav 	options->permit_local_command = -1;
13177aee6ffeSDag-Erling Smørgrav 	options->use_roaming = -1;
1318d4af9e69SDag-Erling Smørgrav 	options->visual_host_key = -1;
1319cce7d346SDag-Erling Smørgrav 	options->zero_knowledge_password_authentication = -1;
13204a421b63SDag-Erling Smørgrav 	options->ip_qos_interactive = -1;
13214a421b63SDag-Erling Smørgrav 	options->ip_qos_bulk = -1;
1322e146993eSDag-Erling Smørgrav 	options->request_tty = -1;
1323462c32cbSDag-Erling Smørgrav 	options->version_addendum = NULL;
1324*e4a9863fSDag-Erling Smørgrav 	options->ignored_unknown = NULL;
132589986192SBrooks Davis 	options->hpn_disabled = -1;
132689986192SBrooks Davis 	options->hpn_buffer_size = -1;
132789986192SBrooks Davis 	options->tcp_rcv_buf_poll = -1;
132889986192SBrooks Davis 	options->tcp_rcv_buf = -1;
132989986192SBrooks Davis #ifdef NONE_CIPHER_ENABLED
133089986192SBrooks Davis 	options->none_enabled = -1;
133189986192SBrooks Davis 	options->none_switch = -1;
133289986192SBrooks Davis #endif
1333511b41d2SMark Murray }
1334511b41d2SMark Murray 
1335511b41d2SMark Murray /*
1336511b41d2SMark Murray  * Called after processing other sources of option data, this fills those
1337511b41d2SMark Murray  * options for which no value has been specified with their default values.
1338511b41d2SMark Murray  */
1339511b41d2SMark Murray 
1340511b41d2SMark Murray void
1341511b41d2SMark Murray fill_default_options(Options * options)
1342511b41d2SMark Murray {
1343511b41d2SMark Murray 	if (options->forward_agent == -1)
1344db1cb46cSKris Kennaway 		options->forward_agent = 0;
1345511b41d2SMark Murray 	if (options->forward_x11 == -1)
13465dc73ebeSBrian Feldman 		options->forward_x11 = 0;
13471ec0d754SDag-Erling Smørgrav 	if (options->forward_x11_trusted == -1)
13481ec0d754SDag-Erling Smørgrav 		options->forward_x11_trusted = 0;
1349e2f6069cSDag-Erling Smørgrav 	if (options->forward_x11_timeout == -1)
1350e2f6069cSDag-Erling Smørgrav 		options->forward_x11_timeout = 1200;
1351333ee039SDag-Erling Smørgrav 	if (options->exit_on_forward_failure == -1)
1352333ee039SDag-Erling Smørgrav 		options->exit_on_forward_failure = 0;
1353c2d3a559SKris Kennaway 	if (options->xauth_location == NULL)
1354af12a3e7SDag-Erling Smørgrav 		options->xauth_location = _PATH_XAUTH;
1355511b41d2SMark Murray 	if (options->gateway_ports == -1)
1356511b41d2SMark Murray 		options->gateway_ports = 0;
1357511b41d2SMark Murray 	if (options->use_privileged_port == -1)
1358ca3176e7SBrian Feldman 		options->use_privileged_port = 0;
1359511b41d2SMark Murray 	if (options->rsa_authentication == -1)
1360511b41d2SMark Murray 		options->rsa_authentication = 1;
1361ca3176e7SBrian Feldman 	if (options->pubkey_authentication == -1)
1362ca3176e7SBrian Feldman 		options->pubkey_authentication = 1;
1363af12a3e7SDag-Erling Smørgrav 	if (options->challenge_response_authentication == -1)
1364af12a3e7SDag-Erling Smørgrav 		options->challenge_response_authentication = 1;
1365cf2b5f3bSDag-Erling Smørgrav 	if (options->gss_authentication == -1)
13661ec0d754SDag-Erling Smørgrav 		options->gss_authentication = 0;
1367cf2b5f3bSDag-Erling Smørgrav 	if (options->gss_deleg_creds == -1)
1368cf2b5f3bSDag-Erling Smørgrav 		options->gss_deleg_creds = 0;
1369511b41d2SMark Murray 	if (options->password_authentication == -1)
1370511b41d2SMark Murray 		options->password_authentication = 1;
137109958426SBrian Feldman 	if (options->kbd_interactive_authentication == -1)
1372ca3176e7SBrian Feldman 		options->kbd_interactive_authentication = 1;
1373511b41d2SMark Murray 	if (options->rhosts_rsa_authentication == -1)
137480628bacSDag-Erling Smørgrav 		options->rhosts_rsa_authentication = 0;
1375ca3176e7SBrian Feldman 	if (options->hostbased_authentication == -1)
1376ca3176e7SBrian Feldman 		options->hostbased_authentication = 0;
1377511b41d2SMark Murray 	if (options->batch_mode == -1)
1378511b41d2SMark Murray 		options->batch_mode = 0;
1379511b41d2SMark Murray 	if (options->check_host_ip == -1)
1380975616f0SDag-Erling Smørgrav 		options->check_host_ip = 0;
1381511b41d2SMark Murray 	if (options->strict_host_key_checking == -1)
1382511b41d2SMark Murray 		options->strict_host_key_checking = 2;	/* 2 is default */
1383511b41d2SMark Murray 	if (options->compression == -1)
1384511b41d2SMark Murray 		options->compression = 0;
13851ec0d754SDag-Erling Smørgrav 	if (options->tcp_keep_alive == -1)
13861ec0d754SDag-Erling Smørgrav 		options->tcp_keep_alive = 1;
1387511b41d2SMark Murray 	if (options->compression_level == -1)
1388511b41d2SMark Murray 		options->compression_level = 6;
1389511b41d2SMark Murray 	if (options->port == -1)
1390511b41d2SMark Murray 		options->port = 0;	/* Filled in ssh_connect. */
1391cf2b5f3bSDag-Erling Smørgrav 	if (options->address_family == -1)
1392cf2b5f3bSDag-Erling Smørgrav 		options->address_family = AF_UNSPEC;
1393511b41d2SMark Murray 	if (options->connection_attempts == -1)
1394af12a3e7SDag-Erling Smørgrav 		options->connection_attempts = 1;
1395511b41d2SMark Murray 	if (options->number_of_password_prompts == -1)
1396511b41d2SMark Murray 		options->number_of_password_prompts = 3;
1397511b41d2SMark Murray 	/* Selected in ssh_login(). */
1398511b41d2SMark Murray 	if (options->cipher == -1)
1399511b41d2SMark Murray 		options->cipher = SSH_CIPHER_NOT_SET;
1400e8aafc91SKris Kennaway 	/* options->ciphers, default set in myproposals.h */
1401ca3176e7SBrian Feldman 	/* options->macs, default set in myproposals.h */
14024a421b63SDag-Erling Smørgrav 	/* options->kex_algorithms, default set in myproposals.h */
1403ca3176e7SBrian Feldman 	/* options->hostkeyalgorithms, default set in myproposals.h */
1404e8aafc91SKris Kennaway 	if (options->protocol == SSH_PROTO_UNKNOWN)
1405b15c8340SDag-Erling Smørgrav 		options->protocol = SSH_PROTO_2;
1406511b41d2SMark Murray 	if (options->num_identity_files == 0) {
1407ca3176e7SBrian Feldman 		if (options->protocol & SSH_PROTO_1) {
140873370613SDag-Erling Smørgrav 			add_identity_file(options, "~/",
140973370613SDag-Erling Smørgrav 			    _PATH_SSH_CLIENT_IDENTITY, 0);
1410511b41d2SMark Murray 		}
1411ca3176e7SBrian Feldman 		if (options->protocol & SSH_PROTO_2) {
141273370613SDag-Erling Smørgrav 			add_identity_file(options, "~/",
141373370613SDag-Erling Smørgrav 			    _PATH_SSH_CLIENT_ID_RSA, 0);
141473370613SDag-Erling Smørgrav 			add_identity_file(options, "~/",
141573370613SDag-Erling Smørgrav 			    _PATH_SSH_CLIENT_ID_DSA, 0);
14164a421b63SDag-Erling Smørgrav #ifdef OPENSSL_HAS_ECC
141773370613SDag-Erling Smørgrav 			add_identity_file(options, "~/",
141873370613SDag-Erling Smørgrav 			    _PATH_SSH_CLIENT_ID_ECDSA, 0);
14194a421b63SDag-Erling Smørgrav #endif
1420ca3176e7SBrian Feldman 		}
1421e8aafc91SKris Kennaway 	}
1422511b41d2SMark Murray 	if (options->escape_char == -1)
1423511b41d2SMark Murray 		options->escape_char = '~';
1424e146993eSDag-Erling Smørgrav 	if (options->num_system_hostfiles == 0) {
1425e146993eSDag-Erling Smørgrav 		options->system_hostfiles[options->num_system_hostfiles++] =
1426e146993eSDag-Erling Smørgrav 		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
1427e146993eSDag-Erling Smørgrav 		options->system_hostfiles[options->num_system_hostfiles++] =
1428e146993eSDag-Erling Smørgrav 		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
1429e146993eSDag-Erling Smørgrav 	}
1430e146993eSDag-Erling Smørgrav 	if (options->num_user_hostfiles == 0) {
1431e146993eSDag-Erling Smørgrav 		options->user_hostfiles[options->num_user_hostfiles++] =
1432e146993eSDag-Erling Smørgrav 		    xstrdup(_PATH_SSH_USER_HOSTFILE);
1433e146993eSDag-Erling Smørgrav 		options->user_hostfiles[options->num_user_hostfiles++] =
1434e146993eSDag-Erling Smørgrav 		    xstrdup(_PATH_SSH_USER_HOSTFILE2);
1435e146993eSDag-Erling Smørgrav 	}
1436af12a3e7SDag-Erling Smørgrav 	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
1437511b41d2SMark Murray 		options->log_level = SYSLOG_LEVEL_INFO;
1438af12a3e7SDag-Erling Smørgrav 	if (options->clear_forwardings == 1)
1439af12a3e7SDag-Erling Smørgrav 		clear_forwardings(options);
1440af12a3e7SDag-Erling Smørgrav 	if (options->no_host_authentication_for_localhost == - 1)
1441af12a3e7SDag-Erling Smørgrav 		options->no_host_authentication_for_localhost = 0;
14425962c0e9SDag-Erling Smørgrav 	if (options->identities_only == -1)
14435962c0e9SDag-Erling Smørgrav 		options->identities_only = 0;
1444e73e9afaSDag-Erling Smørgrav 	if (options->enable_ssh_keysign == -1)
1445e73e9afaSDag-Erling Smørgrav 		options->enable_ssh_keysign = 0;
1446cf2b5f3bSDag-Erling Smørgrav 	if (options->rekey_limit == -1)
1447cf2b5f3bSDag-Erling Smørgrav 		options->rekey_limit = 0;
1448*e4a9863fSDag-Erling Smørgrav 	if (options->rekey_interval == -1)
1449*e4a9863fSDag-Erling Smørgrav 		options->rekey_interval = 0;
145083c6a524SDag-Erling Smørgrav #if HAVE_LDNS
145183c6a524SDag-Erling Smørgrav 	if (options->verify_host_key_dns == -1)
145283c6a524SDag-Erling Smørgrav 		/* automatically trust a verified SSHFP record */
145383c6a524SDag-Erling Smørgrav 		options->verify_host_key_dns = 1;
145483c6a524SDag-Erling Smørgrav #else
1455cf2b5f3bSDag-Erling Smørgrav 	if (options->verify_host_key_dns == -1)
1456cf2b5f3bSDag-Erling Smørgrav 		options->verify_host_key_dns = 0;
145783c6a524SDag-Erling Smørgrav #endif
14581ec0d754SDag-Erling Smørgrav 	if (options->server_alive_interval == -1)
14591ec0d754SDag-Erling Smørgrav 		options->server_alive_interval = 0;
14601ec0d754SDag-Erling Smørgrav 	if (options->server_alive_count_max == -1)
14611ec0d754SDag-Erling Smørgrav 		options->server_alive_count_max = 3;
146221e764dfSDag-Erling Smørgrav 	if (options->control_master == -1)
146321e764dfSDag-Erling Smørgrav 		options->control_master = 0;
1464e2f6069cSDag-Erling Smørgrav 	if (options->control_persist == -1) {
1465e2f6069cSDag-Erling Smørgrav 		options->control_persist = 0;
1466e2f6069cSDag-Erling Smørgrav 		options->control_persist_timeout = 0;
1467e2f6069cSDag-Erling Smørgrav 	}
1468aa49c926SDag-Erling Smørgrav 	if (options->hash_known_hosts == -1)
1469aa49c926SDag-Erling Smørgrav 		options->hash_known_hosts = 0;
1470b74df5b2SDag-Erling Smørgrav 	if (options->tun_open == -1)
1471b74df5b2SDag-Erling Smørgrav 		options->tun_open = SSH_TUNMODE_NO;
1472b74df5b2SDag-Erling Smørgrav 	if (options->tun_local == -1)
1473b74df5b2SDag-Erling Smørgrav 		options->tun_local = SSH_TUNID_ANY;
1474b74df5b2SDag-Erling Smørgrav 	if (options->tun_remote == -1)
1475b74df5b2SDag-Erling Smørgrav 		options->tun_remote = SSH_TUNID_ANY;
1476b74df5b2SDag-Erling Smørgrav 	if (options->permit_local_command == -1)
1477b74df5b2SDag-Erling Smørgrav 		options->permit_local_command = 0;
14787aee6ffeSDag-Erling Smørgrav 	if (options->use_roaming == -1)
14797aee6ffeSDag-Erling Smørgrav 		options->use_roaming = 1;
1480d4af9e69SDag-Erling Smørgrav 	if (options->visual_host_key == -1)
1481d4af9e69SDag-Erling Smørgrav 		options->visual_host_key = 0;
1482cce7d346SDag-Erling Smørgrav 	if (options->zero_knowledge_password_authentication == -1)
1483cce7d346SDag-Erling Smørgrav 		options->zero_knowledge_password_authentication = 0;
14844a421b63SDag-Erling Smørgrav 	if (options->ip_qos_interactive == -1)
14854a421b63SDag-Erling Smørgrav 		options->ip_qos_interactive = IPTOS_LOWDELAY;
14864a421b63SDag-Erling Smørgrav 	if (options->ip_qos_bulk == -1)
14874a421b63SDag-Erling Smørgrav 		options->ip_qos_bulk = IPTOS_THROUGHPUT;
1488e146993eSDag-Erling Smørgrav 	if (options->request_tty == -1)
1489e146993eSDag-Erling Smørgrav 		options->request_tty = REQUEST_TTY_AUTO;
1490b74df5b2SDag-Erling Smørgrav 	/* options->local_command should not be set by default */
1491511b41d2SMark Murray 	/* options->proxy_command should not be set by default */
1492511b41d2SMark Murray 	/* options->user will be set in the main program if appropriate */
1493511b41d2SMark Murray 	/* options->hostname will be set in the main program if appropriate */
1494ca3176e7SBrian Feldman 	/* options->host_key_alias should not be set by default */
1495ca3176e7SBrian Feldman 	/* options->preferred_authentications will be set in ssh */
1496462c32cbSDag-Erling Smørgrav 	if (options->version_addendum == NULL)
1497462c32cbSDag-Erling Smørgrav 		options->version_addendum = xstrdup(SSH_VERSION_FREEBSD);
149889986192SBrooks Davis 	if (options->hpn_disabled == -1)
149989986192SBrooks Davis 		options->hpn_disabled = 0;
150089986192SBrooks Davis 	if (options->hpn_buffer_size > -1)
150189986192SBrooks Davis 	{
150289986192SBrooks Davis 		u_int maxlen;
150389986192SBrooks Davis 
150489986192SBrooks Davis 		/* If a user tries to set the size to 0 set it to 1KB. */
150589986192SBrooks Davis 		if (options->hpn_buffer_size == 0)
150689986192SBrooks Davis 			options->hpn_buffer_size = 1024;
150789986192SBrooks Davis 		/* Limit the buffer to BUFFER_MAX_LEN. */
150889986192SBrooks Davis 		maxlen = buffer_get_max_len();
150989986192SBrooks Davis 		if (options->hpn_buffer_size > (maxlen / 1024)) {
151089986192SBrooks Davis 			debug("User requested buffer larger than %ub: %ub. "
151189986192SBrooks Davis 			    "Request reverted to %ub", maxlen,
151289986192SBrooks Davis 			    options->hpn_buffer_size * 1024, maxlen);
151389986192SBrooks Davis 			options->hpn_buffer_size = maxlen;
151489986192SBrooks Davis 		}
151589986192SBrooks Davis 		debug("hpn_buffer_size set to %d", options->hpn_buffer_size);
151689986192SBrooks Davis 	}
151789986192SBrooks Davis 	if (options->tcp_rcv_buf == 0)
151889986192SBrooks Davis 		options->tcp_rcv_buf = 1;
151989986192SBrooks Davis 	if (options->tcp_rcv_buf > -1)
152089986192SBrooks Davis 		options->tcp_rcv_buf *= 1024;
152189986192SBrooks Davis 	if (options->tcp_rcv_buf_poll == -1)
152289986192SBrooks Davis 		options->tcp_rcv_buf_poll = 1;
152389986192SBrooks Davis #ifdef	NONE_CIPHER_ENABLED
152489986192SBrooks Davis 	/* options->none_enabled must not be set by default */
152589986192SBrooks Davis 	if (options->none_switch == -1)
152689986192SBrooks Davis 		options->none_switch = 0;
152789986192SBrooks Davis #endif
1528511b41d2SMark Murray }
1529aa49c926SDag-Erling Smørgrav 
1530aa49c926SDag-Erling Smørgrav /*
1531aa49c926SDag-Erling Smørgrav  * parse_forward
1532aa49c926SDag-Erling Smørgrav  * parses a string containing a port forwarding specification of the form:
1533cce7d346SDag-Erling Smørgrav  *   dynamicfwd == 0
1534aa49c926SDag-Erling Smørgrav  *	[listenhost:]listenport:connecthost:connectport
1535cce7d346SDag-Erling Smørgrav  *   dynamicfwd == 1
1536cce7d346SDag-Erling Smørgrav  *	[listenhost:]listenport
1537aa49c926SDag-Erling Smørgrav  * returns number of arguments parsed or zero on error
1538aa49c926SDag-Erling Smørgrav  */
1539aa49c926SDag-Erling Smørgrav int
1540cce7d346SDag-Erling Smørgrav parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
1541aa49c926SDag-Erling Smørgrav {
1542aa49c926SDag-Erling Smørgrav 	int i;
1543aa49c926SDag-Erling Smørgrav 	char *p, *cp, *fwdarg[4];
1544aa49c926SDag-Erling Smørgrav 
1545aa49c926SDag-Erling Smørgrav 	memset(fwd, '\0', sizeof(*fwd));
1546aa49c926SDag-Erling Smørgrav 
1547aa49c926SDag-Erling Smørgrav 	cp = p = xstrdup(fwdspec);
1548aa49c926SDag-Erling Smørgrav 
1549aa49c926SDag-Erling Smørgrav 	/* skip leading spaces */
1550d4af9e69SDag-Erling Smørgrav 	while (isspace(*cp))
1551aa49c926SDag-Erling Smørgrav 		cp++;
1552aa49c926SDag-Erling Smørgrav 
1553aa49c926SDag-Erling Smørgrav 	for (i = 0; i < 4; ++i)
1554aa49c926SDag-Erling Smørgrav 		if ((fwdarg[i] = hpdelim(&cp)) == NULL)
1555aa49c926SDag-Erling Smørgrav 			break;
1556aa49c926SDag-Erling Smørgrav 
1557cce7d346SDag-Erling Smørgrav 	/* Check for trailing garbage */
1558aa49c926SDag-Erling Smørgrav 	if (cp != NULL)
1559aa49c926SDag-Erling Smørgrav 		i = 0;	/* failure */
1560aa49c926SDag-Erling Smørgrav 
1561aa49c926SDag-Erling Smørgrav 	switch (i) {
1562cce7d346SDag-Erling Smørgrav 	case 1:
1563cce7d346SDag-Erling Smørgrav 		fwd->listen_host = NULL;
1564cce7d346SDag-Erling Smørgrav 		fwd->listen_port = a2port(fwdarg[0]);
1565cce7d346SDag-Erling Smørgrav 		fwd->connect_host = xstrdup("socks");
1566cce7d346SDag-Erling Smørgrav 		break;
1567cce7d346SDag-Erling Smørgrav 
1568cce7d346SDag-Erling Smørgrav 	case 2:
1569cce7d346SDag-Erling Smørgrav 		fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
1570cce7d346SDag-Erling Smørgrav 		fwd->listen_port = a2port(fwdarg[1]);
1571cce7d346SDag-Erling Smørgrav 		fwd->connect_host = xstrdup("socks");
1572cce7d346SDag-Erling Smørgrav 		break;
1573cce7d346SDag-Erling Smørgrav 
1574aa49c926SDag-Erling Smørgrav 	case 3:
1575aa49c926SDag-Erling Smørgrav 		fwd->listen_host = NULL;
1576aa49c926SDag-Erling Smørgrav 		fwd->listen_port = a2port(fwdarg[0]);
1577aa49c926SDag-Erling Smørgrav 		fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
1578aa49c926SDag-Erling Smørgrav 		fwd->connect_port = a2port(fwdarg[2]);
1579aa49c926SDag-Erling Smørgrav 		break;
1580aa49c926SDag-Erling Smørgrav 
1581aa49c926SDag-Erling Smørgrav 	case 4:
1582aa49c926SDag-Erling Smørgrav 		fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
1583aa49c926SDag-Erling Smørgrav 		fwd->listen_port = a2port(fwdarg[1]);
1584aa49c926SDag-Erling Smørgrav 		fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
1585aa49c926SDag-Erling Smørgrav 		fwd->connect_port = a2port(fwdarg[3]);
1586aa49c926SDag-Erling Smørgrav 		break;
1587aa49c926SDag-Erling Smørgrav 	default:
1588aa49c926SDag-Erling Smørgrav 		i = 0; /* failure */
1589aa49c926SDag-Erling Smørgrav 	}
1590aa49c926SDag-Erling Smørgrav 
1591*e4a9863fSDag-Erling Smørgrav 	free(p);
1592aa49c926SDag-Erling Smørgrav 
1593cce7d346SDag-Erling Smørgrav 	if (dynamicfwd) {
1594cce7d346SDag-Erling Smørgrav 		if (!(i == 1 || i == 2))
1595cce7d346SDag-Erling Smørgrav 			goto fail_free;
1596cce7d346SDag-Erling Smørgrav 	} else {
1597cce7d346SDag-Erling Smørgrav 		if (!(i == 3 || i == 4))
1598cce7d346SDag-Erling Smørgrav 			goto fail_free;
1599cce7d346SDag-Erling Smørgrav 		if (fwd->connect_port <= 0)
1600cce7d346SDag-Erling Smørgrav 			goto fail_free;
1601cce7d346SDag-Erling Smørgrav 	}
1602cce7d346SDag-Erling Smørgrav 
1603cce7d346SDag-Erling Smørgrav 	if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0))
1604aa49c926SDag-Erling Smørgrav 		goto fail_free;
1605aa49c926SDag-Erling Smørgrav 
1606aa49c926SDag-Erling Smørgrav 	if (fwd->connect_host != NULL &&
1607aa49c926SDag-Erling Smørgrav 	    strlen(fwd->connect_host) >= NI_MAXHOST)
1608aa49c926SDag-Erling Smørgrav 		goto fail_free;
1609cce7d346SDag-Erling Smørgrav 	if (fwd->listen_host != NULL &&
1610cce7d346SDag-Erling Smørgrav 	    strlen(fwd->listen_host) >= NI_MAXHOST)
1611cce7d346SDag-Erling Smørgrav 		goto fail_free;
1612cce7d346SDag-Erling Smørgrav 
1613aa49c926SDag-Erling Smørgrav 
1614aa49c926SDag-Erling Smørgrav 	return (i);
1615aa49c926SDag-Erling Smørgrav 
1616aa49c926SDag-Erling Smørgrav  fail_free:
1617*e4a9863fSDag-Erling Smørgrav 	free(fwd->connect_host);
1618cce7d346SDag-Erling Smørgrav 	fwd->connect_host = NULL;
1619*e4a9863fSDag-Erling Smørgrav 	free(fwd->listen_host);
1620cce7d346SDag-Erling Smørgrav 	fwd->listen_host = NULL;
1621aa49c926SDag-Erling Smørgrav 	return (0);
1622aa49c926SDag-Erling Smørgrav }
1623