Home | History | Annotate | Line # | Download | only in dist
readconf.c revision 1.1
      1  1.1  christos /*	$NetBSD: readconf.c,v 1.1 2009/06/07 22:19:15 christos Exp $	*/
      2  1.1  christos /* $OpenBSD: readconf.c,v 1.176 2009/02/12 03:00:56 djm Exp $ */
      3  1.1  christos /*
      4  1.1  christos  * Author: Tatu Ylonen <ylo (at) cs.hut.fi>
      5  1.1  christos  * Copyright (c) 1995 Tatu Ylonen <ylo (at) cs.hut.fi>, Espoo, Finland
      6  1.1  christos  *                    All rights reserved
      7  1.1  christos  * Functions for reading the configuration files.
      8  1.1  christos  *
      9  1.1  christos  * As far as I am concerned, the code I have written for this software
     10  1.1  christos  * can be used freely for any purpose.  Any derived versions of this
     11  1.1  christos  * software must be clearly marked as such, and if the derived work is
     12  1.1  christos  * incompatible with the protocol description in the RFC file, it must be
     13  1.1  christos  * called by a name other than "ssh" or "Secure Shell".
     14  1.1  christos  */
     15  1.1  christos 
     16  1.1  christos #include <sys/types.h>
     17  1.1  christos #include <sys/stat.h>
     18  1.1  christos #include <sys/socket.h>
     19  1.1  christos 
     20  1.1  christos #include <netinet/in.h>
     21  1.1  christos 
     22  1.1  christos #include <ctype.h>
     23  1.1  christos #include <errno.h>
     24  1.1  christos #include <netdb.h>
     25  1.1  christos #include <signal.h>
     26  1.1  christos #include <stdio.h>
     27  1.1  christos #include <string.h>
     28  1.1  christos #include <unistd.h>
     29  1.1  christos 
     30  1.1  christos #include "xmalloc.h"
     31  1.1  christos #include "ssh.h"
     32  1.1  christos #include "compat.h"
     33  1.1  christos #include "cipher.h"
     34  1.1  christos #include "pathnames.h"
     35  1.1  christos #include "log.h"
     36  1.1  christos #include "key.h"
     37  1.1  christos #include "readconf.h"
     38  1.1  christos #include "match.h"
     39  1.1  christos #include "misc.h"
     40  1.1  christos #include "buffer.h"
     41  1.1  christos #include "kex.h"
     42  1.1  christos #include "mac.h"
     43  1.1  christos 
     44  1.1  christos /* Format of the configuration file:
     45  1.1  christos 
     46  1.1  christos    # Configuration data is parsed as follows:
     47  1.1  christos    #  1. command line options
     48  1.1  christos    #  2. user-specific file
     49  1.1  christos    #  3. system-wide file
     50  1.1  christos    # Any configuration value is only changed the first time it is set.
     51  1.1  christos    # Thus, host-specific definitions should be at the beginning of the
     52  1.1  christos    # configuration file, and defaults at the end.
     53  1.1  christos 
     54  1.1  christos    # Host-specific declarations.  These may override anything above.  A single
     55  1.1  christos    # host may match multiple declarations; these are processed in the order
     56  1.1  christos    # that they are given in.
     57  1.1  christos 
     58  1.1  christos    Host *.ngs.fi ngs.fi
     59  1.1  christos      User foo
     60  1.1  christos 
     61  1.1  christos    Host fake.com
     62  1.1  christos      HostName another.host.name.real.org
     63  1.1  christos      User blaah
     64  1.1  christos      Port 34289
     65  1.1  christos      ForwardX11 no
     66  1.1  christos      ForwardAgent no
     67  1.1  christos 
     68  1.1  christos    Host books.com
     69  1.1  christos      RemoteForward 9999 shadows.cs.hut.fi:9999
     70  1.1  christos      Cipher 3des
     71  1.1  christos 
     72  1.1  christos    Host fascist.blob.com
     73  1.1  christos      Port 23123
     74  1.1  christos      User tylonen
     75  1.1  christos      PasswordAuthentication no
     76  1.1  christos 
     77  1.1  christos    Host puukko.hut.fi
     78  1.1  christos      User t35124p
     79  1.1  christos      ProxyCommand ssh-proxy %h %p
     80  1.1  christos 
     81  1.1  christos    Host *.fr
     82  1.1  christos      PublicKeyAuthentication no
     83  1.1  christos 
     84  1.1  christos    Host *.su
     85  1.1  christos      Cipher none
     86  1.1  christos      PasswordAuthentication no
     87  1.1  christos 
     88  1.1  christos    Host vpn.fake.com
     89  1.1  christos      Tunnel yes
     90  1.1  christos      TunnelDevice 3
     91  1.1  christos 
     92  1.1  christos    # Defaults for various options
     93  1.1  christos    Host *
     94  1.1  christos      ForwardAgent no
     95  1.1  christos      ForwardX11 no
     96  1.1  christos      PasswordAuthentication yes
     97  1.1  christos      RSAAuthentication yes
     98  1.1  christos      RhostsRSAAuthentication yes
     99  1.1  christos      StrictHostKeyChecking yes
    100  1.1  christos      TcpKeepAlive no
    101  1.1  christos      IdentityFile ~/.ssh/identity
    102  1.1  christos      Port 22
    103  1.1  christos      EscapeChar ~
    104  1.1  christos 
    105  1.1  christos */
    106  1.1  christos 
    107  1.1  christos /* Keyword tokens. */
    108  1.1  christos 
    109  1.1  christos typedef enum {
    110  1.1  christos 	oBadOption,
    111  1.1  christos 	oForwardAgent, oForwardX11, oForwardX11Trusted, oGatewayPorts,
    112  1.1  christos 	oExitOnForwardFailure,
    113  1.1  christos 	oPasswordAuthentication, oRSAAuthentication,
    114  1.1  christos 	oChallengeResponseAuthentication, oXAuthLocation,
    115  1.1  christos 	oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
    116  1.1  christos 	oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
    117  1.1  christos 	oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
    118  1.1  christos 	oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
    119  1.1  christos 	oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
    120  1.1  christos 	oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
    121  1.1  christos 	oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
    122  1.1  christos 	oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
    123  1.1  christos 	oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
    124  1.1  christos 	oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
    125  1.1  christos 	oClearAllForwardings, oNoHostAuthenticationForLocalhost,
    126  1.1  christos 	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
    127  1.1  christos 	oAddressFamily, oGssAuthentication, oGssDelegateCreds,
    128  1.1  christos 	oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
    129  1.1  christos 	oSendEnv, oControlPath, oControlMaster, oHashKnownHosts,
    130  1.1  christos 	oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
    131  1.1  christos 	oVisualHostKey, oZeroKnowledgePasswordAuthentication,
    132  1.1  christos 	oDeprecated, oUnsupported
    133  1.1  christos } OpCodes;
    134  1.1  christos 
    135  1.1  christos /* Textual representations of the tokens. */
    136  1.1  christos 
    137  1.1  christos static struct {
    138  1.1  christos 	const char *name;
    139  1.1  christos 	OpCodes opcode;
    140  1.1  christos } keywords[] = {
    141  1.1  christos 	{ "forwardagent", oForwardAgent },
    142  1.1  christos 	{ "forwardx11", oForwardX11 },
    143  1.1  christos 	{ "forwardx11trusted", oForwardX11Trusted },
    144  1.1  christos 	{ "exitonforwardfailure", oExitOnForwardFailure },
    145  1.1  christos 	{ "xauthlocation", oXAuthLocation },
    146  1.1  christos 	{ "gatewayports", oGatewayPorts },
    147  1.1  christos 	{ "useprivilegedport", oUsePrivilegedPort },
    148  1.1  christos 	{ "rhostsauthentication", oDeprecated },
    149  1.1  christos 	{ "passwordauthentication", oPasswordAuthentication },
    150  1.1  christos 	{ "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
    151  1.1  christos 	{ "kbdinteractivedevices", oKbdInteractiveDevices },
    152  1.1  christos 	{ "rsaauthentication", oRSAAuthentication },
    153  1.1  christos 	{ "pubkeyauthentication", oPubkeyAuthentication },
    154  1.1  christos 	{ "dsaauthentication", oPubkeyAuthentication },		    /* alias */
    155  1.1  christos 	{ "rhostsrsaauthentication", oRhostsRSAAuthentication },
    156  1.1  christos 	{ "hostbasedauthentication", oHostbasedAuthentication },
    157  1.1  christos 	{ "challengeresponseauthentication", oChallengeResponseAuthentication },
    158  1.1  christos 	{ "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
    159  1.1  christos 	{ "tisauthentication", oChallengeResponseAuthentication },  /* alias */
    160  1.1  christos 	{ "kerberosauthentication", oUnsupported },
    161  1.1  christos 	{ "kerberostgtpassing", oUnsupported },
    162  1.1  christos 	{ "afstokenpassing", oUnsupported },
    163  1.1  christos #if defined(GSSAPI)
    164  1.1  christos 	{ "gssapiauthentication", oGssAuthentication },
    165  1.1  christos 	{ "gssapidelegatecredentials", oGssDelegateCreds },
    166  1.1  christos #else
    167  1.1  christos 	{ "gssapiauthentication", oUnsupported },
    168  1.1  christos 	{ "gssapidelegatecredentials", oUnsupported },
    169  1.1  christos #endif
    170  1.1  christos 	{ "fallbacktorsh", oDeprecated },
    171  1.1  christos 	{ "usersh", oDeprecated },
    172  1.1  christos 	{ "identityfile", oIdentityFile },
    173  1.1  christos 	{ "identityfile2", oIdentityFile },			/* obsolete */
    174  1.1  christos 	{ "identitiesonly", oIdentitiesOnly },
    175  1.1  christos 	{ "hostname", oHostName },
    176  1.1  christos 	{ "hostkeyalias", oHostKeyAlias },
    177  1.1  christos 	{ "proxycommand", oProxyCommand },
    178  1.1  christos 	{ "port", oPort },
    179  1.1  christos 	{ "cipher", oCipher },
    180  1.1  christos 	{ "ciphers", oCiphers },
    181  1.1  christos 	{ "macs", oMacs },
    182  1.1  christos 	{ "protocol", oProtocol },
    183  1.1  christos 	{ "remoteforward", oRemoteForward },
    184  1.1  christos 	{ "localforward", oLocalForward },
    185  1.1  christos 	{ "user", oUser },
    186  1.1  christos 	{ "host", oHost },
    187  1.1  christos 	{ "escapechar", oEscapeChar },
    188  1.1  christos 	{ "globalknownhostsfile", oGlobalKnownHostsFile },
    189  1.1  christos 	{ "globalknownhostsfile2", oGlobalKnownHostsFile2 },	/* obsolete */
    190  1.1  christos 	{ "userknownhostsfile", oUserKnownHostsFile },
    191  1.1  christos 	{ "userknownhostsfile2", oUserKnownHostsFile2 },	/* obsolete */
    192  1.1  christos 	{ "connectionattempts", oConnectionAttempts },
    193  1.1  christos 	{ "batchmode", oBatchMode },
    194  1.1  christos 	{ "checkhostip", oCheckHostIP },
    195  1.1  christos 	{ "stricthostkeychecking", oStrictHostKeyChecking },
    196  1.1  christos 	{ "compression", oCompression },
    197  1.1  christos 	{ "compressionlevel", oCompressionLevel },
    198  1.1  christos 	{ "tcpkeepalive", oTCPKeepAlive },
    199  1.1  christos 	{ "keepalive", oTCPKeepAlive },				/* obsolete */
    200  1.1  christos 	{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
    201  1.1  christos 	{ "loglevel", oLogLevel },
    202  1.1  christos 	{ "dynamicforward", oDynamicForward },
    203  1.1  christos 	{ "preferredauthentications", oPreferredAuthentications },
    204  1.1  christos 	{ "hostkeyalgorithms", oHostKeyAlgorithms },
    205  1.1  christos 	{ "bindaddress", oBindAddress },
    206  1.1  christos #ifdef SMARTCARD
    207  1.1  christos 	{ "smartcarddevice", oSmartcardDevice },
    208  1.1  christos #else
    209  1.1  christos 	{ "smartcarddevice", oUnsupported },
    210  1.1  christos #endif
    211  1.1  christos 	{ "clearallforwardings", oClearAllForwardings },
    212  1.1  christos 	{ "enablesshkeysign", oEnableSSHKeysign },
    213  1.1  christos 	{ "verifyhostkeydns", oVerifyHostKeyDNS },
    214  1.1  christos 	{ "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
    215  1.1  christos 	{ "rekeylimit", oRekeyLimit },
    216  1.1  christos 	{ "connecttimeout", oConnectTimeout },
    217  1.1  christos 	{ "addressfamily", oAddressFamily },
    218  1.1  christos 	{ "serveraliveinterval", oServerAliveInterval },
    219  1.1  christos 	{ "serveralivecountmax", oServerAliveCountMax },
    220  1.1  christos 	{ "sendenv", oSendEnv },
    221  1.1  christos 	{ "controlpath", oControlPath },
    222  1.1  christos 	{ "controlmaster", oControlMaster },
    223  1.1  christos 	{ "hashknownhosts", oHashKnownHosts },
    224  1.1  christos 	{ "tunnel", oTunnel },
    225  1.1  christos 	{ "tunneldevice", oTunnelDevice },
    226  1.1  christos 	{ "localcommand", oLocalCommand },
    227  1.1  christos 	{ "permitlocalcommand", oPermitLocalCommand },
    228  1.1  christos 	{ "visualhostkey", oVisualHostKey },
    229  1.1  christos #ifdef JPAKE
    230  1.1  christos 	{ "zeroknowledgepasswordauthentication",
    231  1.1  christos 	    oZeroKnowledgePasswordAuthentication },
    232  1.1  christos #else
    233  1.1  christos 	{ "zeroknowledgepasswordauthentication", oUnsupported },
    234  1.1  christos #endif
    235  1.1  christos 
    236  1.1  christos 	{ NULL, oBadOption }
    237  1.1  christos };
    238  1.1  christos 
    239  1.1  christos /*
    240  1.1  christos  * Adds a local TCP/IP port forward to options.  Never returns if there is an
    241  1.1  christos  * error.
    242  1.1  christos  */
    243  1.1  christos 
    244  1.1  christos void
    245  1.1  christos add_local_forward(Options *options, const Forward *newfwd)
    246  1.1  christos {
    247  1.1  christos 	Forward *fwd;
    248  1.1  christos 	extern uid_t original_real_uid;
    249  1.1  christos 	if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0)
    250  1.1  christos 		fatal("Privileged ports can only be forwarded by root.");
    251  1.1  christos 	if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
    252  1.1  christos 		fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
    253  1.1  christos 	fwd = &options->local_forwards[options->num_local_forwards++];
    254  1.1  christos 
    255  1.1  christos 	fwd->listen_host = newfwd->listen_host;
    256  1.1  christos 	fwd->listen_port = newfwd->listen_port;
    257  1.1  christos 	fwd->connect_host = newfwd->connect_host;
    258  1.1  christos 	fwd->connect_port = newfwd->connect_port;
    259  1.1  christos }
    260  1.1  christos 
    261  1.1  christos /*
    262  1.1  christos  * Adds a remote TCP/IP port forward to options.  Never returns if there is
    263  1.1  christos  * an error.
    264  1.1  christos  */
    265  1.1  christos 
    266  1.1  christos void
    267  1.1  christos add_remote_forward(Options *options, const Forward *newfwd)
    268  1.1  christos {
    269  1.1  christos 	Forward *fwd;
    270  1.1  christos 	if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
    271  1.1  christos 		fatal("Too many remote forwards (max %d).",
    272  1.1  christos 		    SSH_MAX_FORWARDS_PER_DIRECTION);
    273  1.1  christos 	fwd = &options->remote_forwards[options->num_remote_forwards++];
    274  1.1  christos 
    275  1.1  christos 	fwd->listen_host = newfwd->listen_host;
    276  1.1  christos 	fwd->listen_port = newfwd->listen_port;
    277  1.1  christos 	fwd->connect_host = newfwd->connect_host;
    278  1.1  christos 	fwd->connect_port = newfwd->connect_port;
    279  1.1  christos }
    280  1.1  christos 
    281  1.1  christos static void
    282  1.1  christos clear_forwardings(Options *options)
    283  1.1  christos {
    284  1.1  christos 	int i;
    285  1.1  christos 
    286  1.1  christos 	for (i = 0; i < options->num_local_forwards; i++) {
    287  1.1  christos 		if (options->local_forwards[i].listen_host != NULL)
    288  1.1  christos 			xfree(options->local_forwards[i].listen_host);
    289  1.1  christos 		xfree(options->local_forwards[i].connect_host);
    290  1.1  christos 	}
    291  1.1  christos 	options->num_local_forwards = 0;
    292  1.1  christos 	for (i = 0; i < options->num_remote_forwards; i++) {
    293  1.1  christos 		if (options->remote_forwards[i].listen_host != NULL)
    294  1.1  christos 			xfree(options->remote_forwards[i].listen_host);
    295  1.1  christos 		xfree(options->remote_forwards[i].connect_host);
    296  1.1  christos 	}
    297  1.1  christos 	options->num_remote_forwards = 0;
    298  1.1  christos 	options->tun_open = SSH_TUNMODE_NO;
    299  1.1  christos }
    300  1.1  christos 
    301  1.1  christos /*
    302  1.1  christos  * Returns the number of the token pointed to by cp or oBadOption.
    303  1.1  christos  */
    304  1.1  christos 
    305  1.1  christos static OpCodes
    306  1.1  christos parse_token(const char *cp, const char *filename, int linenum)
    307  1.1  christos {
    308  1.1  christos 	u_int i;
    309  1.1  christos 
    310  1.1  christos 	for (i = 0; keywords[i].name; i++)
    311  1.1  christos 		if (strcasecmp(cp, keywords[i].name) == 0)
    312  1.1  christos 			return keywords[i].opcode;
    313  1.1  christos 
    314  1.1  christos 	error("%s: line %d: Bad configuration option: %s",
    315  1.1  christos 	    filename, linenum, cp);
    316  1.1  christos 	return oBadOption;
    317  1.1  christos }
    318  1.1  christos 
    319  1.1  christos /*
    320  1.1  christos  * Processes a single option line as used in the configuration files. This
    321  1.1  christos  * only sets those values that have not already been set.
    322  1.1  christos  */
    323  1.1  christos #define WHITESPACE " \t\r\n"
    324  1.1  christos 
    325  1.1  christos int
    326  1.1  christos process_config_line(Options *options, const char *host,
    327  1.1  christos 		    char *line, const char *filename, int linenum,
    328  1.1  christos 		    int *activep)
    329  1.1  christos {
    330  1.1  christos 	char *s, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256];
    331  1.1  christos 	int opcode, *intptr, value, value2, scale;
    332  1.1  christos 	LogLevel *log_level_ptr;
    333  1.1  christos 	long long orig, val64;
    334  1.1  christos 	size_t len;
    335  1.1  christos 	Forward fwd;
    336  1.1  christos 
    337  1.1  christos 	/* Strip trailing whitespace */
    338  1.1  christos 	for (len = strlen(line) - 1; len > 0; len--) {
    339  1.1  christos 		if (strchr(WHITESPACE, line[len]) == NULL)
    340  1.1  christos 			break;
    341  1.1  christos 		line[len] = '\0';
    342  1.1  christos 	}
    343  1.1  christos 
    344  1.1  christos 	s = line;
    345  1.1  christos 	/* Get the keyword. (Each line is supposed to begin with a keyword). */
    346  1.1  christos 	if ((keyword = strdelim(&s)) == NULL)
    347  1.1  christos 		return 0;
    348  1.1  christos 	/* Ignore leading whitespace. */
    349  1.1  christos 	if (*keyword == '\0')
    350  1.1  christos 		keyword = strdelim(&s);
    351  1.1  christos 	if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
    352  1.1  christos 		return 0;
    353  1.1  christos 
    354  1.1  christos 	opcode = parse_token(keyword, filename, linenum);
    355  1.1  christos 
    356  1.1  christos 	switch (opcode) {
    357  1.1  christos 	case oBadOption:
    358  1.1  christos 		/* don't panic, but count bad options */
    359  1.1  christos 		return -1;
    360  1.1  christos 		/* NOTREACHED */
    361  1.1  christos 	case oConnectTimeout:
    362  1.1  christos 		intptr = &options->connection_timeout;
    363  1.1  christos parse_time:
    364  1.1  christos 		arg = strdelim(&s);
    365  1.1  christos 		if (!arg || *arg == '\0')
    366  1.1  christos 			fatal("%s line %d: missing time value.",
    367  1.1  christos 			    filename, linenum);
    368  1.1  christos 		if ((value = convtime(arg)) == -1)
    369  1.1  christos 			fatal("%s line %d: invalid time value.",
    370  1.1  christos 			    filename, linenum);
    371  1.1  christos 		if (*activep && *intptr == -1)
    372  1.1  christos 			*intptr = value;
    373  1.1  christos 		break;
    374  1.1  christos 
    375  1.1  christos 	case oForwardAgent:
    376  1.1  christos 		intptr = &options->forward_agent;
    377  1.1  christos parse_flag:
    378  1.1  christos 		arg = strdelim(&s);
    379  1.1  christos 		if (!arg || *arg == '\0')
    380  1.1  christos 			fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
    381  1.1  christos 		value = 0;	/* To avoid compiler warning... */
    382  1.1  christos 		if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
    383  1.1  christos 			value = 1;
    384  1.1  christos 		else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
    385  1.1  christos 			value = 0;
    386  1.1  christos 		else
    387  1.1  christos 			fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
    388  1.1  christos 		if (*activep && *intptr == -1)
    389  1.1  christos 			*intptr = value;
    390  1.1  christos 		break;
    391  1.1  christos 
    392  1.1  christos 	case oForwardX11:
    393  1.1  christos 		intptr = &options->forward_x11;
    394  1.1  christos 		goto parse_flag;
    395  1.1  christos 
    396  1.1  christos 	case oForwardX11Trusted:
    397  1.1  christos 		intptr = &options->forward_x11_trusted;
    398  1.1  christos 		goto parse_flag;
    399  1.1  christos 
    400  1.1  christos 	case oGatewayPorts:
    401  1.1  christos 		intptr = &options->gateway_ports;
    402  1.1  christos 		goto parse_flag;
    403  1.1  christos 
    404  1.1  christos 	case oExitOnForwardFailure:
    405  1.1  christos 		intptr = &options->exit_on_forward_failure;
    406  1.1  christos 		goto parse_flag;
    407  1.1  christos 
    408  1.1  christos 	case oUsePrivilegedPort:
    409  1.1  christos 		intptr = &options->use_privileged_port;
    410  1.1  christos 		goto parse_flag;
    411  1.1  christos 
    412  1.1  christos 	case oPasswordAuthentication:
    413  1.1  christos 		intptr = &options->password_authentication;
    414  1.1  christos 		goto parse_flag;
    415  1.1  christos 
    416  1.1  christos 	case oZeroKnowledgePasswordAuthentication:
    417  1.1  christos 		intptr = &options->zero_knowledge_password_authentication;
    418  1.1  christos 		goto parse_flag;
    419  1.1  christos 
    420  1.1  christos 	case oKbdInteractiveAuthentication:
    421  1.1  christos 		intptr = &options->kbd_interactive_authentication;
    422  1.1  christos 		goto parse_flag;
    423  1.1  christos 
    424  1.1  christos 	case oKbdInteractiveDevices:
    425  1.1  christos 		charptr = &options->kbd_interactive_devices;
    426  1.1  christos 		goto parse_string;
    427  1.1  christos 
    428  1.1  christos 	case oPubkeyAuthentication:
    429  1.1  christos 		intptr = &options->pubkey_authentication;
    430  1.1  christos 		goto parse_flag;
    431  1.1  christos 
    432  1.1  christos 	case oRSAAuthentication:
    433  1.1  christos 		intptr = &options->rsa_authentication;
    434  1.1  christos 		goto parse_flag;
    435  1.1  christos 
    436  1.1  christos 	case oRhostsRSAAuthentication:
    437  1.1  christos 		intptr = &options->rhosts_rsa_authentication;
    438  1.1  christos 		goto parse_flag;
    439  1.1  christos 
    440  1.1  christos 	case oHostbasedAuthentication:
    441  1.1  christos 		intptr = &options->hostbased_authentication;
    442  1.1  christos 		goto parse_flag;
    443  1.1  christos 
    444  1.1  christos 	case oChallengeResponseAuthentication:
    445  1.1  christos 		intptr = &options->challenge_response_authentication;
    446  1.1  christos 		goto parse_flag;
    447  1.1  christos 
    448  1.1  christos 	case oGssAuthentication:
    449  1.1  christos 		intptr = &options->gss_authentication;
    450  1.1  christos 		goto parse_flag;
    451  1.1  christos 
    452  1.1  christos 	case oGssDelegateCreds:
    453  1.1  christos 		intptr = &options->gss_deleg_creds;
    454  1.1  christos 		goto parse_flag;
    455  1.1  christos 
    456  1.1  christos 	case oBatchMode:
    457  1.1  christos 		intptr = &options->batch_mode;
    458  1.1  christos 		goto parse_flag;
    459  1.1  christos 
    460  1.1  christos 	case oCheckHostIP:
    461  1.1  christos 		intptr = &options->check_host_ip;
    462  1.1  christos 		goto parse_flag;
    463  1.1  christos 
    464  1.1  christos 	case oVerifyHostKeyDNS:
    465  1.1  christos 		intptr = &options->verify_host_key_dns;
    466  1.1  christos 		goto parse_yesnoask;
    467  1.1  christos 
    468  1.1  christos 	case oStrictHostKeyChecking:
    469  1.1  christos 		intptr = &options->strict_host_key_checking;
    470  1.1  christos parse_yesnoask:
    471  1.1  christos 		arg = strdelim(&s);
    472  1.1  christos 		if (!arg || *arg == '\0')
    473  1.1  christos 			fatal("%.200s line %d: Missing yes/no/ask argument.",
    474  1.1  christos 			    filename, linenum);
    475  1.1  christos 		value = 0;	/* To avoid compiler warning... */
    476  1.1  christos 		if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
    477  1.1  christos 			value = 1;
    478  1.1  christos 		else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
    479  1.1  christos 			value = 0;
    480  1.1  christos 		else if (strcmp(arg, "ask") == 0)
    481  1.1  christos 			value = 2;
    482  1.1  christos 		else
    483  1.1  christos 			fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
    484  1.1  christos 		if (*activep && *intptr == -1)
    485  1.1  christos 			*intptr = value;
    486  1.1  christos 		break;
    487  1.1  christos 
    488  1.1  christos 	case oCompression:
    489  1.1  christos 		intptr = &options->compression;
    490  1.1  christos 		goto parse_flag;
    491  1.1  christos 
    492  1.1  christos 	case oTCPKeepAlive:
    493  1.1  christos 		intptr = &options->tcp_keep_alive;
    494  1.1  christos 		goto parse_flag;
    495  1.1  christos 
    496  1.1  christos 	case oNoHostAuthenticationForLocalhost:
    497  1.1  christos 		intptr = &options->no_host_authentication_for_localhost;
    498  1.1  christos 		goto parse_flag;
    499  1.1  christos 
    500  1.1  christos 	case oNumberOfPasswordPrompts:
    501  1.1  christos 		intptr = &options->number_of_password_prompts;
    502  1.1  christos 		goto parse_int;
    503  1.1  christos 
    504  1.1  christos 	case oCompressionLevel:
    505  1.1  christos 		intptr = &options->compression_level;
    506  1.1  christos 		goto parse_int;
    507  1.1  christos 
    508  1.1  christos 	case oRekeyLimit:
    509  1.1  christos 		arg = strdelim(&s);
    510  1.1  christos 		if (!arg || *arg == '\0')
    511  1.1  christos 			fatal("%.200s line %d: Missing argument.", filename, linenum);
    512  1.1  christos 		if (arg[0] < '0' || arg[0] > '9')
    513  1.1  christos 			fatal("%.200s line %d: Bad number.", filename, linenum);
    514  1.1  christos 		orig = val64 = strtoll(arg, &endofnumber, 10);
    515  1.1  christos 		if (arg == endofnumber)
    516  1.1  christos 			fatal("%.200s line %d: Bad number.", filename, linenum);
    517  1.1  christos 		switch (toupper(*endofnumber)) {
    518  1.1  christos 		case '\0':
    519  1.1  christos 			scale = 1;
    520  1.1  christos 			break;
    521  1.1  christos 		case 'K':
    522  1.1  christos 			scale = 1<<10;
    523  1.1  christos 			break;
    524  1.1  christos 		case 'M':
    525  1.1  christos 			scale = 1<<20;
    526  1.1  christos 			break;
    527  1.1  christos 		case 'G':
    528  1.1  christos 			scale = 1<<30;
    529  1.1  christos 			break;
    530  1.1  christos 		default:
    531  1.1  christos 			fatal("%.200s line %d: Invalid RekeyLimit suffix",
    532  1.1  christos 			    filename, linenum);
    533  1.1  christos 		}
    534  1.1  christos 		val64 *= scale;
    535  1.1  christos 		/* detect integer wrap and too-large limits */
    536  1.1  christos 		if ((val64 / scale) != orig || val64 > UINT_MAX)
    537  1.1  christos 			fatal("%.200s line %d: RekeyLimit too large",
    538  1.1  christos 			    filename, linenum);
    539  1.1  christos 		if (val64 < 16)
    540  1.1  christos 			fatal("%.200s line %d: RekeyLimit too small",
    541  1.1  christos 			    filename, linenum);
    542  1.1  christos 		if (*activep && options->rekey_limit == -1)
    543  1.1  christos 			options->rekey_limit = (u_int32_t)val64;
    544  1.1  christos 		break;
    545  1.1  christos 
    546  1.1  christos 	case oIdentityFile:
    547  1.1  christos 		arg = strdelim(&s);
    548  1.1  christos 		if (!arg || *arg == '\0')
    549  1.1  christos 			fatal("%.200s line %d: Missing argument.", filename, linenum);
    550  1.1  christos 		if (*activep) {
    551  1.1  christos 			intptr = &options->num_identity_files;
    552  1.1  christos 			if (*intptr >= SSH_MAX_IDENTITY_FILES)
    553  1.1  christos 				fatal("%.200s line %d: Too many identity files specified (max %d).",
    554  1.1  christos 				    filename, linenum, SSH_MAX_IDENTITY_FILES);
    555  1.1  christos 			charptr = &options->identity_files[*intptr];
    556  1.1  christos 			*charptr = xstrdup(arg);
    557  1.1  christos 			*intptr = *intptr + 1;
    558  1.1  christos 		}
    559  1.1  christos 		break;
    560  1.1  christos 
    561  1.1  christos 	case oXAuthLocation:
    562  1.1  christos 		charptr=&options->xauth_location;
    563  1.1  christos 		goto parse_string;
    564  1.1  christos 
    565  1.1  christos 	case oUser:
    566  1.1  christos 		charptr = &options->user;
    567  1.1  christos parse_string:
    568  1.1  christos 		arg = strdelim(&s);
    569  1.1  christos 		if (!arg || *arg == '\0')
    570  1.1  christos 			fatal("%.200s line %d: Missing argument.", filename, linenum);
    571  1.1  christos 		if (*activep && *charptr == NULL)
    572  1.1  christos 			*charptr = xstrdup(arg);
    573  1.1  christos 		break;
    574  1.1  christos 
    575  1.1  christos 	case oGlobalKnownHostsFile:
    576  1.1  christos 		charptr = &options->system_hostfile;
    577  1.1  christos 		goto parse_string;
    578  1.1  christos 
    579  1.1  christos 	case oUserKnownHostsFile:
    580  1.1  christos 		charptr = &options->user_hostfile;
    581  1.1  christos 		goto parse_string;
    582  1.1  christos 
    583  1.1  christos 	case oGlobalKnownHostsFile2:
    584  1.1  christos 		charptr = &options->system_hostfile2;
    585  1.1  christos 		goto parse_string;
    586  1.1  christos 
    587  1.1  christos 	case oUserKnownHostsFile2:
    588  1.1  christos 		charptr = &options->user_hostfile2;
    589  1.1  christos 		goto parse_string;
    590  1.1  christos 
    591  1.1  christos 	case oHostName:
    592  1.1  christos 		charptr = &options->hostname;
    593  1.1  christos 		goto parse_string;
    594  1.1  christos 
    595  1.1  christos 	case oHostKeyAlias:
    596  1.1  christos 		charptr = &options->host_key_alias;
    597  1.1  christos 		goto parse_string;
    598  1.1  christos 
    599  1.1  christos 	case oPreferredAuthentications:
    600  1.1  christos 		charptr = &options->preferred_authentications;
    601  1.1  christos 		goto parse_string;
    602  1.1  christos 
    603  1.1  christos 	case oBindAddress:
    604  1.1  christos 		charptr = &options->bind_address;
    605  1.1  christos 		goto parse_string;
    606  1.1  christos 
    607  1.1  christos 	case oSmartcardDevice:
    608  1.1  christos 		charptr = &options->smartcard_device;
    609  1.1  christos 		goto parse_string;
    610  1.1  christos 
    611  1.1  christos 	case oProxyCommand:
    612  1.1  christos 		charptr = &options->proxy_command;
    613  1.1  christos parse_command:
    614  1.1  christos 		if (s == NULL)
    615  1.1  christos 			fatal("%.200s line %d: Missing argument.", filename, linenum);
    616  1.1  christos 		len = strspn(s, WHITESPACE "=");
    617  1.1  christos 		if (*activep && *charptr == NULL)
    618  1.1  christos 			*charptr = xstrdup(s + len);
    619  1.1  christos 		return 0;
    620  1.1  christos 
    621  1.1  christos 	case oPort:
    622  1.1  christos 		intptr = &options->port;
    623  1.1  christos parse_int:
    624  1.1  christos 		arg = strdelim(&s);
    625  1.1  christos 		if (!arg || *arg == '\0')
    626  1.1  christos 			fatal("%.200s line %d: Missing argument.", filename, linenum);
    627  1.1  christos 		if (arg[0] < '0' || arg[0] > '9')
    628  1.1  christos 			fatal("%.200s line %d: Bad number.", filename, linenum);
    629  1.1  christos 
    630  1.1  christos 		/* Octal, decimal, or hex format? */
    631  1.1  christos 		value = strtol(arg, &endofnumber, 0);
    632  1.1  christos 		if (arg == endofnumber)
    633  1.1  christos 			fatal("%.200s line %d: Bad number.", filename, linenum);
    634  1.1  christos 		if (*activep && *intptr == -1)
    635  1.1  christos 			*intptr = value;
    636  1.1  christos 		break;
    637  1.1  christos 
    638  1.1  christos 	case oConnectionAttempts:
    639  1.1  christos 		intptr = &options->connection_attempts;
    640  1.1  christos 		goto parse_int;
    641  1.1  christos 
    642  1.1  christos 	case oCipher:
    643  1.1  christos 		intptr = &options->cipher;
    644  1.1  christos 		arg = strdelim(&s);
    645  1.1  christos 		if (!arg || *arg == '\0')
    646  1.1  christos 			fatal("%.200s line %d: Missing argument.", filename, linenum);
    647  1.1  christos 		value = cipher_number(arg);
    648  1.1  christos 		if (value == -1)
    649  1.1  christos 			fatal("%.200s line %d: Bad cipher '%s'.",
    650  1.1  christos 			    filename, linenum, arg ? arg : "<NONE>");
    651  1.1  christos 		if (*activep && *intptr == -1)
    652  1.1  christos 			*intptr = value;
    653  1.1  christos 		break;
    654  1.1  christos 
    655  1.1  christos 	case oCiphers:
    656  1.1  christos 		arg = strdelim(&s);
    657  1.1  christos 		if (!arg || *arg == '\0')
    658  1.1  christos 			fatal("%.200s line %d: Missing argument.", filename, linenum);
    659  1.1  christos 		if (!ciphers_valid(arg))
    660  1.1  christos 			fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
    661  1.1  christos 			    filename, linenum, arg ? arg : "<NONE>");
    662  1.1  christos 		if (*activep && options->ciphers == NULL)
    663  1.1  christos 			options->ciphers = xstrdup(arg);
    664  1.1  christos 		break;
    665  1.1  christos 
    666  1.1  christos 	case oMacs:
    667  1.1  christos 		arg = strdelim(&s);
    668  1.1  christos 		if (!arg || *arg == '\0')
    669  1.1  christos 			fatal("%.200s line %d: Missing argument.", filename, linenum);
    670  1.1  christos 		if (!mac_valid(arg))
    671  1.1  christos 			fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
    672  1.1  christos 			    filename, linenum, arg ? arg : "<NONE>");
    673  1.1  christos 		if (*activep && options->macs == NULL)
    674  1.1  christos 			options->macs = xstrdup(arg);
    675  1.1  christos 		break;
    676  1.1  christos 
    677  1.1  christos 	case oHostKeyAlgorithms:
    678  1.1  christos 		arg = strdelim(&s);
    679  1.1  christos 		if (!arg || *arg == '\0')
    680  1.1  christos 			fatal("%.200s line %d: Missing argument.", filename, linenum);
    681  1.1  christos 		if (!key_names_valid2(arg))
    682  1.1  christos 			fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
    683  1.1  christos 			    filename, linenum, arg ? arg : "<NONE>");
    684  1.1  christos 		if (*activep && options->hostkeyalgorithms == NULL)
    685  1.1  christos 			options->hostkeyalgorithms = xstrdup(arg);
    686  1.1  christos 		break;
    687  1.1  christos 
    688  1.1  christos 	case oProtocol:
    689  1.1  christos 		intptr = &options->protocol;
    690  1.1  christos 		arg = strdelim(&s);
    691  1.1  christos 		if (!arg || *arg == '\0')
    692  1.1  christos 			fatal("%.200s line %d: Missing argument.", filename, linenum);
    693  1.1  christos 		value = proto_spec(arg);
    694  1.1  christos 		if (value == SSH_PROTO_UNKNOWN)
    695  1.1  christos 			fatal("%.200s line %d: Bad protocol spec '%s'.",
    696  1.1  christos 			    filename, linenum, arg ? arg : "<NONE>");
    697  1.1  christos 		if (*activep && *intptr == SSH_PROTO_UNKNOWN)
    698  1.1  christos 			*intptr = value;
    699  1.1  christos 		break;
    700  1.1  christos 
    701  1.1  christos 	case oLogLevel:
    702  1.1  christos 		log_level_ptr = &options->log_level;
    703  1.1  christos 		arg = strdelim(&s);
    704  1.1  christos 		value = log_level_number(arg);
    705  1.1  christos 		if (value == SYSLOG_LEVEL_NOT_SET)
    706  1.1  christos 			fatal("%.200s line %d: unsupported log level '%s'",
    707  1.1  christos 			    filename, linenum, arg ? arg : "<NONE>");
    708  1.1  christos 		if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
    709  1.1  christos 			*log_level_ptr = (LogLevel) value;
    710  1.1  christos 		break;
    711  1.1  christos 
    712  1.1  christos 	case oLocalForward:
    713  1.1  christos 	case oRemoteForward:
    714  1.1  christos 	case oDynamicForward:
    715  1.1  christos 		arg = strdelim(&s);
    716  1.1  christos 		if (arg == NULL || *arg == '\0')
    717  1.1  christos 			fatal("%.200s line %d: Missing port argument.",
    718  1.1  christos 			    filename, linenum);
    719  1.1  christos 
    720  1.1  christos 		if (opcode == oLocalForward ||
    721  1.1  christos 		    opcode == oRemoteForward) {
    722  1.1  christos 			arg2 = strdelim(&s);
    723  1.1  christos 			if (arg2 == NULL || *arg2 == '\0')
    724  1.1  christos 				fatal("%.200s line %d: Missing target argument.",
    725  1.1  christos 				    filename, linenum);
    726  1.1  christos 
    727  1.1  christos 			/* construct a string for parse_forward */
    728  1.1  christos 			snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
    729  1.1  christos 		} else if (opcode == oDynamicForward) {
    730  1.1  christos 			strlcpy(fwdarg, arg, sizeof(fwdarg));
    731  1.1  christos 		}
    732  1.1  christos 
    733  1.1  christos 		if (parse_forward(&fwd, fwdarg,
    734  1.1  christos 		    opcode == oDynamicForward ? 1 : 0,
    735  1.1  christos 		    opcode == oRemoteForward ? 1 : 0) == 0)
    736  1.1  christos 			fatal("%.200s line %d: Bad forwarding specification.",
    737  1.1  christos 			    filename, linenum);
    738  1.1  christos 
    739  1.1  christos 		if (*activep) {
    740  1.1  christos 			if (opcode == oLocalForward ||
    741  1.1  christos 			    opcode == oDynamicForward)
    742  1.1  christos 				add_local_forward(options, &fwd);
    743  1.1  christos 			else if (opcode == oRemoteForward)
    744  1.1  christos 				add_remote_forward(options, &fwd);
    745  1.1  christos 		}
    746  1.1  christos 		break;
    747  1.1  christos 
    748  1.1  christos 	case oClearAllForwardings:
    749  1.1  christos 		intptr = &options->clear_forwardings;
    750  1.1  christos 		goto parse_flag;
    751  1.1  christos 
    752  1.1  christos 	case oHost:
    753  1.1  christos 		*activep = 0;
    754  1.1  christos 		while ((arg = strdelim(&s)) != NULL && *arg != '\0')
    755  1.1  christos 			if (match_pattern(host, arg)) {
    756  1.1  christos 				debug("Applying options for %.100s", arg);
    757  1.1  christos 				*activep = 1;
    758  1.1  christos 				break;
    759  1.1  christos 			}
    760  1.1  christos 		/* Avoid garbage check below, as strdelim is done. */
    761  1.1  christos 		return 0;
    762  1.1  christos 
    763  1.1  christos 	case oEscapeChar:
    764  1.1  christos 		intptr = &options->escape_char;
    765  1.1  christos 		arg = strdelim(&s);
    766  1.1  christos 		if (!arg || *arg == '\0')
    767  1.1  christos 			fatal("%.200s line %d: Missing argument.", filename, linenum);
    768  1.1  christos 		if (arg[0] == '^' && arg[2] == 0 &&
    769  1.1  christos 		    (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
    770  1.1  christos 			value = (u_char) arg[1] & 31;
    771  1.1  christos 		else if (strlen(arg) == 1)
    772  1.1  christos 			value = (u_char) arg[0];
    773  1.1  christos 		else if (strcmp(arg, "none") == 0)
    774  1.1  christos 			value = SSH_ESCAPECHAR_NONE;
    775  1.1  christos 		else {
    776  1.1  christos 			fatal("%.200s line %d: Bad escape character.",
    777  1.1  christos 			    filename, linenum);
    778  1.1  christos 			/* NOTREACHED */
    779  1.1  christos 			value = 0;	/* Avoid compiler warning. */
    780  1.1  christos 		}
    781  1.1  christos 		if (*activep && *intptr == -1)
    782  1.1  christos 			*intptr = value;
    783  1.1  christos 		break;
    784  1.1  christos 
    785  1.1  christos 	case oAddressFamily:
    786  1.1  christos 		arg = strdelim(&s);
    787  1.1  christos 		if (!arg || *arg == '\0')
    788  1.1  christos 			fatal("%s line %d: missing address family.",
    789  1.1  christos 			    filename, linenum);
    790  1.1  christos 		intptr = &options->address_family;
    791  1.1  christos 		if (strcasecmp(arg, "inet") == 0)
    792  1.1  christos 			value = AF_INET;
    793  1.1  christos 		else if (strcasecmp(arg, "inet6") == 0)
    794  1.1  christos 			value = AF_INET6;
    795  1.1  christos 		else if (strcasecmp(arg, "any") == 0)
    796  1.1  christos 			value = AF_UNSPEC;
    797  1.1  christos 		else
    798  1.1  christos 			fatal("Unsupported AddressFamily \"%s\"", arg);
    799  1.1  christos 		if (*activep && *intptr == -1)
    800  1.1  christos 			*intptr = value;
    801  1.1  christos 		break;
    802  1.1  christos 
    803  1.1  christos 	case oEnableSSHKeysign:
    804  1.1  christos 		intptr = &options->enable_ssh_keysign;
    805  1.1  christos 		goto parse_flag;
    806  1.1  christos 
    807  1.1  christos 	case oIdentitiesOnly:
    808  1.1  christos 		intptr = &options->identities_only;
    809  1.1  christos 		goto parse_flag;
    810  1.1  christos 
    811  1.1  christos 	case oServerAliveInterval:
    812  1.1  christos 		intptr = &options->server_alive_interval;
    813  1.1  christos 		goto parse_time;
    814  1.1  christos 
    815  1.1  christos 	case oServerAliveCountMax:
    816  1.1  christos 		intptr = &options->server_alive_count_max;
    817  1.1  christos 		goto parse_int;
    818  1.1  christos 
    819  1.1  christos 	case oSendEnv:
    820  1.1  christos 		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
    821  1.1  christos 			if (strchr(arg, '=') != NULL)
    822  1.1  christos 				fatal("%s line %d: Invalid environment name.",
    823  1.1  christos 				    filename, linenum);
    824  1.1  christos 			if (!*activep)
    825  1.1  christos 				continue;
    826  1.1  christos 			if (options->num_send_env >= MAX_SEND_ENV)
    827  1.1  christos 				fatal("%s line %d: too many send env.",
    828  1.1  christos 				    filename, linenum);
    829  1.1  christos 			options->send_env[options->num_send_env++] =
    830  1.1  christos 			    xstrdup(arg);
    831  1.1  christos 		}
    832  1.1  christos 		break;
    833  1.1  christos 
    834  1.1  christos 	case oControlPath:
    835  1.1  christos 		charptr = &options->control_path;
    836  1.1  christos 		goto parse_string;
    837  1.1  christos 
    838  1.1  christos 	case oControlMaster:
    839  1.1  christos 		intptr = &options->control_master;
    840  1.1  christos 		arg = strdelim(&s);
    841  1.1  christos 		if (!arg || *arg == '\0')
    842  1.1  christos 			fatal("%.200s line %d: Missing ControlMaster argument.",
    843  1.1  christos 			    filename, linenum);
    844  1.1  christos 		value = 0;	/* To avoid compiler warning... */
    845  1.1  christos 		if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
    846  1.1  christos 			value = SSHCTL_MASTER_YES;
    847  1.1  christos 		else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
    848  1.1  christos 			value = SSHCTL_MASTER_NO;
    849  1.1  christos 		else if (strcmp(arg, "auto") == 0)
    850  1.1  christos 			value = SSHCTL_MASTER_AUTO;
    851  1.1  christos 		else if (strcmp(arg, "ask") == 0)
    852  1.1  christos 			value = SSHCTL_MASTER_ASK;
    853  1.1  christos 		else if (strcmp(arg, "autoask") == 0)
    854  1.1  christos 			value = SSHCTL_MASTER_AUTO_ASK;
    855  1.1  christos 		else
    856  1.1  christos 			fatal("%.200s line %d: Bad ControlMaster argument.",
    857  1.1  christos 			    filename, linenum);
    858  1.1  christos 		if (*activep && *intptr == -1)
    859  1.1  christos 			*intptr = value;
    860  1.1  christos 		break;
    861  1.1  christos 
    862  1.1  christos 	case oHashKnownHosts:
    863  1.1  christos 		intptr = &options->hash_known_hosts;
    864  1.1  christos 		goto parse_flag;
    865  1.1  christos 
    866  1.1  christos 	case oTunnel:
    867  1.1  christos 		intptr = &options->tun_open;
    868  1.1  christos 		arg = strdelim(&s);
    869  1.1  christos 		if (!arg || *arg == '\0')
    870  1.1  christos 			fatal("%s line %d: Missing yes/point-to-point/"
    871  1.1  christos 			    "ethernet/no argument.", filename, linenum);
    872  1.1  christos 		value = 0;	/* silence compiler */
    873  1.1  christos 		if (strcasecmp(arg, "ethernet") == 0)
    874  1.1  christos 			value = SSH_TUNMODE_ETHERNET;
    875  1.1  christos 		else if (strcasecmp(arg, "point-to-point") == 0)
    876  1.1  christos 			value = SSH_TUNMODE_POINTOPOINT;
    877  1.1  christos 		else if (strcasecmp(arg, "yes") == 0)
    878  1.1  christos 			value = SSH_TUNMODE_DEFAULT;
    879  1.1  christos 		else if (strcasecmp(arg, "no") == 0)
    880  1.1  christos 			value = SSH_TUNMODE_NO;
    881  1.1  christos 		else
    882  1.1  christos 			fatal("%s line %d: Bad yes/point-to-point/ethernet/"
    883  1.1  christos 			    "no argument: %s", filename, linenum, arg);
    884  1.1  christos 		if (*activep)
    885  1.1  christos 			*intptr = value;
    886  1.1  christos 		break;
    887  1.1  christos 
    888  1.1  christos 	case oTunnelDevice:
    889  1.1  christos 		arg = strdelim(&s);
    890  1.1  christos 		if (!arg || *arg == '\0')
    891  1.1  christos 			fatal("%.200s line %d: Missing argument.", filename, linenum);
    892  1.1  christos 		value = a2tun(arg, &value2);
    893  1.1  christos 		if (value == SSH_TUNID_ERR)
    894  1.1  christos 			fatal("%.200s line %d: Bad tun device.", filename, linenum);
    895  1.1  christos 		if (*activep) {
    896  1.1  christos 			options->tun_local = value;
    897  1.1  christos 			options->tun_remote = value2;
    898  1.1  christos 		}
    899  1.1  christos 		break;
    900  1.1  christos 
    901  1.1  christos 	case oLocalCommand:
    902  1.1  christos 		charptr = &options->local_command;
    903  1.1  christos 		goto parse_command;
    904  1.1  christos 
    905  1.1  christos 	case oPermitLocalCommand:
    906  1.1  christos 		intptr = &options->permit_local_command;
    907  1.1  christos 		goto parse_flag;
    908  1.1  christos 
    909  1.1  christos 	case oVisualHostKey:
    910  1.1  christos 		intptr = &options->visual_host_key;
    911  1.1  christos 		goto parse_flag;
    912  1.1  christos 
    913  1.1  christos 	case oDeprecated:
    914  1.1  christos 		debug("%s line %d: Deprecated option \"%s\"",
    915  1.1  christos 		    filename, linenum, keyword);
    916  1.1  christos 		return 0;
    917  1.1  christos 
    918  1.1  christos 	case oUnsupported:
    919  1.1  christos 		error("%s line %d: Unsupported option \"%s\"",
    920  1.1  christos 		    filename, linenum, keyword);
    921  1.1  christos 		return 0;
    922  1.1  christos 
    923  1.1  christos 	default:
    924  1.1  christos 		fatal("process_config_line: Unimplemented opcode %d", opcode);
    925  1.1  christos 	}
    926  1.1  christos 
    927  1.1  christos 	/* Check that there is no garbage at end of line. */
    928  1.1  christos 	if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
    929  1.1  christos 		fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
    930  1.1  christos 		    filename, linenum, arg);
    931  1.1  christos 	}
    932  1.1  christos 	return 0;
    933  1.1  christos }
    934  1.1  christos 
    935  1.1  christos 
    936  1.1  christos /*
    937  1.1  christos  * Reads the config file and modifies the options accordingly.  Options
    938  1.1  christos  * should already be initialized before this call.  This never returns if
    939  1.1  christos  * there is an error.  If the file does not exist, this returns 0.
    940  1.1  christos  */
    941  1.1  christos 
    942  1.1  christos int
    943  1.1  christos read_config_file(const char *filename, const char *host, Options *options,
    944  1.1  christos     int checkperm)
    945  1.1  christos {
    946  1.1  christos 	FILE *f;
    947  1.1  christos 	char line[1024];
    948  1.1  christos 	int active, linenum;
    949  1.1  christos 	int bad_options = 0;
    950  1.1  christos 
    951  1.1  christos 	if ((f = fopen(filename, "r")) == NULL)
    952  1.1  christos 		return 0;
    953  1.1  christos 
    954  1.1  christos 	if (checkperm) {
    955  1.1  christos 		struct stat sb;
    956  1.1  christos 
    957  1.1  christos 		if (fstat(fileno(f), &sb) == -1)
    958  1.1  christos 			fatal("fstat %s: %s", filename, strerror(errno));
    959  1.1  christos 		if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
    960  1.1  christos 		    (sb.st_mode & 022) != 0))
    961  1.1  christos 			fatal("Bad owner or permissions on %s", filename);
    962  1.1  christos 	}
    963  1.1  christos 
    964  1.1  christos 	debug("Reading configuration data %.200s", filename);
    965  1.1  christos 
    966  1.1  christos 	/*
    967  1.1  christos 	 * Mark that we are now processing the options.  This flag is turned
    968  1.1  christos 	 * on/off by Host specifications.
    969  1.1  christos 	 */
    970  1.1  christos 	active = 1;
    971  1.1  christos 	linenum = 0;
    972  1.1  christos 	while (fgets(line, sizeof(line), f)) {
    973  1.1  christos 		/* Update line number counter. */
    974  1.1  christos 		linenum++;
    975  1.1  christos 		if (process_config_line(options, host, line, filename, linenum, &active) != 0)
    976  1.1  christos 			bad_options++;
    977  1.1  christos 	}
    978  1.1  christos 	fclose(f);
    979  1.1  christos 	if (bad_options > 0)
    980  1.1  christos 		fatal("%s: terminating, %d bad configuration options",
    981  1.1  christos 		    filename, bad_options);
    982  1.1  christos 	return 1;
    983  1.1  christos }
    984  1.1  christos 
    985  1.1  christos /*
    986  1.1  christos  * Initializes options to special values that indicate that they have not yet
    987  1.1  christos  * been set.  Read_config_file will only set options with this value. Options
    988  1.1  christos  * are processed in the following order: command line, user config file,
    989  1.1  christos  * system config file.  Last, fill_default_options is called.
    990  1.1  christos  */
    991  1.1  christos 
    992  1.1  christos void
    993  1.1  christos initialize_options(Options * options)
    994  1.1  christos {
    995  1.1  christos 	memset(options, 'X', sizeof(*options));
    996  1.1  christos 	options->forward_agent = -1;
    997  1.1  christos 	options->forward_x11 = -1;
    998  1.1  christos 	options->forward_x11_trusted = -1;
    999  1.1  christos 	options->exit_on_forward_failure = -1;
   1000  1.1  christos 	options->xauth_location = NULL;
   1001  1.1  christos 	options->gateway_ports = -1;
   1002  1.1  christos 	options->use_privileged_port = -1;
   1003  1.1  christos 	options->rsa_authentication = -1;
   1004  1.1  christos 	options->pubkey_authentication = -1;
   1005  1.1  christos 	options->challenge_response_authentication = -1;
   1006  1.1  christos 	options->gss_authentication = -1;
   1007  1.1  christos 	options->gss_deleg_creds = -1;
   1008  1.1  christos 	options->password_authentication = -1;
   1009  1.1  christos 	options->kbd_interactive_authentication = -1;
   1010  1.1  christos 	options->kbd_interactive_devices = NULL;
   1011  1.1  christos 	options->rhosts_rsa_authentication = -1;
   1012  1.1  christos 	options->hostbased_authentication = -1;
   1013  1.1  christos 	options->batch_mode = -1;
   1014  1.1  christos 	options->check_host_ip = -1;
   1015  1.1  christos 	options->strict_host_key_checking = -1;
   1016  1.1  christos 	options->compression = -1;
   1017  1.1  christos 	options->tcp_keep_alive = -1;
   1018  1.1  christos 	options->compression_level = -1;
   1019  1.1  christos 	options->port = -1;
   1020  1.1  christos 	options->address_family = -1;
   1021  1.1  christos 	options->connection_attempts = -1;
   1022  1.1  christos 	options->connection_timeout = -1;
   1023  1.1  christos 	options->number_of_password_prompts = -1;
   1024  1.1  christos 	options->cipher = -1;
   1025  1.1  christos 	options->ciphers = NULL;
   1026  1.1  christos 	options->macs = NULL;
   1027  1.1  christos 	options->hostkeyalgorithms = NULL;
   1028  1.1  christos 	options->protocol = SSH_PROTO_UNKNOWN;
   1029  1.1  christos 	options->num_identity_files = 0;
   1030  1.1  christos 	options->hostname = NULL;
   1031  1.1  christos 	options->host_key_alias = NULL;
   1032  1.1  christos 	options->proxy_command = NULL;
   1033  1.1  christos 	options->user = NULL;
   1034  1.1  christos 	options->escape_char = -1;
   1035  1.1  christos 	options->system_hostfile = NULL;
   1036  1.1  christos 	options->user_hostfile = NULL;
   1037  1.1  christos 	options->system_hostfile2 = NULL;
   1038  1.1  christos 	options->user_hostfile2 = NULL;
   1039  1.1  christos 	options->num_local_forwards = 0;
   1040  1.1  christos 	options->num_remote_forwards = 0;
   1041  1.1  christos 	options->clear_forwardings = -1;
   1042  1.1  christos 	options->log_level = SYSLOG_LEVEL_NOT_SET;
   1043  1.1  christos 	options->preferred_authentications = NULL;
   1044  1.1  christos 	options->bind_address = NULL;
   1045  1.1  christos 	options->smartcard_device = NULL;
   1046  1.1  christos 	options->enable_ssh_keysign = - 1;
   1047  1.1  christos 	options->no_host_authentication_for_localhost = - 1;
   1048  1.1  christos 	options->identities_only = - 1;
   1049  1.1  christos 	options->rekey_limit = - 1;
   1050  1.1  christos 	options->verify_host_key_dns = -1;
   1051  1.1  christos 	options->server_alive_interval = -1;
   1052  1.1  christos 	options->server_alive_count_max = -1;
   1053  1.1  christos 	options->num_send_env = 0;
   1054  1.1  christos 	options->control_path = NULL;
   1055  1.1  christos 	options->control_master = -1;
   1056  1.1  christos 	options->hash_known_hosts = -1;
   1057  1.1  christos 	options->tun_open = -1;
   1058  1.1  christos 	options->tun_local = -1;
   1059  1.1  christos 	options->tun_remote = -1;
   1060  1.1  christos 	options->local_command = NULL;
   1061  1.1  christos 	options->permit_local_command = -1;
   1062  1.1  christos 	options->visual_host_key = -1;
   1063  1.1  christos 	options->zero_knowledge_password_authentication = -1;
   1064  1.1  christos }
   1065  1.1  christos 
   1066  1.1  christos /*
   1067  1.1  christos  * Called after processing other sources of option data, this fills those
   1068  1.1  christos  * options for which no value has been specified with their default values.
   1069  1.1  christos  */
   1070  1.1  christos 
   1071  1.1  christos void
   1072  1.1  christos fill_default_options(Options * options)
   1073  1.1  christos {
   1074  1.1  christos 	int len;
   1075  1.1  christos 
   1076  1.1  christos 	if (options->forward_agent == -1)
   1077  1.1  christos 		options->forward_agent = 0;
   1078  1.1  christos 	if (options->forward_x11 == -1)
   1079  1.1  christos 		options->forward_x11 = 0;
   1080  1.1  christos 	if (options->forward_x11_trusted == -1)
   1081  1.1  christos 		options->forward_x11_trusted = 0;
   1082  1.1  christos 	if (options->exit_on_forward_failure == -1)
   1083  1.1  christos 		options->exit_on_forward_failure = 0;
   1084  1.1  christos 	if (options->xauth_location == NULL)
   1085  1.1  christos 		options->xauth_location = _PATH_XAUTH;
   1086  1.1  christos 	if (options->gateway_ports == -1)
   1087  1.1  christos 		options->gateway_ports = 0;
   1088  1.1  christos 	if (options->use_privileged_port == -1)
   1089  1.1  christos 		options->use_privileged_port = 0;
   1090  1.1  christos 	if (options->rsa_authentication == -1)
   1091  1.1  christos 		options->rsa_authentication = 1;
   1092  1.1  christos 	if (options->pubkey_authentication == -1)
   1093  1.1  christos 		options->pubkey_authentication = 1;
   1094  1.1  christos 	if (options->challenge_response_authentication == -1)
   1095  1.1  christos 		options->challenge_response_authentication = 1;
   1096  1.1  christos 	if (options->gss_authentication == -1)
   1097  1.1  christos 		options->gss_authentication = 0;
   1098  1.1  christos 	if (options->gss_deleg_creds == -1)
   1099  1.1  christos 		options->gss_deleg_creds = 0;
   1100  1.1  christos 	if (options->password_authentication == -1)
   1101  1.1  christos 		options->password_authentication = 1;
   1102  1.1  christos 	if (options->kbd_interactive_authentication == -1)
   1103  1.1  christos 		options->kbd_interactive_authentication = 1;
   1104  1.1  christos 	if (options->rhosts_rsa_authentication == -1)
   1105  1.1  christos 		options->rhosts_rsa_authentication = 0;
   1106  1.1  christos 	if (options->hostbased_authentication == -1)
   1107  1.1  christos 		options->hostbased_authentication = 0;
   1108  1.1  christos 	if (options->batch_mode == -1)
   1109  1.1  christos 		options->batch_mode = 0;
   1110  1.1  christos 	if (options->check_host_ip == -1)
   1111  1.1  christos 		options->check_host_ip = 1;
   1112  1.1  christos 	if (options->strict_host_key_checking == -1)
   1113  1.1  christos 		options->strict_host_key_checking = 2;	/* 2 is default */
   1114  1.1  christos 	if (options->compression == -1)
   1115  1.1  christos 		options->compression = 0;
   1116  1.1  christos 	if (options->tcp_keep_alive == -1)
   1117  1.1  christos 		options->tcp_keep_alive = 1;
   1118  1.1  christos 	if (options->compression_level == -1)
   1119  1.1  christos 		options->compression_level = 6;
   1120  1.1  christos 	if (options->port == -1)
   1121  1.1  christos 		options->port = 0;	/* Filled in ssh_connect. */
   1122  1.1  christos 	if (options->address_family == -1)
   1123  1.1  christos 		options->address_family = AF_UNSPEC;
   1124  1.1  christos 	if (options->connection_attempts == -1)
   1125  1.1  christos 		options->connection_attempts = 1;
   1126  1.1  christos 	if (options->number_of_password_prompts == -1)
   1127  1.1  christos 		options->number_of_password_prompts = 3;
   1128  1.1  christos 	/* Selected in ssh_login(). */
   1129  1.1  christos 	if (options->cipher == -1)
   1130  1.1  christos 		options->cipher = SSH_CIPHER_NOT_SET;
   1131  1.1  christos 	/* options->ciphers, default set in myproposals.h */
   1132  1.1  christos 	/* options->macs, default set in myproposals.h */
   1133  1.1  christos 	/* options->hostkeyalgorithms, default set in myproposals.h */
   1134  1.1  christos 	if (options->protocol == SSH_PROTO_UNKNOWN)
   1135  1.1  christos 		options->protocol = SSH_PROTO_1|SSH_PROTO_2;
   1136  1.1  christos 	if (options->num_identity_files == 0) {
   1137  1.1  christos 		if (options->protocol & SSH_PROTO_1) {
   1138  1.1  christos 			len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1;
   1139  1.1  christos 			options->identity_files[options->num_identity_files] =
   1140  1.1  christos 			    xmalloc(len);
   1141  1.1  christos 			snprintf(options->identity_files[options->num_identity_files++],
   1142  1.1  christos 			    len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY);
   1143  1.1  christos 		}
   1144  1.1  christos 		if (options->protocol & SSH_PROTO_2) {
   1145  1.1  christos 			len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1;
   1146  1.1  christos 			options->identity_files[options->num_identity_files] =
   1147  1.1  christos 			    xmalloc(len);
   1148  1.1  christos 			snprintf(options->identity_files[options->num_identity_files++],
   1149  1.1  christos 			    len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA);
   1150  1.1  christos 
   1151  1.1  christos 			len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1;
   1152  1.1  christos 			options->identity_files[options->num_identity_files] =
   1153  1.1  christos 			    xmalloc(len);
   1154  1.1  christos 			snprintf(options->identity_files[options->num_identity_files++],
   1155  1.1  christos 			    len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA);
   1156  1.1  christos 		}
   1157  1.1  christos 	}
   1158  1.1  christos 	if (options->escape_char == -1)
   1159  1.1  christos 		options->escape_char = '~';
   1160  1.1  christos 	if (options->system_hostfile == NULL)
   1161  1.1  christos 		options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE;
   1162  1.1  christos 	if (options->user_hostfile == NULL)
   1163  1.1  christos 		options->user_hostfile = _PATH_SSH_USER_HOSTFILE;
   1164  1.1  christos 	if (options->system_hostfile2 == NULL)
   1165  1.1  christos 		options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2;
   1166  1.1  christos 	if (options->user_hostfile2 == NULL)
   1167  1.1  christos 		options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2;
   1168  1.1  christos 	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
   1169  1.1  christos 		options->log_level = SYSLOG_LEVEL_INFO;
   1170  1.1  christos 	if (options->clear_forwardings == 1)
   1171  1.1  christos 		clear_forwardings(options);
   1172  1.1  christos 	if (options->no_host_authentication_for_localhost == - 1)
   1173  1.1  christos 		options->no_host_authentication_for_localhost = 0;
   1174  1.1  christos 	if (options->identities_only == -1)
   1175  1.1  christos 		options->identities_only = 0;
   1176  1.1  christos 	if (options->enable_ssh_keysign == -1)
   1177  1.1  christos 		options->enable_ssh_keysign = 0;
   1178  1.1  christos 	if (options->rekey_limit == -1)
   1179  1.1  christos 		options->rekey_limit = 0;
   1180  1.1  christos 	if (options->verify_host_key_dns == -1)
   1181  1.1  christos 		options->verify_host_key_dns = 0;
   1182  1.1  christos 	if (options->server_alive_interval == -1)
   1183  1.1  christos 		options->server_alive_interval = 0;
   1184  1.1  christos 	if (options->server_alive_count_max == -1)
   1185  1.1  christos 		options->server_alive_count_max = 3;
   1186  1.1  christos 	if (options->control_master == -1)
   1187  1.1  christos 		options->control_master = 0;
   1188  1.1  christos 	if (options->hash_known_hosts == -1)
   1189  1.1  christos 		options->hash_known_hosts = 0;
   1190  1.1  christos 	if (options->tun_open == -1)
   1191  1.1  christos 		options->tun_open = SSH_TUNMODE_NO;
   1192  1.1  christos 	if (options->tun_local == -1)
   1193  1.1  christos 		options->tun_local = SSH_TUNID_ANY;
   1194  1.1  christos 	if (options->tun_remote == -1)
   1195  1.1  christos 		options->tun_remote = SSH_TUNID_ANY;
   1196  1.1  christos 	if (options->permit_local_command == -1)
   1197  1.1  christos 		options->permit_local_command = 0;
   1198  1.1  christos 	if (options->visual_host_key == -1)
   1199  1.1  christos 		options->visual_host_key = 0;
   1200  1.1  christos 	if (options->zero_knowledge_password_authentication == -1)
   1201  1.1  christos 		options->zero_knowledge_password_authentication = 0;
   1202  1.1  christos 	/* options->local_command should not be set by default */
   1203  1.1  christos 	/* options->proxy_command should not be set by default */
   1204  1.1  christos 	/* options->user will be set in the main program if appropriate */
   1205  1.1  christos 	/* options->hostname will be set in the main program if appropriate */
   1206  1.1  christos 	/* options->host_key_alias should not be set by default */
   1207  1.1  christos 	/* options->preferred_authentications will be set in ssh */
   1208  1.1  christos }
   1209  1.1  christos 
   1210  1.1  christos /*
   1211  1.1  christos  * parse_forward
   1212  1.1  christos  * parses a string containing a port forwarding specification of the form:
   1213  1.1  christos  *   dynamicfwd == 0
   1214  1.1  christos  *	[listenhost:]listenport:connecthost:connectport
   1215  1.1  christos  *   dynamicfwd == 1
   1216  1.1  christos  *	[listenhost:]listenport
   1217  1.1  christos  * returns number of arguments parsed or zero on error
   1218  1.1  christos  */
   1219  1.1  christos int
   1220  1.1  christos parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
   1221  1.1  christos {
   1222  1.1  christos 	int i;
   1223  1.1  christos 	char *p, *cp, *fwdarg[4];
   1224  1.1  christos 
   1225  1.1  christos 	memset(fwd, '\0', sizeof(*fwd));
   1226  1.1  christos 
   1227  1.1  christos 	cp = p = xstrdup(fwdspec);
   1228  1.1  christos 
   1229  1.1  christos 	/* skip leading spaces */
   1230  1.1  christos 	while (isspace(*cp))
   1231  1.1  christos 		cp++;
   1232  1.1  christos 
   1233  1.1  christos 	for (i = 0; i < 4; ++i)
   1234  1.1  christos 		if ((fwdarg[i] = hpdelim(&cp)) == NULL)
   1235  1.1  christos 			break;
   1236  1.1  christos 
   1237  1.1  christos 	/* Check for trailing garbage */
   1238  1.1  christos 	if (cp != NULL)
   1239  1.1  christos 		i = 0;	/* failure */
   1240  1.1  christos 
   1241  1.1  christos 	switch (i) {
   1242  1.1  christos 	case 1:
   1243  1.1  christos 		fwd->listen_host = NULL;
   1244  1.1  christos 		fwd->listen_port = a2port(fwdarg[0]);
   1245  1.1  christos 		fwd->connect_host = xstrdup("socks");
   1246  1.1  christos 		break;
   1247  1.1  christos 
   1248  1.1  christos 	case 2:
   1249  1.1  christos 		fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
   1250  1.1  christos 		fwd->listen_port = a2port(fwdarg[1]);
   1251  1.1  christos 		fwd->connect_host = xstrdup("socks");
   1252  1.1  christos 		break;
   1253  1.1  christos 
   1254  1.1  christos 	case 3:
   1255  1.1  christos 		fwd->listen_host = NULL;
   1256  1.1  christos 		fwd->listen_port = a2port(fwdarg[0]);
   1257  1.1  christos 		fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
   1258  1.1  christos 		fwd->connect_port = a2port(fwdarg[2]);
   1259  1.1  christos 		break;
   1260  1.1  christos 
   1261  1.1  christos 	case 4:
   1262  1.1  christos 		fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
   1263  1.1  christos 		fwd->listen_port = a2port(fwdarg[1]);
   1264  1.1  christos 		fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
   1265  1.1  christos 		fwd->connect_port = a2port(fwdarg[3]);
   1266  1.1  christos 		break;
   1267  1.1  christos 	default:
   1268  1.1  christos 		i = 0; /* failure */
   1269  1.1  christos 	}
   1270  1.1  christos 
   1271  1.1  christos 	xfree(p);
   1272  1.1  christos 
   1273  1.1  christos 	if (dynamicfwd) {
   1274  1.1  christos 		if (!(i == 1 || i == 2))
   1275  1.1  christos 			goto fail_free;
   1276  1.1  christos 	} else {
   1277  1.1  christos 		if (!(i == 3 || i == 4))
   1278  1.1  christos 			goto fail_free;
   1279  1.1  christos 		if (fwd->connect_port <= 0)
   1280  1.1  christos 			goto fail_free;
   1281  1.1  christos 	}
   1282  1.1  christos 
   1283  1.1  christos 	if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0))
   1284  1.1  christos 		goto fail_free;
   1285  1.1  christos 
   1286  1.1  christos 	if (fwd->connect_host != NULL &&
   1287  1.1  christos 	    strlen(fwd->connect_host) >= NI_MAXHOST)
   1288  1.1  christos 		goto fail_free;
   1289  1.1  christos 	if (fwd->listen_host != NULL &&
   1290  1.1  christos 	    strlen(fwd->listen_host) >= NI_MAXHOST)
   1291  1.1  christos 		goto fail_free;
   1292  1.1  christos 
   1293  1.1  christos 
   1294  1.1  christos 	return (i);
   1295  1.1  christos 
   1296  1.1  christos  fail_free:
   1297  1.1  christos 	if (fwd->connect_host != NULL) {
   1298  1.1  christos 		xfree(fwd->connect_host);
   1299  1.1  christos 		fwd->connect_host = NULL;
   1300  1.1  christos 	}
   1301  1.1  christos 	if (fwd->listen_host != NULL) {
   1302  1.1  christos 		xfree(fwd->listen_host);
   1303  1.1  christos 		fwd->listen_host = NULL;
   1304  1.1  christos 	}
   1305  1.1  christos 	return (0);
   1306  1.1  christos }
   1307