10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * Author: Tatu Ylonen <ylo@cs.hut.fi>
30Sstevel@tonic-gate  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
40Sstevel@tonic-gate  *                    All rights reserved
50Sstevel@tonic-gate  * Functions for reading the configuration files.
60Sstevel@tonic-gate  *
70Sstevel@tonic-gate  * As far as I am concerned, the code I have written for this software
80Sstevel@tonic-gate  * can be used freely for any purpose.  Any derived versions of this
90Sstevel@tonic-gate  * software must be clearly marked as such, and if the derived work is
100Sstevel@tonic-gate  * incompatible with the protocol description in the RFC file, it must be
110Sstevel@tonic-gate  * called by a name other than "ssh" or "Secure Shell".
120Sstevel@tonic-gate  */
130Sstevel@tonic-gate /*
143946Sjp161948  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
150Sstevel@tonic-gate  * Use is subject to license terms.
160Sstevel@tonic-gate  */
170Sstevel@tonic-gate 
180Sstevel@tonic-gate #include "includes.h"
190Sstevel@tonic-gate RCSID("$OpenBSD: readconf.c,v 1.100 2002/06/19 00:27:55 deraadt Exp $");
200Sstevel@tonic-gate 
210Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
220Sstevel@tonic-gate 
230Sstevel@tonic-gate #include "ssh.h"
240Sstevel@tonic-gate #include "xmalloc.h"
250Sstevel@tonic-gate #include "compat.h"
260Sstevel@tonic-gate #include "cipher.h"
270Sstevel@tonic-gate #include "pathnames.h"
280Sstevel@tonic-gate #include "log.h"
290Sstevel@tonic-gate #include "readconf.h"
300Sstevel@tonic-gate #include "match.h"
310Sstevel@tonic-gate #include "misc.h"
320Sstevel@tonic-gate #include "kex.h"
330Sstevel@tonic-gate #include "mac.h"
340Sstevel@tonic-gate 
350Sstevel@tonic-gate /* Format of the configuration file:
360Sstevel@tonic-gate 
370Sstevel@tonic-gate    # Configuration data is parsed as follows:
380Sstevel@tonic-gate    #  1. command line options
390Sstevel@tonic-gate    #  2. user-specific file
400Sstevel@tonic-gate    #  3. system-wide file
410Sstevel@tonic-gate    # Any configuration value is only changed the first time it is set.
420Sstevel@tonic-gate    # Thus, host-specific definitions should be at the beginning of the
430Sstevel@tonic-gate    # configuration file, and defaults at the end.
440Sstevel@tonic-gate 
450Sstevel@tonic-gate    # Host-specific declarations.  These may override anything above.  A single
460Sstevel@tonic-gate    # host may match multiple declarations; these are processed in the order
470Sstevel@tonic-gate    # that they are given in.
480Sstevel@tonic-gate 
490Sstevel@tonic-gate    Host *.ngs.fi ngs.fi
500Sstevel@tonic-gate      User foo
510Sstevel@tonic-gate 
520Sstevel@tonic-gate    Host fake.com
530Sstevel@tonic-gate      HostName another.host.name.real.org
540Sstevel@tonic-gate      User blaah
550Sstevel@tonic-gate      Port 34289
560Sstevel@tonic-gate      ForwardX11 no
570Sstevel@tonic-gate      ForwardAgent no
580Sstevel@tonic-gate 
590Sstevel@tonic-gate    Host books.com
600Sstevel@tonic-gate      RemoteForward 9999 shadows.cs.hut.fi:9999
610Sstevel@tonic-gate      Cipher 3des
620Sstevel@tonic-gate 
630Sstevel@tonic-gate    Host fascist.blob.com
640Sstevel@tonic-gate      Port 23123
650Sstevel@tonic-gate      User tylonen
660Sstevel@tonic-gate      RhostsAuthentication no
670Sstevel@tonic-gate      PasswordAuthentication no
680Sstevel@tonic-gate 
690Sstevel@tonic-gate    Host puukko.hut.fi
700Sstevel@tonic-gate      User t35124p
710Sstevel@tonic-gate      ProxyCommand ssh-proxy %h %p
720Sstevel@tonic-gate 
730Sstevel@tonic-gate    Host *.fr
740Sstevel@tonic-gate      PublicKeyAuthentication no
750Sstevel@tonic-gate 
760Sstevel@tonic-gate    Host *.su
770Sstevel@tonic-gate      Cipher none
780Sstevel@tonic-gate      PasswordAuthentication no
790Sstevel@tonic-gate 
800Sstevel@tonic-gate    # Defaults for various options
810Sstevel@tonic-gate    Host *
820Sstevel@tonic-gate      ForwardAgent no
830Sstevel@tonic-gate      ForwardX11 no
840Sstevel@tonic-gate      RhostsAuthentication yes
850Sstevel@tonic-gate      PasswordAuthentication yes
860Sstevel@tonic-gate      RSAAuthentication yes
870Sstevel@tonic-gate      RhostsRSAAuthentication yes
880Sstevel@tonic-gate      StrictHostKeyChecking yes
890Sstevel@tonic-gate      KeepAlives no
900Sstevel@tonic-gate      IdentityFile ~/.ssh/identity
910Sstevel@tonic-gate      Port 22
920Sstevel@tonic-gate      EscapeChar ~
930Sstevel@tonic-gate 
940Sstevel@tonic-gate */
950Sstevel@tonic-gate 
960Sstevel@tonic-gate /* Keyword tokens. */
970Sstevel@tonic-gate 
980Sstevel@tonic-gate typedef enum {
990Sstevel@tonic-gate 	oBadOption,
1004907Sjp161948 	oForwardAgent, oForwardX11, oForwardX11Trusted, oGatewayPorts,
1014907Sjp161948 	oRhostsAuthentication,
1020Sstevel@tonic-gate 	oPasswordAuthentication, oRSAAuthentication,
1030Sstevel@tonic-gate 	oChallengeResponseAuthentication, oXAuthLocation,
1040Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5)
1050Sstevel@tonic-gate 	oKerberosAuthentication,
1060Sstevel@tonic-gate #endif
1070Sstevel@tonic-gate #ifdef GSSAPI
1080Sstevel@tonic-gate 	oGssKeyEx, oGssAuthentication, oGssDelegateCreds,
1090Sstevel@tonic-gate #ifdef GSI
1100Sstevel@tonic-gate 	oGssGlobusDelegateLimitedCreds,
1110Sstevel@tonic-gate #endif /* GSI */
1120Sstevel@tonic-gate #endif /* GSSAPI */
1130Sstevel@tonic-gate #if defined(AFS) || defined(KRB5)
1140Sstevel@tonic-gate 	oKerberosTgtPassing,
1150Sstevel@tonic-gate #endif
1160Sstevel@tonic-gate #ifdef AFS
1170Sstevel@tonic-gate 	oAFSTokenPassing,
1180Sstevel@tonic-gate #endif
1190Sstevel@tonic-gate 	oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
1200Sstevel@tonic-gate 	oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
1210Sstevel@tonic-gate 	oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
1220Sstevel@tonic-gate 	oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
1230Sstevel@tonic-gate 	oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts,
1240Sstevel@tonic-gate 	oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
1250Sstevel@tonic-gate 	oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
1260Sstevel@tonic-gate 	oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
1270Sstevel@tonic-gate 	oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
1280Sstevel@tonic-gate 	oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
1290Sstevel@tonic-gate 	oClearAllForwardings, oNoHostAuthenticationForLocalhost,
1303946Sjp161948 	oFallBackToRsh, oUseRsh, oConnectTimeout,
131*4958Sjp161948 	oServerAliveInterval, oServerAliveCountMax, oDisableBanner,
1320Sstevel@tonic-gate 	oDeprecated
1330Sstevel@tonic-gate } OpCodes;
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate /* Textual representations of the tokens. */
1360Sstevel@tonic-gate 
1370Sstevel@tonic-gate static struct {
1380Sstevel@tonic-gate 	const char *name;
1390Sstevel@tonic-gate 	OpCodes opcode;
1400Sstevel@tonic-gate } keywords[] = {
1410Sstevel@tonic-gate 	{ "forwardagent", oForwardAgent },
1420Sstevel@tonic-gate 	{ "forwardx11", oForwardX11 },
1434907Sjp161948 	{ "forwardx11trusted", oForwardX11Trusted },
1440Sstevel@tonic-gate 	{ "xauthlocation", oXAuthLocation },
1450Sstevel@tonic-gate 	{ "gatewayports", oGatewayPorts },
1460Sstevel@tonic-gate 	{ "useprivilegedport", oUsePrivilegedPort },
1470Sstevel@tonic-gate 	{ "rhostsauthentication", oRhostsAuthentication },
1480Sstevel@tonic-gate 	{ "passwordauthentication", oPasswordAuthentication },
1490Sstevel@tonic-gate 	{ "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
1500Sstevel@tonic-gate 	{ "kbdinteractivedevices", oKbdInteractiveDevices },
1510Sstevel@tonic-gate 	{ "rsaauthentication", oRSAAuthentication },
1520Sstevel@tonic-gate 	{ "pubkeyauthentication", oPubkeyAuthentication },
1530Sstevel@tonic-gate 	{ "dsaauthentication", oPubkeyAuthentication },		    /* alias */
1540Sstevel@tonic-gate 	{ "rhostsrsaauthentication", oRhostsRSAAuthentication },
1550Sstevel@tonic-gate 	{ "hostbasedauthentication", oHostbasedAuthentication },
1560Sstevel@tonic-gate 	{ "challengeresponseauthentication", oChallengeResponseAuthentication },
1570Sstevel@tonic-gate 	{ "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
1580Sstevel@tonic-gate 	{ "tisauthentication", oChallengeResponseAuthentication },  /* alias */
1590Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5)
1600Sstevel@tonic-gate 	{ "kerberosauthentication", oKerberosAuthentication },
1610Sstevel@tonic-gate #endif
1620Sstevel@tonic-gate #ifdef GSSAPI
1630Sstevel@tonic-gate 	{ "gssapikeyexchange", oGssKeyEx },
1640Sstevel@tonic-gate 	{ "gssapiauthentication", oGssAuthentication },
1650Sstevel@tonic-gate 	{ "gssapidelegatecredentials", oGssDelegateCreds },
1660Sstevel@tonic-gate 	{ "gsskeyex", oGssKeyEx },				/* alias */
1670Sstevel@tonic-gate 	{ "gssauthentication", oGssAuthentication },		/* alias */
1680Sstevel@tonic-gate 	{ "gssdelegatecreds", oGssDelegateCreds },		/* alias */
1690Sstevel@tonic-gate #ifdef GSI
1700Sstevel@tonic-gate 	/* For backwards compatability with old 1.2.27 client code */
1710Sstevel@tonic-gate 	{ "forwardgssapiglobusproxy", oGssDelegateCreds }, /* alias */
1720Sstevel@tonic-gate 	{ "forwardgssapiglobuslimitedproxy", oGssGlobusDelegateLimitedCreds },
1730Sstevel@tonic-gate #endif /* GSI */
1740Sstevel@tonic-gate #endif /* GSSAPI */
1750Sstevel@tonic-gate #if defined(AFS) || defined(KRB5)
1760Sstevel@tonic-gate 	{ "kerberostgtpassing", oKerberosTgtPassing },
1770Sstevel@tonic-gate #endif
1780Sstevel@tonic-gate #ifdef AFS
1790Sstevel@tonic-gate 	{ "afstokenpassing", oAFSTokenPassing },
1800Sstevel@tonic-gate #endif
1810Sstevel@tonic-gate 	{ "fallbacktorsh", oFallBackToRsh },
1820Sstevel@tonic-gate 	{ "usersh", oUseRsh },
1830Sstevel@tonic-gate 	{ "identityfile", oIdentityFile },
1840Sstevel@tonic-gate 	{ "identityfile2", oIdentityFile },			/* alias */
1850Sstevel@tonic-gate 	{ "hostname", oHostName },
1860Sstevel@tonic-gate 	{ "hostkeyalias", oHostKeyAlias },
1870Sstevel@tonic-gate 	{ "proxycommand", oProxyCommand },
1880Sstevel@tonic-gate 	{ "port", oPort },
1890Sstevel@tonic-gate 	{ "cipher", oCipher },
1900Sstevel@tonic-gate 	{ "ciphers", oCiphers },
1910Sstevel@tonic-gate 	{ "macs", oMacs },
1920Sstevel@tonic-gate 	{ "protocol", oProtocol },
1930Sstevel@tonic-gate 	{ "remoteforward", oRemoteForward },
1940Sstevel@tonic-gate 	{ "localforward", oLocalForward },
1950Sstevel@tonic-gate 	{ "user", oUser },
1960Sstevel@tonic-gate 	{ "host", oHost },
1970Sstevel@tonic-gate 	{ "escapechar", oEscapeChar },
1980Sstevel@tonic-gate 	{ "globalknownhostsfile", oGlobalKnownHostsFile },
1990Sstevel@tonic-gate 	{ "userknownhostsfile", oUserKnownHostsFile },		/* obsolete */
2000Sstevel@tonic-gate 	{ "globalknownhostsfile2", oGlobalKnownHostsFile2 },
2010Sstevel@tonic-gate 	{ "userknownhostsfile2", oUserKnownHostsFile2 },	/* obsolete */
2020Sstevel@tonic-gate 	{ "connectionattempts", oConnectionAttempts },
2030Sstevel@tonic-gate 	{ "batchmode", oBatchMode },
2040Sstevel@tonic-gate 	{ "checkhostip", oCheckHostIP },
2050Sstevel@tonic-gate 	{ "stricthostkeychecking", oStrictHostKeyChecking },
2060Sstevel@tonic-gate 	{ "compression", oCompression },
2070Sstevel@tonic-gate 	{ "compressionlevel", oCompressionLevel },
2080Sstevel@tonic-gate 	{ "keepalive", oKeepAlives },
2090Sstevel@tonic-gate 	{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
2100Sstevel@tonic-gate 	{ "loglevel", oLogLevel },
2110Sstevel@tonic-gate 	{ "dynamicforward", oDynamicForward },
2120Sstevel@tonic-gate 	{ "preferredauthentications", oPreferredAuthentications },
2130Sstevel@tonic-gate 	{ "hostkeyalgorithms", oHostKeyAlgorithms },
2140Sstevel@tonic-gate 	{ "bindaddress", oBindAddress },
2150Sstevel@tonic-gate 	{ "smartcarddevice", oSmartcardDevice },
2160Sstevel@tonic-gate 	{ "clearallforwardings", oClearAllForwardings },
2170Sstevel@tonic-gate 	{ "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
2183946Sjp161948 	{ "connecttimeout", oConnectTimeout },
2194668Sjp161948 	{ "serveraliveinterval", oServerAliveInterval },
2204668Sjp161948 	{ "serveralivecountmax", oServerAliveCountMax },
221*4958Sjp161948 	{ "disablebanner", oDisableBanner },
2220Sstevel@tonic-gate 	{ NULL, oBadOption }
2230Sstevel@tonic-gate };
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate /*
2260Sstevel@tonic-gate  * Adds a local TCP/IP port forward to options.  Never returns if there is an
2270Sstevel@tonic-gate  * error.
2280Sstevel@tonic-gate  */
2290Sstevel@tonic-gate 
2300Sstevel@tonic-gate void
2310Sstevel@tonic-gate add_local_forward(Options *options, u_short port, const char *host,
2320Sstevel@tonic-gate 		  u_short host_port)
2330Sstevel@tonic-gate {
2340Sstevel@tonic-gate 	Forward *fwd;
2350Sstevel@tonic-gate #ifndef NO_IPPORT_RESERVED_CONCEPT
2360Sstevel@tonic-gate 	extern uid_t original_real_uid;
2370Sstevel@tonic-gate 	if (port < IPPORT_RESERVED && original_real_uid != 0)
2380Sstevel@tonic-gate 		fatal("Privileged ports can only be forwarded by root.");
2390Sstevel@tonic-gate #endif
2400Sstevel@tonic-gate 	if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
2410Sstevel@tonic-gate 		fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
2420Sstevel@tonic-gate 	fwd = &options->local_forwards[options->num_local_forwards++];
2430Sstevel@tonic-gate 	fwd->port = port;
2440Sstevel@tonic-gate 	fwd->host = xstrdup(host);
2450Sstevel@tonic-gate 	fwd->host_port = host_port;
2460Sstevel@tonic-gate }
2470Sstevel@tonic-gate 
2480Sstevel@tonic-gate /*
2490Sstevel@tonic-gate  * Adds a remote TCP/IP port forward to options.  Never returns if there is
2500Sstevel@tonic-gate  * an error.
2510Sstevel@tonic-gate  */
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate void
2540Sstevel@tonic-gate add_remote_forward(Options *options, u_short port, const char *host,
2550Sstevel@tonic-gate 		   u_short host_port)
2560Sstevel@tonic-gate {
2570Sstevel@tonic-gate 	Forward *fwd;
2580Sstevel@tonic-gate 	if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
2590Sstevel@tonic-gate 		fatal("Too many remote forwards (max %d).",
2600Sstevel@tonic-gate 		    SSH_MAX_FORWARDS_PER_DIRECTION);
2610Sstevel@tonic-gate 	fwd = &options->remote_forwards[options->num_remote_forwards++];
2620Sstevel@tonic-gate 	fwd->port = port;
2630Sstevel@tonic-gate 	fwd->host = xstrdup(host);
2640Sstevel@tonic-gate 	fwd->host_port = host_port;
2650Sstevel@tonic-gate }
2660Sstevel@tonic-gate 
2670Sstevel@tonic-gate static void
2680Sstevel@tonic-gate clear_forwardings(Options *options)
2690Sstevel@tonic-gate {
2700Sstevel@tonic-gate 	int i;
2710Sstevel@tonic-gate 
2720Sstevel@tonic-gate 	for (i = 0; i < options->num_local_forwards; i++)
2730Sstevel@tonic-gate 		xfree(options->local_forwards[i].host);
2740Sstevel@tonic-gate 	options->num_local_forwards = 0;
2750Sstevel@tonic-gate 	for (i = 0; i < options->num_remote_forwards; i++)
2760Sstevel@tonic-gate 		xfree(options->remote_forwards[i].host);
2770Sstevel@tonic-gate 	options->num_remote_forwards = 0;
2780Sstevel@tonic-gate }
2790Sstevel@tonic-gate 
2800Sstevel@tonic-gate /*
2810Sstevel@tonic-gate  * Returns the number of the token pointed to by cp or oBadOption.
2820Sstevel@tonic-gate  */
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate static OpCodes
2850Sstevel@tonic-gate parse_token(const char *cp, const char *filename, int linenum)
2860Sstevel@tonic-gate {
2870Sstevel@tonic-gate 	u_int i;
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate 	for (i = 0; keywords[i].name; i++)
2900Sstevel@tonic-gate 		if (strcasecmp(cp, keywords[i].name) == 0)
2910Sstevel@tonic-gate 			return keywords[i].opcode;
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate 	error("%s: line %d: Bad configuration option: %s",
2940Sstevel@tonic-gate 	    filename, linenum, cp);
2950Sstevel@tonic-gate 	return oBadOption;
2960Sstevel@tonic-gate }
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate /*
2990Sstevel@tonic-gate  * Processes a single option line as used in the configuration files. This
3000Sstevel@tonic-gate  * only sets those values that have not already been set.
3010Sstevel@tonic-gate  */
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate int
3040Sstevel@tonic-gate process_config_line(Options *options, const char *host,
3050Sstevel@tonic-gate 		    char *line, const char *filename, int linenum,
3060Sstevel@tonic-gate 		    int *activep)
3070Sstevel@tonic-gate {
3080Sstevel@tonic-gate 	char buf[256], *s, *string, **charptr, *endofnumber, *keyword, *arg;
3090Sstevel@tonic-gate 	int opcode, *intptr, value;
3100Sstevel@tonic-gate 	u_short fwd_port, fwd_host_port;
3110Sstevel@tonic-gate 	char sfwd_host_port[6];
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate 	s = line;
3140Sstevel@tonic-gate 	/* Get the keyword. (Each line is supposed to begin with a keyword). */
3150Sstevel@tonic-gate 	keyword = strdelim(&s);
3160Sstevel@tonic-gate 	/* Ignore leading whitespace. */
3170Sstevel@tonic-gate 	if (*keyword == '\0')
3180Sstevel@tonic-gate 		keyword = strdelim(&s);
3190Sstevel@tonic-gate 	if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
3200Sstevel@tonic-gate 		return 0;
3210Sstevel@tonic-gate 
3220Sstevel@tonic-gate 	opcode = parse_token(keyword, filename, linenum);
3230Sstevel@tonic-gate 
3240Sstevel@tonic-gate 	switch (opcode) {
3250Sstevel@tonic-gate 	case oBadOption:
3260Sstevel@tonic-gate 		/* don't panic, but count bad options */
3270Sstevel@tonic-gate 		return -1;
3280Sstevel@tonic-gate 		/* NOTREACHED */
3293946Sjp161948 	case oConnectTimeout:
3303946Sjp161948 		intptr = &options->connection_timeout;
3313946Sjp161948 parse_time:
3323946Sjp161948 		arg = strdelim(&s);
3333946Sjp161948 		if (!arg || *arg == '\0')
3343946Sjp161948 			fatal("%s line %d: missing time value.",
3353946Sjp161948 			    filename, linenum);
3363946Sjp161948 		if ((value = convtime(arg)) == -1)
3373946Sjp161948 			fatal("%s line %d: invalid time value.",
3383946Sjp161948 			    filename, linenum);
3393984Sjp161948 		if (*activep && *intptr == -1)
3403946Sjp161948 			*intptr = value;
3413946Sjp161948 		break;
3423946Sjp161948 
3430Sstevel@tonic-gate 	case oForwardAgent:
3440Sstevel@tonic-gate 		intptr = &options->forward_agent;
3450Sstevel@tonic-gate parse_flag:
3460Sstevel@tonic-gate 		arg = strdelim(&s);
3470Sstevel@tonic-gate 		if (!arg || *arg == '\0')
3480Sstevel@tonic-gate 			fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
3490Sstevel@tonic-gate 		value = 0;	/* To avoid compiler warning... */
3500Sstevel@tonic-gate 		if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
3510Sstevel@tonic-gate 			value = 1;
3520Sstevel@tonic-gate 		else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
3530Sstevel@tonic-gate 			value = 0;
3540Sstevel@tonic-gate 		else
3550Sstevel@tonic-gate 			fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
3560Sstevel@tonic-gate 		if (*activep && *intptr == -1)
3570Sstevel@tonic-gate 			*intptr = value;
3580Sstevel@tonic-gate 		break;
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate 	case oForwardX11:
3610Sstevel@tonic-gate 		intptr = &options->forward_x11;
3620Sstevel@tonic-gate 		goto parse_flag;
3630Sstevel@tonic-gate 
3644907Sjp161948 	case oForwardX11Trusted:
3654907Sjp161948 		intptr = &options->forward_x11_trusted;
3664907Sjp161948 		goto parse_flag;
3674907Sjp161948 
3680Sstevel@tonic-gate 	case oGatewayPorts:
3690Sstevel@tonic-gate 		intptr = &options->gateway_ports;
3700Sstevel@tonic-gate 		goto parse_flag;
3710Sstevel@tonic-gate 
3720Sstevel@tonic-gate 	case oUsePrivilegedPort:
3730Sstevel@tonic-gate 		intptr = &options->use_privileged_port;
3740Sstevel@tonic-gate 		goto parse_flag;
3750Sstevel@tonic-gate 
3760Sstevel@tonic-gate 	case oRhostsAuthentication:
3770Sstevel@tonic-gate 		intptr = &options->rhosts_authentication;
3780Sstevel@tonic-gate 		goto parse_flag;
3790Sstevel@tonic-gate 
3800Sstevel@tonic-gate 	case oPasswordAuthentication:
3810Sstevel@tonic-gate 		intptr = &options->password_authentication;
3820Sstevel@tonic-gate 		goto parse_flag;
3830Sstevel@tonic-gate 
3840Sstevel@tonic-gate 	case oKbdInteractiveAuthentication:
3850Sstevel@tonic-gate 		intptr = &options->kbd_interactive_authentication;
3860Sstevel@tonic-gate 		goto parse_flag;
3870Sstevel@tonic-gate 
3880Sstevel@tonic-gate 	case oKbdInteractiveDevices:
3890Sstevel@tonic-gate 		charptr = &options->kbd_interactive_devices;
3900Sstevel@tonic-gate 		goto parse_string;
3910Sstevel@tonic-gate 
3920Sstevel@tonic-gate 	case oPubkeyAuthentication:
3930Sstevel@tonic-gate 		intptr = &options->pubkey_authentication;
3940Sstevel@tonic-gate 		goto parse_flag;
3950Sstevel@tonic-gate 
3960Sstevel@tonic-gate 	case oRSAAuthentication:
3970Sstevel@tonic-gate 		intptr = &options->rsa_authentication;
3980Sstevel@tonic-gate 		goto parse_flag;
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate 	case oRhostsRSAAuthentication:
4010Sstevel@tonic-gate 		intptr = &options->rhosts_rsa_authentication;
4020Sstevel@tonic-gate 		goto parse_flag;
4030Sstevel@tonic-gate 
4040Sstevel@tonic-gate 	case oHostbasedAuthentication:
4050Sstevel@tonic-gate 		intptr = &options->hostbased_authentication;
4060Sstevel@tonic-gate 		goto parse_flag;
4070Sstevel@tonic-gate 
4080Sstevel@tonic-gate 	case oChallengeResponseAuthentication:
4090Sstevel@tonic-gate 		intptr = &options->challenge_response_authentication;
4100Sstevel@tonic-gate 		goto parse_flag;
4110Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5)
4120Sstevel@tonic-gate 	case oKerberosAuthentication:
4130Sstevel@tonic-gate 		intptr = &options->kerberos_authentication;
4140Sstevel@tonic-gate 		goto parse_flag;
4150Sstevel@tonic-gate #endif
4160Sstevel@tonic-gate #ifdef GSSAPI
4170Sstevel@tonic-gate 	case oGssKeyEx:
4180Sstevel@tonic-gate 		intptr = &options->gss_keyex;
4190Sstevel@tonic-gate 		goto parse_flag;
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate 	case oGssAuthentication:
4220Sstevel@tonic-gate 		intptr = &options->gss_authentication;
4230Sstevel@tonic-gate 		goto parse_flag;
4240Sstevel@tonic-gate 
4250Sstevel@tonic-gate 	case oGssDelegateCreds:
4260Sstevel@tonic-gate 		intptr = &options->gss_deleg_creds;
4270Sstevel@tonic-gate 		goto parse_flag;
4280Sstevel@tonic-gate 
4290Sstevel@tonic-gate #ifdef GSI
4300Sstevel@tonic-gate 	case oGssGlobusDelegateLimitedCreds:
4310Sstevel@tonic-gate 		intptr = &options->gss_globus_deleg_limited_proxy;
4320Sstevel@tonic-gate 		goto parse_flag;
4330Sstevel@tonic-gate #endif /* GSI */
4340Sstevel@tonic-gate 
4350Sstevel@tonic-gate #endif /* GSSAPI */
4360Sstevel@tonic-gate 
4370Sstevel@tonic-gate #if defined(AFS) || defined(KRB5)
4380Sstevel@tonic-gate 	case oKerberosTgtPassing:
4390Sstevel@tonic-gate 		intptr = &options->kerberos_tgt_passing;
4400Sstevel@tonic-gate 		goto parse_flag;
4410Sstevel@tonic-gate #endif
4420Sstevel@tonic-gate #ifdef AFS
4430Sstevel@tonic-gate 	case oAFSTokenPassing:
4440Sstevel@tonic-gate 		intptr = &options->afs_token_passing;
4450Sstevel@tonic-gate 		goto parse_flag;
4460Sstevel@tonic-gate #endif
4470Sstevel@tonic-gate 	case oFallBackToRsh:
4480Sstevel@tonic-gate 		intptr = &options->fallback_to_rsh;
4490Sstevel@tonic-gate 		goto parse_flag;
4500Sstevel@tonic-gate 
4510Sstevel@tonic-gate 	case oUseRsh:
4520Sstevel@tonic-gate 		intptr = &options->use_rsh;
4530Sstevel@tonic-gate 		goto parse_flag;
4540Sstevel@tonic-gate 
4550Sstevel@tonic-gate 	case oBatchMode:
4560Sstevel@tonic-gate 		intptr = &options->batch_mode;
4570Sstevel@tonic-gate 		goto parse_flag;
4580Sstevel@tonic-gate 
4590Sstevel@tonic-gate 	case oCheckHostIP:
4600Sstevel@tonic-gate 		intptr = &options->check_host_ip;
4610Sstevel@tonic-gate 		goto parse_flag;
4620Sstevel@tonic-gate 
4630Sstevel@tonic-gate 	case oStrictHostKeyChecking:
4640Sstevel@tonic-gate 		intptr = &options->strict_host_key_checking;
4650Sstevel@tonic-gate 		arg = strdelim(&s);
4660Sstevel@tonic-gate 		if (!arg || *arg == '\0')
4670Sstevel@tonic-gate 			fatal("%.200s line %d: Missing yes/no/ask argument.",
4680Sstevel@tonic-gate 			    filename, linenum);
4690Sstevel@tonic-gate 		value = 0;	/* To avoid compiler warning... */
4700Sstevel@tonic-gate 		if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
4710Sstevel@tonic-gate 			value = 1;
4720Sstevel@tonic-gate 		else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
4730Sstevel@tonic-gate 			value = 0;
4740Sstevel@tonic-gate 		else if (strcmp(arg, "ask") == 0)
4750Sstevel@tonic-gate 			value = 2;
4760Sstevel@tonic-gate 		else
4770Sstevel@tonic-gate 			fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
4780Sstevel@tonic-gate 		if (*activep && *intptr == -1)
4790Sstevel@tonic-gate 			*intptr = value;
4800Sstevel@tonic-gate 		break;
4810Sstevel@tonic-gate 
4820Sstevel@tonic-gate 	case oCompression:
4830Sstevel@tonic-gate 		intptr = &options->compression;
4840Sstevel@tonic-gate 		goto parse_flag;
4850Sstevel@tonic-gate 
4860Sstevel@tonic-gate 	case oKeepAlives:
4870Sstevel@tonic-gate 		intptr = &options->keepalives;
4880Sstevel@tonic-gate 		goto parse_flag;
4890Sstevel@tonic-gate 
4900Sstevel@tonic-gate 	case oNoHostAuthenticationForLocalhost:
4910Sstevel@tonic-gate 		intptr = &options->no_host_authentication_for_localhost;
4920Sstevel@tonic-gate 		goto parse_flag;
4930Sstevel@tonic-gate 
4940Sstevel@tonic-gate 	case oNumberOfPasswordPrompts:
4950Sstevel@tonic-gate 		intptr = &options->number_of_password_prompts;
4960Sstevel@tonic-gate 		goto parse_int;
4970Sstevel@tonic-gate 
4980Sstevel@tonic-gate 	case oCompressionLevel:
4990Sstevel@tonic-gate 		intptr = &options->compression_level;
5000Sstevel@tonic-gate 		goto parse_int;
5010Sstevel@tonic-gate 
5020Sstevel@tonic-gate 	case oIdentityFile:
5030Sstevel@tonic-gate 		arg = strdelim(&s);
5040Sstevel@tonic-gate 		if (!arg || *arg == '\0')
5050Sstevel@tonic-gate 			fatal("%.200s line %d: Missing argument.", filename, linenum);
5060Sstevel@tonic-gate 		if (*activep) {
5070Sstevel@tonic-gate 			intptr = &options->num_identity_files;
5080Sstevel@tonic-gate 			if (*intptr >= SSH_MAX_IDENTITY_FILES)
5090Sstevel@tonic-gate 				fatal("%.200s line %d: Too many identity files specified (max %d).",
5100Sstevel@tonic-gate 				    filename, linenum, SSH_MAX_IDENTITY_FILES);
5110Sstevel@tonic-gate 			charptr =  &options->identity_files[*intptr];
5120Sstevel@tonic-gate 			*charptr = xstrdup(arg);
5130Sstevel@tonic-gate 			*intptr = *intptr + 1;
5140Sstevel@tonic-gate 		}
5150Sstevel@tonic-gate 		break;
5160Sstevel@tonic-gate 
5170Sstevel@tonic-gate 	case oXAuthLocation:
5180Sstevel@tonic-gate 		charptr=&options->xauth_location;
5190Sstevel@tonic-gate 		goto parse_string;
5200Sstevel@tonic-gate 
5210Sstevel@tonic-gate 	case oUser:
5220Sstevel@tonic-gate 		charptr = &options->user;
5230Sstevel@tonic-gate parse_string:
5240Sstevel@tonic-gate 		arg = strdelim(&s);
5250Sstevel@tonic-gate 		if (!arg || *arg == '\0')
5260Sstevel@tonic-gate 			fatal("%.200s line %d: Missing argument.", filename, linenum);
5270Sstevel@tonic-gate 		if (*activep && *charptr == NULL)
5280Sstevel@tonic-gate 			*charptr = xstrdup(arg);
5290Sstevel@tonic-gate 		break;
5300Sstevel@tonic-gate 
5310Sstevel@tonic-gate 	case oGlobalKnownHostsFile:
5320Sstevel@tonic-gate 		charptr = &options->system_hostfile;
5330Sstevel@tonic-gate 		goto parse_string;
5340Sstevel@tonic-gate 
5350Sstevel@tonic-gate 	case oUserKnownHostsFile:
5360Sstevel@tonic-gate 		charptr = &options->user_hostfile;
5370Sstevel@tonic-gate 		goto parse_string;
5380Sstevel@tonic-gate 
5390Sstevel@tonic-gate 	case oGlobalKnownHostsFile2:
5400Sstevel@tonic-gate 		charptr = &options->system_hostfile2;
5410Sstevel@tonic-gate 		goto parse_string;
5420Sstevel@tonic-gate 
5430Sstevel@tonic-gate 	case oUserKnownHostsFile2:
5440Sstevel@tonic-gate 		charptr = &options->user_hostfile2;
5450Sstevel@tonic-gate 		goto parse_string;
5460Sstevel@tonic-gate 
5470Sstevel@tonic-gate 	case oHostName:
5480Sstevel@tonic-gate 		charptr = &options->hostname;
5490Sstevel@tonic-gate 		goto parse_string;
5500Sstevel@tonic-gate 
5510Sstevel@tonic-gate 	case oHostKeyAlias:
5520Sstevel@tonic-gate 		charptr = &options->host_key_alias;
5530Sstevel@tonic-gate 		goto parse_string;
5540Sstevel@tonic-gate 
5550Sstevel@tonic-gate 	case oPreferredAuthentications:
5560Sstevel@tonic-gate 		charptr = &options->preferred_authentications;
5570Sstevel@tonic-gate 		goto parse_string;
5580Sstevel@tonic-gate 
5590Sstevel@tonic-gate 	case oBindAddress:
5600Sstevel@tonic-gate 		charptr = &options->bind_address;
5610Sstevel@tonic-gate 		goto parse_string;
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate 	case oSmartcardDevice:
5640Sstevel@tonic-gate 		charptr = &options->smartcard_device;
5650Sstevel@tonic-gate 		goto parse_string;
5660Sstevel@tonic-gate 
5670Sstevel@tonic-gate 	case oProxyCommand:
5680Sstevel@tonic-gate 		charptr = &options->proxy_command;
5690Sstevel@tonic-gate 		string = xstrdup("");
5700Sstevel@tonic-gate 		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
5710Sstevel@tonic-gate 			string = xrealloc(string, strlen(string) + strlen(arg) + 2);
5720Sstevel@tonic-gate 			strcat(string, " ");
5730Sstevel@tonic-gate 			strcat(string, arg);
5740Sstevel@tonic-gate 		}
5750Sstevel@tonic-gate 		if (*activep && *charptr == NULL)
5760Sstevel@tonic-gate 			*charptr = string;
5770Sstevel@tonic-gate 		else
5780Sstevel@tonic-gate 			xfree(string);
5790Sstevel@tonic-gate 		return 0;
5800Sstevel@tonic-gate 
5810Sstevel@tonic-gate 	case oPort:
5820Sstevel@tonic-gate 		intptr = &options->port;
5830Sstevel@tonic-gate parse_int:
5840Sstevel@tonic-gate 		arg = strdelim(&s);
5850Sstevel@tonic-gate 		if (!arg || *arg == '\0')
5860Sstevel@tonic-gate 			fatal("%.200s line %d: Missing argument.", filename, linenum);
5870Sstevel@tonic-gate 		if (arg[0] < '0' || arg[0] > '9')
5880Sstevel@tonic-gate 			fatal("%.200s line %d: Bad number.", filename, linenum);
5890Sstevel@tonic-gate 
5900Sstevel@tonic-gate 		/* Octal, decimal, or hex format? */
5910Sstevel@tonic-gate 		value = strtol(arg, &endofnumber, 0);
5920Sstevel@tonic-gate 		if (arg == endofnumber)
5930Sstevel@tonic-gate 			fatal("%.200s line %d: Bad number.", filename, linenum);
5940Sstevel@tonic-gate 		if (*activep && *intptr == -1)
5950Sstevel@tonic-gate 			*intptr = value;
5960Sstevel@tonic-gate 		break;
5970Sstevel@tonic-gate 
5980Sstevel@tonic-gate 	case oConnectionAttempts:
5990Sstevel@tonic-gate 		intptr = &options->connection_attempts;
6000Sstevel@tonic-gate 		goto parse_int;
6010Sstevel@tonic-gate 
6020Sstevel@tonic-gate 	case oCipher:
6030Sstevel@tonic-gate 		intptr = &options->cipher;
6040Sstevel@tonic-gate 		arg = strdelim(&s);
6050Sstevel@tonic-gate 		if (!arg || *arg == '\0')
6060Sstevel@tonic-gate 			fatal("%.200s line %d: Missing argument.", filename, linenum);
6070Sstevel@tonic-gate 		value = cipher_number(arg);
6080Sstevel@tonic-gate 		if (value == -1)
6090Sstevel@tonic-gate 			fatal("%.200s line %d: Bad cipher '%s'.",
6100Sstevel@tonic-gate 			    filename, linenum, arg ? arg : "<NONE>");
6110Sstevel@tonic-gate 		if (*activep && *intptr == -1)
6120Sstevel@tonic-gate 			*intptr = value;
6130Sstevel@tonic-gate 		break;
6140Sstevel@tonic-gate 
6150Sstevel@tonic-gate 	case oCiphers:
6160Sstevel@tonic-gate 		arg = strdelim(&s);
6170Sstevel@tonic-gate 		if (!arg || *arg == '\0')
6180Sstevel@tonic-gate 			fatal("%.200s line %d: Missing argument.", filename, linenum);
6190Sstevel@tonic-gate 		if (!ciphers_valid(arg))
6200Sstevel@tonic-gate 			fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
6210Sstevel@tonic-gate 			    filename, linenum, arg ? arg : "<NONE>");
6220Sstevel@tonic-gate 		if (*activep && options->ciphers == NULL)
6230Sstevel@tonic-gate 			options->ciphers = xstrdup(arg);
6240Sstevel@tonic-gate 		break;
6250Sstevel@tonic-gate 
6260Sstevel@tonic-gate 	case oMacs:
6270Sstevel@tonic-gate 		arg = strdelim(&s);
6280Sstevel@tonic-gate 		if (!arg || *arg == '\0')
6290Sstevel@tonic-gate 			fatal("%.200s line %d: Missing argument.", filename, linenum);
6300Sstevel@tonic-gate 		if (!mac_valid(arg))
6310Sstevel@tonic-gate 			fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
6320Sstevel@tonic-gate 			    filename, linenum, arg ? arg : "<NONE>");
6330Sstevel@tonic-gate 		if (*activep && options->macs == NULL)
6340Sstevel@tonic-gate 			options->macs = xstrdup(arg);
6350Sstevel@tonic-gate 		break;
6360Sstevel@tonic-gate 
6370Sstevel@tonic-gate 	case oHostKeyAlgorithms:
6380Sstevel@tonic-gate 		arg = strdelim(&s);
6390Sstevel@tonic-gate 		if (!arg || *arg == '\0')
6400Sstevel@tonic-gate 			fatal("%.200s line %d: Missing argument.", filename, linenum);
6410Sstevel@tonic-gate 		if (!key_names_valid2(arg))
6420Sstevel@tonic-gate 			fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
6430Sstevel@tonic-gate 			    filename, linenum, arg ? arg : "<NONE>");
6440Sstevel@tonic-gate 		if (*activep && options->hostkeyalgorithms == NULL)
6450Sstevel@tonic-gate 			options->hostkeyalgorithms = xstrdup(arg);
6460Sstevel@tonic-gate 		break;
6470Sstevel@tonic-gate 
6480Sstevel@tonic-gate 	case oProtocol:
6490Sstevel@tonic-gate 		intptr = &options->protocol;
6500Sstevel@tonic-gate 		arg = strdelim(&s);
6510Sstevel@tonic-gate 		if (!arg || *arg == '\0')
6520Sstevel@tonic-gate 			fatal("%.200s line %d: Missing argument.", filename, linenum);
6530Sstevel@tonic-gate 		value = proto_spec(arg);
6540Sstevel@tonic-gate 		if (value == SSH_PROTO_UNKNOWN)
6550Sstevel@tonic-gate 			fatal("%.200s line %d: Bad protocol spec '%s'.",
6560Sstevel@tonic-gate 			    filename, linenum, arg ? arg : "<NONE>");
6570Sstevel@tonic-gate 		if (*activep && *intptr == SSH_PROTO_UNKNOWN)
6580Sstevel@tonic-gate 			*intptr = value;
6590Sstevel@tonic-gate 		break;
6600Sstevel@tonic-gate 
6610Sstevel@tonic-gate 	case oLogLevel:
6620Sstevel@tonic-gate 		intptr = (int *) &options->log_level;
6630Sstevel@tonic-gate 		arg = strdelim(&s);
6640Sstevel@tonic-gate 		value = log_level_number(arg);
6650Sstevel@tonic-gate 		if (value == SYSLOG_LEVEL_NOT_SET)
6660Sstevel@tonic-gate 			fatal("%.200s line %d: unsupported log level '%s'",
6670Sstevel@tonic-gate 			    filename, linenum, arg ? arg : "<NONE>");
6680Sstevel@tonic-gate 		if (*activep && (LogLevel) *intptr == SYSLOG_LEVEL_NOT_SET)
6690Sstevel@tonic-gate 			*intptr = (LogLevel) value;
6700Sstevel@tonic-gate 		break;
6710Sstevel@tonic-gate 
6720Sstevel@tonic-gate 	case oLocalForward:
6730Sstevel@tonic-gate 	case oRemoteForward:
6740Sstevel@tonic-gate 		arg = strdelim(&s);
6750Sstevel@tonic-gate 		if (!arg || *arg == '\0')
6760Sstevel@tonic-gate 			fatal("%.200s line %d: Missing port argument.",
6770Sstevel@tonic-gate 			    filename, linenum);
6780Sstevel@tonic-gate 		if ((fwd_port = a2port(arg)) == 0)
6790Sstevel@tonic-gate 			fatal("%.200s line %d: Bad listen port.",
6800Sstevel@tonic-gate 			    filename, linenum);
6810Sstevel@tonic-gate 		arg = strdelim(&s);
6820Sstevel@tonic-gate 		if (!arg || *arg == '\0')
6830Sstevel@tonic-gate 			fatal("%.200s line %d: Missing second argument.",
6840Sstevel@tonic-gate 			    filename, linenum);
6850Sstevel@tonic-gate 		if (sscanf(arg, "%255[^:]:%5[0-9]", buf, sfwd_host_port) != 2 &&
6860Sstevel@tonic-gate 		    sscanf(arg, "%255[^/]/%5[0-9]", buf, sfwd_host_port) != 2)
6870Sstevel@tonic-gate 			fatal("%.200s line %d: Bad forwarding specification.",
6880Sstevel@tonic-gate 			    filename, linenum);
6890Sstevel@tonic-gate 		if ((fwd_host_port = a2port(sfwd_host_port)) == 0)
6900Sstevel@tonic-gate 			fatal("%.200s line %d: Bad forwarding port.",
6910Sstevel@tonic-gate 			    filename, linenum);
6920Sstevel@tonic-gate 		if (*activep) {
6930Sstevel@tonic-gate 			if (opcode == oLocalForward)
6940Sstevel@tonic-gate 				add_local_forward(options, fwd_port, buf,
6950Sstevel@tonic-gate 				    fwd_host_port);
6960Sstevel@tonic-gate 			else if (opcode == oRemoteForward)
6970Sstevel@tonic-gate 				add_remote_forward(options, fwd_port, buf,
6980Sstevel@tonic-gate 				    fwd_host_port);
6990Sstevel@tonic-gate 		}
7000Sstevel@tonic-gate 		break;
7010Sstevel@tonic-gate 
7020Sstevel@tonic-gate 	case oDynamicForward:
7030Sstevel@tonic-gate 		arg = strdelim(&s);
7040Sstevel@tonic-gate 		if (!arg || *arg == '\0')
7050Sstevel@tonic-gate 			fatal("%.200s line %d: Missing port argument.",
7060Sstevel@tonic-gate 			    filename, linenum);
7070Sstevel@tonic-gate 		fwd_port = a2port(arg);
7080Sstevel@tonic-gate 		if (fwd_port == 0)
7090Sstevel@tonic-gate 			fatal("%.200s line %d: Badly formatted port number.",
7100Sstevel@tonic-gate 			    filename, linenum);
7110Sstevel@tonic-gate 		if (*activep)
7120Sstevel@tonic-gate 			add_local_forward(options, fwd_port, "socks4", 0);
7130Sstevel@tonic-gate 		break;
7140Sstevel@tonic-gate 
7150Sstevel@tonic-gate 	case oClearAllForwardings:
7160Sstevel@tonic-gate 		intptr = &options->clear_forwardings;
7170Sstevel@tonic-gate 		goto parse_flag;
7180Sstevel@tonic-gate 
7190Sstevel@tonic-gate 	case oHost:
7200Sstevel@tonic-gate 		*activep = 0;
7210Sstevel@tonic-gate 		while ((arg = strdelim(&s)) != NULL && *arg != '\0')
7220Sstevel@tonic-gate 			if (match_pattern(host, arg)) {
7230Sstevel@tonic-gate 				debug("Applying options for %.100s", arg);
7240Sstevel@tonic-gate 				*activep = 1;
7250Sstevel@tonic-gate 				break;
7260Sstevel@tonic-gate 			}
7270Sstevel@tonic-gate 		/* Avoid garbage check below, as strdelim is done. */
7280Sstevel@tonic-gate 		return 0;
7290Sstevel@tonic-gate 
7300Sstevel@tonic-gate 	case oEscapeChar:
7310Sstevel@tonic-gate 		intptr = &options->escape_char;
7320Sstevel@tonic-gate 		arg = strdelim(&s);
7330Sstevel@tonic-gate 		if (!arg || *arg == '\0')
7340Sstevel@tonic-gate 			fatal("%.200s line %d: Missing argument.", filename, linenum);
7350Sstevel@tonic-gate 		if (arg[0] == '^' && arg[2] == 0 &&
7360Sstevel@tonic-gate 		    (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
7370Sstevel@tonic-gate 			value = (u_char) arg[1] & 31;
7380Sstevel@tonic-gate 		else if (strlen(arg) == 1)
7390Sstevel@tonic-gate 			value = (u_char) arg[0];
7400Sstevel@tonic-gate 		else if (strcmp(arg, "none") == 0)
7410Sstevel@tonic-gate 			value = SSH_ESCAPECHAR_NONE;
7420Sstevel@tonic-gate 		else {
7430Sstevel@tonic-gate 			fatal("%.200s line %d: Bad escape character.",
7440Sstevel@tonic-gate 			    filename, linenum);
7450Sstevel@tonic-gate 			/* NOTREACHED */
7460Sstevel@tonic-gate 			value = 0;	/* Avoid compiler warning. */
7470Sstevel@tonic-gate 		}
7480Sstevel@tonic-gate 		if (*activep && *intptr == -1)
7490Sstevel@tonic-gate 			*intptr = value;
7500Sstevel@tonic-gate 		break;
7510Sstevel@tonic-gate 
7524668Sjp161948 	case oServerAliveInterval:
7534668Sjp161948 		intptr = &options->server_alive_interval;
7544668Sjp161948 		goto parse_time;
7554668Sjp161948 
7564668Sjp161948 	case oServerAliveCountMax:
7574668Sjp161948 		intptr = &options->server_alive_count_max;
7584668Sjp161948 		goto parse_int;
7594668Sjp161948 
760*4958Sjp161948 	case oDisableBanner:
761*4958Sjp161948 		arg = strdelim(&s);
762*4958Sjp161948 		if (get_yes_no_flag(&options->disable_banner, arg, filename,
763*4958Sjp161948 		    linenum, *activep) == 1)
764*4958Sjp161948 			break;
765*4958Sjp161948 
766*4958Sjp161948 		if (strcmp(arg, "in-exec-mode") == 0)
767*4958Sjp161948 			options->disable_banner = SSH_NO_BANNER_IN_EXEC_MODE;
768*4958Sjp161948 		else
769*4958Sjp161948 			fatal("%.200s line %d: Bad yes/no/in-exec-mode "
770*4958Sjp161948 			    "argument.", filename, linenum);
771*4958Sjp161948 		break;
772*4958Sjp161948 
7730Sstevel@tonic-gate 	case oDeprecated:
7740Sstevel@tonic-gate 		debug("%s line %d: Deprecated option \"%s\"",
7750Sstevel@tonic-gate 		    filename, linenum, keyword);
7760Sstevel@tonic-gate 		return 0;
7770Sstevel@tonic-gate 
7780Sstevel@tonic-gate 	default:
7790Sstevel@tonic-gate 		fatal("process_config_line: Unimplemented opcode %d", opcode);
7800Sstevel@tonic-gate 	}
7810Sstevel@tonic-gate 
7820Sstevel@tonic-gate 	/* Check that there is no garbage at end of line. */
7830Sstevel@tonic-gate 	if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
7840Sstevel@tonic-gate 		fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
7850Sstevel@tonic-gate 		     filename, linenum, arg);
7860Sstevel@tonic-gate 	}
7870Sstevel@tonic-gate 	return 0;
7880Sstevel@tonic-gate }
7890Sstevel@tonic-gate 
7900Sstevel@tonic-gate 
7910Sstevel@tonic-gate /*
7920Sstevel@tonic-gate  * Reads the config file and modifies the options accordingly.  Options
7930Sstevel@tonic-gate  * should already be initialized before this call.  This never returns if
7940Sstevel@tonic-gate  * there is an error.  If the file does not exist, this returns 0.
7950Sstevel@tonic-gate  */
7960Sstevel@tonic-gate 
7970Sstevel@tonic-gate int
7980Sstevel@tonic-gate read_config_file(const char *filename, const char *host, Options *options)
7990Sstevel@tonic-gate {
8000Sstevel@tonic-gate 	FILE *f;
8010Sstevel@tonic-gate 	char line[1024];
8020Sstevel@tonic-gate 	int active, linenum;
8030Sstevel@tonic-gate 	int bad_options = 0;
8040Sstevel@tonic-gate 
8050Sstevel@tonic-gate 	/* Open the file. */
8060Sstevel@tonic-gate 	f = fopen(filename, "r");
8070Sstevel@tonic-gate 	if (!f)
8080Sstevel@tonic-gate 		return 0;
8090Sstevel@tonic-gate 
8100Sstevel@tonic-gate 	debug("Reading configuration data %.200s", filename);
8110Sstevel@tonic-gate 
8120Sstevel@tonic-gate 	/*
8130Sstevel@tonic-gate 	 * Mark that we are now processing the options.  This flag is turned
8140Sstevel@tonic-gate 	 * on/off by Host specifications.
8150Sstevel@tonic-gate 	 */
8160Sstevel@tonic-gate 	active = 1;
8170Sstevel@tonic-gate 	linenum = 0;
8180Sstevel@tonic-gate 	while (fgets(line, sizeof(line), f)) {
8190Sstevel@tonic-gate 		/* Update line number counter. */
8200Sstevel@tonic-gate 		linenum++;
8210Sstevel@tonic-gate 		if (process_config_line(options, host, line, filename, linenum, &active) != 0)
8220Sstevel@tonic-gate 			bad_options++;
8230Sstevel@tonic-gate 	}
8240Sstevel@tonic-gate 	fclose(f);
8250Sstevel@tonic-gate 	if (bad_options > 0)
8260Sstevel@tonic-gate 		fatal("%s: terminating, %d bad configuration options",
8270Sstevel@tonic-gate 		    filename, bad_options);
8280Sstevel@tonic-gate 	return 1;
8290Sstevel@tonic-gate }
8300Sstevel@tonic-gate 
8310Sstevel@tonic-gate /*
8320Sstevel@tonic-gate  * Initializes options to special values that indicate that they have not yet
8330Sstevel@tonic-gate  * been set.  Read_config_file will only set options with this value. Options
8340Sstevel@tonic-gate  * are processed in the following order: command line, user config file,
8350Sstevel@tonic-gate  * system config file.  Last, fill_default_options is called.
8360Sstevel@tonic-gate  */
8370Sstevel@tonic-gate 
8380Sstevel@tonic-gate void
8390Sstevel@tonic-gate initialize_options(Options * options)
8400Sstevel@tonic-gate {
8410Sstevel@tonic-gate 	memset(options, 'X', sizeof(*options));
8420Sstevel@tonic-gate 	options->forward_agent = -1;
8430Sstevel@tonic-gate 	options->forward_x11 = -1;
8444907Sjp161948 	options->forward_x11_trusted = -1;
8450Sstevel@tonic-gate 	options->xauth_location = NULL;
8460Sstevel@tonic-gate 	options->gateway_ports = -1;
8470Sstevel@tonic-gate 	options->use_privileged_port = -1;
8480Sstevel@tonic-gate 	options->rhosts_authentication = -1;
8490Sstevel@tonic-gate 	options->rsa_authentication = -1;
8500Sstevel@tonic-gate 	options->pubkey_authentication = -1;
8510Sstevel@tonic-gate 	options->challenge_response_authentication = -1;
8520Sstevel@tonic-gate #ifdef GSSAPI
8530Sstevel@tonic-gate         options->gss_keyex = -1;
8540Sstevel@tonic-gate         options->gss_authentication = -1;
8550Sstevel@tonic-gate         options->gss_deleg_creds = -1;
8560Sstevel@tonic-gate #ifdef GSI
8570Sstevel@tonic-gate         options->gss_globus_deleg_limited_proxy = -1;
8580Sstevel@tonic-gate #endif /* GSI */
8590Sstevel@tonic-gate #endif /* GSSAPI */
8600Sstevel@tonic-gate 
8610Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5)
8620Sstevel@tonic-gate 	options->kerberos_authentication = -1;
8630Sstevel@tonic-gate #endif
8640Sstevel@tonic-gate #if defined(AFS) || defined(KRB5)
8650Sstevel@tonic-gate 	options->kerberos_tgt_passing = -1;
8660Sstevel@tonic-gate #endif
8670Sstevel@tonic-gate #ifdef AFS
8680Sstevel@tonic-gate 	options->afs_token_passing = -1;
8690Sstevel@tonic-gate #endif
8700Sstevel@tonic-gate 	options->password_authentication = -1;
8710Sstevel@tonic-gate 	options->kbd_interactive_authentication = -1;
8720Sstevel@tonic-gate 	options->kbd_interactive_devices = NULL;
8730Sstevel@tonic-gate 	options->rhosts_rsa_authentication = -1;
8740Sstevel@tonic-gate 	options->hostbased_authentication = -1;
8750Sstevel@tonic-gate 	options->batch_mode = -1;
8760Sstevel@tonic-gate 	options->check_host_ip = -1;
8770Sstevel@tonic-gate 	options->strict_host_key_checking = -1;
8780Sstevel@tonic-gate 	options->compression = -1;
8790Sstevel@tonic-gate 	options->keepalives = -1;
8800Sstevel@tonic-gate 	options->compression_level = -1;
8810Sstevel@tonic-gate 	options->port = -1;
8820Sstevel@tonic-gate 	options->connection_attempts = -1;
8833946Sjp161948 	options->connection_timeout = -1;
8840Sstevel@tonic-gate 	options->number_of_password_prompts = -1;
8850Sstevel@tonic-gate 	options->cipher = -1;
8860Sstevel@tonic-gate 	options->ciphers = NULL;
8870Sstevel@tonic-gate 	options->macs = NULL;
8880Sstevel@tonic-gate 	options->hostkeyalgorithms = NULL;
8890Sstevel@tonic-gate 	options->protocol = SSH_PROTO_UNKNOWN;
8900Sstevel@tonic-gate 	options->num_identity_files = 0;
8910Sstevel@tonic-gate 	options->hostname = NULL;
8920Sstevel@tonic-gate 	options->host_key_alias = NULL;
8930Sstevel@tonic-gate 	options->proxy_command = NULL;
8940Sstevel@tonic-gate 	options->user = NULL;
8950Sstevel@tonic-gate 	options->escape_char = -1;
8960Sstevel@tonic-gate 	options->system_hostfile = NULL;
8970Sstevel@tonic-gate 	options->user_hostfile = NULL;
8980Sstevel@tonic-gate 	options->system_hostfile2 = NULL;
8990Sstevel@tonic-gate 	options->user_hostfile2 = NULL;
9000Sstevel@tonic-gate 	options->num_local_forwards = 0;
9010Sstevel@tonic-gate 	options->num_remote_forwards = 0;
9020Sstevel@tonic-gate 	options->clear_forwardings = -1;
9030Sstevel@tonic-gate 	options->log_level = SYSLOG_LEVEL_NOT_SET;
9040Sstevel@tonic-gate 	options->preferred_authentications = NULL;
9050Sstevel@tonic-gate 	options->bind_address = NULL;
9060Sstevel@tonic-gate 	options->smartcard_device = NULL;
9070Sstevel@tonic-gate 	options->no_host_authentication_for_localhost = - 1;
9080Sstevel@tonic-gate 	options->fallback_to_rsh = -1;
9090Sstevel@tonic-gate 	options->use_rsh = -1;
9104668Sjp161948 	options->server_alive_interval = -1;
9114668Sjp161948 	options->server_alive_count_max = -1;
912*4958Sjp161948 	options->disable_banner = -1;
9130Sstevel@tonic-gate }
9140Sstevel@tonic-gate 
9150Sstevel@tonic-gate /*
9160Sstevel@tonic-gate  * Called after processing other sources of option data, this fills those
9170Sstevel@tonic-gate  * options for which no value has been specified with their default values.
9180Sstevel@tonic-gate  */
9190Sstevel@tonic-gate 
9200Sstevel@tonic-gate void
9210Sstevel@tonic-gate fill_default_options(Options * options)
9220Sstevel@tonic-gate {
9230Sstevel@tonic-gate 	int len;
9240Sstevel@tonic-gate 
9250Sstevel@tonic-gate 	if (options->forward_agent == -1)
9260Sstevel@tonic-gate 		options->forward_agent = 0;
9270Sstevel@tonic-gate 	if (options->forward_x11 == -1)
9280Sstevel@tonic-gate 		options->forward_x11 = 0;
9294907Sjp161948 	/*
9304907Sjp161948 	 * Unlike OpenSSH, we keep backward compatibility for '-X' option
9314907Sjp161948 	 * which means that X11 forwarding is trusted by default.
9324907Sjp161948 	 */
9334907Sjp161948 	if (options->forward_x11_trusted == -1)
9344907Sjp161948 		options->forward_x11_trusted = 1;
9350Sstevel@tonic-gate 	if (options->xauth_location == NULL)
9360Sstevel@tonic-gate 		options->xauth_location = _PATH_XAUTH;
9370Sstevel@tonic-gate 	if (options->gateway_ports == -1)
9380Sstevel@tonic-gate 		options->gateway_ports = 0;
9390Sstevel@tonic-gate 	if (options->use_privileged_port == -1)
9400Sstevel@tonic-gate 		options->use_privileged_port = 0;
9410Sstevel@tonic-gate 	if (options->rhosts_authentication == -1)
9420Sstevel@tonic-gate 		options->rhosts_authentication = 0;
9430Sstevel@tonic-gate 	if (options->rsa_authentication == -1)
9440Sstevel@tonic-gate 		options->rsa_authentication = 1;
9450Sstevel@tonic-gate 	if (options->pubkey_authentication == -1)
9460Sstevel@tonic-gate 		options->pubkey_authentication = 1;
9470Sstevel@tonic-gate 	if (options->challenge_response_authentication == -1)
9480Sstevel@tonic-gate 		options->challenge_response_authentication = 1;
9490Sstevel@tonic-gate #ifdef GSSAPI
9500Sstevel@tonic-gate 	if (options->gss_keyex == -1)
9510Sstevel@tonic-gate 		options->gss_keyex = 1;
9520Sstevel@tonic-gate 	if (options->gss_authentication == -1)
9530Sstevel@tonic-gate 		options->gss_authentication = 1;
9540Sstevel@tonic-gate 	if (options->gss_deleg_creds == -1)
9550Sstevel@tonic-gate 		options->gss_deleg_creds = 0;
9560Sstevel@tonic-gate #ifdef GSI
9570Sstevel@tonic-gate 	if (options->gss_globus_deleg_limited_proxy == -1)
9580Sstevel@tonic-gate 		options->gss_globus_deleg_limited_proxy = 0;
9590Sstevel@tonic-gate #endif /* GSI */
9600Sstevel@tonic-gate #endif /* GSSAPI */
9610Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5)
9620Sstevel@tonic-gate 	if (options->kerberos_authentication == -1)
9630Sstevel@tonic-gate 		options->kerberos_authentication = 1;
9640Sstevel@tonic-gate #endif
9650Sstevel@tonic-gate #if defined(AFS) || defined(KRB5)
9660Sstevel@tonic-gate 	if (options->kerberos_tgt_passing == -1)
9670Sstevel@tonic-gate 		options->kerberos_tgt_passing = 1;
9680Sstevel@tonic-gate #endif
9690Sstevel@tonic-gate #ifdef AFS
9700Sstevel@tonic-gate 	if (options->afs_token_passing == -1)
9710Sstevel@tonic-gate 		options->afs_token_passing = 1;
9720Sstevel@tonic-gate #endif
9730Sstevel@tonic-gate 	if (options->password_authentication == -1)
9740Sstevel@tonic-gate 		options->password_authentication = 1;
9750Sstevel@tonic-gate 	if (options->kbd_interactive_authentication == -1)
9760Sstevel@tonic-gate 		options->kbd_interactive_authentication = 1;
9770Sstevel@tonic-gate 	if (options->rhosts_rsa_authentication == -1)
9780Sstevel@tonic-gate 		options->rhosts_rsa_authentication = 0;
9790Sstevel@tonic-gate 	if (options->hostbased_authentication == -1)
9800Sstevel@tonic-gate 		options->hostbased_authentication = 0;
9810Sstevel@tonic-gate 	if (options->batch_mode == -1)
9820Sstevel@tonic-gate 		options->batch_mode = 0;
9830Sstevel@tonic-gate 	if (options->check_host_ip == -1)
9840Sstevel@tonic-gate 		options->check_host_ip = 1;
9850Sstevel@tonic-gate 	if (options->strict_host_key_checking == -1)
9860Sstevel@tonic-gate 		options->strict_host_key_checking = 2;	/* 2 is default */
9870Sstevel@tonic-gate 	if (options->compression == -1)
9880Sstevel@tonic-gate 		options->compression = 0;
9890Sstevel@tonic-gate 	if (options->keepalives == -1)
9900Sstevel@tonic-gate 		options->keepalives = 1;
9910Sstevel@tonic-gate 	if (options->compression_level == -1)
9920Sstevel@tonic-gate 		options->compression_level = 6;
9930Sstevel@tonic-gate 	if (options->port == -1)
9940Sstevel@tonic-gate 		options->port = 0;	/* Filled in ssh_connect. */
9950Sstevel@tonic-gate 	if (options->connection_attempts == -1)
9960Sstevel@tonic-gate 		options->connection_attempts = 1;
9970Sstevel@tonic-gate 	if (options->number_of_password_prompts == -1)
9980Sstevel@tonic-gate 		options->number_of_password_prompts = 3;
9990Sstevel@tonic-gate 	/* Selected in ssh_login(). */
10000Sstevel@tonic-gate 	if (options->cipher == -1)
10010Sstevel@tonic-gate 		options->cipher = SSH_CIPHER_NOT_SET;
10020Sstevel@tonic-gate 	/* options->ciphers, default set in myproposals.h */
10030Sstevel@tonic-gate 	/* options->macs, default set in myproposals.h */
10040Sstevel@tonic-gate 	/* options->hostkeyalgorithms, default set in myproposals.h */
10050Sstevel@tonic-gate 	if (options->protocol == SSH_PROTO_UNKNOWN)
10060Sstevel@tonic-gate 		options->protocol = SSH_PROTO_1|SSH_PROTO_2;
10070Sstevel@tonic-gate 	if (options->num_identity_files == 0) {
10080Sstevel@tonic-gate 		if (options->protocol & SSH_PROTO_1) {
10090Sstevel@tonic-gate 			len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1;
10100Sstevel@tonic-gate 			options->identity_files[options->num_identity_files] =
10110Sstevel@tonic-gate 			    xmalloc(len);
10120Sstevel@tonic-gate 			snprintf(options->identity_files[options->num_identity_files++],
10130Sstevel@tonic-gate 			    len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY);
10140Sstevel@tonic-gate 		}
10150Sstevel@tonic-gate 		if (options->protocol & SSH_PROTO_2) {
10160Sstevel@tonic-gate 			len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1;
10170Sstevel@tonic-gate 			options->identity_files[options->num_identity_files] =
10180Sstevel@tonic-gate 			    xmalloc(len);
10190Sstevel@tonic-gate 			snprintf(options->identity_files[options->num_identity_files++],
10200Sstevel@tonic-gate 			    len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA);
10210Sstevel@tonic-gate 
10220Sstevel@tonic-gate 			len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1;
10230Sstevel@tonic-gate 			options->identity_files[options->num_identity_files] =
10240Sstevel@tonic-gate 			    xmalloc(len);
10250Sstevel@tonic-gate 			snprintf(options->identity_files[options->num_identity_files++],
10260Sstevel@tonic-gate 			    len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA);
10270Sstevel@tonic-gate 		}
10280Sstevel@tonic-gate 	}
10290Sstevel@tonic-gate 	if (options->escape_char == -1)
10300Sstevel@tonic-gate 		options->escape_char = '~';
10310Sstevel@tonic-gate 	if (options->system_hostfile == NULL)
10320Sstevel@tonic-gate 		options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE;
10330Sstevel@tonic-gate 	if (options->user_hostfile == NULL)
10340Sstevel@tonic-gate 		options->user_hostfile = _PATH_SSH_USER_HOSTFILE;
10350Sstevel@tonic-gate 	if (options->system_hostfile2 == NULL)
10360Sstevel@tonic-gate 		options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2;
10370Sstevel@tonic-gate 	if (options->user_hostfile2 == NULL)
10380Sstevel@tonic-gate 		options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2;
10390Sstevel@tonic-gate 	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
10400Sstevel@tonic-gate 		options->log_level = SYSLOG_LEVEL_INFO;
10410Sstevel@tonic-gate 	if (options->clear_forwardings == 1)
10420Sstevel@tonic-gate 		clear_forwardings(options);
10430Sstevel@tonic-gate 	if (options->no_host_authentication_for_localhost == - 1)
10440Sstevel@tonic-gate 		options->no_host_authentication_for_localhost = 0;
10450Sstevel@tonic-gate 	if (options->fallback_to_rsh == - 1)
10460Sstevel@tonic-gate 		options->fallback_to_rsh = 0;
10470Sstevel@tonic-gate 	if (options->use_rsh == - 1)
10480Sstevel@tonic-gate 		options->use_rsh = 0;
10494668Sjp161948 	if (options->server_alive_interval == -1)
10504668Sjp161948 		options->server_alive_interval = 0;
10514668Sjp161948 	if (options->server_alive_count_max == -1)
10524668Sjp161948 		options->server_alive_count_max = 3;
1053*4958Sjp161948 	if (options->disable_banner == -1)
1054*4958Sjp161948 		options->disable_banner = 0;
10550Sstevel@tonic-gate 	/* options->proxy_command should not be set by default */
10560Sstevel@tonic-gate 	/* options->user will be set in the main program if appropriate */
10570Sstevel@tonic-gate 	/* options->hostname will be set in the main program if appropriate */
10580Sstevel@tonic-gate 	/* options->host_key_alias should not be set by default */
10590Sstevel@tonic-gate 	/* options->preferred_authentications will be set in ssh */
10600Sstevel@tonic-gate }
1061