xref: /freebsd/crypto/openssh/readconf.c (revision fa67e83c67cbbe84a998c8564a02d5c10894031f)
1*fa67e83cSDag-Erling Smørgrav /* $OpenBSD: readconf.c,v 1.195 2013/02/17 23:16:57 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>
36333ee039SDag-Erling Smørgrav 
37511b41d2SMark Murray #include "xmalloc.h"
38333ee039SDag-Erling Smørgrav #include "ssh.h"
39e8aafc91SKris Kennaway #include "compat.h"
40ca3176e7SBrian Feldman #include "cipher.h"
41ca3176e7SBrian Feldman #include "pathnames.h"
42ca3176e7SBrian Feldman #include "log.h"
43333ee039SDag-Erling Smørgrav #include "key.h"
44ca3176e7SBrian Feldman #include "readconf.h"
45ca3176e7SBrian Feldman #include "match.h"
46ca3176e7SBrian Feldman #include "misc.h"
47333ee039SDag-Erling Smørgrav #include "buffer.h"
48ca3176e7SBrian Feldman #include "kex.h"
49ca3176e7SBrian Feldman #include "mac.h"
50cce7d346SDag-Erling Smørgrav #include "version.h"
51511b41d2SMark Murray 
52511b41d2SMark Murray /* Format of the configuration file:
53511b41d2SMark Murray 
54511b41d2SMark Murray    # Configuration data is parsed as follows:
55511b41d2SMark Murray    #  1. command line options
56511b41d2SMark Murray    #  2. user-specific file
57511b41d2SMark Murray    #  3. system-wide file
58511b41d2SMark Murray    # Any configuration value is only changed the first time it is set.
59511b41d2SMark Murray    # Thus, host-specific definitions should be at the beginning of the
60511b41d2SMark Murray    # configuration file, and defaults at the end.
61511b41d2SMark Murray 
62511b41d2SMark Murray    # Host-specific declarations.  These may override anything above.  A single
63511b41d2SMark Murray    # host may match multiple declarations; these are processed in the order
64511b41d2SMark Murray    # that they are given in.
65511b41d2SMark Murray 
66511b41d2SMark Murray    Host *.ngs.fi ngs.fi
6780628bacSDag-Erling Smørgrav      User foo
68511b41d2SMark Murray 
69511b41d2SMark Murray    Host fake.com
70511b41d2SMark Murray      HostName another.host.name.real.org
71511b41d2SMark Murray      User blaah
72511b41d2SMark Murray      Port 34289
73511b41d2SMark Murray      ForwardX11 no
74511b41d2SMark Murray      ForwardAgent no
75511b41d2SMark Murray 
76511b41d2SMark Murray    Host books.com
77511b41d2SMark Murray      RemoteForward 9999 shadows.cs.hut.fi:9999
78511b41d2SMark Murray      Cipher 3des
79511b41d2SMark Murray 
80511b41d2SMark Murray    Host fascist.blob.com
81511b41d2SMark Murray      Port 23123
82511b41d2SMark Murray      User tylonen
83511b41d2SMark Murray      PasswordAuthentication no
84511b41d2SMark Murray 
85511b41d2SMark Murray    Host puukko.hut.fi
86511b41d2SMark Murray      User t35124p
87511b41d2SMark Murray      ProxyCommand ssh-proxy %h %p
88511b41d2SMark Murray 
89511b41d2SMark Murray    Host *.fr
9080628bacSDag-Erling Smørgrav      PublicKeyAuthentication no
91511b41d2SMark Murray 
92511b41d2SMark Murray    Host *.su
93511b41d2SMark Murray      Cipher none
94511b41d2SMark Murray      PasswordAuthentication no
95511b41d2SMark Murray 
96b74df5b2SDag-Erling Smørgrav    Host vpn.fake.com
97b74df5b2SDag-Erling Smørgrav      Tunnel yes
98b74df5b2SDag-Erling Smørgrav      TunnelDevice 3
99b74df5b2SDag-Erling Smørgrav 
100511b41d2SMark Murray    # Defaults for various options
101511b41d2SMark Murray    Host *
102511b41d2SMark Murray      ForwardAgent no
103ca3176e7SBrian Feldman      ForwardX11 no
104511b41d2SMark Murray      PasswordAuthentication yes
105511b41d2SMark Murray      RSAAuthentication yes
106511b41d2SMark Murray      RhostsRSAAuthentication yes
107511b41d2SMark Murray      StrictHostKeyChecking yes
1081ec0d754SDag-Erling Smørgrav      TcpKeepAlive no
109511b41d2SMark Murray      IdentityFile ~/.ssh/identity
110511b41d2SMark Murray      Port 22
111511b41d2SMark Murray      EscapeChar ~
112511b41d2SMark Murray 
113511b41d2SMark Murray */
114511b41d2SMark Murray 
115511b41d2SMark Murray /* Keyword tokens. */
116511b41d2SMark Murray 
117511b41d2SMark Murray typedef enum {
118511b41d2SMark Murray 	oBadOption,
119e2f6069cSDag-Erling Smørgrav 	oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
120e2f6069cSDag-Erling Smørgrav 	oGatewayPorts, oExitOnForwardFailure,
12180628bacSDag-Erling Smørgrav 	oPasswordAuthentication, oRSAAuthentication,
122ca3176e7SBrian Feldman 	oChallengeResponseAuthentication, oXAuthLocation,
123511b41d2SMark Murray 	oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
124511b41d2SMark Murray 	oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
125511b41d2SMark Murray 	oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
126511b41d2SMark Murray 	oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
1271ec0d754SDag-Erling Smørgrav 	oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
128ca3176e7SBrian Feldman 	oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
129ca3176e7SBrian Feldman 	oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
130ca3176e7SBrian Feldman 	oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
131ca3176e7SBrian Feldman 	oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
132b15c8340SDag-Erling Smørgrav 	oHostKeyAlgorithms, oBindAddress, oPKCS11Provider,
1339e2cbe04SDag-Erling Smørgrav 	oClearAllForwardings, oNoHostAuthenticationForLocalhost,
134cf2b5f3bSDag-Erling Smørgrav 	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
135cf2b5f3bSDag-Erling Smørgrav 	oAddressFamily, oGssAuthentication, oGssDelegateCreds,
1365962c0e9SDag-Erling Smørgrav 	oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
137e2f6069cSDag-Erling Smørgrav 	oSendEnv, oControlPath, oControlMaster, oControlPersist,
138e2f6069cSDag-Erling Smørgrav 	oHashKnownHosts,
139b74df5b2SDag-Erling Smørgrav 	oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
1407aee6ffeSDag-Erling Smørgrav 	oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication,
141e146993eSDag-Erling Smørgrav 	oKexAlgorithms, oIPQoS, oRequestTTY,
14289986192SBrooks Davis 	oHPNDisabled, oHPNBufferSize, oTcpRcvBufPoll, oTcpRcvBuf,
14389986192SBrooks Davis #ifdef NONE_CIPHER_ENABLED
14489986192SBrooks Davis 	oNoneEnabled, oNoneSwitch,
14589986192SBrooks Davis #endif
146cfa59440SDag-Erling Smørgrav 	oVersionAddendum,
147cf2b5f3bSDag-Erling Smørgrav 	oDeprecated, oUnsupported
148511b41d2SMark Murray } OpCodes;
149511b41d2SMark Murray 
150511b41d2SMark Murray /* Textual representations of the tokens. */
151511b41d2SMark Murray 
152511b41d2SMark Murray static struct {
153511b41d2SMark Murray 	const char *name;
154511b41d2SMark Murray 	OpCodes opcode;
155511b41d2SMark Murray } keywords[] = {
156511b41d2SMark Murray 	{ "forwardagent", oForwardAgent },
157511b41d2SMark Murray 	{ "forwardx11", oForwardX11 },
1581ec0d754SDag-Erling Smørgrav 	{ "forwardx11trusted", oForwardX11Trusted },
159e2f6069cSDag-Erling Smørgrav 	{ "forwardx11timeout", oForwardX11Timeout },
160333ee039SDag-Erling Smørgrav 	{ "exitonforwardfailure", oExitOnForwardFailure },
161c2d3a559SKris Kennaway 	{ "xauthlocation", oXAuthLocation },
162511b41d2SMark Murray 	{ "gatewayports", oGatewayPorts },
163511b41d2SMark Murray 	{ "useprivilegedport", oUsePrivilegedPort },
164cf2b5f3bSDag-Erling Smørgrav 	{ "rhostsauthentication", oDeprecated },
165511b41d2SMark Murray 	{ "passwordauthentication", oPasswordAuthentication },
16609958426SBrian Feldman 	{ "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
16709958426SBrian Feldman 	{ "kbdinteractivedevices", oKbdInteractiveDevices },
168511b41d2SMark Murray 	{ "rsaauthentication", oRSAAuthentication },
169ca3176e7SBrian Feldman 	{ "pubkeyauthentication", oPubkeyAuthentication },
170ca3176e7SBrian Feldman 	{ "dsaauthentication", oPubkeyAuthentication },		    /* alias */
171ca3176e7SBrian Feldman 	{ "rhostsrsaauthentication", oRhostsRSAAuthentication },
172ca3176e7SBrian Feldman 	{ "hostbasedauthentication", oHostbasedAuthentication },
173ca3176e7SBrian Feldman 	{ "challengeresponseauthentication", oChallengeResponseAuthentication },
174ca3176e7SBrian Feldman 	{ "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
175ca3176e7SBrian Feldman 	{ "tisauthentication", oChallengeResponseAuthentication },  /* alias */
176cf2b5f3bSDag-Erling Smørgrav 	{ "kerberosauthentication", oUnsupported },
177cf2b5f3bSDag-Erling Smørgrav 	{ "kerberostgtpassing", oUnsupported },
178cf2b5f3bSDag-Erling Smørgrav 	{ "afstokenpassing", oUnsupported },
179cf2b5f3bSDag-Erling Smørgrav #if defined(GSSAPI)
180cf2b5f3bSDag-Erling Smørgrav 	{ "gssapiauthentication", oGssAuthentication },
181cf2b5f3bSDag-Erling Smørgrav 	{ "gssapidelegatecredentials", oGssDelegateCreds },
182cf2b5f3bSDag-Erling Smørgrav #else
183cf2b5f3bSDag-Erling Smørgrav 	{ "gssapiauthentication", oUnsupported },
184cf2b5f3bSDag-Erling Smørgrav 	{ "gssapidelegatecredentials", oUnsupported },
185511b41d2SMark Murray #endif
18680628bacSDag-Erling Smørgrav 	{ "fallbacktorsh", oDeprecated },
18780628bacSDag-Erling Smørgrav 	{ "usersh", oDeprecated },
188511b41d2SMark Murray 	{ "identityfile", oIdentityFile },
189cce7d346SDag-Erling Smørgrav 	{ "identityfile2", oIdentityFile },			/* obsolete */
1905962c0e9SDag-Erling Smørgrav 	{ "identitiesonly", oIdentitiesOnly },
191511b41d2SMark Murray 	{ "hostname", oHostName },
192ca3176e7SBrian Feldman 	{ "hostkeyalias", oHostKeyAlias },
193511b41d2SMark Murray 	{ "proxycommand", oProxyCommand },
194511b41d2SMark Murray 	{ "port", oPort },
195511b41d2SMark Murray 	{ "cipher", oCipher },
196e8aafc91SKris Kennaway 	{ "ciphers", oCiphers },
197ca3176e7SBrian Feldman 	{ "macs", oMacs },
198e8aafc91SKris Kennaway 	{ "protocol", oProtocol },
199511b41d2SMark Murray 	{ "remoteforward", oRemoteForward },
200511b41d2SMark Murray 	{ "localforward", oLocalForward },
201511b41d2SMark Murray 	{ "user", oUser },
202511b41d2SMark Murray 	{ "host", oHost },
203511b41d2SMark Murray 	{ "escapechar", oEscapeChar },
204511b41d2SMark Murray 	{ "globalknownhostsfile", oGlobalKnownHostsFile },
205e146993eSDag-Erling Smørgrav 	{ "globalknownhostsfile2", oDeprecated },
206cce7d346SDag-Erling Smørgrav 	{ "userknownhostsfile", oUserKnownHostsFile },
207e146993eSDag-Erling Smørgrav 	{ "userknownhostsfile2", oDeprecated },
208511b41d2SMark Murray 	{ "connectionattempts", oConnectionAttempts },
209511b41d2SMark Murray 	{ "batchmode", oBatchMode },
210511b41d2SMark Murray 	{ "checkhostip", oCheckHostIP },
211511b41d2SMark Murray 	{ "stricthostkeychecking", oStrictHostKeyChecking },
212511b41d2SMark Murray 	{ "compression", oCompression },
213511b41d2SMark Murray 	{ "compressionlevel", oCompressionLevel },
2141ec0d754SDag-Erling Smørgrav 	{ "tcpkeepalive", oTCPKeepAlive },
2151ec0d754SDag-Erling Smørgrav 	{ "keepalive", oTCPKeepAlive },				/* obsolete */
216511b41d2SMark Murray 	{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
217511b41d2SMark Murray 	{ "loglevel", oLogLevel },
218ca3176e7SBrian Feldman 	{ "dynamicforward", oDynamicForward },
219ca3176e7SBrian Feldman 	{ "preferredauthentications", oPreferredAuthentications },
220ca3176e7SBrian Feldman 	{ "hostkeyalgorithms", oHostKeyAlgorithms },
221af12a3e7SDag-Erling Smørgrav 	{ "bindaddress", oBindAddress },
222b15c8340SDag-Erling Smørgrav #ifdef ENABLE_PKCS11
223b15c8340SDag-Erling Smørgrav 	{ "smartcarddevice", oPKCS11Provider },
224b15c8340SDag-Erling Smørgrav 	{ "pkcs11provider", oPKCS11Provider },
225cf2b5f3bSDag-Erling Smørgrav #else
226cf2b5f3bSDag-Erling Smørgrav 	{ "smartcarddevice", oUnsupported },
227b15c8340SDag-Erling Smørgrav 	{ "pkcs11provider", oUnsupported },
228cf2b5f3bSDag-Erling Smørgrav #endif
229af12a3e7SDag-Erling Smørgrav 	{ "clearallforwardings", oClearAllForwardings },
230e73e9afaSDag-Erling Smørgrav 	{ "enablesshkeysign", oEnableSSHKeysign },
231cf2b5f3bSDag-Erling Smørgrav 	{ "verifyhostkeydns", oVerifyHostKeyDNS },
232af12a3e7SDag-Erling Smørgrav 	{ "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
233cf2b5f3bSDag-Erling Smørgrav 	{ "rekeylimit", oRekeyLimit },
234cf2b5f3bSDag-Erling Smørgrav 	{ "connecttimeout", oConnectTimeout },
235cf2b5f3bSDag-Erling Smørgrav 	{ "addressfamily", oAddressFamily },
2361ec0d754SDag-Erling Smørgrav 	{ "serveraliveinterval", oServerAliveInterval },
2371ec0d754SDag-Erling Smørgrav 	{ "serveralivecountmax", oServerAliveCountMax },
23821e764dfSDag-Erling Smørgrav 	{ "sendenv", oSendEnv },
23921e764dfSDag-Erling Smørgrav 	{ "controlpath", oControlPath },
24021e764dfSDag-Erling Smørgrav 	{ "controlmaster", oControlMaster },
241e2f6069cSDag-Erling Smørgrav 	{ "controlpersist", oControlPersist },
242aa49c926SDag-Erling Smørgrav 	{ "hashknownhosts", oHashKnownHosts },
243b74df5b2SDag-Erling Smørgrav 	{ "tunnel", oTunnel },
244b74df5b2SDag-Erling Smørgrav 	{ "tunneldevice", oTunnelDevice },
245b74df5b2SDag-Erling Smørgrav 	{ "localcommand", oLocalCommand },
246b74df5b2SDag-Erling Smørgrav 	{ "permitlocalcommand", oPermitLocalCommand },
247d4af9e69SDag-Erling Smørgrav 	{ "visualhostkey", oVisualHostKey },
2487aee6ffeSDag-Erling Smørgrav 	{ "useroaming", oUseRoaming },
249cce7d346SDag-Erling Smørgrav #ifdef JPAKE
250cce7d346SDag-Erling Smørgrav 	{ "zeroknowledgepasswordauthentication",
251cce7d346SDag-Erling Smørgrav 	    oZeroKnowledgePasswordAuthentication },
252cce7d346SDag-Erling Smørgrav #else
253cce7d346SDag-Erling Smørgrav 	{ "zeroknowledgepasswordauthentication", oUnsupported },
254cce7d346SDag-Erling Smørgrav #endif
2554a421b63SDag-Erling Smørgrav 	{ "kexalgorithms", oKexAlgorithms },
2564a421b63SDag-Erling Smørgrav 	{ "ipqos", oIPQoS },
257e146993eSDag-Erling Smørgrav 	{ "requesttty", oRequestTTY },
25889986192SBrooks Davis 	{ "hpndisabled", oHPNDisabled },
25989986192SBrooks Davis 	{ "hpnbuffersize", oHPNBufferSize },
26089986192SBrooks Davis 	{ "tcprcvbufpoll", oTcpRcvBufPoll },
26189986192SBrooks Davis 	{ "tcprcvbuf", oTcpRcvBuf },
26289986192SBrooks Davis #ifdef	NONE_CIPHER_ENABLED
26389986192SBrooks Davis 	{ "noneenabled", oNoneEnabled },
26489986192SBrooks Davis 	{ "noneswitch", oNoneSwitch },
26589986192SBrooks Davis #endif
266975616f0SDag-Erling Smørgrav 	{ "versionaddendum", oVersionAddendum },
26735762f59SEd Schouten 
268af12a3e7SDag-Erling Smørgrav 	{ NULL, oBadOption }
269511b41d2SMark Murray };
270511b41d2SMark Murray 
271511b41d2SMark Murray /*
272511b41d2SMark Murray  * Adds a local TCP/IP port forward to options.  Never returns if there is an
273511b41d2SMark Murray  * error.
274511b41d2SMark Murray  */
275511b41d2SMark Murray 
276511b41d2SMark Murray void
277aa49c926SDag-Erling Smørgrav add_local_forward(Options *options, const Forward *newfwd)
278511b41d2SMark Murray {
279511b41d2SMark Murray 	Forward *fwd;
280f388f5efSDag-Erling Smørgrav #ifndef NO_IPPORT_RESERVED_CONCEPT
281511b41d2SMark Murray 	extern uid_t original_real_uid;
28203f6c5cdSDag-Erling Smørgrav 	int ipport_reserved;
28303f6c5cdSDag-Erling Smørgrav #ifdef __FreeBSD__
28403f6c5cdSDag-Erling Smørgrav 	size_t len_ipport_reserved = sizeof(ipport_reserved);
28503f6c5cdSDag-Erling Smørgrav 
28603f6c5cdSDag-Erling Smørgrav 	if (sysctlbyname("net.inet.ip.portrange.reservedhigh",
28703f6c5cdSDag-Erling Smørgrav 	    &ipport_reserved, &len_ipport_reserved, NULL, 0) != 0)
28803f6c5cdSDag-Erling Smørgrav 		ipport_reserved = IPPORT_RESERVED;
28903f6c5cdSDag-Erling Smørgrav 	else
29003f6c5cdSDag-Erling Smørgrav 		ipport_reserved++;
29103f6c5cdSDag-Erling Smørgrav #else
29203f6c5cdSDag-Erling Smørgrav 	ipport_reserved = IPPORT_RESERVED;
29303f6c5cdSDag-Erling Smørgrav #endif
29403f6c5cdSDag-Erling Smørgrav 	if (newfwd->listen_port < ipport_reserved && original_real_uid != 0)
295ca3176e7SBrian Feldman 		fatal("Privileged ports can only be forwarded by root.");
296989dd127SDag-Erling Smørgrav #endif
297e2f6069cSDag-Erling Smørgrav 	options->local_forwards = xrealloc(options->local_forwards,
298e2f6069cSDag-Erling Smørgrav 	    options->num_local_forwards + 1,
299e2f6069cSDag-Erling Smørgrav 	    sizeof(*options->local_forwards));
300511b41d2SMark Murray 	fwd = &options->local_forwards[options->num_local_forwards++];
301aa49c926SDag-Erling Smørgrav 
302cce7d346SDag-Erling Smørgrav 	fwd->listen_host = newfwd->listen_host;
303aa49c926SDag-Erling Smørgrav 	fwd->listen_port = newfwd->listen_port;
304cce7d346SDag-Erling Smørgrav 	fwd->connect_host = newfwd->connect_host;
305aa49c926SDag-Erling Smørgrav 	fwd->connect_port = newfwd->connect_port;
306511b41d2SMark Murray }
307511b41d2SMark Murray 
308511b41d2SMark Murray /*
309511b41d2SMark Murray  * Adds a remote TCP/IP port forward to options.  Never returns if there is
310511b41d2SMark Murray  * an error.
311511b41d2SMark Murray  */
312511b41d2SMark Murray 
313511b41d2SMark Murray void
314aa49c926SDag-Erling Smørgrav add_remote_forward(Options *options, const Forward *newfwd)
315511b41d2SMark Murray {
316511b41d2SMark Murray 	Forward *fwd;
317e2f6069cSDag-Erling Smørgrav 
318e2f6069cSDag-Erling Smørgrav 	options->remote_forwards = xrealloc(options->remote_forwards,
319e2f6069cSDag-Erling Smørgrav 	    options->num_remote_forwards + 1,
320e2f6069cSDag-Erling Smørgrav 	    sizeof(*options->remote_forwards));
321511b41d2SMark Murray 	fwd = &options->remote_forwards[options->num_remote_forwards++];
322aa49c926SDag-Erling Smørgrav 
323cce7d346SDag-Erling Smørgrav 	fwd->listen_host = newfwd->listen_host;
324aa49c926SDag-Erling Smørgrav 	fwd->listen_port = newfwd->listen_port;
325cce7d346SDag-Erling Smørgrav 	fwd->connect_host = newfwd->connect_host;
326aa49c926SDag-Erling Smørgrav 	fwd->connect_port = newfwd->connect_port;
327462c32cbSDag-Erling Smørgrav 	fwd->handle = newfwd->handle;
328e2f6069cSDag-Erling Smørgrav 	fwd->allocated_port = 0;
329511b41d2SMark Murray }
330511b41d2SMark Murray 
331af12a3e7SDag-Erling Smørgrav static void
332af12a3e7SDag-Erling Smørgrav clear_forwardings(Options *options)
333af12a3e7SDag-Erling Smørgrav {
334af12a3e7SDag-Erling Smørgrav 	int i;
335af12a3e7SDag-Erling Smørgrav 
336aa49c926SDag-Erling Smørgrav 	for (i = 0; i < options->num_local_forwards; i++) {
337aa49c926SDag-Erling Smørgrav 		if (options->local_forwards[i].listen_host != NULL)
338aa49c926SDag-Erling Smørgrav 			xfree(options->local_forwards[i].listen_host);
339aa49c926SDag-Erling Smørgrav 		xfree(options->local_forwards[i].connect_host);
340aa49c926SDag-Erling Smørgrav 	}
341e2f6069cSDag-Erling Smørgrav 	if (options->num_local_forwards > 0) {
342e2f6069cSDag-Erling Smørgrav 		xfree(options->local_forwards);
343e2f6069cSDag-Erling Smørgrav 		options->local_forwards = NULL;
344e2f6069cSDag-Erling Smørgrav 	}
345af12a3e7SDag-Erling Smørgrav 	options->num_local_forwards = 0;
346aa49c926SDag-Erling Smørgrav 	for (i = 0; i < options->num_remote_forwards; i++) {
347aa49c926SDag-Erling Smørgrav 		if (options->remote_forwards[i].listen_host != NULL)
348aa49c926SDag-Erling Smørgrav 			xfree(options->remote_forwards[i].listen_host);
349aa49c926SDag-Erling Smørgrav 		xfree(options->remote_forwards[i].connect_host);
350aa49c926SDag-Erling Smørgrav 	}
351e2f6069cSDag-Erling Smørgrav 	if (options->num_remote_forwards > 0) {
352e2f6069cSDag-Erling Smørgrav 		xfree(options->remote_forwards);
353e2f6069cSDag-Erling Smørgrav 		options->remote_forwards = NULL;
354e2f6069cSDag-Erling Smørgrav 	}
355af12a3e7SDag-Erling Smørgrav 	options->num_remote_forwards = 0;
356b74df5b2SDag-Erling Smørgrav 	options->tun_open = SSH_TUNMODE_NO;
357af12a3e7SDag-Erling Smørgrav }
358af12a3e7SDag-Erling Smørgrav 
359*fa67e83cSDag-Erling Smørgrav void
360*fa67e83cSDag-Erling Smørgrav add_identity_file(Options *options, const char *dir, const char *filename,
361*fa67e83cSDag-Erling Smørgrav     int userprovided)
362*fa67e83cSDag-Erling Smørgrav {
363*fa67e83cSDag-Erling Smørgrav 	char *path;
364*fa67e83cSDag-Erling Smørgrav 
365*fa67e83cSDag-Erling Smørgrav 	if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
366*fa67e83cSDag-Erling Smørgrav 		fatal("Too many identity files specified (max %d)",
367*fa67e83cSDag-Erling Smørgrav 		    SSH_MAX_IDENTITY_FILES);
368*fa67e83cSDag-Erling Smørgrav 
369*fa67e83cSDag-Erling Smørgrav 	if (dir == NULL) /* no dir, filename is absolute */
370*fa67e83cSDag-Erling Smørgrav 		path = xstrdup(filename);
371*fa67e83cSDag-Erling Smørgrav 	else
372*fa67e83cSDag-Erling Smørgrav 		(void)xasprintf(&path, "%.100s%.100s", dir, filename);
373*fa67e83cSDag-Erling Smørgrav 
374*fa67e83cSDag-Erling Smørgrav 	options->identity_file_userprovided[options->num_identity_files] =
375*fa67e83cSDag-Erling Smørgrav 	    userprovided;
376*fa67e83cSDag-Erling Smørgrav 	options->identity_files[options->num_identity_files++] = path;
377*fa67e83cSDag-Erling Smørgrav }
378*fa67e83cSDag-Erling Smørgrav 
379511b41d2SMark Murray /*
380ca3176e7SBrian Feldman  * Returns the number of the token pointed to by cp or oBadOption.
381511b41d2SMark Murray  */
382511b41d2SMark Murray 
383511b41d2SMark Murray static OpCodes
384511b41d2SMark Murray parse_token(const char *cp, const char *filename, int linenum)
385511b41d2SMark Murray {
386ca3176e7SBrian Feldman 	u_int i;
387511b41d2SMark Murray 
388511b41d2SMark Murray 	for (i = 0; keywords[i].name; i++)
389511b41d2SMark Murray 		if (strcasecmp(cp, keywords[i].name) == 0)
390511b41d2SMark Murray 			return keywords[i].opcode;
391511b41d2SMark Murray 
392ca3176e7SBrian Feldman 	error("%s: line %d: Bad configuration option: %s",
393511b41d2SMark Murray 	    filename, linenum, cp);
394511b41d2SMark Murray 	return oBadOption;
395511b41d2SMark Murray }
396511b41d2SMark Murray 
397511b41d2SMark Murray /*
398511b41d2SMark Murray  * Processes a single option line as used in the configuration files. This
399511b41d2SMark Murray  * only sets those values that have not already been set.
400511b41d2SMark Murray  */
401e73e9afaSDag-Erling Smørgrav #define WHITESPACE " \t\r\n"
402511b41d2SMark Murray 
403511b41d2SMark Murray int
404511b41d2SMark Murray process_config_line(Options *options, const char *host,
405511b41d2SMark Murray 		    char *line, const char *filename, int linenum,
406511b41d2SMark Murray 		    int *activep)
407511b41d2SMark Murray {
408e146993eSDag-Erling Smørgrav 	char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;
409e146993eSDag-Erling Smørgrav 	char **cpptr, fwdarg[256];
410e146993eSDag-Erling Smørgrav 	u_int *uintptr, max_entries = 0;
411e146993eSDag-Erling Smørgrav 	int negated, opcode, *intptr, value, value2, scale;
412d4af9e69SDag-Erling Smørgrav 	LogLevel *log_level_ptr;
413333ee039SDag-Erling Smørgrav 	long long orig, val64;
414e73e9afaSDag-Erling Smørgrav 	size_t len;
415aa49c926SDag-Erling Smørgrav 	Forward fwd;
416511b41d2SMark Murray 
417cf2b5f3bSDag-Erling Smørgrav 	/* Strip trailing whitespace */
418cf2b5f3bSDag-Erling Smørgrav 	for (len = strlen(line) - 1; len > 0; len--) {
419cf2b5f3bSDag-Erling Smørgrav 		if (strchr(WHITESPACE, line[len]) == NULL)
420cf2b5f3bSDag-Erling Smørgrav 			break;
421cf2b5f3bSDag-Erling Smørgrav 		line[len] = '\0';
422cf2b5f3bSDag-Erling Smørgrav 	}
423cf2b5f3bSDag-Erling Smørgrav 
424c2d3a559SKris Kennaway 	s = line;
425c2d3a559SKris Kennaway 	/* Get the keyword. (Each line is supposed to begin with a keyword). */
426333ee039SDag-Erling Smørgrav 	if ((keyword = strdelim(&s)) == NULL)
427333ee039SDag-Erling Smørgrav 		return 0;
428c2d3a559SKris Kennaway 	/* Ignore leading whitespace. */
429c2d3a559SKris Kennaway 	if (*keyword == '\0')
430c2d3a559SKris Kennaway 		keyword = strdelim(&s);
431ca3176e7SBrian Feldman 	if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
432511b41d2SMark Murray 		return 0;
433511b41d2SMark Murray 
434c2d3a559SKris Kennaway 	opcode = parse_token(keyword, filename, linenum);
435511b41d2SMark Murray 
436511b41d2SMark Murray 	switch (opcode) {
437511b41d2SMark Murray 	case oBadOption:
438511b41d2SMark Murray 		/* don't panic, but count bad options */
439511b41d2SMark Murray 		return -1;
440511b41d2SMark Murray 		/* NOTREACHED */
441cf2b5f3bSDag-Erling Smørgrav 	case oConnectTimeout:
442cf2b5f3bSDag-Erling Smørgrav 		intptr = &options->connection_timeout;
4431ec0d754SDag-Erling Smørgrav parse_time:
444cf2b5f3bSDag-Erling Smørgrav 		arg = strdelim(&s);
445cf2b5f3bSDag-Erling Smørgrav 		if (!arg || *arg == '\0')
446cf2b5f3bSDag-Erling Smørgrav 			fatal("%s line %d: missing time value.",
447cf2b5f3bSDag-Erling Smørgrav 			    filename, linenum);
448cf2b5f3bSDag-Erling Smørgrav 		if ((value = convtime(arg)) == -1)
449cf2b5f3bSDag-Erling Smørgrav 			fatal("%s line %d: invalid time value.",
450cf2b5f3bSDag-Erling Smørgrav 			    filename, linenum);
451d4af9e69SDag-Erling Smørgrav 		if (*activep && *intptr == -1)
452cf2b5f3bSDag-Erling Smørgrav 			*intptr = value;
453cf2b5f3bSDag-Erling Smørgrav 		break;
454cf2b5f3bSDag-Erling Smørgrav 
455511b41d2SMark Murray 	case oForwardAgent:
456511b41d2SMark Murray 		intptr = &options->forward_agent;
457511b41d2SMark Murray parse_flag:
458c2d3a559SKris Kennaway 		arg = strdelim(&s);
459c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
460511b41d2SMark Murray 			fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
461511b41d2SMark Murray 		value = 0;	/* To avoid compiler warning... */
462c2d3a559SKris Kennaway 		if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
463511b41d2SMark Murray 			value = 1;
464c2d3a559SKris Kennaway 		else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
465511b41d2SMark Murray 			value = 0;
466511b41d2SMark Murray 		else
467511b41d2SMark Murray 			fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
468511b41d2SMark Murray 		if (*activep && *intptr == -1)
469511b41d2SMark Murray 			*intptr = value;
470511b41d2SMark Murray 		break;
471511b41d2SMark Murray 
472511b41d2SMark Murray 	case oForwardX11:
473511b41d2SMark Murray 		intptr = &options->forward_x11;
474511b41d2SMark Murray 		goto parse_flag;
475511b41d2SMark Murray 
4761ec0d754SDag-Erling Smørgrav 	case oForwardX11Trusted:
4771ec0d754SDag-Erling Smørgrav 		intptr = &options->forward_x11_trusted;
4781ec0d754SDag-Erling Smørgrav 		goto parse_flag;
4791ec0d754SDag-Erling Smørgrav 
480e2f6069cSDag-Erling Smørgrav 	case oForwardX11Timeout:
481e2f6069cSDag-Erling Smørgrav 		intptr = &options->forward_x11_timeout;
482e2f6069cSDag-Erling Smørgrav 		goto parse_time;
483e2f6069cSDag-Erling Smørgrav 
484511b41d2SMark Murray 	case oGatewayPorts:
485511b41d2SMark Murray 		intptr = &options->gateway_ports;
486511b41d2SMark Murray 		goto parse_flag;
487511b41d2SMark Murray 
488333ee039SDag-Erling Smørgrav 	case oExitOnForwardFailure:
489333ee039SDag-Erling Smørgrav 		intptr = &options->exit_on_forward_failure;
490333ee039SDag-Erling Smørgrav 		goto parse_flag;
491333ee039SDag-Erling Smørgrav 
492511b41d2SMark Murray 	case oUsePrivilegedPort:
493511b41d2SMark Murray 		intptr = &options->use_privileged_port;
494511b41d2SMark Murray 		goto parse_flag;
495511b41d2SMark Murray 
496511b41d2SMark Murray 	case oPasswordAuthentication:
497511b41d2SMark Murray 		intptr = &options->password_authentication;
498511b41d2SMark Murray 		goto parse_flag;
499511b41d2SMark Murray 
500cce7d346SDag-Erling Smørgrav 	case oZeroKnowledgePasswordAuthentication:
501cce7d346SDag-Erling Smørgrav 		intptr = &options->zero_knowledge_password_authentication;
502cce7d346SDag-Erling Smørgrav 		goto parse_flag;
503cce7d346SDag-Erling Smørgrav 
50409958426SBrian Feldman 	case oKbdInteractiveAuthentication:
50509958426SBrian Feldman 		intptr = &options->kbd_interactive_authentication;
50609958426SBrian Feldman 		goto parse_flag;
50709958426SBrian Feldman 
50809958426SBrian Feldman 	case oKbdInteractiveDevices:
50909958426SBrian Feldman 		charptr = &options->kbd_interactive_devices;
51009958426SBrian Feldman 		goto parse_string;
51109958426SBrian Feldman 
512ca3176e7SBrian Feldman 	case oPubkeyAuthentication:
513ca3176e7SBrian Feldman 		intptr = &options->pubkey_authentication;
514e8aafc91SKris Kennaway 		goto parse_flag;
515e8aafc91SKris Kennaway 
516511b41d2SMark Murray 	case oRSAAuthentication:
517511b41d2SMark Murray 		intptr = &options->rsa_authentication;
518511b41d2SMark Murray 		goto parse_flag;
519511b41d2SMark Murray 
520511b41d2SMark Murray 	case oRhostsRSAAuthentication:
521511b41d2SMark Murray 		intptr = &options->rhosts_rsa_authentication;
522511b41d2SMark Murray 		goto parse_flag;
523511b41d2SMark Murray 
524ca3176e7SBrian Feldman 	case oHostbasedAuthentication:
525ca3176e7SBrian Feldman 		intptr = &options->hostbased_authentication;
526511b41d2SMark Murray 		goto parse_flag;
527511b41d2SMark Murray 
528af12a3e7SDag-Erling Smørgrav 	case oChallengeResponseAuthentication:
529af12a3e7SDag-Erling Smørgrav 		intptr = &options->challenge_response_authentication;
530af12a3e7SDag-Erling Smørgrav 		goto parse_flag;
531cf2b5f3bSDag-Erling Smørgrav 
532cf2b5f3bSDag-Erling Smørgrav 	case oGssAuthentication:
533cf2b5f3bSDag-Erling Smørgrav 		intptr = &options->gss_authentication;
534511b41d2SMark Murray 		goto parse_flag;
535cf2b5f3bSDag-Erling Smørgrav 
536cf2b5f3bSDag-Erling Smørgrav 	case oGssDelegateCreds:
537cf2b5f3bSDag-Erling Smørgrav 		intptr = &options->gss_deleg_creds;
538ca3176e7SBrian Feldman 		goto parse_flag;
539cf2b5f3bSDag-Erling Smørgrav 
540511b41d2SMark Murray 	case oBatchMode:
541511b41d2SMark Murray 		intptr = &options->batch_mode;
542511b41d2SMark Murray 		goto parse_flag;
543511b41d2SMark Murray 
544511b41d2SMark Murray 	case oCheckHostIP:
545511b41d2SMark Murray 		intptr = &options->check_host_ip;
546511b41d2SMark Murray 		goto parse_flag;
547511b41d2SMark Murray 
548cf2b5f3bSDag-Erling Smørgrav 	case oVerifyHostKeyDNS:
549cf2b5f3bSDag-Erling Smørgrav 		intptr = &options->verify_host_key_dns;
5501ec0d754SDag-Erling Smørgrav 		goto parse_yesnoask;
551cf2b5f3bSDag-Erling Smørgrav 
552511b41d2SMark Murray 	case oStrictHostKeyChecking:
553511b41d2SMark Murray 		intptr = &options->strict_host_key_checking;
5541ec0d754SDag-Erling Smørgrav parse_yesnoask:
555c2d3a559SKris Kennaway 		arg = strdelim(&s);
556c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
557ca3176e7SBrian Feldman 			fatal("%.200s line %d: Missing yes/no/ask argument.",
558511b41d2SMark Murray 			    filename, linenum);
559511b41d2SMark Murray 		value = 0;	/* To avoid compiler warning... */
560c2d3a559SKris Kennaway 		if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
561511b41d2SMark Murray 			value = 1;
562c2d3a559SKris Kennaway 		else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
563511b41d2SMark Murray 			value = 0;
564c2d3a559SKris Kennaway 		else if (strcmp(arg, "ask") == 0)
565511b41d2SMark Murray 			value = 2;
566511b41d2SMark Murray 		else
567511b41d2SMark Murray 			fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
568511b41d2SMark Murray 		if (*activep && *intptr == -1)
569511b41d2SMark Murray 			*intptr = value;
570511b41d2SMark Murray 		break;
571511b41d2SMark Murray 
572511b41d2SMark Murray 	case oCompression:
573511b41d2SMark Murray 		intptr = &options->compression;
574511b41d2SMark Murray 		goto parse_flag;
575511b41d2SMark Murray 
5761ec0d754SDag-Erling Smørgrav 	case oTCPKeepAlive:
5771ec0d754SDag-Erling Smørgrav 		intptr = &options->tcp_keep_alive;
578511b41d2SMark Murray 		goto parse_flag;
579511b41d2SMark Murray 
580af12a3e7SDag-Erling Smørgrav 	case oNoHostAuthenticationForLocalhost:
581af12a3e7SDag-Erling Smørgrav 		intptr = &options->no_host_authentication_for_localhost;
582af12a3e7SDag-Erling Smørgrav 		goto parse_flag;
583af12a3e7SDag-Erling Smørgrav 
584511b41d2SMark Murray 	case oNumberOfPasswordPrompts:
585511b41d2SMark Murray 		intptr = &options->number_of_password_prompts;
586511b41d2SMark Murray 		goto parse_int;
587511b41d2SMark Murray 
588511b41d2SMark Murray 	case oCompressionLevel:
589511b41d2SMark Murray 		intptr = &options->compression_level;
590511b41d2SMark Murray 		goto parse_int;
591511b41d2SMark Murray 
592cf2b5f3bSDag-Erling Smørgrav 	case oRekeyLimit:
593cf2b5f3bSDag-Erling Smørgrav 		arg = strdelim(&s);
594cf2b5f3bSDag-Erling Smørgrav 		if (!arg || *arg == '\0')
595cf2b5f3bSDag-Erling Smørgrav 			fatal("%.200s line %d: Missing argument.", filename, linenum);
596cf2b5f3bSDag-Erling Smørgrav 		if (arg[0] < '0' || arg[0] > '9')
597cf2b5f3bSDag-Erling Smørgrav 			fatal("%.200s line %d: Bad number.", filename, linenum);
598333ee039SDag-Erling Smørgrav 		orig = val64 = strtoll(arg, &endofnumber, 10);
599cf2b5f3bSDag-Erling Smørgrav 		if (arg == endofnumber)
600cf2b5f3bSDag-Erling Smørgrav 			fatal("%.200s line %d: Bad number.", filename, linenum);
601cf2b5f3bSDag-Erling Smørgrav 		switch (toupper(*endofnumber)) {
602333ee039SDag-Erling Smørgrav 		case '\0':
603333ee039SDag-Erling Smørgrav 			scale = 1;
604333ee039SDag-Erling Smørgrav 			break;
605cf2b5f3bSDag-Erling Smørgrav 		case 'K':
606333ee039SDag-Erling Smørgrav 			scale = 1<<10;
607cf2b5f3bSDag-Erling Smørgrav 			break;
608cf2b5f3bSDag-Erling Smørgrav 		case 'M':
609333ee039SDag-Erling Smørgrav 			scale = 1<<20;
610cf2b5f3bSDag-Erling Smørgrav 			break;
611cf2b5f3bSDag-Erling Smørgrav 		case 'G':
612333ee039SDag-Erling Smørgrav 			scale = 1<<30;
613cf2b5f3bSDag-Erling Smørgrav 			break;
614333ee039SDag-Erling Smørgrav 		default:
615333ee039SDag-Erling Smørgrav 			fatal("%.200s line %d: Invalid RekeyLimit suffix",
616333ee039SDag-Erling Smørgrav 			    filename, linenum);
617cf2b5f3bSDag-Erling Smørgrav 		}
618333ee039SDag-Erling Smørgrav 		val64 *= scale;
619333ee039SDag-Erling Smørgrav 		/* detect integer wrap and too-large limits */
620d4af9e69SDag-Erling Smørgrav 		if ((val64 / scale) != orig || val64 > UINT_MAX)
621333ee039SDag-Erling Smørgrav 			fatal("%.200s line %d: RekeyLimit too large",
622333ee039SDag-Erling Smørgrav 			    filename, linenum);
623333ee039SDag-Erling Smørgrav 		if (val64 < 16)
624333ee039SDag-Erling Smørgrav 			fatal("%.200s line %d: RekeyLimit too small",
625333ee039SDag-Erling Smørgrav 			    filename, linenum);
626d4af9e69SDag-Erling Smørgrav 		if (*activep && options->rekey_limit == -1)
627d4af9e69SDag-Erling Smørgrav 			options->rekey_limit = (u_int32_t)val64;
628cf2b5f3bSDag-Erling Smørgrav 		break;
629cf2b5f3bSDag-Erling Smørgrav 
630511b41d2SMark Murray 	case oIdentityFile:
631c2d3a559SKris Kennaway 		arg = strdelim(&s);
632c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
633511b41d2SMark Murray 			fatal("%.200s line %d: Missing argument.", filename, linenum);
634511b41d2SMark Murray 		if (*activep) {
635ca3176e7SBrian Feldman 			intptr = &options->num_identity_files;
636e8aafc91SKris Kennaway 			if (*intptr >= SSH_MAX_IDENTITY_FILES)
637511b41d2SMark Murray 				fatal("%.200s line %d: Too many identity files specified (max %d).",
638511b41d2SMark Murray 				    filename, linenum, SSH_MAX_IDENTITY_FILES);
639*fa67e83cSDag-Erling Smørgrav 			add_identity_file(options, NULL, arg, 1);
640511b41d2SMark Murray 		}
641511b41d2SMark Murray 		break;
642511b41d2SMark Murray 
643c2d3a559SKris Kennaway 	case oXAuthLocation:
644c2d3a559SKris Kennaway 		charptr=&options->xauth_location;
645c2d3a559SKris Kennaway 		goto parse_string;
646c2d3a559SKris Kennaway 
647511b41d2SMark Murray 	case oUser:
648511b41d2SMark Murray 		charptr = &options->user;
649511b41d2SMark Murray parse_string:
650c2d3a559SKris Kennaway 		arg = strdelim(&s);
651c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
652e146993eSDag-Erling Smørgrav 			fatal("%.200s line %d: Missing argument.",
653e146993eSDag-Erling Smørgrav 			    filename, linenum);
654511b41d2SMark Murray 		if (*activep && *charptr == NULL)
655c2d3a559SKris Kennaway 			*charptr = xstrdup(arg);
656511b41d2SMark Murray 		break;
657511b41d2SMark Murray 
658511b41d2SMark Murray 	case oGlobalKnownHostsFile:
659e146993eSDag-Erling Smørgrav 		cpptr = (char **)&options->system_hostfiles;
660e146993eSDag-Erling Smørgrav 		uintptr = &options->num_system_hostfiles;
661e146993eSDag-Erling Smørgrav 		max_entries = SSH_MAX_HOSTS_FILES;
662e146993eSDag-Erling Smørgrav parse_char_array:
663e146993eSDag-Erling Smørgrav 		if (*activep && *uintptr == 0) {
664e146993eSDag-Erling Smørgrav 			while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
665e146993eSDag-Erling Smørgrav 				if ((*uintptr) >= max_entries)
666e146993eSDag-Erling Smørgrav 					fatal("%s line %d: "
667e146993eSDag-Erling Smørgrav 					    "too many authorized keys files.",
668e146993eSDag-Erling Smørgrav 					    filename, linenum);
669e146993eSDag-Erling Smørgrav 				cpptr[(*uintptr)++] = xstrdup(arg);
670e146993eSDag-Erling Smørgrav 			}
671e146993eSDag-Erling Smørgrav 		}
672e146993eSDag-Erling Smørgrav 		return 0;
673511b41d2SMark Murray 
674511b41d2SMark Murray 	case oUserKnownHostsFile:
675e146993eSDag-Erling Smørgrav 		cpptr = (char **)&options->user_hostfiles;
676e146993eSDag-Erling Smørgrav 		uintptr = &options->num_user_hostfiles;
677e146993eSDag-Erling Smørgrav 		max_entries = SSH_MAX_HOSTS_FILES;
678e146993eSDag-Erling Smørgrav 		goto parse_char_array;
679e8aafc91SKris Kennaway 
680511b41d2SMark Murray 	case oHostName:
681511b41d2SMark Murray 		charptr = &options->hostname;
682511b41d2SMark Murray 		goto parse_string;
683511b41d2SMark Murray 
684ca3176e7SBrian Feldman 	case oHostKeyAlias:
685ca3176e7SBrian Feldman 		charptr = &options->host_key_alias;
686ca3176e7SBrian Feldman 		goto parse_string;
687ca3176e7SBrian Feldman 
688ca3176e7SBrian Feldman 	case oPreferredAuthentications:
689ca3176e7SBrian Feldman 		charptr = &options->preferred_authentications;
690ca3176e7SBrian Feldman 		goto parse_string;
691ca3176e7SBrian Feldman 
692af12a3e7SDag-Erling Smørgrav 	case oBindAddress:
693af12a3e7SDag-Erling Smørgrav 		charptr = &options->bind_address;
694af12a3e7SDag-Erling Smørgrav 		goto parse_string;
695af12a3e7SDag-Erling Smørgrav 
696b15c8340SDag-Erling Smørgrav 	case oPKCS11Provider:
697b15c8340SDag-Erling Smørgrav 		charptr = &options->pkcs11_provider;
698af12a3e7SDag-Erling Smørgrav 		goto parse_string;
699af12a3e7SDag-Erling Smørgrav 
700511b41d2SMark Murray 	case oProxyCommand:
701b74df5b2SDag-Erling Smørgrav 		charptr = &options->proxy_command;
702b74df5b2SDag-Erling Smørgrav parse_command:
703cf2b5f3bSDag-Erling Smørgrav 		if (s == NULL)
704cf2b5f3bSDag-Erling Smørgrav 			fatal("%.200s line %d: Missing argument.", filename, linenum);
705e73e9afaSDag-Erling Smørgrav 		len = strspn(s, WHITESPACE "=");
706511b41d2SMark Murray 		if (*activep && *charptr == NULL)
707e73e9afaSDag-Erling Smørgrav 			*charptr = xstrdup(s + len);
708511b41d2SMark Murray 		return 0;
709511b41d2SMark Murray 
710511b41d2SMark Murray 	case oPort:
711511b41d2SMark Murray 		intptr = &options->port;
712511b41d2SMark Murray parse_int:
713c2d3a559SKris Kennaway 		arg = strdelim(&s);
714c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
715511b41d2SMark Murray 			fatal("%.200s line %d: Missing argument.", filename, linenum);
716c2d3a559SKris Kennaway 		if (arg[0] < '0' || arg[0] > '9')
717511b41d2SMark Murray 			fatal("%.200s line %d: Bad number.", filename, linenum);
718511b41d2SMark Murray 
719511b41d2SMark Murray 		/* Octal, decimal, or hex format? */
720c2d3a559SKris Kennaway 		value = strtol(arg, &endofnumber, 0);
721c2d3a559SKris Kennaway 		if (arg == endofnumber)
722511b41d2SMark Murray 			fatal("%.200s line %d: Bad number.", filename, linenum);
723511b41d2SMark Murray 		if (*activep && *intptr == -1)
724511b41d2SMark Murray 			*intptr = value;
725511b41d2SMark Murray 		break;
726511b41d2SMark Murray 
727511b41d2SMark Murray 	case oConnectionAttempts:
728511b41d2SMark Murray 		intptr = &options->connection_attempts;
729511b41d2SMark Murray 		goto parse_int;
730511b41d2SMark Murray 
731511b41d2SMark Murray 	case oCipher:
732511b41d2SMark Murray 		intptr = &options->cipher;
733c2d3a559SKris Kennaway 		arg = strdelim(&s);
734c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
735db1cb46cSKris Kennaway 			fatal("%.200s line %d: Missing argument.", filename, linenum);
736c2d3a559SKris Kennaway 		value = cipher_number(arg);
737511b41d2SMark Murray 		if (value == -1)
738511b41d2SMark Murray 			fatal("%.200s line %d: Bad cipher '%s'.",
739c2d3a559SKris Kennaway 			    filename, linenum, arg ? arg : "<NONE>");
740511b41d2SMark Murray 		if (*activep && *intptr == -1)
741511b41d2SMark Murray 			*intptr = value;
742511b41d2SMark Murray 		break;
743511b41d2SMark Murray 
744e8aafc91SKris Kennaway 	case oCiphers:
745c2d3a559SKris Kennaway 		arg = strdelim(&s);
746c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
747db1cb46cSKris Kennaway 			fatal("%.200s line %d: Missing argument.", filename, linenum);
748c2d3a559SKris Kennaway 		if (!ciphers_valid(arg))
749e8aafc91SKris Kennaway 			fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
750c2d3a559SKris Kennaway 			    filename, linenum, arg ? arg : "<NONE>");
751e8aafc91SKris Kennaway 		if (*activep && options->ciphers == NULL)
752c2d3a559SKris Kennaway 			options->ciphers = xstrdup(arg);
753e8aafc91SKris Kennaway 		break;
754e8aafc91SKris Kennaway 
755ca3176e7SBrian Feldman 	case oMacs:
756ca3176e7SBrian Feldman 		arg = strdelim(&s);
757ca3176e7SBrian Feldman 		if (!arg || *arg == '\0')
758ca3176e7SBrian Feldman 			fatal("%.200s line %d: Missing argument.", filename, linenum);
759ca3176e7SBrian Feldman 		if (!mac_valid(arg))
760ca3176e7SBrian Feldman 			fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
761ca3176e7SBrian Feldman 			    filename, linenum, arg ? arg : "<NONE>");
762ca3176e7SBrian Feldman 		if (*activep && options->macs == NULL)
763ca3176e7SBrian Feldman 			options->macs = xstrdup(arg);
764ca3176e7SBrian Feldman 		break;
765ca3176e7SBrian Feldman 
7664a421b63SDag-Erling Smørgrav 	case oKexAlgorithms:
7674a421b63SDag-Erling Smørgrav 		arg = strdelim(&s);
7684a421b63SDag-Erling Smørgrav 		if (!arg || *arg == '\0')
7694a421b63SDag-Erling Smørgrav 			fatal("%.200s line %d: Missing argument.",
7704a421b63SDag-Erling Smørgrav 			    filename, linenum);
7714a421b63SDag-Erling Smørgrav 		if (!kex_names_valid(arg))
7724a421b63SDag-Erling Smørgrav 			fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
7734a421b63SDag-Erling Smørgrav 			    filename, linenum, arg ? arg : "<NONE>");
7744a421b63SDag-Erling Smørgrav 		if (*activep && options->kex_algorithms == NULL)
7754a421b63SDag-Erling Smørgrav 			options->kex_algorithms = xstrdup(arg);
7764a421b63SDag-Erling Smørgrav 		break;
7774a421b63SDag-Erling Smørgrav 
778ca3176e7SBrian Feldman 	case oHostKeyAlgorithms:
779ca3176e7SBrian Feldman 		arg = strdelim(&s);
780ca3176e7SBrian Feldman 		if (!arg || *arg == '\0')
781ca3176e7SBrian Feldman 			fatal("%.200s line %d: Missing argument.", filename, linenum);
782ca3176e7SBrian Feldman 		if (!key_names_valid2(arg))
783ca3176e7SBrian Feldman 			fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
784ca3176e7SBrian Feldman 			    filename, linenum, arg ? arg : "<NONE>");
785ca3176e7SBrian Feldman 		if (*activep && options->hostkeyalgorithms == NULL)
786ca3176e7SBrian Feldman 			options->hostkeyalgorithms = xstrdup(arg);
787ca3176e7SBrian Feldman 		break;
788ca3176e7SBrian Feldman 
789e8aafc91SKris Kennaway 	case oProtocol:
790e8aafc91SKris Kennaway 		intptr = &options->protocol;
791c2d3a559SKris Kennaway 		arg = strdelim(&s);
792c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
793db1cb46cSKris Kennaway 			fatal("%.200s line %d: Missing argument.", filename, linenum);
794c2d3a559SKris Kennaway 		value = proto_spec(arg);
795e8aafc91SKris Kennaway 		if (value == SSH_PROTO_UNKNOWN)
796e8aafc91SKris Kennaway 			fatal("%.200s line %d: Bad protocol spec '%s'.",
797c2d3a559SKris Kennaway 			    filename, linenum, arg ? arg : "<NONE>");
798e8aafc91SKris Kennaway 		if (*activep && *intptr == SSH_PROTO_UNKNOWN)
799e8aafc91SKris Kennaway 			*intptr = value;
800e8aafc91SKris Kennaway 		break;
801e8aafc91SKris Kennaway 
802511b41d2SMark Murray 	case oLogLevel:
803d4af9e69SDag-Erling Smørgrav 		log_level_ptr = &options->log_level;
804c2d3a559SKris Kennaway 		arg = strdelim(&s);
805c2d3a559SKris Kennaway 		value = log_level_number(arg);
806af12a3e7SDag-Erling Smørgrav 		if (value == SYSLOG_LEVEL_NOT_SET)
807ca3176e7SBrian Feldman 			fatal("%.200s line %d: unsupported log level '%s'",
808c2d3a559SKris Kennaway 			    filename, linenum, arg ? arg : "<NONE>");
809d4af9e69SDag-Erling Smørgrav 		if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
810d4af9e69SDag-Erling Smørgrav 			*log_level_ptr = (LogLevel) value;
811511b41d2SMark Murray 		break;
812511b41d2SMark Murray 
813af12a3e7SDag-Erling Smørgrav 	case oLocalForward:
814511b41d2SMark Murray 	case oRemoteForward:
815cce7d346SDag-Erling Smørgrav 	case oDynamicForward:
816c2d3a559SKris Kennaway 		arg = strdelim(&s);
817aa49c926SDag-Erling Smørgrav 		if (arg == NULL || *arg == '\0')
818af12a3e7SDag-Erling Smørgrav 			fatal("%.200s line %d: Missing port argument.",
819af12a3e7SDag-Erling Smørgrav 			    filename, linenum);
820cce7d346SDag-Erling Smørgrav 
821cce7d346SDag-Erling Smørgrav 		if (opcode == oLocalForward ||
822cce7d346SDag-Erling Smørgrav 		    opcode == oRemoteForward) {
823aa49c926SDag-Erling Smørgrav 			arg2 = strdelim(&s);
824aa49c926SDag-Erling Smørgrav 			if (arg2 == NULL || *arg2 == '\0')
825aa49c926SDag-Erling Smørgrav 				fatal("%.200s line %d: Missing target argument.",
826511b41d2SMark Murray 				    filename, linenum);
827aa49c926SDag-Erling Smørgrav 
828aa49c926SDag-Erling Smørgrav 			/* construct a string for parse_forward */
829aa49c926SDag-Erling Smørgrav 			snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
830cce7d346SDag-Erling Smørgrav 		} else if (opcode == oDynamicForward) {
831cce7d346SDag-Erling Smørgrav 			strlcpy(fwdarg, arg, sizeof(fwdarg));
832cce7d346SDag-Erling Smørgrav 		}
833aa49c926SDag-Erling Smørgrav 
834cce7d346SDag-Erling Smørgrav 		if (parse_forward(&fwd, fwdarg,
835cce7d346SDag-Erling Smørgrav 		    opcode == oDynamicForward ? 1 : 0,
836cce7d346SDag-Erling Smørgrav 		    opcode == oRemoteForward ? 1 : 0) == 0)
837af12a3e7SDag-Erling Smørgrav 			fatal("%.200s line %d: Bad forwarding specification.",
838511b41d2SMark Murray 			    filename, linenum);
839aa49c926SDag-Erling Smørgrav 
840af12a3e7SDag-Erling Smørgrav 		if (*activep) {
841cce7d346SDag-Erling Smørgrav 			if (opcode == oLocalForward ||
842cce7d346SDag-Erling Smørgrav 			    opcode == oDynamicForward)
843aa49c926SDag-Erling Smørgrav 				add_local_forward(options, &fwd);
844af12a3e7SDag-Erling Smørgrav 			else if (opcode == oRemoteForward)
845aa49c926SDag-Erling Smørgrav 				add_remote_forward(options, &fwd);
846af12a3e7SDag-Erling Smørgrav 		}
847511b41d2SMark Murray 		break;
848511b41d2SMark Murray 
849af12a3e7SDag-Erling Smørgrav 	case oClearAllForwardings:
850af12a3e7SDag-Erling Smørgrav 		intptr = &options->clear_forwardings;
851af12a3e7SDag-Erling Smørgrav 		goto parse_flag;
852af12a3e7SDag-Erling Smørgrav 
853511b41d2SMark Murray 	case oHost:
854511b41d2SMark Murray 		*activep = 0;
855e146993eSDag-Erling Smørgrav 		arg2 = NULL;
856e146993eSDag-Erling Smørgrav 		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
857e146993eSDag-Erling Smørgrav 			negated = *arg == '!';
858e146993eSDag-Erling Smørgrav 			if (negated)
859e146993eSDag-Erling Smørgrav 				arg++;
860c2d3a559SKris Kennaway 			if (match_pattern(host, arg)) {
861e146993eSDag-Erling Smørgrav 				if (negated) {
862e146993eSDag-Erling Smørgrav 					debug("%.200s line %d: Skipping Host "
863e146993eSDag-Erling Smørgrav 					    "block because of negated match "
864e146993eSDag-Erling Smørgrav 					    "for %.100s", filename, linenum,
865e146993eSDag-Erling Smørgrav 					    arg);
866e146993eSDag-Erling Smørgrav 					*activep = 0;
867511b41d2SMark Murray 					break;
868511b41d2SMark Murray 				}
869e146993eSDag-Erling Smørgrav 				if (!*activep)
870e146993eSDag-Erling Smørgrav 					arg2 = arg; /* logged below */
871e146993eSDag-Erling Smørgrav 				*activep = 1;
872e146993eSDag-Erling Smørgrav 			}
873e146993eSDag-Erling Smørgrav 		}
874e146993eSDag-Erling Smørgrav 		if (*activep)
875e146993eSDag-Erling Smørgrav 			debug("%.200s line %d: Applying options for %.100s",
876e146993eSDag-Erling Smørgrav 			    filename, linenum, arg2);
877c2d3a559SKris Kennaway 		/* Avoid garbage check below, as strdelim is done. */
878511b41d2SMark Murray 		return 0;
879511b41d2SMark Murray 
880511b41d2SMark Murray 	case oEscapeChar:
881511b41d2SMark Murray 		intptr = &options->escape_char;
882c2d3a559SKris Kennaway 		arg = strdelim(&s);
883c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
884511b41d2SMark Murray 			fatal("%.200s line %d: Missing argument.", filename, linenum);
885c2d3a559SKris Kennaway 		if (arg[0] == '^' && arg[2] == 0 &&
886ca3176e7SBrian Feldman 		    (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
887ca3176e7SBrian Feldman 			value = (u_char) arg[1] & 31;
888c2d3a559SKris Kennaway 		else if (strlen(arg) == 1)
889ca3176e7SBrian Feldman 			value = (u_char) arg[0];
890c2d3a559SKris Kennaway 		else if (strcmp(arg, "none") == 0)
891af12a3e7SDag-Erling Smørgrav 			value = SSH_ESCAPECHAR_NONE;
892511b41d2SMark Murray 		else {
893511b41d2SMark Murray 			fatal("%.200s line %d: Bad escape character.",
894511b41d2SMark Murray 			    filename, linenum);
895511b41d2SMark Murray 			/* NOTREACHED */
896511b41d2SMark Murray 			value = 0;	/* Avoid compiler warning. */
897511b41d2SMark Murray 		}
898511b41d2SMark Murray 		if (*activep && *intptr == -1)
899511b41d2SMark Murray 			*intptr = value;
900511b41d2SMark Murray 		break;
901511b41d2SMark Murray 
902cf2b5f3bSDag-Erling Smørgrav 	case oAddressFamily:
903cf2b5f3bSDag-Erling Smørgrav 		arg = strdelim(&s);
904d4ecd108SDag-Erling Smørgrav 		if (!arg || *arg == '\0')
905d4ecd108SDag-Erling Smørgrav 			fatal("%s line %d: missing address family.",
906d4ecd108SDag-Erling Smørgrav 			    filename, linenum);
907cf2b5f3bSDag-Erling Smørgrav 		intptr = &options->address_family;
908cf2b5f3bSDag-Erling Smørgrav 		if (strcasecmp(arg, "inet") == 0)
909cf2b5f3bSDag-Erling Smørgrav 			value = AF_INET;
910cf2b5f3bSDag-Erling Smørgrav 		else if (strcasecmp(arg, "inet6") == 0)
911cf2b5f3bSDag-Erling Smørgrav 			value = AF_INET6;
912cf2b5f3bSDag-Erling Smørgrav 		else if (strcasecmp(arg, "any") == 0)
913cf2b5f3bSDag-Erling Smørgrav 			value = AF_UNSPEC;
914cf2b5f3bSDag-Erling Smørgrav 		else
915cf2b5f3bSDag-Erling Smørgrav 			fatal("Unsupported AddressFamily \"%s\"", arg);
916cf2b5f3bSDag-Erling Smørgrav 		if (*activep && *intptr == -1)
917cf2b5f3bSDag-Erling Smørgrav 			*intptr = value;
918cf2b5f3bSDag-Erling Smørgrav 		break;
919cf2b5f3bSDag-Erling Smørgrav 
920e73e9afaSDag-Erling Smørgrav 	case oEnableSSHKeysign:
921e73e9afaSDag-Erling Smørgrav 		intptr = &options->enable_ssh_keysign;
922e73e9afaSDag-Erling Smørgrav 		goto parse_flag;
923e73e9afaSDag-Erling Smørgrav 
9245962c0e9SDag-Erling Smørgrav 	case oIdentitiesOnly:
9255962c0e9SDag-Erling Smørgrav 		intptr = &options->identities_only;
9265962c0e9SDag-Erling Smørgrav 		goto parse_flag;
9275962c0e9SDag-Erling Smørgrav 
9281ec0d754SDag-Erling Smørgrav 	case oServerAliveInterval:
9291ec0d754SDag-Erling Smørgrav 		intptr = &options->server_alive_interval;
9301ec0d754SDag-Erling Smørgrav 		goto parse_time;
9311ec0d754SDag-Erling Smørgrav 
9321ec0d754SDag-Erling Smørgrav 	case oServerAliveCountMax:
9331ec0d754SDag-Erling Smørgrav 		intptr = &options->server_alive_count_max;
9341ec0d754SDag-Erling Smørgrav 		goto parse_int;
9351ec0d754SDag-Erling Smørgrav 
93621e764dfSDag-Erling Smørgrav 	case oSendEnv:
93721e764dfSDag-Erling Smørgrav 		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
93821e764dfSDag-Erling Smørgrav 			if (strchr(arg, '=') != NULL)
93921e764dfSDag-Erling Smørgrav 				fatal("%s line %d: Invalid environment name.",
94021e764dfSDag-Erling Smørgrav 				    filename, linenum);
941aa49c926SDag-Erling Smørgrav 			if (!*activep)
942aa49c926SDag-Erling Smørgrav 				continue;
94321e764dfSDag-Erling Smørgrav 			if (options->num_send_env >= MAX_SEND_ENV)
94421e764dfSDag-Erling Smørgrav 				fatal("%s line %d: too many send env.",
94521e764dfSDag-Erling Smørgrav 				    filename, linenum);
94621e764dfSDag-Erling Smørgrav 			options->send_env[options->num_send_env++] =
94721e764dfSDag-Erling Smørgrav 			    xstrdup(arg);
94821e764dfSDag-Erling Smørgrav 		}
94921e764dfSDag-Erling Smørgrav 		break;
95021e764dfSDag-Erling Smørgrav 
95121e764dfSDag-Erling Smørgrav 	case oControlPath:
95221e764dfSDag-Erling Smørgrav 		charptr = &options->control_path;
95321e764dfSDag-Erling Smørgrav 		goto parse_string;
95421e764dfSDag-Erling Smørgrav 
95521e764dfSDag-Erling Smørgrav 	case oControlMaster:
95621e764dfSDag-Erling Smørgrav 		intptr = &options->control_master;
957d4ecd108SDag-Erling Smørgrav 		arg = strdelim(&s);
958d4ecd108SDag-Erling Smørgrav 		if (!arg || *arg == '\0')
959d4ecd108SDag-Erling Smørgrav 			fatal("%.200s line %d: Missing ControlMaster argument.",
960d4ecd108SDag-Erling Smørgrav 			    filename, linenum);
961d4ecd108SDag-Erling Smørgrav 		value = 0;	/* To avoid compiler warning... */
962d4ecd108SDag-Erling Smørgrav 		if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
963d4ecd108SDag-Erling Smørgrav 			value = SSHCTL_MASTER_YES;
964d4ecd108SDag-Erling Smørgrav 		else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
965d4ecd108SDag-Erling Smørgrav 			value = SSHCTL_MASTER_NO;
966d4ecd108SDag-Erling Smørgrav 		else if (strcmp(arg, "auto") == 0)
967d4ecd108SDag-Erling Smørgrav 			value = SSHCTL_MASTER_AUTO;
968d4ecd108SDag-Erling Smørgrav 		else if (strcmp(arg, "ask") == 0)
969d4ecd108SDag-Erling Smørgrav 			value = SSHCTL_MASTER_ASK;
970d4ecd108SDag-Erling Smørgrav 		else if (strcmp(arg, "autoask") == 0)
971d4ecd108SDag-Erling Smørgrav 			value = SSHCTL_MASTER_AUTO_ASK;
972d4ecd108SDag-Erling Smørgrav 		else
973d4ecd108SDag-Erling Smørgrav 			fatal("%.200s line %d: Bad ControlMaster argument.",
974d4ecd108SDag-Erling Smørgrav 			    filename, linenum);
975d4ecd108SDag-Erling Smørgrav 		if (*activep && *intptr == -1)
976d4ecd108SDag-Erling Smørgrav 			*intptr = value;
977d4ecd108SDag-Erling Smørgrav 		break;
97821e764dfSDag-Erling Smørgrav 
979e2f6069cSDag-Erling Smørgrav 	case oControlPersist:
980e2f6069cSDag-Erling Smørgrav 		/* no/false/yes/true, or a time spec */
981e2f6069cSDag-Erling Smørgrav 		intptr = &options->control_persist;
982e2f6069cSDag-Erling Smørgrav 		arg = strdelim(&s);
983e2f6069cSDag-Erling Smørgrav 		if (!arg || *arg == '\0')
984e2f6069cSDag-Erling Smørgrav 			fatal("%.200s line %d: Missing ControlPersist"
985e2f6069cSDag-Erling Smørgrav 			    " argument.", filename, linenum);
986e2f6069cSDag-Erling Smørgrav 		value = 0;
987e2f6069cSDag-Erling Smørgrav 		value2 = 0;	/* timeout */
988e2f6069cSDag-Erling Smørgrav 		if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
989e2f6069cSDag-Erling Smørgrav 			value = 0;
990e2f6069cSDag-Erling Smørgrav 		else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
991e2f6069cSDag-Erling Smørgrav 			value = 1;
992e2f6069cSDag-Erling Smørgrav 		else if ((value2 = convtime(arg)) >= 0)
993e2f6069cSDag-Erling Smørgrav 			value = 1;
994e2f6069cSDag-Erling Smørgrav 		else
995e2f6069cSDag-Erling Smørgrav 			fatal("%.200s line %d: Bad ControlPersist argument.",
996e2f6069cSDag-Erling Smørgrav 			    filename, linenum);
997e2f6069cSDag-Erling Smørgrav 		if (*activep && *intptr == -1) {
998e2f6069cSDag-Erling Smørgrav 			*intptr = value;
999e2f6069cSDag-Erling Smørgrav 			options->control_persist_timeout = value2;
1000e2f6069cSDag-Erling Smørgrav 		}
1001e2f6069cSDag-Erling Smørgrav 		break;
1002e2f6069cSDag-Erling Smørgrav 
1003aa49c926SDag-Erling Smørgrav 	case oHashKnownHosts:
1004aa49c926SDag-Erling Smørgrav 		intptr = &options->hash_known_hosts;
1005aa49c926SDag-Erling Smørgrav 		goto parse_flag;
1006aa49c926SDag-Erling Smørgrav 
1007b74df5b2SDag-Erling Smørgrav 	case oTunnel:
1008b74df5b2SDag-Erling Smørgrav 		intptr = &options->tun_open;
1009b74df5b2SDag-Erling Smørgrav 		arg = strdelim(&s);
1010b74df5b2SDag-Erling Smørgrav 		if (!arg || *arg == '\0')
1011b74df5b2SDag-Erling Smørgrav 			fatal("%s line %d: Missing yes/point-to-point/"
1012b74df5b2SDag-Erling Smørgrav 			    "ethernet/no argument.", filename, linenum);
1013b74df5b2SDag-Erling Smørgrav 		value = 0;	/* silence compiler */
1014b74df5b2SDag-Erling Smørgrav 		if (strcasecmp(arg, "ethernet") == 0)
1015b74df5b2SDag-Erling Smørgrav 			value = SSH_TUNMODE_ETHERNET;
1016b74df5b2SDag-Erling Smørgrav 		else if (strcasecmp(arg, "point-to-point") == 0)
1017b74df5b2SDag-Erling Smørgrav 			value = SSH_TUNMODE_POINTOPOINT;
1018b74df5b2SDag-Erling Smørgrav 		else if (strcasecmp(arg, "yes") == 0)
1019b74df5b2SDag-Erling Smørgrav 			value = SSH_TUNMODE_DEFAULT;
1020b74df5b2SDag-Erling Smørgrav 		else if (strcasecmp(arg, "no") == 0)
1021b74df5b2SDag-Erling Smørgrav 			value = SSH_TUNMODE_NO;
1022b74df5b2SDag-Erling Smørgrav 		else
1023b74df5b2SDag-Erling Smørgrav 			fatal("%s line %d: Bad yes/point-to-point/ethernet/"
1024b74df5b2SDag-Erling Smørgrav 			    "no argument: %s", filename, linenum, arg);
1025b74df5b2SDag-Erling Smørgrav 		if (*activep)
1026b74df5b2SDag-Erling Smørgrav 			*intptr = value;
1027b74df5b2SDag-Erling Smørgrav 		break;
1028b74df5b2SDag-Erling Smørgrav 
1029b74df5b2SDag-Erling Smørgrav 	case oTunnelDevice:
1030b74df5b2SDag-Erling Smørgrav 		arg = strdelim(&s);
1031b74df5b2SDag-Erling Smørgrav 		if (!arg || *arg == '\0')
1032b74df5b2SDag-Erling Smørgrav 			fatal("%.200s line %d: Missing argument.", filename, linenum);
1033b74df5b2SDag-Erling Smørgrav 		value = a2tun(arg, &value2);
1034b74df5b2SDag-Erling Smørgrav 		if (value == SSH_TUNID_ERR)
1035b74df5b2SDag-Erling Smørgrav 			fatal("%.200s line %d: Bad tun device.", filename, linenum);
1036b74df5b2SDag-Erling Smørgrav 		if (*activep) {
1037b74df5b2SDag-Erling Smørgrav 			options->tun_local = value;
1038b74df5b2SDag-Erling Smørgrav 			options->tun_remote = value2;
1039b74df5b2SDag-Erling Smørgrav 		}
1040b74df5b2SDag-Erling Smørgrav 		break;
1041b74df5b2SDag-Erling Smørgrav 
1042b74df5b2SDag-Erling Smørgrav 	case oLocalCommand:
1043b74df5b2SDag-Erling Smørgrav 		charptr = &options->local_command;
1044b74df5b2SDag-Erling Smørgrav 		goto parse_command;
1045b74df5b2SDag-Erling Smørgrav 
1046b74df5b2SDag-Erling Smørgrav 	case oPermitLocalCommand:
1047b74df5b2SDag-Erling Smørgrav 		intptr = &options->permit_local_command;
1048b74df5b2SDag-Erling Smørgrav 		goto parse_flag;
1049b74df5b2SDag-Erling Smørgrav 
1050d4af9e69SDag-Erling Smørgrav 	case oVisualHostKey:
1051d4af9e69SDag-Erling Smørgrav 		intptr = &options->visual_host_key;
1052d4af9e69SDag-Erling Smørgrav 		goto parse_flag;
1053d4af9e69SDag-Erling Smørgrav 
10544a421b63SDag-Erling Smørgrav 	case oIPQoS:
10554a421b63SDag-Erling Smørgrav 		arg = strdelim(&s);
10564a421b63SDag-Erling Smørgrav 		if ((value = parse_ipqos(arg)) == -1)
10574a421b63SDag-Erling Smørgrav 			fatal("%s line %d: Bad IPQoS value: %s",
10584a421b63SDag-Erling Smørgrav 			    filename, linenum, arg);
10594a421b63SDag-Erling Smørgrav 		arg = strdelim(&s);
10604a421b63SDag-Erling Smørgrav 		if (arg == NULL)
10614a421b63SDag-Erling Smørgrav 			value2 = value;
10624a421b63SDag-Erling Smørgrav 		else if ((value2 = 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 		if (*activep) {
10664a421b63SDag-Erling Smørgrav 			options->ip_qos_interactive = value;
10674a421b63SDag-Erling Smørgrav 			options->ip_qos_bulk = value2;
10684a421b63SDag-Erling Smørgrav 		}
10694a421b63SDag-Erling Smørgrav 		break;
10704a421b63SDag-Erling Smørgrav 
10717aee6ffeSDag-Erling Smørgrav 	case oUseRoaming:
10727aee6ffeSDag-Erling Smørgrav 		intptr = &options->use_roaming;
10737aee6ffeSDag-Erling Smørgrav 		goto parse_flag;
10747aee6ffeSDag-Erling Smørgrav 
1075e146993eSDag-Erling Smørgrav 	case oRequestTTY:
1076975616f0SDag-Erling Smørgrav 		arg = strdelim(&s);
1077e146993eSDag-Erling Smørgrav 		if (!arg || *arg == '\0')
1078e146993eSDag-Erling Smørgrav 			fatal("%s line %d: missing argument.",
1079e146993eSDag-Erling Smørgrav 			    filename, linenum);
1080e146993eSDag-Erling Smørgrav 		intptr = &options->request_tty;
1081e146993eSDag-Erling Smørgrav 		if (strcasecmp(arg, "yes") == 0)
1082e146993eSDag-Erling Smørgrav 			value = REQUEST_TTY_YES;
1083e146993eSDag-Erling Smørgrav 		else if (strcasecmp(arg, "no") == 0)
1084e146993eSDag-Erling Smørgrav 			value = REQUEST_TTY_NO;
1085e146993eSDag-Erling Smørgrav 		else if (strcasecmp(arg, "force") == 0)
1086e146993eSDag-Erling Smørgrav 			value = REQUEST_TTY_FORCE;
1087e146993eSDag-Erling Smørgrav 		else if (strcasecmp(arg, "auto") == 0)
1088e146993eSDag-Erling Smørgrav 			value = REQUEST_TTY_AUTO;
1089e146993eSDag-Erling Smørgrav 		else
1090e146993eSDag-Erling Smørgrav 			fatal("Unsupported RequestTTY \"%s\"", arg);
1091e146993eSDag-Erling Smørgrav 		if (*activep && *intptr == -1)
1092e146993eSDag-Erling Smørgrav 			*intptr = value;
1093975616f0SDag-Erling Smørgrav 		break;
1094975616f0SDag-Erling Smørgrav 
109589986192SBrooks Davis 	case oHPNDisabled:
109689986192SBrooks Davis 		intptr = &options->hpn_disabled;
109789986192SBrooks Davis 		goto parse_flag;
109889986192SBrooks Davis 
109989986192SBrooks Davis 	case oHPNBufferSize:
110089986192SBrooks Davis 		intptr = &options->hpn_buffer_size;
110189986192SBrooks Davis 		goto parse_int;
110289986192SBrooks Davis 
110389986192SBrooks Davis 	case oTcpRcvBufPoll:
110489986192SBrooks Davis 		intptr = &options->tcp_rcv_buf_poll;
110589986192SBrooks Davis 		goto parse_flag;
110689986192SBrooks Davis 
110789986192SBrooks Davis 	case oTcpRcvBuf:
110889986192SBrooks Davis 		intptr = &options->tcp_rcv_buf;
110989986192SBrooks Davis 		goto parse_int;
111089986192SBrooks Davis 
111189986192SBrooks Davis #ifdef	NONE_CIPHER_ENABLED
111289986192SBrooks Davis 	case oNoneEnabled:
111389986192SBrooks Davis 		intptr = &options->none_enabled;
111489986192SBrooks Davis 		goto parse_flag;
111589986192SBrooks Davis 
111689986192SBrooks Davis 	/*
111789986192SBrooks Davis 	 * We check to see if the command comes from the command line or not.
111889986192SBrooks Davis 	 * If it does then enable it otherwise fail.  NONE must never be a
111989986192SBrooks Davis 	 * default configuration.
112089986192SBrooks Davis 	 */
112189986192SBrooks Davis 	case oNoneSwitch:
112289986192SBrooks Davis 		if (strcmp(filename,"command-line") == 0) {
112389986192SBrooks Davis 			intptr = &options->none_switch;
112489986192SBrooks Davis 			goto parse_flag;
112589986192SBrooks Davis 		} else {
112689986192SBrooks Davis 			debug("NoneSwitch directive found in %.200s.",
112789986192SBrooks Davis 			    filename);
112889986192SBrooks Davis 			error("NoneSwitch is found in %.200s.\n"
112989986192SBrooks Davis 			    "You may only use this configuration option "
113089986192SBrooks Davis 			    "from the command line", filename);
113189986192SBrooks Davis 			error("Continuing...");
113289986192SBrooks Davis 			return 0;
113389986192SBrooks Davis 		}
113489986192SBrooks Davis #endif
113589986192SBrooks Davis 
1136e146993eSDag-Erling Smørgrav 	case oVersionAddendum:
1137462c32cbSDag-Erling Smørgrav 		if (s == NULL)
1138462c32cbSDag-Erling Smørgrav 			fatal("%.200s line %d: Missing argument.", filename,
1139462c32cbSDag-Erling Smørgrav 			    linenum);
1140462c32cbSDag-Erling Smørgrav 		len = strspn(s, WHITESPACE);
1141462c32cbSDag-Erling Smørgrav 		if (*activep && options->version_addendum == NULL) {
1142462c32cbSDag-Erling Smørgrav 			if (strcasecmp(s + len, "none") == 0)
1143462c32cbSDag-Erling Smørgrav 				options->version_addendum = xstrdup("");
1144462c32cbSDag-Erling Smørgrav 			else if (strchr(s + len, '\r') != NULL)
1145462c32cbSDag-Erling Smørgrav 				fatal("%.200s line %d: Invalid argument",
1146462c32cbSDag-Erling Smørgrav 				    filename, linenum);
1147462c32cbSDag-Erling Smørgrav 			else
1148462c32cbSDag-Erling Smørgrav 				options->version_addendum = xstrdup(s + len);
1149462c32cbSDag-Erling Smørgrav 		}
1150462c32cbSDag-Erling Smørgrav 		return 0;
1151e146993eSDag-Erling Smørgrav 
115280628bacSDag-Erling Smørgrav 	case oDeprecated:
115380628bacSDag-Erling Smørgrav 		debug("%s line %d: Deprecated option \"%s\"",
115480628bacSDag-Erling Smørgrav 		    filename, linenum, keyword);
115580628bacSDag-Erling Smørgrav 		return 0;
115680628bacSDag-Erling Smørgrav 
1157cf2b5f3bSDag-Erling Smørgrav 	case oUnsupported:
1158cf2b5f3bSDag-Erling Smørgrav 		error("%s line %d: Unsupported option \"%s\"",
1159cf2b5f3bSDag-Erling Smørgrav 		    filename, linenum, keyword);
1160cf2b5f3bSDag-Erling Smørgrav 		return 0;
1161cf2b5f3bSDag-Erling Smørgrav 
1162511b41d2SMark Murray 	default:
1163511b41d2SMark Murray 		fatal("process_config_line: Unimplemented opcode %d", opcode);
1164511b41d2SMark Murray 	}
1165511b41d2SMark Murray 
1166511b41d2SMark Murray 	/* Check that there is no garbage at end of line. */
1167ca3176e7SBrian Feldman 	if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1168c2d3a559SKris Kennaway 		fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
1169c2d3a559SKris Kennaway 		    filename, linenum, arg);
1170c2d3a559SKris Kennaway 	}
1171511b41d2SMark Murray 	return 0;
1172511b41d2SMark Murray }
1173511b41d2SMark Murray 
1174511b41d2SMark Murray 
1175511b41d2SMark Murray /*
1176511b41d2SMark Murray  * Reads the config file and modifies the options accordingly.  Options
1177511b41d2SMark Murray  * should already be initialized before this call.  This never returns if
1178af12a3e7SDag-Erling Smørgrav  * there is an error.  If the file does not exist, this returns 0.
1179511b41d2SMark Murray  */
1180511b41d2SMark Murray 
1181af12a3e7SDag-Erling Smørgrav int
118221e764dfSDag-Erling Smørgrav read_config_file(const char *filename, const char *host, Options *options,
118321e764dfSDag-Erling Smørgrav     int checkperm)
1184511b41d2SMark Murray {
1185511b41d2SMark Murray 	FILE *f;
1186511b41d2SMark Murray 	char line[1024];
1187511b41d2SMark Murray 	int active, linenum;
1188511b41d2SMark Murray 	int bad_options = 0;
1189511b41d2SMark Murray 
119021e764dfSDag-Erling Smørgrav 	if ((f = fopen(filename, "r")) == NULL)
1191af12a3e7SDag-Erling Smørgrav 		return 0;
1192511b41d2SMark Murray 
119321e764dfSDag-Erling Smørgrav 	if (checkperm) {
119421e764dfSDag-Erling Smørgrav 		struct stat sb;
119521e764dfSDag-Erling Smørgrav 
119621e764dfSDag-Erling Smørgrav 		if (fstat(fileno(f), &sb) == -1)
119721e764dfSDag-Erling Smørgrav 			fatal("fstat %s: %s", filename, strerror(errno));
119821e764dfSDag-Erling Smørgrav 		if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
119921e764dfSDag-Erling Smørgrav 		    (sb.st_mode & 022) != 0))
120021e764dfSDag-Erling Smørgrav 			fatal("Bad owner or permissions on %s", filename);
120121e764dfSDag-Erling Smørgrav 	}
120221e764dfSDag-Erling Smørgrav 
1203511b41d2SMark Murray 	debug("Reading configuration data %.200s", filename);
1204511b41d2SMark Murray 
1205511b41d2SMark Murray 	/*
1206511b41d2SMark Murray 	 * Mark that we are now processing the options.  This flag is turned
1207511b41d2SMark Murray 	 * on/off by Host specifications.
1208511b41d2SMark Murray 	 */
1209511b41d2SMark Murray 	active = 1;
1210511b41d2SMark Murray 	linenum = 0;
1211511b41d2SMark Murray 	while (fgets(line, sizeof(line), f)) {
1212511b41d2SMark Murray 		/* Update line number counter. */
1213511b41d2SMark Murray 		linenum++;
1214511b41d2SMark Murray 		if (process_config_line(options, host, line, filename, linenum, &active) != 0)
1215511b41d2SMark Murray 			bad_options++;
1216511b41d2SMark Murray 	}
1217511b41d2SMark Murray 	fclose(f);
1218511b41d2SMark Murray 	if (bad_options > 0)
1219ca3176e7SBrian Feldman 		fatal("%s: terminating, %d bad configuration options",
1220511b41d2SMark Murray 		    filename, bad_options);
1221af12a3e7SDag-Erling Smørgrav 	return 1;
1222511b41d2SMark Murray }
1223511b41d2SMark Murray 
1224511b41d2SMark Murray /*
1225511b41d2SMark Murray  * Initializes options to special values that indicate that they have not yet
1226511b41d2SMark Murray  * been set.  Read_config_file will only set options with this value. Options
1227511b41d2SMark Murray  * are processed in the following order: command line, user config file,
1228511b41d2SMark Murray  * system config file.  Last, fill_default_options is called.
1229511b41d2SMark Murray  */
1230511b41d2SMark Murray 
1231511b41d2SMark Murray void
1232511b41d2SMark Murray initialize_options(Options * options)
1233511b41d2SMark Murray {
1234511b41d2SMark Murray 	memset(options, 'X', sizeof(*options));
1235511b41d2SMark Murray 	options->forward_agent = -1;
1236511b41d2SMark Murray 	options->forward_x11 = -1;
12371ec0d754SDag-Erling Smørgrav 	options->forward_x11_trusted = -1;
1238e2f6069cSDag-Erling Smørgrav 	options->forward_x11_timeout = -1;
1239333ee039SDag-Erling Smørgrav 	options->exit_on_forward_failure = -1;
1240c2d3a559SKris Kennaway 	options->xauth_location = NULL;
1241511b41d2SMark Murray 	options->gateway_ports = -1;
1242511b41d2SMark Murray 	options->use_privileged_port = -1;
1243511b41d2SMark Murray 	options->rsa_authentication = -1;
1244ca3176e7SBrian Feldman 	options->pubkey_authentication = -1;
1245af12a3e7SDag-Erling Smørgrav 	options->challenge_response_authentication = -1;
1246cf2b5f3bSDag-Erling Smørgrav 	options->gss_authentication = -1;
1247cf2b5f3bSDag-Erling Smørgrav 	options->gss_deleg_creds = -1;
1248511b41d2SMark Murray 	options->password_authentication = -1;
124909958426SBrian Feldman 	options->kbd_interactive_authentication = -1;
125009958426SBrian Feldman 	options->kbd_interactive_devices = NULL;
1251511b41d2SMark Murray 	options->rhosts_rsa_authentication = -1;
1252ca3176e7SBrian Feldman 	options->hostbased_authentication = -1;
1253511b41d2SMark Murray 	options->batch_mode = -1;
1254511b41d2SMark Murray 	options->check_host_ip = -1;
1255511b41d2SMark Murray 	options->strict_host_key_checking = -1;
1256511b41d2SMark Murray 	options->compression = -1;
12571ec0d754SDag-Erling Smørgrav 	options->tcp_keep_alive = -1;
1258511b41d2SMark Murray 	options->compression_level = -1;
1259511b41d2SMark Murray 	options->port = -1;
1260cf2b5f3bSDag-Erling Smørgrav 	options->address_family = -1;
1261511b41d2SMark Murray 	options->connection_attempts = -1;
1262cf2b5f3bSDag-Erling Smørgrav 	options->connection_timeout = -1;
1263511b41d2SMark Murray 	options->number_of_password_prompts = -1;
1264511b41d2SMark Murray 	options->cipher = -1;
1265e8aafc91SKris Kennaway 	options->ciphers = NULL;
1266ca3176e7SBrian Feldman 	options->macs = NULL;
12674a421b63SDag-Erling Smørgrav 	options->kex_algorithms = NULL;
1268ca3176e7SBrian Feldman 	options->hostkeyalgorithms = NULL;
1269e8aafc91SKris Kennaway 	options->protocol = SSH_PROTO_UNKNOWN;
1270511b41d2SMark Murray 	options->num_identity_files = 0;
1271511b41d2SMark Murray 	options->hostname = NULL;
1272ca3176e7SBrian Feldman 	options->host_key_alias = NULL;
1273511b41d2SMark Murray 	options->proxy_command = NULL;
1274511b41d2SMark Murray 	options->user = NULL;
1275511b41d2SMark Murray 	options->escape_char = -1;
1276e146993eSDag-Erling Smørgrav 	options->num_system_hostfiles = 0;
1277e146993eSDag-Erling Smørgrav 	options->num_user_hostfiles = 0;
1278e2f6069cSDag-Erling Smørgrav 	options->local_forwards = NULL;
1279511b41d2SMark Murray 	options->num_local_forwards = 0;
1280e2f6069cSDag-Erling Smørgrav 	options->remote_forwards = NULL;
1281511b41d2SMark Murray 	options->num_remote_forwards = 0;
1282af12a3e7SDag-Erling Smørgrav 	options->clear_forwardings = -1;
1283af12a3e7SDag-Erling Smørgrav 	options->log_level = SYSLOG_LEVEL_NOT_SET;
1284ca3176e7SBrian Feldman 	options->preferred_authentications = NULL;
1285af12a3e7SDag-Erling Smørgrav 	options->bind_address = NULL;
1286b15c8340SDag-Erling Smørgrav 	options->pkcs11_provider = NULL;
1287e73e9afaSDag-Erling Smørgrav 	options->enable_ssh_keysign = - 1;
1288af12a3e7SDag-Erling Smørgrav 	options->no_host_authentication_for_localhost = - 1;
12895962c0e9SDag-Erling Smørgrav 	options->identities_only = - 1;
1290cf2b5f3bSDag-Erling Smørgrav 	options->rekey_limit = - 1;
1291cf2b5f3bSDag-Erling Smørgrav 	options->verify_host_key_dns = -1;
12921ec0d754SDag-Erling Smørgrav 	options->server_alive_interval = -1;
12931ec0d754SDag-Erling Smørgrav 	options->server_alive_count_max = -1;
129421e764dfSDag-Erling Smørgrav 	options->num_send_env = 0;
129521e764dfSDag-Erling Smørgrav 	options->control_path = NULL;
129621e764dfSDag-Erling Smørgrav 	options->control_master = -1;
1297e2f6069cSDag-Erling Smørgrav 	options->control_persist = -1;
1298e2f6069cSDag-Erling Smørgrav 	options->control_persist_timeout = 0;
1299aa49c926SDag-Erling Smørgrav 	options->hash_known_hosts = -1;
1300b74df5b2SDag-Erling Smørgrav 	options->tun_open = -1;
1301b74df5b2SDag-Erling Smørgrav 	options->tun_local = -1;
1302b74df5b2SDag-Erling Smørgrav 	options->tun_remote = -1;
1303b74df5b2SDag-Erling Smørgrav 	options->local_command = NULL;
1304b74df5b2SDag-Erling Smørgrav 	options->permit_local_command = -1;
13057aee6ffeSDag-Erling Smørgrav 	options->use_roaming = -1;
1306d4af9e69SDag-Erling Smørgrav 	options->visual_host_key = -1;
1307cce7d346SDag-Erling Smørgrav 	options->zero_knowledge_password_authentication = -1;
13084a421b63SDag-Erling Smørgrav 	options->ip_qos_interactive = -1;
13094a421b63SDag-Erling Smørgrav 	options->ip_qos_bulk = -1;
1310e146993eSDag-Erling Smørgrav 	options->request_tty = -1;
1311462c32cbSDag-Erling Smørgrav 	options->version_addendum = NULL;
131289986192SBrooks Davis 	options->hpn_disabled = -1;
131389986192SBrooks Davis 	options->hpn_buffer_size = -1;
131489986192SBrooks Davis 	options->tcp_rcv_buf_poll = -1;
131589986192SBrooks Davis 	options->tcp_rcv_buf = -1;
131689986192SBrooks Davis #ifdef NONE_CIPHER_ENABLED
131789986192SBrooks Davis 	options->none_enabled = -1;
131889986192SBrooks Davis 	options->none_switch = -1;
131989986192SBrooks Davis #endif
1320511b41d2SMark Murray }
1321511b41d2SMark Murray 
1322511b41d2SMark Murray /*
1323511b41d2SMark Murray  * Called after processing other sources of option data, this fills those
1324511b41d2SMark Murray  * options for which no value has been specified with their default values.
1325511b41d2SMark Murray  */
1326511b41d2SMark Murray 
1327511b41d2SMark Murray void
1328511b41d2SMark Murray fill_default_options(Options * options)
1329511b41d2SMark Murray {
1330ca3176e7SBrian Feldman 	int len;
1331ca3176e7SBrian Feldman 
1332511b41d2SMark Murray 	if (options->forward_agent == -1)
1333db1cb46cSKris Kennaway 		options->forward_agent = 0;
1334511b41d2SMark Murray 	if (options->forward_x11 == -1)
13355dc73ebeSBrian Feldman 		options->forward_x11 = 0;
13361ec0d754SDag-Erling Smørgrav 	if (options->forward_x11_trusted == -1)
13371ec0d754SDag-Erling Smørgrav 		options->forward_x11_trusted = 0;
1338e2f6069cSDag-Erling Smørgrav 	if (options->forward_x11_timeout == -1)
1339e2f6069cSDag-Erling Smørgrav 		options->forward_x11_timeout = 1200;
1340333ee039SDag-Erling Smørgrav 	if (options->exit_on_forward_failure == -1)
1341333ee039SDag-Erling Smørgrav 		options->exit_on_forward_failure = 0;
1342c2d3a559SKris Kennaway 	if (options->xauth_location == NULL)
1343af12a3e7SDag-Erling Smørgrav 		options->xauth_location = _PATH_XAUTH;
1344511b41d2SMark Murray 	if (options->gateway_ports == -1)
1345511b41d2SMark Murray 		options->gateway_ports = 0;
1346511b41d2SMark Murray 	if (options->use_privileged_port == -1)
1347ca3176e7SBrian Feldman 		options->use_privileged_port = 0;
1348511b41d2SMark Murray 	if (options->rsa_authentication == -1)
1349511b41d2SMark Murray 		options->rsa_authentication = 1;
1350ca3176e7SBrian Feldman 	if (options->pubkey_authentication == -1)
1351ca3176e7SBrian Feldman 		options->pubkey_authentication = 1;
1352af12a3e7SDag-Erling Smørgrav 	if (options->challenge_response_authentication == -1)
1353af12a3e7SDag-Erling Smørgrav 		options->challenge_response_authentication = 1;
1354cf2b5f3bSDag-Erling Smørgrav 	if (options->gss_authentication == -1)
13551ec0d754SDag-Erling Smørgrav 		options->gss_authentication = 0;
1356cf2b5f3bSDag-Erling Smørgrav 	if (options->gss_deleg_creds == -1)
1357cf2b5f3bSDag-Erling Smørgrav 		options->gss_deleg_creds = 0;
1358511b41d2SMark Murray 	if (options->password_authentication == -1)
1359511b41d2SMark Murray 		options->password_authentication = 1;
136009958426SBrian Feldman 	if (options->kbd_interactive_authentication == -1)
1361ca3176e7SBrian Feldman 		options->kbd_interactive_authentication = 1;
1362511b41d2SMark Murray 	if (options->rhosts_rsa_authentication == -1)
136380628bacSDag-Erling Smørgrav 		options->rhosts_rsa_authentication = 0;
1364ca3176e7SBrian Feldman 	if (options->hostbased_authentication == -1)
1365ca3176e7SBrian Feldman 		options->hostbased_authentication = 0;
1366511b41d2SMark Murray 	if (options->batch_mode == -1)
1367511b41d2SMark Murray 		options->batch_mode = 0;
1368511b41d2SMark Murray 	if (options->check_host_ip == -1)
1369975616f0SDag-Erling Smørgrav 		options->check_host_ip = 0;
1370511b41d2SMark Murray 	if (options->strict_host_key_checking == -1)
1371511b41d2SMark Murray 		options->strict_host_key_checking = 2;	/* 2 is default */
1372511b41d2SMark Murray 	if (options->compression == -1)
1373511b41d2SMark Murray 		options->compression = 0;
13741ec0d754SDag-Erling Smørgrav 	if (options->tcp_keep_alive == -1)
13751ec0d754SDag-Erling Smørgrav 		options->tcp_keep_alive = 1;
1376511b41d2SMark Murray 	if (options->compression_level == -1)
1377511b41d2SMark Murray 		options->compression_level = 6;
1378511b41d2SMark Murray 	if (options->port == -1)
1379511b41d2SMark Murray 		options->port = 0;	/* Filled in ssh_connect. */
1380cf2b5f3bSDag-Erling Smørgrav 	if (options->address_family == -1)
1381cf2b5f3bSDag-Erling Smørgrav 		options->address_family = AF_UNSPEC;
1382511b41d2SMark Murray 	if (options->connection_attempts == -1)
1383af12a3e7SDag-Erling Smørgrav 		options->connection_attempts = 1;
1384511b41d2SMark Murray 	if (options->number_of_password_prompts == -1)
1385511b41d2SMark Murray 		options->number_of_password_prompts = 3;
1386511b41d2SMark Murray 	/* Selected in ssh_login(). */
1387511b41d2SMark Murray 	if (options->cipher == -1)
1388511b41d2SMark Murray 		options->cipher = SSH_CIPHER_NOT_SET;
1389e8aafc91SKris Kennaway 	/* options->ciphers, default set in myproposals.h */
1390ca3176e7SBrian Feldman 	/* options->macs, default set in myproposals.h */
13914a421b63SDag-Erling Smørgrav 	/* options->kex_algorithms, default set in myproposals.h */
1392ca3176e7SBrian Feldman 	/* options->hostkeyalgorithms, default set in myproposals.h */
1393e8aafc91SKris Kennaway 	if (options->protocol == SSH_PROTO_UNKNOWN)
1394b15c8340SDag-Erling Smørgrav 		options->protocol = SSH_PROTO_2;
1395511b41d2SMark Murray 	if (options->num_identity_files == 0) {
1396ca3176e7SBrian Feldman 		if (options->protocol & SSH_PROTO_1) {
1397ca3176e7SBrian Feldman 			len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1;
1398ca3176e7SBrian Feldman 			options->identity_files[options->num_identity_files] =
1399ca3176e7SBrian Feldman 			    xmalloc(len);
1400ca3176e7SBrian Feldman 			snprintf(options->identity_files[options->num_identity_files++],
1401ca3176e7SBrian Feldman 			    len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY);
1402511b41d2SMark Murray 		}
1403ca3176e7SBrian Feldman 		if (options->protocol & SSH_PROTO_2) {
1404ca3176e7SBrian Feldman 			len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1;
1405ca3176e7SBrian Feldman 			options->identity_files[options->num_identity_files] =
1406ca3176e7SBrian Feldman 			    xmalloc(len);
1407ca3176e7SBrian Feldman 			snprintf(options->identity_files[options->num_identity_files++],
1408ca3176e7SBrian Feldman 			    len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA);
1409ca3176e7SBrian Feldman 
1410ca3176e7SBrian Feldman 			len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1;
1411ca3176e7SBrian Feldman 			options->identity_files[options->num_identity_files] =
1412ca3176e7SBrian Feldman 			    xmalloc(len);
1413ca3176e7SBrian Feldman 			snprintf(options->identity_files[options->num_identity_files++],
1414ca3176e7SBrian Feldman 			    len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA);
14154a421b63SDag-Erling Smørgrav #ifdef OPENSSL_HAS_ECC
14164a421b63SDag-Erling Smørgrav 			len = 2 + strlen(_PATH_SSH_CLIENT_ID_ECDSA) + 1;
14174a421b63SDag-Erling Smørgrav 			options->identity_files[options->num_identity_files] =
14184a421b63SDag-Erling Smørgrav 			    xmalloc(len);
14194a421b63SDag-Erling Smørgrav 			snprintf(options->identity_files[options->num_identity_files++],
14204a421b63SDag-Erling Smørgrav 			    len, "~/%.100s", _PATH_SSH_CLIENT_ID_ECDSA);
14214a421b63SDag-Erling Smørgrav #endif
1422ca3176e7SBrian Feldman 		}
1423e8aafc91SKris Kennaway 	}
1424511b41d2SMark Murray 	if (options->escape_char == -1)
1425511b41d2SMark Murray 		options->escape_char = '~';
1426e146993eSDag-Erling Smørgrav 	if (options->num_system_hostfiles == 0) {
1427e146993eSDag-Erling Smørgrav 		options->system_hostfiles[options->num_system_hostfiles++] =
1428e146993eSDag-Erling Smørgrav 		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
1429e146993eSDag-Erling Smørgrav 		options->system_hostfiles[options->num_system_hostfiles++] =
1430e146993eSDag-Erling Smørgrav 		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
1431e146993eSDag-Erling Smørgrav 	}
1432e146993eSDag-Erling Smørgrav 	if (options->num_user_hostfiles == 0) {
1433e146993eSDag-Erling Smørgrav 		options->user_hostfiles[options->num_user_hostfiles++] =
1434e146993eSDag-Erling Smørgrav 		    xstrdup(_PATH_SSH_USER_HOSTFILE);
1435e146993eSDag-Erling Smørgrav 		options->user_hostfiles[options->num_user_hostfiles++] =
1436e146993eSDag-Erling Smørgrav 		    xstrdup(_PATH_SSH_USER_HOSTFILE2);
1437e146993eSDag-Erling Smørgrav 	}
1438af12a3e7SDag-Erling Smørgrav 	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
1439511b41d2SMark Murray 		options->log_level = SYSLOG_LEVEL_INFO;
1440af12a3e7SDag-Erling Smørgrav 	if (options->clear_forwardings == 1)
1441af12a3e7SDag-Erling Smørgrav 		clear_forwardings(options);
1442af12a3e7SDag-Erling Smørgrav 	if (options->no_host_authentication_for_localhost == - 1)
1443af12a3e7SDag-Erling Smørgrav 		options->no_host_authentication_for_localhost = 0;
14445962c0e9SDag-Erling Smørgrav 	if (options->identities_only == -1)
14455962c0e9SDag-Erling Smørgrav 		options->identities_only = 0;
1446e73e9afaSDag-Erling Smørgrav 	if (options->enable_ssh_keysign == -1)
1447e73e9afaSDag-Erling Smørgrav 		options->enable_ssh_keysign = 0;
1448cf2b5f3bSDag-Erling Smørgrav 	if (options->rekey_limit == -1)
1449cf2b5f3bSDag-Erling Smørgrav 		options->rekey_limit = 0;
1450cf2b5f3bSDag-Erling Smørgrav 	if (options->verify_host_key_dns == -1)
1451cf2b5f3bSDag-Erling Smørgrav 		options->verify_host_key_dns = 0;
14521ec0d754SDag-Erling Smørgrav 	if (options->server_alive_interval == -1)
14531ec0d754SDag-Erling Smørgrav 		options->server_alive_interval = 0;
14541ec0d754SDag-Erling Smørgrav 	if (options->server_alive_count_max == -1)
14551ec0d754SDag-Erling Smørgrav 		options->server_alive_count_max = 3;
145621e764dfSDag-Erling Smørgrav 	if (options->control_master == -1)
145721e764dfSDag-Erling Smørgrav 		options->control_master = 0;
1458e2f6069cSDag-Erling Smørgrav 	if (options->control_persist == -1) {
1459e2f6069cSDag-Erling Smørgrav 		options->control_persist = 0;
1460e2f6069cSDag-Erling Smørgrav 		options->control_persist_timeout = 0;
1461e2f6069cSDag-Erling Smørgrav 	}
1462aa49c926SDag-Erling Smørgrav 	if (options->hash_known_hosts == -1)
1463aa49c926SDag-Erling Smørgrav 		options->hash_known_hosts = 0;
1464b74df5b2SDag-Erling Smørgrav 	if (options->tun_open == -1)
1465b74df5b2SDag-Erling Smørgrav 		options->tun_open = SSH_TUNMODE_NO;
1466b74df5b2SDag-Erling Smørgrav 	if (options->tun_local == -1)
1467b74df5b2SDag-Erling Smørgrav 		options->tun_local = SSH_TUNID_ANY;
1468b74df5b2SDag-Erling Smørgrav 	if (options->tun_remote == -1)
1469b74df5b2SDag-Erling Smørgrav 		options->tun_remote = SSH_TUNID_ANY;
1470b74df5b2SDag-Erling Smørgrav 	if (options->permit_local_command == -1)
1471b74df5b2SDag-Erling Smørgrav 		options->permit_local_command = 0;
14727aee6ffeSDag-Erling Smørgrav 	if (options->use_roaming == -1)
14737aee6ffeSDag-Erling Smørgrav 		options->use_roaming = 1;
1474d4af9e69SDag-Erling Smørgrav 	if (options->visual_host_key == -1)
1475d4af9e69SDag-Erling Smørgrav 		options->visual_host_key = 0;
1476cce7d346SDag-Erling Smørgrav 	if (options->zero_knowledge_password_authentication == -1)
1477cce7d346SDag-Erling Smørgrav 		options->zero_knowledge_password_authentication = 0;
14784a421b63SDag-Erling Smørgrav 	if (options->ip_qos_interactive == -1)
14794a421b63SDag-Erling Smørgrav 		options->ip_qos_interactive = IPTOS_LOWDELAY;
14804a421b63SDag-Erling Smørgrav 	if (options->ip_qos_bulk == -1)
14814a421b63SDag-Erling Smørgrav 		options->ip_qos_bulk = IPTOS_THROUGHPUT;
1482e146993eSDag-Erling Smørgrav 	if (options->request_tty == -1)
1483e146993eSDag-Erling Smørgrav 		options->request_tty = REQUEST_TTY_AUTO;
1484b74df5b2SDag-Erling Smørgrav 	/* options->local_command should not be set by default */
1485511b41d2SMark Murray 	/* options->proxy_command should not be set by default */
1486511b41d2SMark Murray 	/* options->user will be set in the main program if appropriate */
1487511b41d2SMark Murray 	/* options->hostname will be set in the main program if appropriate */
1488ca3176e7SBrian Feldman 	/* options->host_key_alias should not be set by default */
1489ca3176e7SBrian Feldman 	/* options->preferred_authentications will be set in ssh */
1490462c32cbSDag-Erling Smørgrav 	if (options->version_addendum == NULL)
1491462c32cbSDag-Erling Smørgrav 		options->version_addendum = xstrdup(SSH_VERSION_FREEBSD);
149289986192SBrooks Davis 	if (options->hpn_disabled == -1)
149389986192SBrooks Davis 		options->hpn_disabled = 0;
149489986192SBrooks Davis 	if (options->hpn_buffer_size > -1)
149589986192SBrooks Davis 	{
149689986192SBrooks Davis 		u_int maxlen;
149789986192SBrooks Davis 
149889986192SBrooks Davis 		/* If a user tries to set the size to 0 set it to 1KB. */
149989986192SBrooks Davis 		if (options->hpn_buffer_size == 0)
150089986192SBrooks Davis 			options->hpn_buffer_size = 1024;
150189986192SBrooks Davis 		/* Limit the buffer to BUFFER_MAX_LEN. */
150289986192SBrooks Davis 		maxlen = buffer_get_max_len();
150389986192SBrooks Davis 		if (options->hpn_buffer_size > (maxlen / 1024)) {
150489986192SBrooks Davis 			debug("User requested buffer larger than %ub: %ub. "
150589986192SBrooks Davis 			    "Request reverted to %ub", maxlen,
150689986192SBrooks Davis 			    options->hpn_buffer_size * 1024, maxlen);
150789986192SBrooks Davis 			options->hpn_buffer_size = maxlen;
150889986192SBrooks Davis 		}
150989986192SBrooks Davis 		debug("hpn_buffer_size set to %d", options->hpn_buffer_size);
151089986192SBrooks Davis 	}
151189986192SBrooks Davis 	if (options->tcp_rcv_buf == 0)
151289986192SBrooks Davis 		options->tcp_rcv_buf = 1;
151389986192SBrooks Davis 	if (options->tcp_rcv_buf > -1)
151489986192SBrooks Davis 		options->tcp_rcv_buf *= 1024;
151589986192SBrooks Davis 	if (options->tcp_rcv_buf_poll == -1)
151689986192SBrooks Davis 		options->tcp_rcv_buf_poll = 1;
151789986192SBrooks Davis #ifdef	NONE_CIPHER_ENABLED
151889986192SBrooks Davis 	/* options->none_enabled must not be set by default */
151989986192SBrooks Davis 	if (options->none_switch == -1)
152089986192SBrooks Davis 		options->none_switch = 0;
152189986192SBrooks Davis #endif
1522511b41d2SMark Murray }
1523aa49c926SDag-Erling Smørgrav 
1524aa49c926SDag-Erling Smørgrav /*
1525aa49c926SDag-Erling Smørgrav  * parse_forward
1526aa49c926SDag-Erling Smørgrav  * parses a string containing a port forwarding specification of the form:
1527cce7d346SDag-Erling Smørgrav  *   dynamicfwd == 0
1528aa49c926SDag-Erling Smørgrav  *	[listenhost:]listenport:connecthost:connectport
1529cce7d346SDag-Erling Smørgrav  *   dynamicfwd == 1
1530cce7d346SDag-Erling Smørgrav  *	[listenhost:]listenport
1531aa49c926SDag-Erling Smørgrav  * returns number of arguments parsed or zero on error
1532aa49c926SDag-Erling Smørgrav  */
1533aa49c926SDag-Erling Smørgrav int
1534cce7d346SDag-Erling Smørgrav parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
1535aa49c926SDag-Erling Smørgrav {
1536aa49c926SDag-Erling Smørgrav 	int i;
1537aa49c926SDag-Erling Smørgrav 	char *p, *cp, *fwdarg[4];
1538aa49c926SDag-Erling Smørgrav 
1539aa49c926SDag-Erling Smørgrav 	memset(fwd, '\0', sizeof(*fwd));
1540aa49c926SDag-Erling Smørgrav 
1541aa49c926SDag-Erling Smørgrav 	cp = p = xstrdup(fwdspec);
1542aa49c926SDag-Erling Smørgrav 
1543aa49c926SDag-Erling Smørgrav 	/* skip leading spaces */
1544d4af9e69SDag-Erling Smørgrav 	while (isspace(*cp))
1545aa49c926SDag-Erling Smørgrav 		cp++;
1546aa49c926SDag-Erling Smørgrav 
1547aa49c926SDag-Erling Smørgrav 	for (i = 0; i < 4; ++i)
1548aa49c926SDag-Erling Smørgrav 		if ((fwdarg[i] = hpdelim(&cp)) == NULL)
1549aa49c926SDag-Erling Smørgrav 			break;
1550aa49c926SDag-Erling Smørgrav 
1551cce7d346SDag-Erling Smørgrav 	/* Check for trailing garbage */
1552aa49c926SDag-Erling Smørgrav 	if (cp != NULL)
1553aa49c926SDag-Erling Smørgrav 		i = 0;	/* failure */
1554aa49c926SDag-Erling Smørgrav 
1555aa49c926SDag-Erling Smørgrav 	switch (i) {
1556cce7d346SDag-Erling Smørgrav 	case 1:
1557cce7d346SDag-Erling Smørgrav 		fwd->listen_host = NULL;
1558cce7d346SDag-Erling Smørgrav 		fwd->listen_port = a2port(fwdarg[0]);
1559cce7d346SDag-Erling Smørgrav 		fwd->connect_host = xstrdup("socks");
1560cce7d346SDag-Erling Smørgrav 		break;
1561cce7d346SDag-Erling Smørgrav 
1562cce7d346SDag-Erling Smørgrav 	case 2:
1563cce7d346SDag-Erling Smørgrav 		fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
1564cce7d346SDag-Erling Smørgrav 		fwd->listen_port = a2port(fwdarg[1]);
1565cce7d346SDag-Erling Smørgrav 		fwd->connect_host = xstrdup("socks");
1566cce7d346SDag-Erling Smørgrav 		break;
1567cce7d346SDag-Erling Smørgrav 
1568aa49c926SDag-Erling Smørgrav 	case 3:
1569aa49c926SDag-Erling Smørgrav 		fwd->listen_host = NULL;
1570aa49c926SDag-Erling Smørgrav 		fwd->listen_port = a2port(fwdarg[0]);
1571aa49c926SDag-Erling Smørgrav 		fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
1572aa49c926SDag-Erling Smørgrav 		fwd->connect_port = a2port(fwdarg[2]);
1573aa49c926SDag-Erling Smørgrav 		break;
1574aa49c926SDag-Erling Smørgrav 
1575aa49c926SDag-Erling Smørgrav 	case 4:
1576aa49c926SDag-Erling Smørgrav 		fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
1577aa49c926SDag-Erling Smørgrav 		fwd->listen_port = a2port(fwdarg[1]);
1578aa49c926SDag-Erling Smørgrav 		fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
1579aa49c926SDag-Erling Smørgrav 		fwd->connect_port = a2port(fwdarg[3]);
1580aa49c926SDag-Erling Smørgrav 		break;
1581aa49c926SDag-Erling Smørgrav 	default:
1582aa49c926SDag-Erling Smørgrav 		i = 0; /* failure */
1583aa49c926SDag-Erling Smørgrav 	}
1584aa49c926SDag-Erling Smørgrav 
1585aa49c926SDag-Erling Smørgrav 	xfree(p);
1586aa49c926SDag-Erling Smørgrav 
1587cce7d346SDag-Erling Smørgrav 	if (dynamicfwd) {
1588cce7d346SDag-Erling Smørgrav 		if (!(i == 1 || i == 2))
1589cce7d346SDag-Erling Smørgrav 			goto fail_free;
1590cce7d346SDag-Erling Smørgrav 	} else {
1591cce7d346SDag-Erling Smørgrav 		if (!(i == 3 || i == 4))
1592cce7d346SDag-Erling Smørgrav 			goto fail_free;
1593cce7d346SDag-Erling Smørgrav 		if (fwd->connect_port <= 0)
1594cce7d346SDag-Erling Smørgrav 			goto fail_free;
1595cce7d346SDag-Erling Smørgrav 	}
1596cce7d346SDag-Erling Smørgrav 
1597cce7d346SDag-Erling Smørgrav 	if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0))
1598aa49c926SDag-Erling Smørgrav 		goto fail_free;
1599aa49c926SDag-Erling Smørgrav 
1600aa49c926SDag-Erling Smørgrav 	if (fwd->connect_host != NULL &&
1601aa49c926SDag-Erling Smørgrav 	    strlen(fwd->connect_host) >= NI_MAXHOST)
1602aa49c926SDag-Erling Smørgrav 		goto fail_free;
1603cce7d346SDag-Erling Smørgrav 	if (fwd->listen_host != NULL &&
1604cce7d346SDag-Erling Smørgrav 	    strlen(fwd->listen_host) >= NI_MAXHOST)
1605cce7d346SDag-Erling Smørgrav 		goto fail_free;
1606cce7d346SDag-Erling Smørgrav 
1607aa49c926SDag-Erling Smørgrav 
1608aa49c926SDag-Erling Smørgrav 	return (i);
1609aa49c926SDag-Erling Smørgrav 
1610aa49c926SDag-Erling Smørgrav  fail_free:
1611cce7d346SDag-Erling Smørgrav 	if (fwd->connect_host != NULL) {
1612aa49c926SDag-Erling Smørgrav 		xfree(fwd->connect_host);
1613cce7d346SDag-Erling Smørgrav 		fwd->connect_host = NULL;
1614cce7d346SDag-Erling Smørgrav 	}
1615cce7d346SDag-Erling Smørgrav 	if (fwd->listen_host != NULL) {
1616aa49c926SDag-Erling Smørgrav 		xfree(fwd->listen_host);
1617cce7d346SDag-Erling Smørgrav 		fwd->listen_host = NULL;
1618cce7d346SDag-Erling Smørgrav 	}
1619aa49c926SDag-Erling Smørgrav 	return (0);
1620aa49c926SDag-Erling Smørgrav }
1621