readconf.c revision 224638
1221420Sdes/* $OpenBSD: readconf.c,v 1.190 2010/11/13 23:27:50 djm Exp $ */
2224638Sbrooks/* $FreeBSD: head/crypto/openssh/readconf.c 224638 2011-08-03 19:14:22Z brooks $ */
357429Smarkm/*
457429Smarkm * Author: Tatu Ylonen <ylo@cs.hut.fi>
557429Smarkm * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
657429Smarkm *                    All rights reserved
757429Smarkm * Functions for reading the configuration files.
860576Skris *
965674Skris * As far as I am concerned, the code I have written for this software
1065674Skris * can be used freely for any purpose.  Any derived versions of this
1165674Skris * software must be clearly marked as such, and if the derived work is
1265674Skris * incompatible with the protocol description in the RFC file, it must be
1365674Skris * called by a name other than "ssh" or "Secure Shell".
1457429Smarkm */
1557429Smarkm
1657429Smarkm#include "includes.h"
17162856Sdes__RCSID("$FreeBSD: head/crypto/openssh/readconf.c 224638 2011-08-03 19:14:22Z brooks $");
1857429Smarkm
19162856Sdes#include <sys/types.h>
20162856Sdes#include <sys/stat.h>
21162856Sdes#include <sys/socket.h>
22181918Sdes#include <sys/sysctl.h>
23162856Sdes
24162856Sdes#include <netinet/in.h>
25221420Sdes#include <netinet/in_systm.h>
26221420Sdes#include <netinet/ip.h>
27162856Sdes
28162856Sdes#include <ctype.h>
29162856Sdes#include <errno.h>
30162856Sdes#include <netdb.h>
31162856Sdes#include <signal.h>
32162856Sdes#include <stdarg.h>
33162856Sdes#include <stdio.h>
34162856Sdes#include <string.h>
35162856Sdes#include <unistd.h>
36162856Sdes
37162856Sdes#include "xmalloc.h"
3857429Smarkm#include "ssh.h"
3976262Sgreen#include "compat.h"
4076262Sgreen#include "cipher.h"
4176262Sgreen#include "pathnames.h"
4276262Sgreen#include "log.h"
43162856Sdes#include "key.h"
4457429Smarkm#include "readconf.h"
4560576Skris#include "match.h"
4676262Sgreen#include "misc.h"
47162856Sdes#include "buffer.h"
4876262Sgreen#include "kex.h"
4976262Sgreen#include "mac.h"
50192595Sdes#include "version.h"
5157429Smarkm
5257429Smarkm/* Format of the configuration file:
5357429Smarkm
5457429Smarkm   # Configuration data is parsed as follows:
5557429Smarkm   #  1. command line options
5657429Smarkm   #  2. user-specific file
5757429Smarkm   #  3. system-wide file
5857429Smarkm   # Any configuration value is only changed the first time it is set.
5957429Smarkm   # Thus, host-specific definitions should be at the beginning of the
6057429Smarkm   # configuration file, and defaults at the end.
6157429Smarkm
6257429Smarkm   # Host-specific declarations.  These may override anything above.  A single
6357429Smarkm   # host may match multiple declarations; these are processed in the order
6457429Smarkm   # that they are given in.
6557429Smarkm
6657429Smarkm   Host *.ngs.fi ngs.fi
6798684Sdes     User foo
6857429Smarkm
6957429Smarkm   Host fake.com
7057429Smarkm     HostName another.host.name.real.org
7157429Smarkm     User blaah
7257429Smarkm     Port 34289
7357429Smarkm     ForwardX11 no
7457429Smarkm     ForwardAgent no
7557429Smarkm
7657429Smarkm   Host books.com
7757429Smarkm     RemoteForward 9999 shadows.cs.hut.fi:9999
7857429Smarkm     Cipher 3des
7957429Smarkm
8057429Smarkm   Host fascist.blob.com
8157429Smarkm     Port 23123
8257429Smarkm     User tylonen
8357429Smarkm     PasswordAuthentication no
8457429Smarkm
8557429Smarkm   Host puukko.hut.fi
8657429Smarkm     User t35124p
8757429Smarkm     ProxyCommand ssh-proxy %h %p
8857429Smarkm
8957429Smarkm   Host *.fr
9098684Sdes     PublicKeyAuthentication no
9157429Smarkm
9257429Smarkm   Host *.su
9357429Smarkm     Cipher none
9457429Smarkm     PasswordAuthentication no
9557429Smarkm
96157019Sdes   Host vpn.fake.com
97157019Sdes     Tunnel yes
98157019Sdes     TunnelDevice 3
99157019Sdes
10057429Smarkm   # Defaults for various options
10157429Smarkm   Host *
10257429Smarkm     ForwardAgent no
10376262Sgreen     ForwardX11 no
10457429Smarkm     PasswordAuthentication yes
10557429Smarkm     RSAAuthentication yes
10657429Smarkm     RhostsRSAAuthentication yes
10757429Smarkm     StrictHostKeyChecking yes
108126277Sdes     TcpKeepAlive no
10957429Smarkm     IdentityFile ~/.ssh/identity
11057429Smarkm     Port 22
11157429Smarkm     EscapeChar ~
11257429Smarkm
11357429Smarkm*/
11457429Smarkm
11557429Smarkm/* Keyword tokens. */
11657429Smarkm
11757429Smarkmtypedef enum {
11857429Smarkm	oBadOption,
119215116Sdes	oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
120215116Sdes	oGatewayPorts, oExitOnForwardFailure,
12198684Sdes	oPasswordAuthentication, oRSAAuthentication,
12276262Sgreen	oChallengeResponseAuthentication, oXAuthLocation,
12357429Smarkm	oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
12457429Smarkm	oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
12557429Smarkm	oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
12657429Smarkm	oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
127126277Sdes	oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
12876262Sgreen	oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
12976262Sgreen	oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
13076262Sgreen	oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
13176262Sgreen	oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
132204917Sdes	oHostKeyAlgorithms, oBindAddress, oPKCS11Provider,
13393698Sdes	oClearAllForwardings, oNoHostAuthenticationForLocalhost,
134124211Sdes	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
135124211Sdes	oAddressFamily, oGssAuthentication, oGssDelegateCreds,
136128461Sdes	oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
137215116Sdes	oSendEnv, oControlPath, oControlMaster, oControlPersist,
138215116Sdes	oHashKnownHosts,
139157019Sdes	oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
140197679Sdes	oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication,
141221420Sdes	oKexAlgorithms, oIPQoS,
142224638Sbrooks	oHPNDisabled, oHPNBufferSize, oTcpRcvBufPoll, oTcpRcvBuf,
143224638Sbrooks#ifdef NONE_CIPHER_ENABLED
144224638Sbrooks	oNoneEnabled, oNoneSwitch,
145224638Sbrooks#endif
14699048Sdes	oVersionAddendum,
147124211Sdes	oDeprecated, oUnsupported
14857429Smarkm} OpCodes;
14957429Smarkm
15057429Smarkm/* Textual representations of the tokens. */
15157429Smarkm
15257429Smarkmstatic struct {
15357429Smarkm	const char *name;
15457429Smarkm	OpCodes opcode;
15557429Smarkm} keywords[] = {
15657429Smarkm	{ "forwardagent", oForwardAgent },
15757429Smarkm	{ "forwardx11", oForwardX11 },
158126277Sdes	{ "forwardx11trusted", oForwardX11Trusted },
159215116Sdes	{ "forwardx11timeout", oForwardX11Timeout },
160162856Sdes	{ "exitonforwardfailure", oExitOnForwardFailure },
16165674Skris	{ "xauthlocation", oXAuthLocation },
16257429Smarkm	{ "gatewayports", oGatewayPorts },
16357429Smarkm	{ "useprivilegedport", oUsePrivilegedPort },
164124211Sdes	{ "rhostsauthentication", oDeprecated },
16557429Smarkm	{ "passwordauthentication", oPasswordAuthentication },
16669591Sgreen	{ "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
16769591Sgreen	{ "kbdinteractivedevices", oKbdInteractiveDevices },
16857429Smarkm	{ "rsaauthentication", oRSAAuthentication },
16976262Sgreen	{ "pubkeyauthentication", oPubkeyAuthentication },
17076262Sgreen	{ "dsaauthentication", oPubkeyAuthentication },		    /* alias */
17176262Sgreen	{ "rhostsrsaauthentication", oRhostsRSAAuthentication },
17276262Sgreen	{ "hostbasedauthentication", oHostbasedAuthentication },
17376262Sgreen	{ "challengeresponseauthentication", oChallengeResponseAuthentication },
17476262Sgreen	{ "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
17576262Sgreen	{ "tisauthentication", oChallengeResponseAuthentication },  /* alias */
176124211Sdes	{ "kerberosauthentication", oUnsupported },
177124211Sdes	{ "kerberostgtpassing", oUnsupported },
178124211Sdes	{ "afstokenpassing", oUnsupported },
179124211Sdes#if defined(GSSAPI)
180124211Sdes	{ "gssapiauthentication", oGssAuthentication },
181124211Sdes	{ "gssapidelegatecredentials", oGssDelegateCreds },
182124211Sdes#else
183124211Sdes	{ "gssapiauthentication", oUnsupported },
184124211Sdes	{ "gssapidelegatecredentials", oUnsupported },
18592559Sdes#endif
18698684Sdes	{ "fallbacktorsh", oDeprecated },
18798684Sdes	{ "usersh", oDeprecated },
18857429Smarkm	{ "identityfile", oIdentityFile },
189192595Sdes	{ "identityfile2", oIdentityFile },			/* obsolete */
190128460Sdes	{ "identitiesonly", oIdentitiesOnly },
19157429Smarkm	{ "hostname", oHostName },
19276262Sgreen	{ "hostkeyalias", oHostKeyAlias },
19357429Smarkm	{ "proxycommand", oProxyCommand },
19457429Smarkm	{ "port", oPort },
19557429Smarkm	{ "cipher", oCipher },
19660576Skris	{ "ciphers", oCiphers },
19776262Sgreen	{ "macs", oMacs },
19860576Skris	{ "protocol", oProtocol },
19957429Smarkm	{ "remoteforward", oRemoteForward },
20057429Smarkm	{ "localforward", oLocalForward },
20157429Smarkm	{ "user", oUser },
20257429Smarkm	{ "host", oHost },
20357429Smarkm	{ "escapechar", oEscapeChar },
20457429Smarkm	{ "globalknownhostsfile", oGlobalKnownHostsFile },
205192595Sdes	{ "globalknownhostsfile2", oGlobalKnownHostsFile2 },	/* obsolete */
206192595Sdes	{ "userknownhostsfile", oUserKnownHostsFile },
20792559Sdes	{ "userknownhostsfile2", oUserKnownHostsFile2 },	/* obsolete */
20857429Smarkm	{ "connectionattempts", oConnectionAttempts },
20957429Smarkm	{ "batchmode", oBatchMode },
21057429Smarkm	{ "checkhostip", oCheckHostIP },
21157429Smarkm	{ "stricthostkeychecking", oStrictHostKeyChecking },
21257429Smarkm	{ "compression", oCompression },
21357429Smarkm	{ "compressionlevel", oCompressionLevel },
214126277Sdes	{ "tcpkeepalive", oTCPKeepAlive },
215126277Sdes	{ "keepalive", oTCPKeepAlive },				/* obsolete */
21657429Smarkm	{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
21757429Smarkm	{ "loglevel", oLogLevel },
21876262Sgreen	{ "dynamicforward", oDynamicForward },
21976262Sgreen	{ "preferredauthentications", oPreferredAuthentications },
22076262Sgreen	{ "hostkeyalgorithms", oHostKeyAlgorithms },
22192559Sdes	{ "bindaddress", oBindAddress },
222204917Sdes#ifdef ENABLE_PKCS11
223204917Sdes	{ "smartcarddevice", oPKCS11Provider },
224204917Sdes	{ "pkcs11provider", oPKCS11Provider },
225124211Sdes#else
226124211Sdes	{ "smartcarddevice", oUnsupported },
227204917Sdes	{ "pkcs11provider", oUnsupported },
228124211Sdes#endif
22992559Sdes	{ "clearallforwardings", oClearAllForwardings },
230113911Sdes	{ "enablesshkeysign", oEnableSSHKeysign },
231124211Sdes	{ "verifyhostkeydns", oVerifyHostKeyDNS },
23292559Sdes	{ "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
233124211Sdes	{ "rekeylimit", oRekeyLimit },
234124211Sdes	{ "connecttimeout", oConnectTimeout },
235124211Sdes	{ "addressfamily", oAddressFamily },
236126277Sdes	{ "serveraliveinterval", oServerAliveInterval },
237126277Sdes	{ "serveralivecountmax", oServerAliveCountMax },
238137019Sdes	{ "sendenv", oSendEnv },
239137019Sdes	{ "controlpath", oControlPath },
240137019Sdes	{ "controlmaster", oControlMaster },
241215116Sdes	{ "controlpersist", oControlPersist },
242147005Sdes	{ "hashknownhosts", oHashKnownHosts },
243157019Sdes	{ "tunnel", oTunnel },
244157019Sdes	{ "tunneldevice", oTunnelDevice },
245157019Sdes	{ "localcommand", oLocalCommand },
246157019Sdes	{ "permitlocalcommand", oPermitLocalCommand },
247181111Sdes	{ "visualhostkey", oVisualHostKey },
248197679Sdes	{ "useroaming", oUseRoaming },
249192595Sdes#ifdef JPAKE
250192595Sdes	{ "zeroknowledgepasswordauthentication",
251192595Sdes	    oZeroKnowledgePasswordAuthentication },
252192595Sdes#else
253192595Sdes	{ "zeroknowledgepasswordauthentication", oUnsupported },
254192595Sdes#endif
255221420Sdes	{ "kexalgorithms", oKexAlgorithms },
256221420Sdes	{ "ipqos", oIPQoS },
257224638Sbrooks	{ "hpndisabled", oHPNDisabled },
258224638Sbrooks	{ "hpnbuffersize", oHPNBufferSize },
259224638Sbrooks	{ "tcprcvbufpoll", oTcpRcvBufPoll },
260224638Sbrooks	{ "tcprcvbuf", oTcpRcvBuf },
261224638Sbrooks#ifdef	NONE_CIPHER_ENABLED
262224638Sbrooks	{ "noneenabled", oNoneEnabled },
263224638Sbrooks	{ "noneswitch", oNoneSwitch },
264224638Sbrooks#endif
265192595Sdes
26699048Sdes	{ "versionaddendum", oVersionAddendum },
26792559Sdes	{ NULL, oBadOption }
26857429Smarkm};
26957429Smarkm
27057429Smarkm/*
27157429Smarkm * Adds a local TCP/IP port forward to options.  Never returns if there is an
27257429Smarkm * error.
27357429Smarkm */
27457429Smarkm
27560576Skrisvoid
276147005Sdesadd_local_forward(Options *options, const Forward *newfwd)
27757429Smarkm{
27857429Smarkm	Forward *fwd;
279106130Sdes#ifndef NO_IPPORT_RESERVED_CONCEPT
28057429Smarkm	extern uid_t original_real_uid;
281181918Sdes	int ipport_reserved;
282181918Sdes#ifdef __FreeBSD__
283181918Sdes	size_t len_ipport_reserved = sizeof(ipport_reserved);
284181918Sdes
285181918Sdes	if (sysctlbyname("net.inet.ip.portrange.reservedhigh",
286181918Sdes	    &ipport_reserved, &len_ipport_reserved, NULL, 0) != 0)
287181918Sdes		ipport_reserved = IPPORT_RESERVED;
288181918Sdes	else
289181918Sdes		ipport_reserved++;
290181918Sdes#else
291181918Sdes	ipport_reserved = IPPORT_RESERVED;
292181918Sdes#endif
293181918Sdes	if (newfwd->listen_port < ipport_reserved && original_real_uid != 0)
29476262Sgreen		fatal("Privileged ports can only be forwarded by root.");
29598941Sdes#endif
296215116Sdes	options->local_forwards = xrealloc(options->local_forwards,
297215116Sdes	    options->num_local_forwards + 1,
298215116Sdes	    sizeof(*options->local_forwards));
29957429Smarkm	fwd = &options->local_forwards[options->num_local_forwards++];
300147005Sdes
301192595Sdes	fwd->listen_host = newfwd->listen_host;
302147005Sdes	fwd->listen_port = newfwd->listen_port;
303192595Sdes	fwd->connect_host = newfwd->connect_host;
304147005Sdes	fwd->connect_port = newfwd->connect_port;
30557429Smarkm}
30657429Smarkm
30757429Smarkm/*
30857429Smarkm * Adds a remote TCP/IP port forward to options.  Never returns if there is
30957429Smarkm * an error.
31057429Smarkm */
31157429Smarkm
31260576Skrisvoid
313147005Sdesadd_remote_forward(Options *options, const Forward *newfwd)
31457429Smarkm{
31557429Smarkm	Forward *fwd;
316215116Sdes
317215116Sdes	options->remote_forwards = xrealloc(options->remote_forwards,
318215116Sdes	    options->num_remote_forwards + 1,
319215116Sdes	    sizeof(*options->remote_forwards));
32057429Smarkm	fwd = &options->remote_forwards[options->num_remote_forwards++];
321147005Sdes
322192595Sdes	fwd->listen_host = newfwd->listen_host;
323147005Sdes	fwd->listen_port = newfwd->listen_port;
324192595Sdes	fwd->connect_host = newfwd->connect_host;
325147005Sdes	fwd->connect_port = newfwd->connect_port;
326215116Sdes	fwd->allocated_port = 0;
32757429Smarkm}
32857429Smarkm
32992559Sdesstatic void
33092559Sdesclear_forwardings(Options *options)
33192559Sdes{
33292559Sdes	int i;
33392559Sdes
334147005Sdes	for (i = 0; i < options->num_local_forwards; i++) {
335147005Sdes		if (options->local_forwards[i].listen_host != NULL)
336147005Sdes			xfree(options->local_forwards[i].listen_host);
337147005Sdes		xfree(options->local_forwards[i].connect_host);
338147005Sdes	}
339215116Sdes	if (options->num_local_forwards > 0) {
340215116Sdes		xfree(options->local_forwards);
341215116Sdes		options->local_forwards = NULL;
342215116Sdes	}
34392559Sdes	options->num_local_forwards = 0;
344147005Sdes	for (i = 0; i < options->num_remote_forwards; i++) {
345147005Sdes		if (options->remote_forwards[i].listen_host != NULL)
346147005Sdes			xfree(options->remote_forwards[i].listen_host);
347147005Sdes		xfree(options->remote_forwards[i].connect_host);
348147005Sdes	}
349215116Sdes	if (options->num_remote_forwards > 0) {
350215116Sdes		xfree(options->remote_forwards);
351215116Sdes		options->remote_forwards = NULL;
352215116Sdes	}
35392559Sdes	options->num_remote_forwards = 0;
354157019Sdes	options->tun_open = SSH_TUNMODE_NO;
35592559Sdes}
35692559Sdes
35757429Smarkm/*
35876262Sgreen * Returns the number of the token pointed to by cp or oBadOption.
35957429Smarkm */
36057429Smarkm
36160576Skrisstatic OpCodes
36257429Smarkmparse_token(const char *cp, const char *filename, int linenum)
36357429Smarkm{
36476262Sgreen	u_int i;
36557429Smarkm
36657429Smarkm	for (i = 0; keywords[i].name; i++)
36757429Smarkm		if (strcasecmp(cp, keywords[i].name) == 0)
36857429Smarkm			return keywords[i].opcode;
36957429Smarkm
37076262Sgreen	error("%s: line %d: Bad configuration option: %s",
37176262Sgreen	    filename, linenum, cp);
37257429Smarkm	return oBadOption;
37357429Smarkm}
37457429Smarkm
37557429Smarkm/*
37657429Smarkm * Processes a single option line as used in the configuration files. This
37757429Smarkm * only sets those values that have not already been set.
37857429Smarkm */
379113911Sdes#define WHITESPACE " \t\r\n"
38057429Smarkm
38157429Smarkmint
38257429Smarkmprocess_config_line(Options *options, const char *host,
38357429Smarkm		    char *line, const char *filename, int linenum,
38457429Smarkm		    int *activep)
38557429Smarkm{
386147005Sdes	char *s, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256];
387162856Sdes	int opcode, *intptr, value, value2, scale;
388181111Sdes	LogLevel *log_level_ptr;
389162856Sdes	long long orig, val64;
390113911Sdes	size_t len;
391147005Sdes	Forward fwd;
39257429Smarkm
393124211Sdes	/* Strip trailing whitespace */
394147005Sdes	for (len = strlen(line) - 1; len > 0; len--) {
395124211Sdes		if (strchr(WHITESPACE, line[len]) == NULL)
396124211Sdes			break;
397124211Sdes		line[len] = '\0';
398124211Sdes	}
399124211Sdes
40065674Skris	s = line;
40165674Skris	/* Get the keyword. (Each line is supposed to begin with a keyword). */
402162856Sdes	if ((keyword = strdelim(&s)) == NULL)
403162856Sdes		return 0;
40465674Skris	/* Ignore leading whitespace. */
40565674Skris	if (*keyword == '\0')
40665674Skris		keyword = strdelim(&s);
40776262Sgreen	if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
40857429Smarkm		return 0;
40957429Smarkm
41065674Skris	opcode = parse_token(keyword, filename, linenum);
41157429Smarkm
41257429Smarkm	switch (opcode) {
41357429Smarkm	case oBadOption:
41457429Smarkm		/* don't panic, but count bad options */
41557429Smarkm		return -1;
41657429Smarkm		/* NOTREACHED */
417124211Sdes	case oConnectTimeout:
418124211Sdes		intptr = &options->connection_timeout;
419126277Sdesparse_time:
420124211Sdes		arg = strdelim(&s);
421124211Sdes		if (!arg || *arg == '\0')
422124211Sdes			fatal("%s line %d: missing time value.",
423124211Sdes			    filename, linenum);
424124211Sdes		if ((value = convtime(arg)) == -1)
425124211Sdes			fatal("%s line %d: invalid time value.",
426124211Sdes			    filename, linenum);
427181111Sdes		if (*activep && *intptr == -1)
428124211Sdes			*intptr = value;
429124211Sdes		break;
430124211Sdes
43157429Smarkm	case oForwardAgent:
43257429Smarkm		intptr = &options->forward_agent;
43357429Smarkmparse_flag:
43465674Skris		arg = strdelim(&s);
43565674Skris		if (!arg || *arg == '\0')
43657429Smarkm			fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
43757429Smarkm		value = 0;	/* To avoid compiler warning... */
43865674Skris		if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
43957429Smarkm			value = 1;
44065674Skris		else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
44157429Smarkm			value = 0;
44257429Smarkm		else
44357429Smarkm			fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
44457429Smarkm		if (*activep && *intptr == -1)
44557429Smarkm			*intptr = value;
44657429Smarkm		break;
44757429Smarkm
44857429Smarkm	case oForwardX11:
44957429Smarkm		intptr = &options->forward_x11;
45057429Smarkm		goto parse_flag;
45157429Smarkm
452126277Sdes	case oForwardX11Trusted:
453126277Sdes		intptr = &options->forward_x11_trusted;
454126277Sdes		goto parse_flag;
455215116Sdes
456215116Sdes	case oForwardX11Timeout:
457215116Sdes		intptr = &options->forward_x11_timeout;
458215116Sdes		goto parse_time;
459126277Sdes
46057429Smarkm	case oGatewayPorts:
46157429Smarkm		intptr = &options->gateway_ports;
46257429Smarkm		goto parse_flag;
46357429Smarkm
464162856Sdes	case oExitOnForwardFailure:
465162856Sdes		intptr = &options->exit_on_forward_failure;
466162856Sdes		goto parse_flag;
467162856Sdes
46857429Smarkm	case oUsePrivilegedPort:
46957429Smarkm		intptr = &options->use_privileged_port;
47057429Smarkm		goto parse_flag;
47157429Smarkm
47257429Smarkm	case oPasswordAuthentication:
47357429Smarkm		intptr = &options->password_authentication;
47457429Smarkm		goto parse_flag;
47557429Smarkm
476192595Sdes	case oZeroKnowledgePasswordAuthentication:
477192595Sdes		intptr = &options->zero_knowledge_password_authentication;
478192595Sdes		goto parse_flag;
479192595Sdes
48069591Sgreen	case oKbdInteractiveAuthentication:
48169591Sgreen		intptr = &options->kbd_interactive_authentication;
48269591Sgreen		goto parse_flag;
48369591Sgreen
48469591Sgreen	case oKbdInteractiveDevices:
48569591Sgreen		charptr = &options->kbd_interactive_devices;
48669591Sgreen		goto parse_string;
48769591Sgreen
48876262Sgreen	case oPubkeyAuthentication:
48976262Sgreen		intptr = &options->pubkey_authentication;
49060576Skris		goto parse_flag;
49160576Skris
49257429Smarkm	case oRSAAuthentication:
49357429Smarkm		intptr = &options->rsa_authentication;
49457429Smarkm		goto parse_flag;
49557429Smarkm
49657429Smarkm	case oRhostsRSAAuthentication:
49757429Smarkm		intptr = &options->rhosts_rsa_authentication;
49857429Smarkm		goto parse_flag;
49957429Smarkm
50076262Sgreen	case oHostbasedAuthentication:
50176262Sgreen		intptr = &options->hostbased_authentication;
50257429Smarkm		goto parse_flag;
50357429Smarkm
50492559Sdes	case oChallengeResponseAuthentication:
50592559Sdes		intptr = &options->challenge_response_authentication;
50692559Sdes		goto parse_flag;
507124211Sdes
508124211Sdes	case oGssAuthentication:
509124211Sdes		intptr = &options->gss_authentication;
51057429Smarkm		goto parse_flag;
511124211Sdes
512124211Sdes	case oGssDelegateCreds:
513124211Sdes		intptr = &options->gss_deleg_creds;
51476262Sgreen		goto parse_flag;
515124211Sdes
51657429Smarkm	case oBatchMode:
51757429Smarkm		intptr = &options->batch_mode;
51857429Smarkm		goto parse_flag;
51957429Smarkm
52057429Smarkm	case oCheckHostIP:
52157429Smarkm		intptr = &options->check_host_ip;
52257429Smarkm		goto parse_flag;
52357429Smarkm
524124211Sdes	case oVerifyHostKeyDNS:
525124211Sdes		intptr = &options->verify_host_key_dns;
526126277Sdes		goto parse_yesnoask;
527124211Sdes
52857429Smarkm	case oStrictHostKeyChecking:
52957429Smarkm		intptr = &options->strict_host_key_checking;
530126277Sdesparse_yesnoask:
53165674Skris		arg = strdelim(&s);
53265674Skris		if (!arg || *arg == '\0')
53376262Sgreen			fatal("%.200s line %d: Missing yes/no/ask argument.",
53492559Sdes			    filename, linenum);
53557429Smarkm		value = 0;	/* To avoid compiler warning... */
53665674Skris		if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
53757429Smarkm			value = 1;
53865674Skris		else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
53957429Smarkm			value = 0;
54065674Skris		else if (strcmp(arg, "ask") == 0)
54157429Smarkm			value = 2;
54257429Smarkm		else
54357429Smarkm			fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
54457429Smarkm		if (*activep && *intptr == -1)
54557429Smarkm			*intptr = value;
54657429Smarkm		break;
54757429Smarkm
54857429Smarkm	case oCompression:
54957429Smarkm		intptr = &options->compression;
55057429Smarkm		goto parse_flag;
55157429Smarkm
552126277Sdes	case oTCPKeepAlive:
553126277Sdes		intptr = &options->tcp_keep_alive;
55457429Smarkm		goto parse_flag;
55557429Smarkm
55692559Sdes	case oNoHostAuthenticationForLocalhost:
55792559Sdes		intptr = &options->no_host_authentication_for_localhost;
55892559Sdes		goto parse_flag;
55992559Sdes
56057429Smarkm	case oNumberOfPasswordPrompts:
56157429Smarkm		intptr = &options->number_of_password_prompts;
56257429Smarkm		goto parse_int;
56357429Smarkm
56457429Smarkm	case oCompressionLevel:
56557429Smarkm		intptr = &options->compression_level;
56657429Smarkm		goto parse_int;
56757429Smarkm
568124211Sdes	case oRekeyLimit:
569124211Sdes		arg = strdelim(&s);
570124211Sdes		if (!arg || *arg == '\0')
571124211Sdes			fatal("%.200s line %d: Missing argument.", filename, linenum);
572124211Sdes		if (arg[0] < '0' || arg[0] > '9')
573124211Sdes			fatal("%.200s line %d: Bad number.", filename, linenum);
574162856Sdes		orig = val64 = strtoll(arg, &endofnumber, 10);
575124211Sdes		if (arg == endofnumber)
576124211Sdes			fatal("%.200s line %d: Bad number.", filename, linenum);
577124211Sdes		switch (toupper(*endofnumber)) {
578162856Sdes		case '\0':
579162856Sdes			scale = 1;
580162856Sdes			break;
581124211Sdes		case 'K':
582162856Sdes			scale = 1<<10;
583124211Sdes			break;
584124211Sdes		case 'M':
585162856Sdes			scale = 1<<20;
586124211Sdes			break;
587124211Sdes		case 'G':
588162856Sdes			scale = 1<<30;
589124211Sdes			break;
590162856Sdes		default:
591162856Sdes			fatal("%.200s line %d: Invalid RekeyLimit suffix",
592162856Sdes			    filename, linenum);
593124211Sdes		}
594162856Sdes		val64 *= scale;
595162856Sdes		/* detect integer wrap and too-large limits */
596181111Sdes		if ((val64 / scale) != orig || val64 > UINT_MAX)
597162856Sdes			fatal("%.200s line %d: RekeyLimit too large",
598162856Sdes			    filename, linenum);
599162856Sdes		if (val64 < 16)
600162856Sdes			fatal("%.200s line %d: RekeyLimit too small",
601162856Sdes			    filename, linenum);
602181111Sdes		if (*activep && options->rekey_limit == -1)
603181111Sdes			options->rekey_limit = (u_int32_t)val64;
604124211Sdes		break;
605124211Sdes
60657429Smarkm	case oIdentityFile:
60765674Skris		arg = strdelim(&s);
60865674Skris		if (!arg || *arg == '\0')
60957429Smarkm			fatal("%.200s line %d: Missing argument.", filename, linenum);
61057429Smarkm		if (*activep) {
61176262Sgreen			intptr = &options->num_identity_files;
61260576Skris			if (*intptr >= SSH_MAX_IDENTITY_FILES)
61357429Smarkm				fatal("%.200s line %d: Too many identity files specified (max %d).",
61492559Sdes				    filename, linenum, SSH_MAX_IDENTITY_FILES);
615181111Sdes			charptr = &options->identity_files[*intptr];
61665674Skris			*charptr = xstrdup(arg);
61760576Skris			*intptr = *intptr + 1;
61857429Smarkm		}
61957429Smarkm		break;
62057429Smarkm
62165674Skris	case oXAuthLocation:
62265674Skris		charptr=&options->xauth_location;
62365674Skris		goto parse_string;
62465674Skris
62557429Smarkm	case oUser:
62657429Smarkm		charptr = &options->user;
62757429Smarkmparse_string:
62865674Skris		arg = strdelim(&s);
62965674Skris		if (!arg || *arg == '\0')
63057429Smarkm			fatal("%.200s line %d: Missing argument.", filename, linenum);
63157429Smarkm		if (*activep && *charptr == NULL)
63265674Skris			*charptr = xstrdup(arg);
63357429Smarkm		break;
63457429Smarkm
63557429Smarkm	case oGlobalKnownHostsFile:
63657429Smarkm		charptr = &options->system_hostfile;
63757429Smarkm		goto parse_string;
63857429Smarkm
63957429Smarkm	case oUserKnownHostsFile:
64057429Smarkm		charptr = &options->user_hostfile;
64157429Smarkm		goto parse_string;
64257429Smarkm
64360576Skris	case oGlobalKnownHostsFile2:
64460576Skris		charptr = &options->system_hostfile2;
64560576Skris		goto parse_string;
64660576Skris
64760576Skris	case oUserKnownHostsFile2:
64860576Skris		charptr = &options->user_hostfile2;
64960576Skris		goto parse_string;
65060576Skris
65157429Smarkm	case oHostName:
65257429Smarkm		charptr = &options->hostname;
65357429Smarkm		goto parse_string;
65457429Smarkm
65576262Sgreen	case oHostKeyAlias:
65676262Sgreen		charptr = &options->host_key_alias;
65776262Sgreen		goto parse_string;
65876262Sgreen
65976262Sgreen	case oPreferredAuthentications:
66076262Sgreen		charptr = &options->preferred_authentications;
66176262Sgreen		goto parse_string;
66276262Sgreen
66392559Sdes	case oBindAddress:
66492559Sdes		charptr = &options->bind_address;
66592559Sdes		goto parse_string;
66692559Sdes
667204917Sdes	case oPKCS11Provider:
668204917Sdes		charptr = &options->pkcs11_provider;
66992559Sdes		goto parse_string;
67092559Sdes
67157429Smarkm	case oProxyCommand:
672157019Sdes		charptr = &options->proxy_command;
673157019Sdesparse_command:
674124211Sdes		if (s == NULL)
675124211Sdes			fatal("%.200s line %d: Missing argument.", filename, linenum);
676113911Sdes		len = strspn(s, WHITESPACE "=");
67757429Smarkm		if (*activep && *charptr == NULL)
678113911Sdes			*charptr = xstrdup(s + len);
67957429Smarkm		return 0;
68057429Smarkm
68157429Smarkm	case oPort:
68257429Smarkm		intptr = &options->port;
68357429Smarkmparse_int:
68465674Skris		arg = strdelim(&s);
68565674Skris		if (!arg || *arg == '\0')
68657429Smarkm			fatal("%.200s line %d: Missing argument.", filename, linenum);
68765674Skris		if (arg[0] < '0' || arg[0] > '9')
68857429Smarkm			fatal("%.200s line %d: Bad number.", filename, linenum);
68957429Smarkm
69057429Smarkm		/* Octal, decimal, or hex format? */
69165674Skris		value = strtol(arg, &endofnumber, 0);
69265674Skris		if (arg == endofnumber)
69357429Smarkm			fatal("%.200s line %d: Bad number.", filename, linenum);
69457429Smarkm		if (*activep && *intptr == -1)
69557429Smarkm			*intptr = value;
69657429Smarkm		break;
69757429Smarkm
69857429Smarkm	case oConnectionAttempts:
69957429Smarkm		intptr = &options->connection_attempts;
70057429Smarkm		goto parse_int;
70157429Smarkm
70257429Smarkm	case oCipher:
70357429Smarkm		intptr = &options->cipher;
70465674Skris		arg = strdelim(&s);
70565674Skris		if (!arg || *arg == '\0')
70661203Skris			fatal("%.200s line %d: Missing argument.", filename, linenum);
70765674Skris		value = cipher_number(arg);
70857429Smarkm		if (value == -1)
70957429Smarkm			fatal("%.200s line %d: Bad cipher '%s'.",
71092559Sdes			    filename, linenum, arg ? arg : "<NONE>");
71157429Smarkm		if (*activep && *intptr == -1)
71257429Smarkm			*intptr = value;
71357429Smarkm		break;
71457429Smarkm
71560576Skris	case oCiphers:
71665674Skris		arg = strdelim(&s);
71765674Skris		if (!arg || *arg == '\0')
71861203Skris			fatal("%.200s line %d: Missing argument.", filename, linenum);
71965674Skris		if (!ciphers_valid(arg))
72060576Skris			fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
72192559Sdes			    filename, linenum, arg ? arg : "<NONE>");
72260576Skris		if (*activep && options->ciphers == NULL)
72365674Skris			options->ciphers = xstrdup(arg);
72460576Skris		break;
72560576Skris
72676262Sgreen	case oMacs:
72776262Sgreen		arg = strdelim(&s);
72876262Sgreen		if (!arg || *arg == '\0')
72976262Sgreen			fatal("%.200s line %d: Missing argument.", filename, linenum);
73076262Sgreen		if (!mac_valid(arg))
73176262Sgreen			fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
73292559Sdes			    filename, linenum, arg ? arg : "<NONE>");
73376262Sgreen		if (*activep && options->macs == NULL)
73476262Sgreen			options->macs = xstrdup(arg);
73576262Sgreen		break;
73676262Sgreen
737221420Sdes	case oKexAlgorithms:
738221420Sdes		arg = strdelim(&s);
739221420Sdes		if (!arg || *arg == '\0')
740221420Sdes			fatal("%.200s line %d: Missing argument.",
741221420Sdes			    filename, linenum);
742221420Sdes		if (!kex_names_valid(arg))
743221420Sdes			fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
744221420Sdes			    filename, linenum, arg ? arg : "<NONE>");
745221420Sdes		if (*activep && options->kex_algorithms == NULL)
746221420Sdes			options->kex_algorithms = xstrdup(arg);
747221420Sdes		break;
748221420Sdes
74976262Sgreen	case oHostKeyAlgorithms:
75076262Sgreen		arg = strdelim(&s);
75176262Sgreen		if (!arg || *arg == '\0')
75276262Sgreen			fatal("%.200s line %d: Missing argument.", filename, linenum);
75376262Sgreen		if (!key_names_valid2(arg))
75476262Sgreen			fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
75592559Sdes			    filename, linenum, arg ? arg : "<NONE>");
75676262Sgreen		if (*activep && options->hostkeyalgorithms == NULL)
75776262Sgreen			options->hostkeyalgorithms = xstrdup(arg);
75876262Sgreen		break;
75976262Sgreen
76060576Skris	case oProtocol:
76160576Skris		intptr = &options->protocol;
76265674Skris		arg = strdelim(&s);
76365674Skris		if (!arg || *arg == '\0')
76461203Skris			fatal("%.200s line %d: Missing argument.", filename, linenum);
76565674Skris		value = proto_spec(arg);
76660576Skris		if (value == SSH_PROTO_UNKNOWN)
76760576Skris			fatal("%.200s line %d: Bad protocol spec '%s'.",
76892559Sdes			    filename, linenum, arg ? arg : "<NONE>");
76960576Skris		if (*activep && *intptr == SSH_PROTO_UNKNOWN)
77060576Skris			*intptr = value;
77160576Skris		break;
77260576Skris
77357429Smarkm	case oLogLevel:
774181111Sdes		log_level_ptr = &options->log_level;
77565674Skris		arg = strdelim(&s);
77665674Skris		value = log_level_number(arg);
77792559Sdes		if (value == SYSLOG_LEVEL_NOT_SET)
77876262Sgreen			fatal("%.200s line %d: unsupported log level '%s'",
77992559Sdes			    filename, linenum, arg ? arg : "<NONE>");
780181111Sdes		if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
781181111Sdes			*log_level_ptr = (LogLevel) value;
78257429Smarkm		break;
78357429Smarkm
78492559Sdes	case oLocalForward:
78557429Smarkm	case oRemoteForward:
786192595Sdes	case oDynamicForward:
78765674Skris		arg = strdelim(&s);
788147005Sdes		if (arg == NULL || *arg == '\0')
78992559Sdes			fatal("%.200s line %d: Missing port argument.",
79092559Sdes			    filename, linenum);
791147005Sdes
792192595Sdes		if (opcode == oLocalForward ||
793192595Sdes		    opcode == oRemoteForward) {
794192595Sdes			arg2 = strdelim(&s);
795192595Sdes			if (arg2 == NULL || *arg2 == '\0')
796192595Sdes				fatal("%.200s line %d: Missing target argument.",
797192595Sdes				    filename, linenum);
798147005Sdes
799192595Sdes			/* construct a string for parse_forward */
800192595Sdes			snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
801192595Sdes		} else if (opcode == oDynamicForward) {
802192595Sdes			strlcpy(fwdarg, arg, sizeof(fwdarg));
803192595Sdes		}
804192595Sdes
805192595Sdes		if (parse_forward(&fwd, fwdarg,
806192595Sdes		    opcode == oDynamicForward ? 1 : 0,
807192595Sdes		    opcode == oRemoteForward ? 1 : 0) == 0)
80892559Sdes			fatal("%.200s line %d: Bad forwarding specification.",
80992559Sdes			    filename, linenum);
810147005Sdes
81192559Sdes		if (*activep) {
812192595Sdes			if (opcode == oLocalForward ||
813192595Sdes			    opcode == oDynamicForward)
814147005Sdes				add_local_forward(options, &fwd);
81592559Sdes			else if (opcode == oRemoteForward)
816147005Sdes				add_remote_forward(options, &fwd);
81792559Sdes		}
81857429Smarkm		break;
81957429Smarkm
82092559Sdes	case oClearAllForwardings:
82192559Sdes		intptr = &options->clear_forwardings;
82292559Sdes		goto parse_flag;
82392559Sdes
82457429Smarkm	case oHost:
82557429Smarkm		*activep = 0;
82665674Skris		while ((arg = strdelim(&s)) != NULL && *arg != '\0')
82765674Skris			if (match_pattern(host, arg)) {
82865674Skris				debug("Applying options for %.100s", arg);
82957429Smarkm				*activep = 1;
83057429Smarkm				break;
83157429Smarkm			}
83265674Skris		/* Avoid garbage check below, as strdelim is done. */
83357429Smarkm		return 0;
83457429Smarkm
83557429Smarkm	case oEscapeChar:
83657429Smarkm		intptr = &options->escape_char;
83765674Skris		arg = strdelim(&s);
83865674Skris		if (!arg || *arg == '\0')
83957429Smarkm			fatal("%.200s line %d: Missing argument.", filename, linenum);
84065674Skris		if (arg[0] == '^' && arg[2] == 0 &&
84176262Sgreen		    (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
84276262Sgreen			value = (u_char) arg[1] & 31;
84365674Skris		else if (strlen(arg) == 1)
84476262Sgreen			value = (u_char) arg[0];
84565674Skris		else if (strcmp(arg, "none") == 0)
84692559Sdes			value = SSH_ESCAPECHAR_NONE;
84757429Smarkm		else {
84857429Smarkm			fatal("%.200s line %d: Bad escape character.",
84992559Sdes			    filename, linenum);
85057429Smarkm			/* NOTREACHED */
85157429Smarkm			value = 0;	/* Avoid compiler warning. */
85257429Smarkm		}
85357429Smarkm		if (*activep && *intptr == -1)
85457429Smarkm			*intptr = value;
85557429Smarkm		break;
85657429Smarkm
857124211Sdes	case oAddressFamily:
858124211Sdes		arg = strdelim(&s);
859149753Sdes		if (!arg || *arg == '\0')
860149753Sdes			fatal("%s line %d: missing address family.",
861149753Sdes			    filename, linenum);
862124211Sdes		intptr = &options->address_family;
863124211Sdes		if (strcasecmp(arg, "inet") == 0)
864124211Sdes			value = AF_INET;
865124211Sdes		else if (strcasecmp(arg, "inet6") == 0)
866124211Sdes			value = AF_INET6;
867124211Sdes		else if (strcasecmp(arg, "any") == 0)
868124211Sdes			value = AF_UNSPEC;
869124211Sdes		else
870124211Sdes			fatal("Unsupported AddressFamily \"%s\"", arg);
871124211Sdes		if (*activep && *intptr == -1)
872124211Sdes			*intptr = value;
873124211Sdes		break;
874124211Sdes
875113911Sdes	case oEnableSSHKeysign:
876113911Sdes		intptr = &options->enable_ssh_keysign;
877113911Sdes		goto parse_flag;
878113911Sdes
879128460Sdes	case oIdentitiesOnly:
880128460Sdes		intptr = &options->identities_only;
881128460Sdes		goto parse_flag;
882128460Sdes
883126277Sdes	case oServerAliveInterval:
884126277Sdes		intptr = &options->server_alive_interval;
885126277Sdes		goto parse_time;
886126277Sdes
887126277Sdes	case oServerAliveCountMax:
888126277Sdes		intptr = &options->server_alive_count_max;
889126277Sdes		goto parse_int;
890126277Sdes
891137019Sdes	case oSendEnv:
892137019Sdes		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
893137019Sdes			if (strchr(arg, '=') != NULL)
894137019Sdes				fatal("%s line %d: Invalid environment name.",
895137019Sdes				    filename, linenum);
896147005Sdes			if (!*activep)
897147005Sdes				continue;
898137019Sdes			if (options->num_send_env >= MAX_SEND_ENV)
899137019Sdes				fatal("%s line %d: too many send env.",
900137019Sdes				    filename, linenum);
901137019Sdes			options->send_env[options->num_send_env++] =
902137019Sdes			    xstrdup(arg);
903137019Sdes		}
904137019Sdes		break;
905137019Sdes
906137019Sdes	case oControlPath:
907137019Sdes		charptr = &options->control_path;
908137019Sdes		goto parse_string;
909137019Sdes
910137019Sdes	case oControlMaster:
911137019Sdes		intptr = &options->control_master;
912149753Sdes		arg = strdelim(&s);
913149753Sdes		if (!arg || *arg == '\0')
914149753Sdes			fatal("%.200s line %d: Missing ControlMaster argument.",
915149753Sdes			    filename, linenum);
916149753Sdes		value = 0;	/* To avoid compiler warning... */
917149753Sdes		if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
918149753Sdes			value = SSHCTL_MASTER_YES;
919149753Sdes		else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
920149753Sdes			value = SSHCTL_MASTER_NO;
921149753Sdes		else if (strcmp(arg, "auto") == 0)
922149753Sdes			value = SSHCTL_MASTER_AUTO;
923149753Sdes		else if (strcmp(arg, "ask") == 0)
924149753Sdes			value = SSHCTL_MASTER_ASK;
925149753Sdes		else if (strcmp(arg, "autoask") == 0)
926149753Sdes			value = SSHCTL_MASTER_AUTO_ASK;
927149753Sdes		else
928149753Sdes			fatal("%.200s line %d: Bad ControlMaster argument.",
929149753Sdes			    filename, linenum);
930149753Sdes		if (*activep && *intptr == -1)
931149753Sdes			*intptr = value;
932149753Sdes		break;
933137019Sdes
934215116Sdes	case oControlPersist:
935215116Sdes		/* no/false/yes/true, or a time spec */
936215116Sdes		intptr = &options->control_persist;
937215116Sdes		arg = strdelim(&s);
938215116Sdes		if (!arg || *arg == '\0')
939215116Sdes			fatal("%.200s line %d: Missing ControlPersist"
940215116Sdes			    " argument.", filename, linenum);
941215116Sdes		value = 0;
942215116Sdes		value2 = 0;	/* timeout */
943215116Sdes		if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
944215116Sdes			value = 0;
945215116Sdes		else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
946215116Sdes			value = 1;
947215116Sdes		else if ((value2 = convtime(arg)) >= 0)
948215116Sdes			value = 1;
949215116Sdes		else
950215116Sdes			fatal("%.200s line %d: Bad ControlPersist argument.",
951215116Sdes			    filename, linenum);
952215116Sdes		if (*activep && *intptr == -1) {
953215116Sdes			*intptr = value;
954215116Sdes			options->control_persist_timeout = value2;
955215116Sdes		}
956215116Sdes		break;
957215116Sdes
958147005Sdes	case oHashKnownHosts:
959147005Sdes		intptr = &options->hash_known_hosts;
960147005Sdes		goto parse_flag;
961147005Sdes
962157019Sdes	case oTunnel:
963157019Sdes		intptr = &options->tun_open;
964157019Sdes		arg = strdelim(&s);
965157019Sdes		if (!arg || *arg == '\0')
966157019Sdes			fatal("%s line %d: Missing yes/point-to-point/"
967157019Sdes			    "ethernet/no argument.", filename, linenum);
968157019Sdes		value = 0;	/* silence compiler */
969157019Sdes		if (strcasecmp(arg, "ethernet") == 0)
970157019Sdes			value = SSH_TUNMODE_ETHERNET;
971157019Sdes		else if (strcasecmp(arg, "point-to-point") == 0)
972157019Sdes			value = SSH_TUNMODE_POINTOPOINT;
973157019Sdes		else if (strcasecmp(arg, "yes") == 0)
974157019Sdes			value = SSH_TUNMODE_DEFAULT;
975157019Sdes		else if (strcasecmp(arg, "no") == 0)
976157019Sdes			value = SSH_TUNMODE_NO;
977157019Sdes		else
978157019Sdes			fatal("%s line %d: Bad yes/point-to-point/ethernet/"
979157019Sdes			    "no argument: %s", filename, linenum, arg);
980157019Sdes		if (*activep)
981157019Sdes			*intptr = value;
982157019Sdes		break;
983157019Sdes
984157019Sdes	case oTunnelDevice:
985157019Sdes		arg = strdelim(&s);
986157019Sdes		if (!arg || *arg == '\0')
987157019Sdes			fatal("%.200s line %d: Missing argument.", filename, linenum);
988157019Sdes		value = a2tun(arg, &value2);
989157019Sdes		if (value == SSH_TUNID_ERR)
990157019Sdes			fatal("%.200s line %d: Bad tun device.", filename, linenum);
991157019Sdes		if (*activep) {
992157019Sdes			options->tun_local = value;
993157019Sdes			options->tun_remote = value2;
994157019Sdes		}
995157019Sdes		break;
996157019Sdes
997157019Sdes	case oLocalCommand:
998157019Sdes		charptr = &options->local_command;
999157019Sdes		goto parse_command;
1000157019Sdes
1001157019Sdes	case oPermitLocalCommand:
1002157019Sdes		intptr = &options->permit_local_command;
1003157019Sdes		goto parse_flag;
1004157019Sdes
1005181111Sdes	case oVisualHostKey:
1006181111Sdes		intptr = &options->visual_host_key;
1007181111Sdes		goto parse_flag;
1008181111Sdes
1009221420Sdes	case oIPQoS:
1010221420Sdes		arg = strdelim(&s);
1011221420Sdes		if ((value = parse_ipqos(arg)) == -1)
1012221420Sdes			fatal("%s line %d: Bad IPQoS value: %s",
1013221420Sdes			    filename, linenum, arg);
1014221420Sdes		arg = strdelim(&s);
1015221420Sdes		if (arg == NULL)
1016221420Sdes			value2 = value;
1017221420Sdes		else if ((value2 = parse_ipqos(arg)) == -1)
1018221420Sdes			fatal("%s line %d: Bad IPQoS value: %s",
1019221420Sdes			    filename, linenum, arg);
1020221420Sdes		if (*activep) {
1021221420Sdes			options->ip_qos_interactive = value;
1022221420Sdes			options->ip_qos_bulk = value2;
1023221420Sdes		}
1024221420Sdes		break;
1025221420Sdes
1026197679Sdes	case oUseRoaming:
1027197679Sdes		intptr = &options->use_roaming;
1028197679Sdes		goto parse_flag;
1029197679Sdes
103099048Sdes	case oVersionAddendum:
103199048Sdes		ssh_version_set_addendum(strtok(s, "\n"));
103299048Sdes		do {
103399048Sdes			arg = strdelim(&s);
103499048Sdes		} while (arg != NULL && *arg != '\0');
103599048Sdes		break;
103699048Sdes
1037224638Sbrooks	case oHPNDisabled:
1038224638Sbrooks		intptr = &options->hpn_disabled;
1039224638Sbrooks		goto parse_flag;
1040224638Sbrooks
1041224638Sbrooks	case oHPNBufferSize:
1042224638Sbrooks		intptr = &options->hpn_buffer_size;
1043224638Sbrooks		goto parse_int;
1044224638Sbrooks
1045224638Sbrooks	case oTcpRcvBufPoll:
1046224638Sbrooks		intptr = &options->tcp_rcv_buf_poll;
1047224638Sbrooks		goto parse_flag;
1048224638Sbrooks
1049224638Sbrooks	case oTcpRcvBuf:
1050224638Sbrooks		intptr = &options->tcp_rcv_buf;
1051224638Sbrooks		goto parse_int;
1052224638Sbrooks
1053224638Sbrooks#ifdef	NONE_CIPHER_ENABLED
1054224638Sbrooks	case oNoneEnabled:
1055224638Sbrooks		intptr = &options->none_enabled;
1056224638Sbrooks		goto parse_flag;
1057224638Sbrooks
1058224638Sbrooks	/*
1059224638Sbrooks         * We check to see if the command comes from the command line or not.
1060224638Sbrooks	 * If it does then enable it otherwise fail.  NONE must never be a
1061224638Sbrooks	 * default configuration.
1062224638Sbrooks	 */
1063224638Sbrooks	case oNoneSwitch:
1064224638Sbrooks		if (strcmp(filename,"command-line") == 0) {
1065224638Sbrooks			intptr = &options->none_switch;
1066224638Sbrooks			goto parse_flag;
1067224638Sbrooks		} else {
1068224638Sbrooks			debug("NoneSwitch directive found in %.200s.",
1069224638Sbrooks			    filename);
1070224638Sbrooks			error("NoneSwitch is found in %.200s.\n"
1071224638Sbrooks			    "You may only use this configuration option "
1072224638Sbrooks			    "from the command line", filename);
1073224638Sbrooks			error("Continuing...");
1074224638Sbrooks			return 0;
1075224638Sbrooks	        }
1076224638Sbrooks#endif
1077224638Sbrooks
107898684Sdes	case oDeprecated:
107998684Sdes		debug("%s line %d: Deprecated option \"%s\"",
108098684Sdes		    filename, linenum, keyword);
108198684Sdes		return 0;
108298684Sdes
1083124211Sdes	case oUnsupported:
1084124211Sdes		error("%s line %d: Unsupported option \"%s\"",
1085124211Sdes		    filename, linenum, keyword);
1086124211Sdes		return 0;
1087124211Sdes
108857429Smarkm	default:
108957429Smarkm		fatal("process_config_line: Unimplemented opcode %d", opcode);
109057429Smarkm	}
109157429Smarkm
109257429Smarkm	/* Check that there is no garbage at end of line. */
109376262Sgreen	if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
109465674Skris		fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
1095149753Sdes		    filename, linenum, arg);
109665674Skris	}
109757429Smarkm	return 0;
109857429Smarkm}
109957429Smarkm
110057429Smarkm
110157429Smarkm/*
110257429Smarkm * Reads the config file and modifies the options accordingly.  Options
110357429Smarkm * should already be initialized before this call.  This never returns if
110492559Sdes * there is an error.  If the file does not exist, this returns 0.
110557429Smarkm */
110657429Smarkm
110792559Sdesint
1108137019Sdesread_config_file(const char *filename, const char *host, Options *options,
1109137019Sdes    int checkperm)
111057429Smarkm{
111157429Smarkm	FILE *f;
111257429Smarkm	char line[1024];
111357429Smarkm	int active, linenum;
111457429Smarkm	int bad_options = 0;
111557429Smarkm
1116137019Sdes	if ((f = fopen(filename, "r")) == NULL)
111792559Sdes		return 0;
111857429Smarkm
1119137019Sdes	if (checkperm) {
1120137019Sdes		struct stat sb;
1121137019Sdes
1122137019Sdes		if (fstat(fileno(f), &sb) == -1)
1123137019Sdes			fatal("fstat %s: %s", filename, strerror(errno));
1124137019Sdes		if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
1125137019Sdes		    (sb.st_mode & 022) != 0))
1126137019Sdes			fatal("Bad owner or permissions on %s", filename);
1127137019Sdes	}
1128137019Sdes
112957429Smarkm	debug("Reading configuration data %.200s", filename);
113057429Smarkm
113157429Smarkm	/*
113257429Smarkm	 * Mark that we are now processing the options.  This flag is turned
113357429Smarkm	 * on/off by Host specifications.
113457429Smarkm	 */
113557429Smarkm	active = 1;
113657429Smarkm	linenum = 0;
113757429Smarkm	while (fgets(line, sizeof(line), f)) {
113857429Smarkm		/* Update line number counter. */
113957429Smarkm		linenum++;
114057429Smarkm		if (process_config_line(options, host, line, filename, linenum, &active) != 0)
114157429Smarkm			bad_options++;
114257429Smarkm	}
114357429Smarkm	fclose(f);
114457429Smarkm	if (bad_options > 0)
114576262Sgreen		fatal("%s: terminating, %d bad configuration options",
114692559Sdes		    filename, bad_options);
114792559Sdes	return 1;
114857429Smarkm}
114957429Smarkm
115057429Smarkm/*
115157429Smarkm * Initializes options to special values that indicate that they have not yet
115257429Smarkm * been set.  Read_config_file will only set options with this value. Options
115357429Smarkm * are processed in the following order: command line, user config file,
115457429Smarkm * system config file.  Last, fill_default_options is called.
115557429Smarkm */
115657429Smarkm
115760576Skrisvoid
115857429Smarkminitialize_options(Options * options)
115957429Smarkm{
116057429Smarkm	memset(options, 'X', sizeof(*options));
116157429Smarkm	options->forward_agent = -1;
116257429Smarkm	options->forward_x11 = -1;
1163126277Sdes	options->forward_x11_trusted = -1;
1164215116Sdes	options->forward_x11_timeout = -1;
1165162856Sdes	options->exit_on_forward_failure = -1;
116665674Skris	options->xauth_location = NULL;
116757429Smarkm	options->gateway_ports = -1;
116857429Smarkm	options->use_privileged_port = -1;
116957429Smarkm	options->rsa_authentication = -1;
117076262Sgreen	options->pubkey_authentication = -1;
117192559Sdes	options->challenge_response_authentication = -1;
1172124211Sdes	options->gss_authentication = -1;
1173124211Sdes	options->gss_deleg_creds = -1;
117457429Smarkm	options->password_authentication = -1;
117569591Sgreen	options->kbd_interactive_authentication = -1;
117669591Sgreen	options->kbd_interactive_devices = NULL;
117757429Smarkm	options->rhosts_rsa_authentication = -1;
117876262Sgreen	options->hostbased_authentication = -1;
117957429Smarkm	options->batch_mode = -1;
118057429Smarkm	options->check_host_ip = -1;
118157429Smarkm	options->strict_host_key_checking = -1;
118257429Smarkm	options->compression = -1;
1183126277Sdes	options->tcp_keep_alive = -1;
118457429Smarkm	options->compression_level = -1;
118557429Smarkm	options->port = -1;
1186124211Sdes	options->address_family = -1;
118757429Smarkm	options->connection_attempts = -1;
1188124211Sdes	options->connection_timeout = -1;
118957429Smarkm	options->number_of_password_prompts = -1;
119057429Smarkm	options->cipher = -1;
119160576Skris	options->ciphers = NULL;
119276262Sgreen	options->macs = NULL;
1193221420Sdes	options->kex_algorithms = NULL;
119476262Sgreen	options->hostkeyalgorithms = NULL;
119560576Skris	options->protocol = SSH_PROTO_UNKNOWN;
119657429Smarkm	options->num_identity_files = 0;
119757429Smarkm	options->hostname = NULL;
119876262Sgreen	options->host_key_alias = NULL;
119957429Smarkm	options->proxy_command = NULL;
120057429Smarkm	options->user = NULL;
120157429Smarkm	options->escape_char = -1;
120257429Smarkm	options->system_hostfile = NULL;
120357429Smarkm	options->user_hostfile = NULL;
120460576Skris	options->system_hostfile2 = NULL;
120560576Skris	options->user_hostfile2 = NULL;
1206215116Sdes	options->local_forwards = NULL;
120757429Smarkm	options->num_local_forwards = 0;
1208215116Sdes	options->remote_forwards = NULL;
120957429Smarkm	options->num_remote_forwards = 0;
121092559Sdes	options->clear_forwardings = -1;
121192559Sdes	options->log_level = SYSLOG_LEVEL_NOT_SET;
121276262Sgreen	options->preferred_authentications = NULL;
121392559Sdes	options->bind_address = NULL;
1214204917Sdes	options->pkcs11_provider = NULL;
1215113911Sdes	options->enable_ssh_keysign = - 1;
121692559Sdes	options->no_host_authentication_for_localhost = - 1;
1217128460Sdes	options->identities_only = - 1;
1218124211Sdes	options->rekey_limit = - 1;
1219124211Sdes	options->verify_host_key_dns = -1;
1220126277Sdes	options->server_alive_interval = -1;
1221126277Sdes	options->server_alive_count_max = -1;
1222137019Sdes	options->num_send_env = 0;
1223137019Sdes	options->control_path = NULL;
1224137019Sdes	options->control_master = -1;
1225215116Sdes	options->control_persist = -1;
1226215116Sdes	options->control_persist_timeout = 0;
1227147005Sdes	options->hash_known_hosts = -1;
1228157019Sdes	options->tun_open = -1;
1229157019Sdes	options->tun_local = -1;
1230157019Sdes	options->tun_remote = -1;
1231157019Sdes	options->local_command = NULL;
1232157019Sdes	options->permit_local_command = -1;
1233197679Sdes	options->use_roaming = -1;
1234181111Sdes	options->visual_host_key = -1;
1235192595Sdes	options->zero_knowledge_password_authentication = -1;
1236221420Sdes	options->ip_qos_interactive = -1;
1237221420Sdes	options->ip_qos_bulk = -1;
1238224638Sbrooks	options->hpn_disabled = -1;
1239224638Sbrooks	options->hpn_buffer_size = -1;
1240224638Sbrooks	options->tcp_rcv_buf_poll = -1;
1241224638Sbrooks	options->tcp_rcv_buf = -1;
1242224638Sbrooks#ifdef NONE_CIPHER_ENABLED
1243224638Sbrooks	options->none_enabled = -1;
1244224638Sbrooks	options->none_switch = -1;
1245224638Sbrooks#endif
124657429Smarkm}
124757429Smarkm
124857429Smarkm/*
124957429Smarkm * Called after processing other sources of option data, this fills those
125057429Smarkm * options for which no value has been specified with their default values.
125157429Smarkm */
125257429Smarkm
125360576Skrisvoid
125457429Smarkmfill_default_options(Options * options)
125557429Smarkm{
125676262Sgreen	int len;
125776262Sgreen
125857429Smarkm	if (options->forward_agent == -1)
125961203Skris		options->forward_agent = 0;
126057429Smarkm	if (options->forward_x11 == -1)
126157708Sgreen		options->forward_x11 = 0;
1262126277Sdes	if (options->forward_x11_trusted == -1)
1263126277Sdes		options->forward_x11_trusted = 0;
1264215116Sdes	if (options->forward_x11_timeout == -1)
1265215116Sdes		options->forward_x11_timeout = 1200;
1266162856Sdes	if (options->exit_on_forward_failure == -1)
1267162856Sdes		options->exit_on_forward_failure = 0;
126865674Skris	if (options->xauth_location == NULL)
126992559Sdes		options->xauth_location = _PATH_XAUTH;
127057429Smarkm	if (options->gateway_ports == -1)
127157429Smarkm		options->gateway_ports = 0;
127257429Smarkm	if (options->use_privileged_port == -1)
127376262Sgreen		options->use_privileged_port = 0;
127457429Smarkm	if (options->rsa_authentication == -1)
127557429Smarkm		options->rsa_authentication = 1;
127676262Sgreen	if (options->pubkey_authentication == -1)
127776262Sgreen		options->pubkey_authentication = 1;
127892559Sdes	if (options->challenge_response_authentication == -1)
127992559Sdes		options->challenge_response_authentication = 1;
1280124211Sdes	if (options->gss_authentication == -1)
1281126277Sdes		options->gss_authentication = 0;
1282124211Sdes	if (options->gss_deleg_creds == -1)
1283124211Sdes		options->gss_deleg_creds = 0;
128457429Smarkm	if (options->password_authentication == -1)
128557429Smarkm		options->password_authentication = 1;
128669591Sgreen	if (options->kbd_interactive_authentication == -1)
128776262Sgreen		options->kbd_interactive_authentication = 1;
128857429Smarkm	if (options->rhosts_rsa_authentication == -1)
128998684Sdes		options->rhosts_rsa_authentication = 0;
129076262Sgreen	if (options->hostbased_authentication == -1)
129176262Sgreen		options->hostbased_authentication = 0;
129257429Smarkm	if (options->batch_mode == -1)
129357429Smarkm		options->batch_mode = 0;
129457429Smarkm	if (options->check_host_ip == -1)
129599048Sdes		options->check_host_ip = 0;
129657429Smarkm	if (options->strict_host_key_checking == -1)
129757429Smarkm		options->strict_host_key_checking = 2;	/* 2 is default */
129857429Smarkm	if (options->compression == -1)
129957429Smarkm		options->compression = 0;
1300126277Sdes	if (options->tcp_keep_alive == -1)
1301126277Sdes		options->tcp_keep_alive = 1;
130257429Smarkm	if (options->compression_level == -1)
130357429Smarkm		options->compression_level = 6;
130457429Smarkm	if (options->port == -1)
130557429Smarkm		options->port = 0;	/* Filled in ssh_connect. */
1306124211Sdes	if (options->address_family == -1)
1307124211Sdes		options->address_family = AF_UNSPEC;
130857429Smarkm	if (options->connection_attempts == -1)
130992559Sdes		options->connection_attempts = 1;
131057429Smarkm	if (options->number_of_password_prompts == -1)
131157429Smarkm		options->number_of_password_prompts = 3;
131257429Smarkm	/* Selected in ssh_login(). */
131357429Smarkm	if (options->cipher == -1)
131457429Smarkm		options->cipher = SSH_CIPHER_NOT_SET;
131560576Skris	/* options->ciphers, default set in myproposals.h */
131676262Sgreen	/* options->macs, default set in myproposals.h */
1317221420Sdes	/* options->kex_algorithms, default set in myproposals.h */
131876262Sgreen	/* options->hostkeyalgorithms, default set in myproposals.h */
131960576Skris	if (options->protocol == SSH_PROTO_UNKNOWN)
1320204917Sdes		options->protocol = SSH_PROTO_2;
132157429Smarkm	if (options->num_identity_files == 0) {
132276262Sgreen		if (options->protocol & SSH_PROTO_1) {
132376262Sgreen			len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1;
132476262Sgreen			options->identity_files[options->num_identity_files] =
132576262Sgreen			    xmalloc(len);
132676262Sgreen			snprintf(options->identity_files[options->num_identity_files++],
132776262Sgreen			    len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY);
132876262Sgreen		}
132976262Sgreen		if (options->protocol & SSH_PROTO_2) {
133076262Sgreen			len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1;
133176262Sgreen			options->identity_files[options->num_identity_files] =
133276262Sgreen			    xmalloc(len);
133376262Sgreen			snprintf(options->identity_files[options->num_identity_files++],
133476262Sgreen			    len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA);
133576262Sgreen
133676262Sgreen			len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1;
133776262Sgreen			options->identity_files[options->num_identity_files] =
133876262Sgreen			    xmalloc(len);
133976262Sgreen			snprintf(options->identity_files[options->num_identity_files++],
134076262Sgreen			    len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA);
1341221420Sdes#ifdef OPENSSL_HAS_ECC
1342221420Sdes			len = 2 + strlen(_PATH_SSH_CLIENT_ID_ECDSA) + 1;
1343221420Sdes			options->identity_files[options->num_identity_files] =
1344221420Sdes			    xmalloc(len);
1345221420Sdes			snprintf(options->identity_files[options->num_identity_files++],
1346221420Sdes			    len, "~/%.100s", _PATH_SSH_CLIENT_ID_ECDSA);
1347221420Sdes#endif
134876262Sgreen		}
134957429Smarkm	}
135057429Smarkm	if (options->escape_char == -1)
135157429Smarkm		options->escape_char = '~';
135257429Smarkm	if (options->system_hostfile == NULL)
135376262Sgreen		options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE;
135457429Smarkm	if (options->user_hostfile == NULL)
135576262Sgreen		options->user_hostfile = _PATH_SSH_USER_HOSTFILE;
135660576Skris	if (options->system_hostfile2 == NULL)
135776262Sgreen		options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2;
135860576Skris	if (options->user_hostfile2 == NULL)
135976262Sgreen		options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2;
136092559Sdes	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
136157429Smarkm		options->log_level = SYSLOG_LEVEL_INFO;
136292559Sdes	if (options->clear_forwardings == 1)
136392559Sdes		clear_forwardings(options);
136492559Sdes	if (options->no_host_authentication_for_localhost == - 1)
136592559Sdes		options->no_host_authentication_for_localhost = 0;
1366128460Sdes	if (options->identities_only == -1)
1367128460Sdes		options->identities_only = 0;
1368113911Sdes	if (options->enable_ssh_keysign == -1)
1369113911Sdes		options->enable_ssh_keysign = 0;
1370124211Sdes	if (options->rekey_limit == -1)
1371124211Sdes		options->rekey_limit = 0;
1372124211Sdes	if (options->verify_host_key_dns == -1)
1373124211Sdes		options->verify_host_key_dns = 0;
1374126277Sdes	if (options->server_alive_interval == -1)
1375126277Sdes		options->server_alive_interval = 0;
1376126277Sdes	if (options->server_alive_count_max == -1)
1377126277Sdes		options->server_alive_count_max = 3;
1378137019Sdes	if (options->control_master == -1)
1379137019Sdes		options->control_master = 0;
1380215116Sdes	if (options->control_persist == -1) {
1381215116Sdes		options->control_persist = 0;
1382215116Sdes		options->control_persist_timeout = 0;
1383215116Sdes	}
1384147005Sdes	if (options->hash_known_hosts == -1)
1385147005Sdes		options->hash_known_hosts = 0;
1386157019Sdes	if (options->tun_open == -1)
1387157019Sdes		options->tun_open = SSH_TUNMODE_NO;
1388157019Sdes	if (options->tun_local == -1)
1389157019Sdes		options->tun_local = SSH_TUNID_ANY;
1390157019Sdes	if (options->tun_remote == -1)
1391157019Sdes		options->tun_remote = SSH_TUNID_ANY;
1392157019Sdes	if (options->permit_local_command == -1)
1393157019Sdes		options->permit_local_command = 0;
1394197679Sdes	if (options->use_roaming == -1)
1395197679Sdes		options->use_roaming = 1;
1396181111Sdes	if (options->visual_host_key == -1)
1397181111Sdes		options->visual_host_key = 0;
1398192595Sdes	if (options->zero_knowledge_password_authentication == -1)
1399192595Sdes		options->zero_knowledge_password_authentication = 0;
1400221420Sdes	if (options->ip_qos_interactive == -1)
1401221420Sdes		options->ip_qos_interactive = IPTOS_LOWDELAY;
1402221420Sdes	if (options->ip_qos_bulk == -1)
1403221420Sdes		options->ip_qos_bulk = IPTOS_THROUGHPUT;
1404157019Sdes	/* options->local_command should not be set by default */
140557429Smarkm	/* options->proxy_command should not be set by default */
140657429Smarkm	/* options->user will be set in the main program if appropriate */
140757429Smarkm	/* options->hostname will be set in the main program if appropriate */
140876262Sgreen	/* options->host_key_alias should not be set by default */
140976262Sgreen	/* options->preferred_authentications will be set in ssh */
1410224638Sbrooks	if (options->hpn_disabled == -1)
1411224638Sbrooks	        options->hpn_disabled = 0;
1412224638Sbrooks	if (options->hpn_buffer_size > -1)
1413224638Sbrooks	{
1414224638Sbrooks		u_int maxlen;
1415224638Sbrooks
1416224638Sbrooks		/* If a user tries to set the size to 0 set it to 1KB. */
1417224638Sbrooks		if (options->hpn_buffer_size == 0)
1418224638Sbrooks			options->hpn_buffer_size = 1024;
1419224638Sbrooks		/* Limit the buffer to BUFFER_MAX_LEN. */
1420224638Sbrooks		maxlen = buffer_get_max_len();
1421224638Sbrooks		if (options->hpn_buffer_size > (maxlen / 1024)) {
1422224638Sbrooks			debug("User requested buffer larger than %ub: %ub. "
1423224638Sbrooks			    "Request reverted to %ub", maxlen,
1424224638Sbrooks			    options->hpn_buffer_size * 1024, maxlen);
1425224638Sbrooks			options->hpn_buffer_size = maxlen;
1426224638Sbrooks		}
1427224638Sbrooks		debug("hpn_buffer_size set to %d", options->hpn_buffer_size);
1428224638Sbrooks	}
1429224638Sbrooks	if (options->tcp_rcv_buf == 0)
1430224638Sbrooks		options->tcp_rcv_buf = 1;
1431224638Sbrooks	if (options->tcp_rcv_buf > -1)
1432224638Sbrooks		options->tcp_rcv_buf *= 1024;
1433224638Sbrooks	if (options->tcp_rcv_buf_poll == -1)
1434224638Sbrooks		options->tcp_rcv_buf_poll = 1;
1435224638Sbrooks#ifdef	NONE_CIPHER_ENABLED
1436224638Sbrooks	/* options->none_enabled must not be set by default */
1437224638Sbrooks	if (options->none_switch == -1)
1438224638Sbrooks		options->none_switch = 0;
1439224638Sbrooks#endif
144057429Smarkm}
1441147005Sdes
1442147005Sdes/*
1443147005Sdes * parse_forward
1444147005Sdes * parses a string containing a port forwarding specification of the form:
1445192595Sdes *   dynamicfwd == 0
1446147005Sdes *	[listenhost:]listenport:connecthost:connectport
1447192595Sdes *   dynamicfwd == 1
1448192595Sdes *	[listenhost:]listenport
1449147005Sdes * returns number of arguments parsed or zero on error
1450147005Sdes */
1451147005Sdesint
1452192595Sdesparse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
1453147005Sdes{
1454147005Sdes	int i;
1455147005Sdes	char *p, *cp, *fwdarg[4];
1456147005Sdes
1457147005Sdes	memset(fwd, '\0', sizeof(*fwd));
1458147005Sdes
1459147005Sdes	cp = p = xstrdup(fwdspec);
1460147005Sdes
1461147005Sdes	/* skip leading spaces */
1462181111Sdes	while (isspace(*cp))
1463147005Sdes		cp++;
1464147005Sdes
1465147005Sdes	for (i = 0; i < 4; ++i)
1466147005Sdes		if ((fwdarg[i] = hpdelim(&cp)) == NULL)
1467147005Sdes			break;
1468147005Sdes
1469192595Sdes	/* Check for trailing garbage */
1470147005Sdes	if (cp != NULL)
1471147005Sdes		i = 0;	/* failure */
1472147005Sdes
1473147005Sdes	switch (i) {
1474192595Sdes	case 1:
1475192595Sdes		fwd->listen_host = NULL;
1476192595Sdes		fwd->listen_port = a2port(fwdarg[0]);
1477192595Sdes		fwd->connect_host = xstrdup("socks");
1478192595Sdes		break;
1479192595Sdes
1480192595Sdes	case 2:
1481192595Sdes		fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
1482192595Sdes		fwd->listen_port = a2port(fwdarg[1]);
1483192595Sdes		fwd->connect_host = xstrdup("socks");
1484192595Sdes		break;
1485192595Sdes
1486147005Sdes	case 3:
1487147005Sdes		fwd->listen_host = NULL;
1488147005Sdes		fwd->listen_port = a2port(fwdarg[0]);
1489147005Sdes		fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
1490147005Sdes		fwd->connect_port = a2port(fwdarg[2]);
1491147005Sdes		break;
1492147005Sdes
1493147005Sdes	case 4:
1494147005Sdes		fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
1495147005Sdes		fwd->listen_port = a2port(fwdarg[1]);
1496147005Sdes		fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
1497147005Sdes		fwd->connect_port = a2port(fwdarg[3]);
1498147005Sdes		break;
1499147005Sdes	default:
1500147005Sdes		i = 0; /* failure */
1501147005Sdes	}
1502147005Sdes
1503147005Sdes	xfree(p);
1504147005Sdes
1505192595Sdes	if (dynamicfwd) {
1506192595Sdes		if (!(i == 1 || i == 2))
1507192595Sdes			goto fail_free;
1508192595Sdes	} else {
1509192595Sdes		if (!(i == 3 || i == 4))
1510192595Sdes			goto fail_free;
1511192595Sdes		if (fwd->connect_port <= 0)
1512192595Sdes			goto fail_free;
1513192595Sdes	}
1514192595Sdes
1515192595Sdes	if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0))
1516147005Sdes		goto fail_free;
1517147005Sdes
1518147005Sdes	if (fwd->connect_host != NULL &&
1519147005Sdes	    strlen(fwd->connect_host) >= NI_MAXHOST)
1520147005Sdes		goto fail_free;
1521192595Sdes	if (fwd->listen_host != NULL &&
1522192595Sdes	    strlen(fwd->listen_host) >= NI_MAXHOST)
1523192595Sdes		goto fail_free;
1524147005Sdes
1525192595Sdes
1526147005Sdes	return (i);
1527147005Sdes
1528147005Sdes fail_free:
1529192595Sdes	if (fwd->connect_host != NULL) {
1530147005Sdes		xfree(fwd->connect_host);
1531192595Sdes		fwd->connect_host = NULL;
1532192595Sdes	}
1533192595Sdes	if (fwd->listen_host != NULL) {
1534147005Sdes		xfree(fwd->listen_host);
1535192595Sdes		fwd->listen_host = NULL;
1536192595Sdes	}
1537147005Sdes	return (0);
1538147005Sdes}
1539