Home | History | Annotate | Line # | Download | only in dist
readconf.c revision 1.12
      1  1.11  christos /*	$NetBSD: readconf.c,v 1.12 2014/10/19 16:30:58 christos Exp $	*/
      2  1.12  christos /* $OpenBSD: readconf.c,v 1.220 2014/07/15 15:54:14 millert 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.2  christos #include "includes.h"
     17  1.11  christos __RCSID("$NetBSD: readconf.c,v 1.12 2014/10/19 16:30:58 christos Exp $");
     18   1.1  christos #include <sys/types.h>
     19   1.1  christos #include <sys/stat.h>
     20   1.1  christos #include <sys/socket.h>
     21  1.12  christos #include <sys/wait.h>
     22  1.12  christos #include <sys/un.h>
     23   1.1  christos 
     24   1.1  christos #include <netinet/in.h>
     25   1.5  christos #include <netinet/in_systm.h>
     26   1.5  christos #include <netinet/ip.h>
     27   1.1  christos 
     28   1.1  christos #include <ctype.h>
     29   1.1  christos #include <errno.h>
     30  1.12  christos #include <fcntl.h>
     31   1.1  christos #include <netdb.h>
     32  1.12  christos #include <paths.h>
     33  1.12  christos #include <pwd.h>
     34   1.1  christos #include <signal.h>
     35   1.1  christos #include <stdio.h>
     36   1.1  christos #include <string.h>
     37   1.1  christos #include <unistd.h>
     38   1.2  christos #include <limits.h>
     39  1.11  christos #include <util.h>
     40   1.1  christos 
     41   1.1  christos #include "xmalloc.h"
     42   1.1  christos #include "ssh.h"
     43   1.1  christos #include "compat.h"
     44   1.1  christos #include "cipher.h"
     45   1.1  christos #include "pathnames.h"
     46   1.1  christos #include "log.h"
     47   1.1  christos #include "key.h"
     48  1.12  christos #include "misc.h"
     49   1.1  christos #include "readconf.h"
     50   1.1  christos #include "match.h"
     51   1.1  christos #include "buffer.h"
     52   1.1  christos #include "kex.h"
     53   1.1  christos #include "mac.h"
     54  1.11  christos #include "fmt_scaled.h"
     55  1.12  christos #include "uidswap.h"
     56   1.1  christos 
     57   1.1  christos /* Format of the configuration file:
     58   1.1  christos 
     59   1.1  christos    # Configuration data is parsed as follows:
     60   1.1  christos    #  1. command line options
     61   1.1  christos    #  2. user-specific file
     62   1.1  christos    #  3. system-wide file
     63   1.1  christos    # Any configuration value is only changed the first time it is set.
     64   1.1  christos    # Thus, host-specific definitions should be at the beginning of the
     65   1.1  christos    # configuration file, and defaults at the end.
     66   1.1  christos 
     67   1.1  christos    # Host-specific declarations.  These may override anything above.  A single
     68   1.1  christos    # host may match multiple declarations; these are processed in the order
     69   1.1  christos    # that they are given in.
     70   1.1  christos 
     71   1.1  christos    Host *.ngs.fi ngs.fi
     72   1.1  christos      User foo
     73   1.1  christos 
     74   1.1  christos    Host fake.com
     75   1.1  christos      HostName another.host.name.real.org
     76   1.1  christos      User blaah
     77   1.1  christos      Port 34289
     78   1.1  christos      ForwardX11 no
     79   1.1  christos      ForwardAgent no
     80   1.1  christos 
     81   1.1  christos    Host books.com
     82   1.1  christos      RemoteForward 9999 shadows.cs.hut.fi:9999
     83   1.1  christos      Cipher 3des
     84   1.1  christos 
     85   1.1  christos    Host fascist.blob.com
     86   1.1  christos      Port 23123
     87   1.1  christos      User tylonen
     88   1.1  christos      PasswordAuthentication no
     89   1.1  christos 
     90   1.1  christos    Host puukko.hut.fi
     91   1.1  christos      User t35124p
     92   1.1  christos      ProxyCommand ssh-proxy %h %p
     93   1.1  christos 
     94   1.1  christos    Host *.fr
     95   1.1  christos      PublicKeyAuthentication no
     96   1.1  christos 
     97   1.1  christos    Host *.su
     98   1.1  christos      Cipher none
     99   1.1  christos      PasswordAuthentication no
    100   1.1  christos 
    101   1.1  christos    Host vpn.fake.com
    102   1.1  christos      Tunnel yes
    103   1.1  christos      TunnelDevice 3
    104   1.1  christos 
    105   1.1  christos    # Defaults for various options
    106   1.1  christos    Host *
    107   1.1  christos      ForwardAgent no
    108   1.1  christos      ForwardX11 no
    109   1.1  christos      PasswordAuthentication yes
    110   1.1  christos      RSAAuthentication yes
    111   1.1  christos      RhostsRSAAuthentication yes
    112   1.1  christos      StrictHostKeyChecking yes
    113   1.1  christos      TcpKeepAlive no
    114   1.1  christos      IdentityFile ~/.ssh/identity
    115   1.1  christos      Port 22
    116   1.1  christos      EscapeChar ~
    117   1.1  christos 
    118   1.1  christos */
    119   1.1  christos 
    120   1.1  christos /* Keyword tokens. */
    121   1.1  christos 
    122   1.1  christos typedef enum {
    123   1.1  christos 	oBadOption,
    124  1.12  christos 	oHost, oMatch,
    125   1.4      adam 	oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
    126   1.4      adam 	oGatewayPorts, oExitOnForwardFailure,
    127   1.1  christos 	oPasswordAuthentication, oRSAAuthentication,
    128   1.1  christos 	oChallengeResponseAuthentication, oXAuthLocation,
    129   1.2  christos #if defined(KRB4) || defined(KRB5)
    130   1.2  christos 	oKerberosAuthentication,
    131   1.2  christos #endif
    132   1.2  christos #if defined(AFS) || defined(KRB5)
    133   1.2  christos 	oKerberosTgtPassing,
    134   1.2  christos #endif
    135   1.2  christos #ifdef AFS
    136   1.2  christos 	oAFSTokenPassing,
    137   1.2  christos #endif
    138   1.1  christos 	oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
    139  1.12  christos 	oUser, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
    140   1.1  christos 	oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
    141   1.1  christos 	oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
    142   1.1  christos 	oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
    143   1.1  christos 	oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
    144   1.1  christos 	oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
    145   1.1  christos 	oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
    146   1.1  christos 	oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
    147   1.4      adam 	oHostKeyAlgorithms, oBindAddress, oPKCS11Provider,
    148   1.1  christos 	oClearAllForwardings, oNoHostAuthenticationForLocalhost,
    149   1.1  christos 	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
    150   1.1  christos 	oAddressFamily, oGssAuthentication, oGssDelegateCreds,
    151   1.1  christos 	oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
    152   1.4      adam 	oSendEnv, oControlPath, oControlMaster, oControlPersist,
    153   1.4      adam 	oHashKnownHosts,
    154   1.1  christos 	oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
    155  1.12  christos 	oVisualHostKey, oUseRoaming,
    156  1.12  christos 	oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass,
    157  1.12  christos 	oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
    158  1.12  christos 	oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
    159  1.12  christos 	oStreamLocalBindMask, oStreamLocalBindUnlink,
    160   1.2  christos 	oNoneEnabled, oTcpRcvBufPoll, oTcpRcvBuf, oNoneSwitch, oHPNDisabled,
    161   1.2  christos 	oHPNBufferSize,
    162   1.7       tls 	oSendVersionFirst,
    163  1.12  christos 	oIgnoredUnknownOption, oDeprecated, oUnsupported
    164   1.1  christos } OpCodes;
    165   1.1  christos 
    166   1.1  christos /* Textual representations of the tokens. */
    167   1.1  christos 
    168   1.1  christos static struct {
    169   1.1  christos 	const char *name;
    170   1.1  christos 	OpCodes opcode;
    171   1.1  christos } keywords[] = {
    172   1.1  christos 	{ "forwardagent", oForwardAgent },
    173   1.1  christos 	{ "forwardx11", oForwardX11 },
    174   1.1  christos 	{ "forwardx11trusted", oForwardX11Trusted },
    175   1.4      adam 	{ "forwardx11timeout", oForwardX11Timeout },
    176   1.1  christos 	{ "exitonforwardfailure", oExitOnForwardFailure },
    177   1.1  christos 	{ "xauthlocation", oXAuthLocation },
    178   1.1  christos 	{ "gatewayports", oGatewayPorts },
    179   1.1  christos 	{ "useprivilegedport", oUsePrivilegedPort },
    180   1.1  christos 	{ "rhostsauthentication", oDeprecated },
    181   1.1  christos 	{ "passwordauthentication", oPasswordAuthentication },
    182   1.1  christos 	{ "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
    183   1.1  christos 	{ "kbdinteractivedevices", oKbdInteractiveDevices },
    184   1.1  christos 	{ "rsaauthentication", oRSAAuthentication },
    185   1.1  christos 	{ "pubkeyauthentication", oPubkeyAuthentication },
    186   1.1  christos 	{ "dsaauthentication", oPubkeyAuthentication },		    /* alias */
    187   1.1  christos 	{ "rhostsrsaauthentication", oRhostsRSAAuthentication },
    188   1.1  christos 	{ "hostbasedauthentication", oHostbasedAuthentication },
    189   1.1  christos 	{ "challengeresponseauthentication", oChallengeResponseAuthentication },
    190   1.1  christos 	{ "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
    191   1.1  christos 	{ "tisauthentication", oChallengeResponseAuthentication },  /* alias */
    192   1.2  christos #if defined(KRB4) || defined(KRB5)
    193   1.2  christos 	{ "kerberosauthentication", oKerberosAuthentication },
    194   1.2  christos #endif
    195   1.2  christos #if defined(AFS) || defined(KRB5)
    196   1.2  christos 	{ "kerberostgtpassing", oKerberosTgtPassing },
    197   1.2  christos 	{ "kerberos5tgtpassing", oKerberosTgtPassing },		/* alias */
    198   1.2  christos 	{ "kerberos4tgtpassing", oKerberosTgtPassing },		/* alias */
    199   1.2  christos #endif
    200   1.2  christos #ifdef AFS
    201   1.2  christos 	{ "afstokenpassing", oAFSTokenPassing },
    202   1.2  christos #endif
    203   1.1  christos #if defined(GSSAPI)
    204   1.1  christos 	{ "gssapiauthentication", oGssAuthentication },
    205   1.1  christos 	{ "gssapidelegatecredentials", oGssDelegateCreds },
    206   1.1  christos #else
    207   1.1  christos 	{ "gssapiauthentication", oUnsupported },
    208   1.1  christos 	{ "gssapidelegatecredentials", oUnsupported },
    209   1.1  christos #endif
    210   1.1  christos 	{ "fallbacktorsh", oDeprecated },
    211   1.1  christos 	{ "usersh", oDeprecated },
    212   1.1  christos 	{ "identityfile", oIdentityFile },
    213   1.1  christos 	{ "identityfile2", oIdentityFile },			/* obsolete */
    214   1.1  christos 	{ "identitiesonly", oIdentitiesOnly },
    215   1.1  christos 	{ "hostname", oHostName },
    216   1.1  christos 	{ "hostkeyalias", oHostKeyAlias },
    217   1.1  christos 	{ "proxycommand", oProxyCommand },
    218   1.1  christos 	{ "port", oPort },
    219   1.1  christos 	{ "cipher", oCipher },
    220   1.1  christos 	{ "ciphers", oCiphers },
    221   1.1  christos 	{ "macs", oMacs },
    222   1.1  christos 	{ "protocol", oProtocol },
    223   1.1  christos 	{ "remoteforward", oRemoteForward },
    224   1.1  christos 	{ "localforward", oLocalForward },
    225   1.1  christos 	{ "user", oUser },
    226   1.1  christos 	{ "host", oHost },
    227  1.12  christos 	{ "match", oMatch },
    228   1.1  christos 	{ "escapechar", oEscapeChar },
    229   1.1  christos 	{ "globalknownhostsfile", oGlobalKnownHostsFile },
    230   1.6  christos 	{ "globalknownhostsfile2", oDeprecated },
    231   1.1  christos 	{ "userknownhostsfile", oUserKnownHostsFile },
    232   1.6  christos 	{ "userknownhostsfile2", oDeprecated },
    233   1.1  christos 	{ "connectionattempts", oConnectionAttempts },
    234   1.1  christos 	{ "batchmode", oBatchMode },
    235   1.1  christos 	{ "checkhostip", oCheckHostIP },
    236   1.1  christos 	{ "stricthostkeychecking", oStrictHostKeyChecking },
    237   1.1  christos 	{ "compression", oCompression },
    238   1.1  christos 	{ "compressionlevel", oCompressionLevel },
    239   1.1  christos 	{ "tcpkeepalive", oTCPKeepAlive },
    240   1.1  christos 	{ "keepalive", oTCPKeepAlive },				/* obsolete */
    241   1.1  christos 	{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
    242   1.1  christos 	{ "loglevel", oLogLevel },
    243   1.1  christos 	{ "dynamicforward", oDynamicForward },
    244   1.1  christos 	{ "preferredauthentications", oPreferredAuthentications },
    245   1.1  christos 	{ "hostkeyalgorithms", oHostKeyAlgorithms },
    246   1.1  christos 	{ "bindaddress", oBindAddress },
    247   1.4      adam #ifdef ENABLE_PKCS11
    248   1.4      adam 	{ "smartcarddevice", oPKCS11Provider },
    249   1.4      adam 	{ "pkcs11provider", oPKCS11Provider },
    250   1.1  christos #else
    251   1.1  christos 	{ "smartcarddevice", oUnsupported },
    252   1.4      adam 	{ "pkcs11provider", oUnsupported },
    253   1.1  christos #endif
    254   1.1  christos 	{ "clearallforwardings", oClearAllForwardings },
    255   1.1  christos 	{ "enablesshkeysign", oEnableSSHKeysign },
    256   1.1  christos 	{ "verifyhostkeydns", oVerifyHostKeyDNS },
    257   1.1  christos 	{ "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
    258   1.1  christos 	{ "rekeylimit", oRekeyLimit },
    259   1.1  christos 	{ "connecttimeout", oConnectTimeout },
    260   1.1  christos 	{ "addressfamily", oAddressFamily },
    261   1.1  christos 	{ "serveraliveinterval", oServerAliveInterval },
    262   1.1  christos 	{ "serveralivecountmax", oServerAliveCountMax },
    263   1.1  christos 	{ "sendenv", oSendEnv },
    264   1.1  christos 	{ "controlpath", oControlPath },
    265   1.1  christos 	{ "controlmaster", oControlMaster },
    266   1.4      adam 	{ "controlpersist", oControlPersist },
    267   1.1  christos 	{ "hashknownhosts", oHashKnownHosts },
    268   1.1  christos 	{ "tunnel", oTunnel },
    269   1.1  christos 	{ "tunneldevice", oTunnelDevice },
    270   1.1  christos 	{ "localcommand", oLocalCommand },
    271   1.1  christos 	{ "permitlocalcommand", oPermitLocalCommand },
    272   1.1  christos 	{ "visualhostkey", oVisualHostKey },
    273   1.3  christos 	{ "useroaming", oUseRoaming },
    274   1.5  christos 	{ "kexalgorithms", oKexAlgorithms },
    275   1.5  christos 	{ "ipqos", oIPQoS },
    276   1.6  christos 	{ "requesttty", oRequestTTY },
    277  1.12  christos 	{ "proxyusefdpass", oProxyUseFdpass },
    278  1.12  christos 	{ "canonicaldomains", oCanonicalDomains },
    279  1.12  christos 	{ "canonicalizefallbacklocal", oCanonicalizeFallbackLocal },
    280  1.12  christos 	{ "canonicalizehostname", oCanonicalizeHostname },
    281  1.12  christos 	{ "canonicalizemaxdots", oCanonicalizeMaxDots },
    282  1.12  christos 	{ "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs },
    283  1.12  christos 	{ "streamlocalbindmask", oStreamLocalBindMask },
    284  1.12  christos 	{ "streamlocalbindunlink", oStreamLocalBindUnlink },
    285   1.2  christos 	{ "noneenabled", oNoneEnabled },
    286   1.2  christos 	{ "tcprcvbufpoll", oTcpRcvBufPoll },
    287   1.2  christos 	{ "tcprcvbuf", oTcpRcvBuf },
    288   1.2  christos 	{ "noneswitch", oNoneSwitch },
    289   1.2  christos 	{ "hpndisabled", oHPNDisabled },
    290   1.2  christos 	{ "hpnbuffersize", oHPNBufferSize },
    291   1.7       tls 	{ "sendversionfirst", oSendVersionFirst },
    292  1.12  christos 	{ "ignoreunknown", oIgnoreUnknown },
    293   1.1  christos 	{ NULL, oBadOption }
    294   1.1  christos };
    295   1.1  christos 
    296   1.1  christos /*
    297   1.1  christos  * Adds a local TCP/IP port forward to options.  Never returns if there is an
    298   1.1  christos  * error.
    299   1.1  christos  */
    300   1.1  christos 
    301   1.1  christos void
    302  1.12  christos add_local_forward(Options *options, const struct Forward *newfwd)
    303   1.1  christos {
    304  1.12  christos 	struct Forward *fwd;
    305   1.1  christos 	extern uid_t original_real_uid;
    306   1.4      adam 
    307  1.12  christos 	if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0 &&
    308  1.12  christos 	    newfwd->listen_path == NULL)
    309   1.1  christos 		fatal("Privileged ports can only be forwarded by root.");
    310   1.4      adam 	options->local_forwards = xrealloc(options->local_forwards,
    311   1.4      adam 	    options->num_local_forwards + 1,
    312   1.4      adam 	    sizeof(*options->local_forwards));
    313   1.1  christos 	fwd = &options->local_forwards[options->num_local_forwards++];
    314   1.1  christos 
    315   1.1  christos 	fwd->listen_host = newfwd->listen_host;
    316   1.1  christos 	fwd->listen_port = newfwd->listen_port;
    317  1.12  christos 	fwd->listen_path = newfwd->listen_path;
    318   1.1  christos 	fwd->connect_host = newfwd->connect_host;
    319   1.1  christos 	fwd->connect_port = newfwd->connect_port;
    320  1.12  christos 	fwd->connect_path = newfwd->connect_path;
    321   1.1  christos }
    322   1.1  christos 
    323   1.1  christos /*
    324   1.1  christos  * Adds a remote TCP/IP port forward to options.  Never returns if there is
    325   1.1  christos  * an error.
    326   1.1  christos  */
    327   1.1  christos 
    328   1.1  christos void
    329  1.12  christos add_remote_forward(Options *options, const struct Forward *newfwd)
    330   1.1  christos {
    331  1.12  christos 	struct Forward *fwd;
    332   1.4      adam 
    333   1.4      adam 	options->remote_forwards = xrealloc(options->remote_forwards,
    334   1.4      adam 	    options->num_remote_forwards + 1,
    335   1.4      adam 	    sizeof(*options->remote_forwards));
    336   1.1  christos 	fwd = &options->remote_forwards[options->num_remote_forwards++];
    337   1.1  christos 
    338   1.1  christos 	fwd->listen_host = newfwd->listen_host;
    339   1.1  christos 	fwd->listen_port = newfwd->listen_port;
    340  1.12  christos 	fwd->listen_path = newfwd->listen_path;
    341   1.1  christos 	fwd->connect_host = newfwd->connect_host;
    342   1.1  christos 	fwd->connect_port = newfwd->connect_port;
    343  1.12  christos 	fwd->connect_path = newfwd->connect_path;
    344   1.8  christos 	fwd->handle = newfwd->handle;
    345   1.4      adam 	fwd->allocated_port = 0;
    346   1.1  christos }
    347   1.1  christos 
    348   1.1  christos static void
    349   1.1  christos clear_forwardings(Options *options)
    350   1.1  christos {
    351   1.1  christos 	int i;
    352   1.1  christos 
    353   1.1  christos 	for (i = 0; i < options->num_local_forwards; i++) {
    354  1.11  christos 		free(options->local_forwards[i].listen_host);
    355  1.12  christos 		free(options->local_forwards[i].listen_path);
    356  1.11  christos 		free(options->local_forwards[i].connect_host);
    357  1.12  christos 		free(options->local_forwards[i].connect_path);
    358   1.1  christos 	}
    359   1.4      adam 	if (options->num_local_forwards > 0) {
    360  1.11  christos 		free(options->local_forwards);
    361   1.4      adam 		options->local_forwards = NULL;
    362   1.4      adam 	}
    363   1.1  christos 	options->num_local_forwards = 0;
    364   1.1  christos 	for (i = 0; i < options->num_remote_forwards; i++) {
    365  1.11  christos 		free(options->remote_forwards[i].listen_host);
    366  1.12  christos 		free(options->remote_forwards[i].listen_path);
    367  1.11  christos 		free(options->remote_forwards[i].connect_host);
    368  1.12  christos 		free(options->remote_forwards[i].connect_path);
    369   1.1  christos 	}
    370   1.4      adam 	if (options->num_remote_forwards > 0) {
    371  1.11  christos 		free(options->remote_forwards);
    372   1.4      adam 		options->remote_forwards = NULL;
    373   1.4      adam 	}
    374   1.1  christos 	options->num_remote_forwards = 0;
    375   1.1  christos 	options->tun_open = SSH_TUNMODE_NO;
    376   1.1  christos }
    377   1.1  christos 
    378   1.9   mlelstv void
    379   1.9   mlelstv add_identity_file(Options *options, const char *dir, const char *filename,
    380   1.9   mlelstv     int userprovided)
    381   1.9   mlelstv {
    382   1.9   mlelstv 	char *path;
    383  1.12  christos 	int i;
    384   1.9   mlelstv 
    385   1.9   mlelstv 	if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
    386   1.9   mlelstv 		fatal("Too many identity files specified (max %d)",
    387   1.9   mlelstv 		    SSH_MAX_IDENTITY_FILES);
    388   1.9   mlelstv 
    389   1.9   mlelstv 	if (dir == NULL) /* no dir, filename is absolute */
    390   1.9   mlelstv 		path = xstrdup(filename);
    391   1.9   mlelstv 	else
    392   1.9   mlelstv 		(void)xasprintf(&path, "%.100s%.100s", dir, filename);
    393   1.9   mlelstv 
    394  1.12  christos 	/* Avoid registering duplicates */
    395  1.12  christos 	for (i = 0; i < options->num_identity_files; i++) {
    396  1.12  christos 		if (options->identity_file_userprovided[i] == userprovided &&
    397  1.12  christos 		    strcmp(options->identity_files[i], path) == 0) {
    398  1.12  christos 			debug2("%s: ignoring duplicate key %s", __func__, path);
    399  1.12  christos 			free(path);
    400  1.12  christos 			return;
    401  1.12  christos 		}
    402  1.12  christos 	}
    403  1.12  christos 
    404   1.9   mlelstv 	options->identity_file_userprovided[options->num_identity_files] =
    405   1.9   mlelstv 	    userprovided;
    406   1.9   mlelstv 	options->identity_files[options->num_identity_files++] = path;
    407   1.9   mlelstv }
    408   1.9   mlelstv 
    409  1.12  christos int
    410  1.12  christos default_ssh_port(void)
    411  1.12  christos {
    412  1.12  christos 	static int port;
    413  1.12  christos 	struct servent *sp;
    414  1.12  christos 
    415  1.12  christos 	if (port == 0) {
    416  1.12  christos 		sp = getservbyname(SSH_SERVICE_NAME, "tcp");
    417  1.12  christos 		port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT;
    418  1.12  christos 	}
    419  1.12  christos 	return port;
    420  1.12  christos }
    421  1.12  christos 
    422  1.12  christos /*
    423  1.12  christos  * Execute a command in a shell.
    424  1.12  christos  * Return its exit status or -1 on abnormal exit.
    425  1.12  christos  */
    426  1.12  christos static int
    427  1.12  christos execute_in_shell(const char *cmd)
    428  1.12  christos {
    429  1.12  christos 	const char *shell;
    430  1.12  christos 	char *command_string;
    431  1.12  christos 	pid_t pid;
    432  1.12  christos 	int devnull, status;
    433  1.12  christos 	extern uid_t original_real_uid;
    434  1.12  christos 
    435  1.12  christos 	if ((shell = getenv("SHELL")) == NULL)
    436  1.12  christos 		shell = _PATH_BSHELL;
    437  1.12  christos 
    438  1.12  christos 	/*
    439  1.12  christos 	 * Use "exec" to avoid "sh -c" processes on some platforms
    440  1.12  christos 	 * (e.g. Solaris)
    441  1.12  christos 	 */
    442  1.12  christos 	xasprintf(&command_string, "exec %s", cmd);
    443  1.12  christos 
    444  1.12  christos 	/* Need this to redirect subprocess stdin/out */
    445  1.12  christos 	if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1)
    446  1.12  christos 		fatal("open(/dev/null): %s", strerror(errno));
    447  1.12  christos 
    448  1.12  christos 	debug("Executing command: '%.500s'", cmd);
    449  1.12  christos 
    450  1.12  christos 	/* Fork and execute the command. */
    451  1.12  christos 	if ((pid = fork()) == 0) {
    452  1.12  christos 		char *argv[4];
    453  1.12  christos 
    454  1.12  christos 		/* Child.  Permanently give up superuser privileges. */
    455  1.12  christos 		permanently_drop_suid(original_real_uid);
    456  1.12  christos 
    457  1.12  christos 		/* Redirect child stdin and stdout. Leave stderr */
    458  1.12  christos 		if (dup2(devnull, STDIN_FILENO) == -1)
    459  1.12  christos 			fatal("dup2: %s", strerror(errno));
    460  1.12  christos 		if (dup2(devnull, STDOUT_FILENO) == -1)
    461  1.12  christos 			fatal("dup2: %s", strerror(errno));
    462  1.12  christos 		if (devnull > STDERR_FILENO)
    463  1.12  christos 			close(devnull);
    464  1.12  christos 		closefrom(STDERR_FILENO + 1);
    465  1.12  christos 
    466  1.12  christos 		argv[0] = __UNCONST(shell);
    467  1.12  christos 		argv[1] = __UNCONST("-c");
    468  1.12  christos 		argv[2] = command_string;
    469  1.12  christos 		argv[3] = NULL;
    470  1.12  christos 
    471  1.12  christos 		execv(argv[0], argv);
    472  1.12  christos 		error("Unable to execute '%.100s': %s", cmd, strerror(errno));
    473  1.12  christos 		/* Die with signal to make this error apparent to parent. */
    474  1.12  christos 		signal(SIGTERM, SIG_DFL);
    475  1.12  christos 		kill(getpid(), SIGTERM);
    476  1.12  christos 		_exit(1);
    477  1.12  christos 	}
    478  1.12  christos 	/* Parent. */
    479  1.12  christos 	if (pid < 0)
    480  1.12  christos 		fatal("%s: fork: %.100s", __func__, strerror(errno));
    481  1.12  christos 
    482  1.12  christos 	close(devnull);
    483  1.12  christos 	free(command_string);
    484  1.12  christos 
    485  1.12  christos 	while (waitpid(pid, &status, 0) == -1) {
    486  1.12  christos 		if (errno != EINTR && errno != EAGAIN)
    487  1.12  christos 			fatal("%s: waitpid: %s", __func__, strerror(errno));
    488  1.12  christos 	}
    489  1.12  christos 	if (!WIFEXITED(status)) {
    490  1.12  christos 		error("command '%.100s' exited abnormally", cmd);
    491  1.12  christos 		return -1;
    492  1.12  christos 	}
    493  1.12  christos 	debug3("command returned status %d", WEXITSTATUS(status));
    494  1.12  christos 	return WEXITSTATUS(status);
    495  1.12  christos }
    496  1.12  christos 
    497  1.12  christos /*
    498  1.12  christos  * Parse and execute a Match directive.
    499  1.12  christos  */
    500  1.12  christos static int
    501  1.12  christos match_cfg_line(Options *options, char **condition, struct passwd *pw,
    502  1.12  christos     const char *host_arg, const char *filename, int linenum)
    503  1.12  christos {
    504  1.12  christos 	char *arg, *attrib, *cmd, *cp = *condition, *host;
    505  1.12  christos 	const char *ruser;
    506  1.12  christos 	int r, port, result = 1, attributes = 0;
    507  1.12  christos 	size_t len;
    508  1.12  christos 	char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
    509  1.12  christos 
    510  1.12  christos 	/*
    511  1.12  christos 	 * Configuration is likely to be incomplete at this point so we
    512  1.12  christos 	 * must be prepared to use default values.
    513  1.12  christos 	 */
    514  1.12  christos 	port = options->port <= 0 ? default_ssh_port() : options->port;
    515  1.12  christos 	ruser = options->user == NULL ? pw->pw_name : options->user;
    516  1.12  christos 	if (options->hostname != NULL) {
    517  1.12  christos 		/* NB. Please keep in sync with ssh.c:main() */
    518  1.12  christos 		host = percent_expand(options->hostname,
    519  1.12  christos 		    "h", host_arg, (char *)NULL);
    520  1.12  christos 	} else
    521  1.12  christos 		host = xstrdup(host_arg);
    522  1.12  christos 
    523  1.12  christos 	debug3("checking match for '%s' host %s", cp, host);
    524  1.12  christos 	while ((attrib = strdelim(&cp)) && *attrib != '\0') {
    525  1.12  christos 		attributes++;
    526  1.12  christos 		if (strcasecmp(attrib, "all") == 0) {
    527  1.12  christos 			if (attributes != 1 ||
    528  1.12  christos 			    ((arg = strdelim(&cp)) != NULL && *arg != '\0')) {
    529  1.12  christos 				error("'all' cannot be combined with other "
    530  1.12  christos 				    "Match attributes");
    531  1.12  christos 				result = -1;
    532  1.12  christos 				goto out;
    533  1.12  christos 			}
    534  1.12  christos 			*condition = cp;
    535  1.12  christos 			result = 1;
    536  1.12  christos 			goto out;
    537  1.12  christos 		}
    538  1.12  christos 		if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
    539  1.12  christos 			error("Missing Match criteria for %s", attrib);
    540  1.12  christos 			result = -1;
    541  1.12  christos 			goto out;
    542  1.12  christos 		}
    543  1.12  christos 		len = strlen(arg);
    544  1.12  christos 		if (strcasecmp(attrib, "host") == 0) {
    545  1.12  christos 			if (match_hostname(host, arg, len) != 1)
    546  1.12  christos 				result = 0;
    547  1.12  christos 			else
    548  1.12  christos 				debug("%.200s line %d: matched 'Host %.100s' ",
    549  1.12  christos 				    filename, linenum, host);
    550  1.12  christos 		} else if (strcasecmp(attrib, "originalhost") == 0) {
    551  1.12  christos 			if (match_hostname(host_arg, arg, len) != 1)
    552  1.12  christos 				result = 0;
    553  1.12  christos 			else
    554  1.12  christos 				debug("%.200s line %d: matched "
    555  1.12  christos 				    "'OriginalHost %.100s' ",
    556  1.12  christos 				    filename, linenum, host_arg);
    557  1.12  christos 		} else if (strcasecmp(attrib, "user") == 0) {
    558  1.12  christos 			if (match_pattern_list(ruser, arg, len, 0) != 1)
    559  1.12  christos 				result = 0;
    560  1.12  christos 			else
    561  1.12  christos 				debug("%.200s line %d: matched 'User %.100s' ",
    562  1.12  christos 				    filename, linenum, ruser);
    563  1.12  christos 		} else if (strcasecmp(attrib, "localuser") == 0) {
    564  1.12  christos 			if (match_pattern_list(pw->pw_name, arg, len, 0) != 1)
    565  1.12  christos 				result = 0;
    566  1.12  christos 			else
    567  1.12  christos 				debug("%.200s line %d: matched "
    568  1.12  christos 				    "'LocalUser %.100s' ",
    569  1.12  christos 				    filename, linenum, pw->pw_name);
    570  1.12  christos 		} else if (strcasecmp(attrib, "exec") == 0) {
    571  1.12  christos 			if (gethostname(thishost, sizeof(thishost)) == -1)
    572  1.12  christos 				fatal("gethostname: %s", strerror(errno));
    573  1.12  christos 			strlcpy(shorthost, thishost, sizeof(shorthost));
    574  1.12  christos 			shorthost[strcspn(thishost, ".")] = '\0';
    575  1.12  christos 			snprintf(portstr, sizeof(portstr), "%d", port);
    576  1.12  christos 
    577  1.12  christos 			cmd = percent_expand(arg,
    578  1.12  christos 			    "L", shorthost,
    579  1.12  christos 			    "d", pw->pw_dir,
    580  1.12  christos 			    "h", host,
    581  1.12  christos 			    "l", thishost,
    582  1.12  christos 			    "n", host_arg,
    583  1.12  christos 			    "p", portstr,
    584  1.12  christos 			    "r", ruser,
    585  1.12  christos 			    "u", pw->pw_name,
    586  1.12  christos 			    (char *)NULL);
    587  1.12  christos 			if (result != 1) {
    588  1.12  christos 				/* skip execution if prior predicate failed */
    589  1.12  christos 				debug("%.200s line %d: skipped exec \"%.100s\"",
    590  1.12  christos 				    filename, linenum, cmd);
    591  1.12  christos 			} else {
    592  1.12  christos 				r = execute_in_shell(cmd);
    593  1.12  christos 				if (r == -1) {
    594  1.12  christos 					fatal("%.200s line %d: match exec "
    595  1.12  christos 					    "'%.100s' error", filename,
    596  1.12  christos 					    linenum, cmd);
    597  1.12  christos 				} else if (r == 0) {
    598  1.12  christos 					debug("%.200s line %d: matched "
    599  1.12  christos 					    "'exec \"%.100s\"'", filename,
    600  1.12  christos 					    linenum, cmd);
    601  1.12  christos 				} else {
    602  1.12  christos 					debug("%.200s line %d: no match "
    603  1.12  christos 					    "'exec \"%.100s\"'", filename,
    604  1.12  christos 					    linenum, cmd);
    605  1.12  christos 					result = 0;
    606  1.12  christos 				}
    607  1.12  christos 			}
    608  1.12  christos 			free(cmd);
    609  1.12  christos 		} else {
    610  1.12  christos 			error("Unsupported Match attribute %s", attrib);
    611  1.12  christos 			result = -1;
    612  1.12  christos 			goto out;
    613  1.12  christos 		}
    614  1.12  christos 	}
    615  1.12  christos 	if (attributes == 0) {
    616  1.12  christos 		error("One or more attributes required for Match");
    617  1.12  christos 		result = -1;
    618  1.12  christos 		goto out;
    619  1.12  christos 	}
    620  1.12  christos 	debug3("match %sfound", result ? "" : "not ");
    621  1.12  christos 	*condition = cp;
    622  1.12  christos  out:
    623  1.12  christos 	free(host);
    624  1.12  christos 	return result;
    625  1.12  christos }
    626  1.12  christos 
    627  1.12  christos /* Check and prepare a domain name: removes trailing '.' and lowercases */
    628  1.12  christos static void
    629  1.12  christos valid_domain(char *name, const char *filename, int linenum)
    630  1.12  christos {
    631  1.12  christos 	size_t i, l = strlen(name);
    632  1.12  christos 	u_char c, last = '\0';
    633  1.12  christos 
    634  1.12  christos 	if (l == 0)
    635  1.12  christos 		fatal("%s line %d: empty hostname suffix", filename, linenum);
    636  1.12  christos 	if (!isalpha((u_char)name[0]) && !isdigit((u_char)name[0]))
    637  1.12  christos 		fatal("%s line %d: hostname suffix \"%.100s\" "
    638  1.12  christos 		    "starts with invalid character", filename, linenum, name);
    639  1.12  christos 	for (i = 0; i < l; i++) {
    640  1.12  christos 		c = tolower((u_char)name[i]);
    641  1.12  christos 		name[i] = (char)c;
    642  1.12  christos 		if (last == '.' && c == '.')
    643  1.12  christos 			fatal("%s line %d: hostname suffix \"%.100s\" contains "
    644  1.12  christos 			    "consecutive separators", filename, linenum, name);
    645  1.12  christos 		if (c != '.' && c != '-' && !isalnum(c) &&
    646  1.12  christos 		    c != '_') /* technically invalid, but common */
    647  1.12  christos 			fatal("%s line %d: hostname suffix \"%.100s\" contains "
    648  1.12  christos 			    "invalid characters", filename, linenum, name);
    649  1.12  christos 		last = c;
    650  1.12  christos 	}
    651  1.12  christos 	if (name[l - 1] == '.')
    652  1.12  christos 		name[l - 1] = '\0';
    653  1.12  christos }
    654  1.12  christos 
    655   1.1  christos /*
    656   1.1  christos  * Returns the number of the token pointed to by cp or oBadOption.
    657   1.1  christos  */
    658   1.1  christos static OpCodes
    659  1.11  christos parse_token(const char *cp, const char *filename, int linenum,
    660  1.11  christos     const char *ignored_unknown)
    661   1.1  christos {
    662  1.11  christos 	int i;
    663   1.1  christos 
    664   1.1  christos 	for (i = 0; keywords[i].name; i++)
    665  1.11  christos 		if (strcmp(cp, keywords[i].name) == 0)
    666   1.1  christos 			return keywords[i].opcode;
    667  1.11  christos 	if (ignored_unknown != NULL && match_pattern_list(cp, ignored_unknown,
    668  1.11  christos 	    strlen(ignored_unknown), 1) == 1)
    669  1.11  christos 		return oIgnoredUnknownOption;
    670   1.1  christos 	error("%s: line %d: Bad configuration option: %s",
    671   1.1  christos 	    filename, linenum, cp);
    672   1.1  christos 	return oBadOption;
    673   1.1  christos }
    674   1.1  christos 
    675  1.12  christos /* Multistate option parsing */
    676  1.12  christos struct multistate {
    677  1.12  christos 	const char *key;
    678  1.12  christos 	int value;
    679  1.12  christos };
    680  1.12  christos static const struct multistate multistate_flag[] = {
    681  1.12  christos 	{ "true",			1 },
    682  1.12  christos 	{ "false",			0 },
    683  1.12  christos 	{ "yes",			1 },
    684  1.12  christos 	{ "no",				0 },
    685  1.12  christos 	{ NULL, -1 }
    686  1.12  christos };
    687  1.12  christos static const struct multistate multistate_yesnoask[] = {
    688  1.12  christos 	{ "true",			1 },
    689  1.12  christos 	{ "false",			0 },
    690  1.12  christos 	{ "yes",			1 },
    691  1.12  christos 	{ "no",				0 },
    692  1.12  christos 	{ "ask",			2 },
    693  1.12  christos 	{ NULL, -1 }
    694  1.12  christos };
    695  1.12  christos static const struct multistate multistate_addressfamily[] = {
    696  1.12  christos 	{ "inet",			AF_INET },
    697  1.12  christos 	{ "inet6",			AF_INET6 },
    698  1.12  christos 	{ "any",			AF_UNSPEC },
    699  1.12  christos 	{ NULL, -1 }
    700  1.12  christos };
    701  1.12  christos static const struct multistate multistate_controlmaster[] = {
    702  1.12  christos 	{ "true",			SSHCTL_MASTER_YES },
    703  1.12  christos 	{ "yes",			SSHCTL_MASTER_YES },
    704  1.12  christos 	{ "false",			SSHCTL_MASTER_NO },
    705  1.12  christos 	{ "no",				SSHCTL_MASTER_NO },
    706  1.12  christos 	{ "auto",			SSHCTL_MASTER_AUTO },
    707  1.12  christos 	{ "ask",			SSHCTL_MASTER_ASK },
    708  1.12  christos 	{ "autoask",			SSHCTL_MASTER_AUTO_ASK },
    709  1.12  christos 	{ NULL, -1 }
    710  1.12  christos };
    711  1.12  christos static const struct multistate multistate_tunnel[] = {
    712  1.12  christos 	{ "ethernet",			SSH_TUNMODE_ETHERNET },
    713  1.12  christos 	{ "point-to-point",		SSH_TUNMODE_POINTOPOINT },
    714  1.12  christos 	{ "true",			SSH_TUNMODE_DEFAULT },
    715  1.12  christos 	{ "yes",			SSH_TUNMODE_DEFAULT },
    716  1.12  christos 	{ "false",			SSH_TUNMODE_NO },
    717  1.12  christos 	{ "no",				SSH_TUNMODE_NO },
    718  1.12  christos 	{ NULL, -1 }
    719  1.12  christos };
    720  1.12  christos static const struct multistate multistate_requesttty[] = {
    721  1.12  christos 	{ "true",			REQUEST_TTY_YES },
    722  1.12  christos 	{ "yes",			REQUEST_TTY_YES },
    723  1.12  christos 	{ "false",			REQUEST_TTY_NO },
    724  1.12  christos 	{ "no",				REQUEST_TTY_NO },
    725  1.12  christos 	{ "force",			REQUEST_TTY_FORCE },
    726  1.12  christos 	{ "auto",			REQUEST_TTY_AUTO },
    727  1.12  christos 	{ NULL, -1 }
    728  1.12  christos };
    729  1.12  christos static const struct multistate multistate_canonicalizehostname[] = {
    730  1.12  christos 	{ "true",			SSH_CANONICALISE_YES },
    731  1.12  christos 	{ "false",			SSH_CANONICALISE_NO },
    732  1.12  christos 	{ "yes",			SSH_CANONICALISE_YES },
    733  1.12  christos 	{ "no",				SSH_CANONICALISE_NO },
    734  1.12  christos 	{ "always",			SSH_CANONICALISE_ALWAYS },
    735  1.12  christos 	{ NULL, -1 }
    736  1.12  christos };
    737  1.12  christos 
    738   1.1  christos /*
    739   1.1  christos  * Processes a single option line as used in the configuration files. This
    740   1.1  christos  * only sets those values that have not already been set.
    741   1.1  christos  */
    742   1.1  christos #define WHITESPACE " \t\r\n"
    743   1.1  christos int
    744  1.12  christos process_config_line(Options *options, struct passwd *pw, const char *host,
    745  1.12  christos     char *line, const char *filename, int linenum, int *activep, int userconfig)
    746   1.1  christos {
    747   1.6  christos 	char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;
    748   1.6  christos 	char **cpptr, fwdarg[256];
    749  1.11  christos 	u_int i, *uintptr, max_entries = 0;
    750  1.12  christos 	int negated, opcode, *intptr, value, value2, cmdline = 0;
    751   1.1  christos 	LogLevel *log_level_ptr;
    752  1.11  christos 	long long val64;
    753   1.1  christos 	size_t len;
    754  1.12  christos 	struct Forward fwd;
    755  1.12  christos 	const struct multistate *multistate_ptr;
    756  1.12  christos 	struct allowed_cname *cname;
    757  1.12  christos 
    758  1.12  christos 	if (activep == NULL) { /* We are processing a command line directive */
    759  1.12  christos 		cmdline = 1;
    760  1.12  christos 		activep = &cmdline;
    761  1.12  christos 	}
    762   1.1  christos 
    763   1.1  christos 	/* Strip trailing whitespace */
    764   1.1  christos 	for (len = strlen(line) - 1; len > 0; len--) {
    765   1.1  christos 		if (strchr(WHITESPACE, line[len]) == NULL)
    766   1.1  christos 			break;
    767   1.1  christos 		line[len] = '\0';
    768   1.1  christos 	}
    769   1.1  christos 
    770   1.1  christos 	s = line;
    771   1.1  christos 	/* Get the keyword. (Each line is supposed to begin with a keyword). */
    772   1.1  christos 	if ((keyword = strdelim(&s)) == NULL)
    773   1.1  christos 		return 0;
    774   1.1  christos 	/* Ignore leading whitespace. */
    775   1.1  christos 	if (*keyword == '\0')
    776   1.1  christos 		keyword = strdelim(&s);
    777   1.1  christos 	if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
    778   1.1  christos 		return 0;
    779  1.11  christos 	/* Match lowercase keyword */
    780  1.12  christos 	lowercase(keyword);
    781   1.1  christos 
    782  1.11  christos 	opcode = parse_token(keyword, filename, linenum,
    783  1.11  christos 	    options->ignored_unknown);
    784   1.1  christos 
    785   1.1  christos 	switch (opcode) {
    786   1.1  christos 	case oBadOption:
    787   1.1  christos 		/* don't panic, but count bad options */
    788   1.1  christos 		return -1;
    789   1.1  christos 		/* NOTREACHED */
    790  1.11  christos 	case oIgnoredUnknownOption:
    791  1.11  christos 		debug("%s line %d: Ignored unknown option \"%s\"",
    792  1.11  christos 		    filename, linenum, keyword);
    793  1.11  christos 		return 0;
    794   1.1  christos 	case oConnectTimeout:
    795   1.1  christos 		intptr = &options->connection_timeout;
    796   1.1  christos parse_time:
    797   1.1  christos 		arg = strdelim(&s);
    798   1.1  christos 		if (!arg || *arg == '\0')
    799   1.1  christos 			fatal("%s line %d: missing time value.",
    800   1.1  christos 			    filename, linenum);
    801   1.1  christos 		if ((value = convtime(arg)) == -1)
    802   1.1  christos 			fatal("%s line %d: invalid time value.",
    803   1.1  christos 			    filename, linenum);
    804   1.1  christos 		if (*activep && *intptr == -1)
    805   1.1  christos 			*intptr = value;
    806   1.1  christos 		break;
    807   1.1  christos 
    808   1.1  christos 	case oForwardAgent:
    809   1.1  christos 		intptr = &options->forward_agent;
    810  1.12  christos  parse_flag:
    811  1.12  christos 		multistate_ptr = multistate_flag;
    812  1.12  christos  parse_multistate:
    813   1.1  christos 		arg = strdelim(&s);
    814   1.1  christos 		if (!arg || *arg == '\0')
    815  1.12  christos 			fatal("%s line %d: missing argument.",
    816  1.12  christos 			    filename, linenum);
    817  1.12  christos 		value = -1;
    818  1.12  christos 		for (i = 0; multistate_ptr[i].key != NULL; i++) {
    819  1.12  christos 			if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
    820  1.12  christos 				value = multistate_ptr[i].value;
    821  1.12  christos 				break;
    822  1.12  christos 			}
    823  1.12  christos 		}
    824  1.12  christos 		if (value == -1)
    825  1.12  christos 			fatal("%s line %d: unsupported option \"%s\".",
    826  1.12  christos 			    filename, linenum, arg);
    827   1.1  christos 		if (*activep && *intptr == -1)
    828   1.1  christos 			*intptr = value;
    829   1.1  christos 		break;
    830   1.1  christos 
    831   1.1  christos 	case oForwardX11:
    832   1.1  christos 		intptr = &options->forward_x11;
    833   1.1  christos 		goto parse_flag;
    834   1.1  christos 
    835   1.1  christos 	case oForwardX11Trusted:
    836   1.1  christos 		intptr = &options->forward_x11_trusted;
    837   1.1  christos 		goto parse_flag;
    838   1.4      adam 
    839   1.4      adam 	case oForwardX11Timeout:
    840   1.4      adam 		intptr = &options->forward_x11_timeout;
    841   1.4      adam 		goto parse_time;
    842   1.1  christos 
    843   1.1  christos 	case oGatewayPorts:
    844  1.12  christos 		intptr = &options->fwd_opts.gateway_ports;
    845   1.1  christos 		goto parse_flag;
    846   1.1  christos 
    847   1.1  christos 	case oExitOnForwardFailure:
    848   1.1  christos 		intptr = &options->exit_on_forward_failure;
    849   1.1  christos 		goto parse_flag;
    850   1.1  christos 
    851   1.1  christos 	case oUsePrivilegedPort:
    852   1.1  christos 		intptr = &options->use_privileged_port;
    853   1.1  christos 		goto parse_flag;
    854   1.1  christos 
    855   1.1  christos 	case oPasswordAuthentication:
    856   1.1  christos 		intptr = &options->password_authentication;
    857   1.1  christos 		goto parse_flag;
    858   1.1  christos 
    859   1.1  christos 	case oKbdInteractiveAuthentication:
    860   1.1  christos 		intptr = &options->kbd_interactive_authentication;
    861   1.1  christos 		goto parse_flag;
    862   1.1  christos 
    863   1.1  christos 	case oKbdInteractiveDevices:
    864   1.1  christos 		charptr = &options->kbd_interactive_devices;
    865   1.1  christos 		goto parse_string;
    866   1.1  christos 
    867   1.1  christos 	case oPubkeyAuthentication:
    868   1.1  christos 		intptr = &options->pubkey_authentication;
    869   1.1  christos 		goto parse_flag;
    870   1.1  christos 
    871   1.1  christos 	case oRSAAuthentication:
    872   1.1  christos 		intptr = &options->rsa_authentication;
    873   1.1  christos 		goto parse_flag;
    874   1.1  christos 
    875   1.1  christos 	case oRhostsRSAAuthentication:
    876   1.1  christos 		intptr = &options->rhosts_rsa_authentication;
    877   1.1  christos 		goto parse_flag;
    878   1.1  christos 
    879   1.1  christos 	case oHostbasedAuthentication:
    880   1.1  christos 		intptr = &options->hostbased_authentication;
    881   1.1  christos 		goto parse_flag;
    882   1.1  christos 
    883   1.1  christos 	case oChallengeResponseAuthentication:
    884   1.1  christos 		intptr = &options->challenge_response_authentication;
    885   1.1  christos 		goto parse_flag;
    886   1.1  christos 
    887   1.2  christos #if defined(KRB4) || defined(KRB5)
    888   1.2  christos 	case oKerberosAuthentication:
    889   1.2  christos 		intptr = &options->kerberos_authentication;
    890   1.2  christos 		goto parse_flag;
    891   1.2  christos #endif
    892   1.2  christos #if defined(AFS) || defined(KRB5)
    893   1.2  christos 	case oKerberosTgtPassing:
    894   1.2  christos 		intptr = &options->kerberos_tgt_passing;
    895   1.2  christos 		goto parse_flag;
    896   1.2  christos #endif
    897   1.2  christos 
    898   1.1  christos 	case oGssAuthentication:
    899   1.1  christos 		intptr = &options->gss_authentication;
    900   1.1  christos 		goto parse_flag;
    901   1.1  christos 
    902   1.2  christos #ifdef AFS
    903   1.2  christos 	case oAFSTokenPassing:
    904   1.2  christos 		intptr = &options->afs_token_passing;
    905   1.2  christos  		goto parse_flag;
    906   1.2  christos #endif
    907   1.2  christos 
    908   1.1  christos 	case oGssDelegateCreds:
    909   1.1  christos 		intptr = &options->gss_deleg_creds;
    910   1.1  christos 		goto parse_flag;
    911   1.1  christos 
    912   1.1  christos 	case oBatchMode:
    913   1.1  christos 		intptr = &options->batch_mode;
    914   1.1  christos 		goto parse_flag;
    915   1.1  christos 
    916   1.1  christos 	case oCheckHostIP:
    917   1.1  christos 		intptr = &options->check_host_ip;
    918   1.1  christos 		goto parse_flag;
    919   1.1  christos 
    920   1.2  christos 	case oNoneEnabled:
    921   1.2  christos 		intptr = &options->none_enabled;
    922   1.2  christos 		goto parse_flag;
    923   1.2  christos 
    924   1.2  christos 	/* we check to see if the command comes from the */
    925   1.2  christos 	/* command line or not. If it does then enable it */
    926   1.2  christos 	/* otherwise fail. NONE should never be a default configuration */
    927   1.2  christos 	case oNoneSwitch:
    928   1.2  christos 		if(strcmp(filename,"command-line")==0)
    929   1.2  christos 		{
    930   1.2  christos 		    intptr = &options->none_switch;
    931   1.2  christos 		    goto parse_flag;
    932   1.2  christos 		} else {
    933   1.2  christos 		    error("NoneSwitch is found in %.200s.\nYou may only use this configuration option from the command line", filename);
    934   1.2  christos 		    error("Continuing...");
    935   1.2  christos 		    debug("NoneSwitch directive found in %.200s.", filename);
    936   1.2  christos 		    return 0;
    937   1.2  christos 	        }
    938   1.2  christos 
    939   1.2  christos 	case oHPNDisabled:
    940   1.2  christos 		intptr = &options->hpn_disabled;
    941   1.2  christos 		goto parse_flag;
    942   1.2  christos 
    943   1.2  christos 	case oHPNBufferSize:
    944   1.2  christos 		intptr = &options->hpn_buffer_size;
    945   1.2  christos 		goto parse_int;
    946   1.2  christos 
    947   1.2  christos 	case oTcpRcvBufPoll:
    948   1.2  christos 		intptr = &options->tcp_rcv_buf_poll;
    949   1.2  christos 		goto parse_flag;
    950   1.2  christos 
    951   1.1  christos 	case oVerifyHostKeyDNS:
    952   1.1  christos 		intptr = &options->verify_host_key_dns;
    953  1.12  christos 		multistate_ptr = multistate_yesnoask;
    954  1.12  christos 		goto parse_multistate;
    955   1.1  christos 
    956   1.1  christos 	case oStrictHostKeyChecking:
    957   1.1  christos 		intptr = &options->strict_host_key_checking;
    958  1.12  christos 		multistate_ptr = multistate_yesnoask;
    959  1.12  christos 		goto parse_multistate;
    960   1.1  christos 
    961   1.1  christos 	case oCompression:
    962   1.1  christos 		intptr = &options->compression;
    963   1.1  christos 		goto parse_flag;
    964   1.1  christos 
    965   1.1  christos 	case oTCPKeepAlive:
    966   1.1  christos 		intptr = &options->tcp_keep_alive;
    967   1.1  christos 		goto parse_flag;
    968   1.1  christos 
    969   1.1  christos 	case oNoHostAuthenticationForLocalhost:
    970   1.1  christos 		intptr = &options->no_host_authentication_for_localhost;
    971   1.1  christos 		goto parse_flag;
    972   1.1  christos 
    973   1.1  christos 	case oNumberOfPasswordPrompts:
    974   1.1  christos 		intptr = &options->number_of_password_prompts;
    975   1.1  christos 		goto parse_int;
    976   1.1  christos 
    977   1.1  christos 	case oCompressionLevel:
    978   1.1  christos 		intptr = &options->compression_level;
    979   1.1  christos 		goto parse_int;
    980   1.1  christos 
    981   1.1  christos 	case oRekeyLimit:
    982   1.1  christos 		arg = strdelim(&s);
    983   1.1  christos 		if (!arg || *arg == '\0')
    984  1.11  christos 			fatal("%.200s line %d: Missing argument.", filename,
    985  1.11  christos 			    linenum);
    986  1.11  christos 		if (strcmp(arg, "default") == 0) {
    987  1.11  christos 			val64 = 0;
    988  1.11  christos 		} else {
    989  1.11  christos 			if (scan_scaled(arg, &val64) == -1)
    990  1.11  christos 				fatal("%.200s line %d: Bad number '%s': %s",
    991  1.11  christos 				    filename, linenum, arg, strerror(errno));
    992  1.11  christos 			/* check for too-large or too-small limits */
    993  1.11  christos 			if (val64 > UINT_MAX)
    994  1.11  christos 				fatal("%.200s line %d: RekeyLimit too large",
    995  1.11  christos 				    filename, linenum);
    996  1.11  christos 			if (val64 != 0 && val64 < 16)
    997  1.11  christos 				fatal("%.200s line %d: RekeyLimit too small",
    998  1.11  christos 				    filename, linenum);
    999   1.1  christos 		}
   1000   1.1  christos 		if (*activep && options->rekey_limit == -1)
   1001   1.1  christos 			options->rekey_limit = (u_int32_t)val64;
   1002  1.11  christos 		if (s != NULL) { /* optional rekey interval present */
   1003  1.11  christos 			if (strcmp(s, "none") == 0) {
   1004  1.11  christos 				(void)strdelim(&s);	/* discard */
   1005  1.11  christos 				break;
   1006  1.11  christos 			}
   1007  1.11  christos 			intptr = &options->rekey_interval;
   1008  1.11  christos 			goto parse_time;
   1009  1.11  christos 		}
   1010   1.1  christos 		break;
   1011   1.1  christos 
   1012   1.1  christos 	case oIdentityFile:
   1013   1.1  christos 		arg = strdelim(&s);
   1014   1.1  christos 		if (!arg || *arg == '\0')
   1015   1.1  christos 			fatal("%.200s line %d: Missing argument.", filename, linenum);
   1016   1.1  christos 		if (*activep) {
   1017   1.1  christos 			intptr = &options->num_identity_files;
   1018   1.1  christos 			if (*intptr >= SSH_MAX_IDENTITY_FILES)
   1019   1.1  christos 				fatal("%.200s line %d: Too many identity files specified (max %d).",
   1020   1.1  christos 				    filename, linenum, SSH_MAX_IDENTITY_FILES);
   1021   1.9   mlelstv 			add_identity_file(options, NULL, arg, userconfig);
   1022   1.1  christos 		}
   1023   1.1  christos 		break;
   1024   1.1  christos 
   1025   1.1  christos 	case oXAuthLocation:
   1026   1.1  christos 		charptr=&options->xauth_location;
   1027   1.1  christos 		goto parse_string;
   1028   1.1  christos 
   1029   1.1  christos 	case oUser:
   1030   1.1  christos 		charptr = &options->user;
   1031   1.1  christos parse_string:
   1032   1.1  christos 		arg = strdelim(&s);
   1033   1.1  christos 		if (!arg || *arg == '\0')
   1034   1.6  christos 			fatal("%.200s line %d: Missing argument.",
   1035   1.6  christos 			    filename, linenum);
   1036   1.1  christos 		if (*activep && *charptr == NULL)
   1037   1.1  christos 			*charptr = xstrdup(arg);
   1038   1.1  christos 		break;
   1039   1.1  christos 
   1040   1.1  christos 	case oGlobalKnownHostsFile:
   1041   1.6  christos 		cpptr = (char **)&options->system_hostfiles;
   1042   1.6  christos 		uintptr = &options->num_system_hostfiles;
   1043   1.6  christos 		max_entries = SSH_MAX_HOSTS_FILES;
   1044   1.6  christos parse_char_array:
   1045   1.6  christos 		if (*activep && *uintptr == 0) {
   1046   1.6  christos 			while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
   1047   1.6  christos 				if ((*uintptr) >= max_entries)
   1048   1.6  christos 					fatal("%s line %d: "
   1049   1.6  christos 					    "too many authorized keys files.",
   1050   1.6  christos 					    filename, linenum);
   1051   1.6  christos 				cpptr[(*uintptr)++] = xstrdup(arg);
   1052   1.6  christos 			}
   1053   1.6  christos 		}
   1054   1.6  christos 		return 0;
   1055   1.1  christos 
   1056   1.1  christos 	case oUserKnownHostsFile:
   1057   1.6  christos 		cpptr = (char **)&options->user_hostfiles;
   1058   1.6  christos 		uintptr = &options->num_user_hostfiles;
   1059   1.6  christos 		max_entries = SSH_MAX_HOSTS_FILES;
   1060   1.6  christos 		goto parse_char_array;
   1061   1.1  christos 
   1062   1.1  christos 	case oHostName:
   1063   1.1  christos 		charptr = &options->hostname;
   1064   1.1  christos 		goto parse_string;
   1065   1.1  christos 
   1066   1.1  christos 	case oHostKeyAlias:
   1067   1.1  christos 		charptr = &options->host_key_alias;
   1068   1.1  christos 		goto parse_string;
   1069   1.1  christos 
   1070   1.1  christos 	case oPreferredAuthentications:
   1071   1.1  christos 		charptr = &options->preferred_authentications;
   1072   1.1  christos 		goto parse_string;
   1073   1.1  christos 
   1074   1.1  christos 	case oBindAddress:
   1075   1.1  christos 		charptr = &options->bind_address;
   1076   1.1  christos 		goto parse_string;
   1077   1.1  christos 
   1078   1.4      adam 	case oPKCS11Provider:
   1079   1.4      adam 		charptr = &options->pkcs11_provider;
   1080   1.1  christos 		goto parse_string;
   1081   1.1  christos 
   1082   1.1  christos 	case oProxyCommand:
   1083   1.1  christos 		charptr = &options->proxy_command;
   1084   1.1  christos parse_command:
   1085   1.1  christos 		if (s == NULL)
   1086   1.1  christos 			fatal("%.200s line %d: Missing argument.", filename, linenum);
   1087   1.1  christos 		len = strspn(s, WHITESPACE "=");
   1088   1.1  christos 		if (*activep && *charptr == NULL)
   1089   1.1  christos 			*charptr = xstrdup(s + len);
   1090   1.1  christos 		return 0;
   1091   1.1  christos 
   1092   1.1  christos 	case oPort:
   1093   1.1  christos 		intptr = &options->port;
   1094   1.1  christos parse_int:
   1095   1.1  christos 		arg = strdelim(&s);
   1096   1.1  christos 		if (!arg || *arg == '\0')
   1097   1.1  christos 			fatal("%.200s line %d: Missing argument.", filename, linenum);
   1098   1.1  christos 		if (arg[0] < '0' || arg[0] > '9')
   1099   1.1  christos 			fatal("%.200s line %d: Bad number.", filename, linenum);
   1100   1.1  christos 
   1101   1.1  christos 		/* Octal, decimal, or hex format? */
   1102   1.1  christos 		value = strtol(arg, &endofnumber, 0);
   1103   1.1  christos 		if (arg == endofnumber)
   1104   1.1  christos 			fatal("%.200s line %d: Bad number.", filename, linenum);
   1105   1.1  christos 		if (*activep && *intptr == -1)
   1106   1.1  christos 			*intptr = value;
   1107   1.1  christos 		break;
   1108   1.1  christos 
   1109   1.1  christos 	case oConnectionAttempts:
   1110   1.1  christos 		intptr = &options->connection_attempts;
   1111   1.1  christos 		goto parse_int;
   1112   1.1  christos 
   1113   1.2  christos 	case oTcpRcvBuf:
   1114   1.2  christos 		intptr = &options->tcp_rcv_buf;
   1115   1.2  christos 		goto parse_int;
   1116   1.2  christos 
   1117   1.1  christos 	case oCipher:
   1118   1.1  christos 		intptr = &options->cipher;
   1119   1.1  christos 		arg = strdelim(&s);
   1120   1.1  christos 		if (!arg || *arg == '\0')
   1121   1.1  christos 			fatal("%.200s line %d: Missing argument.", filename, linenum);
   1122   1.1  christos 		value = cipher_number(arg);
   1123   1.1  christos 		if (value == -1)
   1124   1.1  christos 			fatal("%.200s line %d: Bad cipher '%s'.",
   1125   1.1  christos 			    filename, linenum, arg ? arg : "<NONE>");
   1126   1.1  christos 		if (*activep && *intptr == -1)
   1127   1.1  christos 			*intptr = value;
   1128   1.1  christos 		break;
   1129   1.1  christos 
   1130   1.1  christos 	case oCiphers:
   1131   1.1  christos 		arg = strdelim(&s);
   1132   1.1  christos 		if (!arg || *arg == '\0')
   1133   1.1  christos 			fatal("%.200s line %d: Missing argument.", filename, linenum);
   1134   1.1  christos 		if (!ciphers_valid(arg))
   1135   1.1  christos 			fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
   1136   1.1  christos 			    filename, linenum, arg ? arg : "<NONE>");
   1137   1.1  christos 		if (*activep && options->ciphers == NULL)
   1138   1.1  christos 			options->ciphers = xstrdup(arg);
   1139   1.1  christos 		break;
   1140   1.1  christos 
   1141   1.1  christos 	case oMacs:
   1142   1.1  christos 		arg = strdelim(&s);
   1143   1.1  christos 		if (!arg || *arg == '\0')
   1144   1.1  christos 			fatal("%.200s line %d: Missing argument.", filename, linenum);
   1145   1.1  christos 		if (!mac_valid(arg))
   1146   1.1  christos 			fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
   1147   1.1  christos 			    filename, linenum, arg ? arg : "<NONE>");
   1148   1.1  christos 		if (*activep && options->macs == NULL)
   1149   1.1  christos 			options->macs = xstrdup(arg);
   1150   1.1  christos 		break;
   1151   1.1  christos 
   1152   1.5  christos 	case oKexAlgorithms:
   1153   1.5  christos 		arg = strdelim(&s);
   1154   1.5  christos 		if (!arg || *arg == '\0')
   1155   1.5  christos 			fatal("%.200s line %d: Missing argument.",
   1156   1.5  christos 			    filename, linenum);
   1157   1.5  christos 		if (!kex_names_valid(arg))
   1158   1.5  christos 			fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
   1159   1.5  christos 			    filename, linenum, arg ? arg : "<NONE>");
   1160   1.5  christos 		if (*activep && options->kex_algorithms == NULL)
   1161   1.5  christos 			options->kex_algorithms = xstrdup(arg);
   1162   1.5  christos 		break;
   1163   1.5  christos 
   1164   1.1  christos 	case oHostKeyAlgorithms:
   1165   1.1  christos 		arg = strdelim(&s);
   1166   1.1  christos 		if (!arg || *arg == '\0')
   1167   1.1  christos 			fatal("%.200s line %d: Missing argument.", filename, linenum);
   1168   1.1  christos 		if (!key_names_valid2(arg))
   1169   1.1  christos 			fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
   1170   1.1  christos 			    filename, linenum, arg ? arg : "<NONE>");
   1171   1.1  christos 		if (*activep && options->hostkeyalgorithms == NULL)
   1172   1.1  christos 			options->hostkeyalgorithms = xstrdup(arg);
   1173   1.1  christos 		break;
   1174   1.1  christos 
   1175   1.1  christos 	case oProtocol:
   1176   1.1  christos 		intptr = &options->protocol;
   1177   1.1  christos 		arg = strdelim(&s);
   1178   1.1  christos 		if (!arg || *arg == '\0')
   1179   1.1  christos 			fatal("%.200s line %d: Missing argument.", filename, linenum);
   1180   1.1  christos 		value = proto_spec(arg);
   1181   1.1  christos 		if (value == SSH_PROTO_UNKNOWN)
   1182   1.1  christos 			fatal("%.200s line %d: Bad protocol spec '%s'.",
   1183   1.1  christos 			    filename, linenum, arg ? arg : "<NONE>");
   1184   1.1  christos 		if (*activep && *intptr == SSH_PROTO_UNKNOWN)
   1185   1.1  christos 			*intptr = value;
   1186   1.1  christos 		break;
   1187   1.1  christos 
   1188   1.1  christos 	case oLogLevel:
   1189   1.1  christos 		log_level_ptr = &options->log_level;
   1190   1.1  christos 		arg = strdelim(&s);
   1191   1.1  christos 		value = log_level_number(arg);
   1192   1.1  christos 		if (value == SYSLOG_LEVEL_NOT_SET)
   1193   1.1  christos 			fatal("%.200s line %d: unsupported log level '%s'",
   1194   1.1  christos 			    filename, linenum, arg ? arg : "<NONE>");
   1195   1.1  christos 		if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
   1196   1.1  christos 			*log_level_ptr = (LogLevel) value;
   1197   1.1  christos 		break;
   1198   1.1  christos 
   1199   1.1  christos 	case oLocalForward:
   1200   1.1  christos 	case oRemoteForward:
   1201   1.1  christos 	case oDynamicForward:
   1202   1.1  christos 		arg = strdelim(&s);
   1203   1.1  christos 		if (arg == NULL || *arg == '\0')
   1204   1.1  christos 			fatal("%.200s line %d: Missing port argument.",
   1205   1.1  christos 			    filename, linenum);
   1206   1.1  christos 
   1207   1.1  christos 		if (opcode == oLocalForward ||
   1208   1.1  christos 		    opcode == oRemoteForward) {
   1209   1.1  christos 			arg2 = strdelim(&s);
   1210   1.1  christos 			if (arg2 == NULL || *arg2 == '\0')
   1211   1.1  christos 				fatal("%.200s line %d: Missing target argument.",
   1212   1.1  christos 				    filename, linenum);
   1213   1.1  christos 
   1214   1.1  christos 			/* construct a string for parse_forward */
   1215   1.1  christos 			snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
   1216   1.1  christos 		} else if (opcode == oDynamicForward) {
   1217   1.1  christos 			strlcpy(fwdarg, arg, sizeof(fwdarg));
   1218   1.1  christos 		}
   1219   1.1  christos 
   1220   1.1  christos 		if (parse_forward(&fwd, fwdarg,
   1221   1.1  christos 		    opcode == oDynamicForward ? 1 : 0,
   1222   1.1  christos 		    opcode == oRemoteForward ? 1 : 0) == 0)
   1223   1.1  christos 			fatal("%.200s line %d: Bad forwarding specification.",
   1224   1.1  christos 			    filename, linenum);
   1225   1.1  christos 
   1226   1.1  christos 		if (*activep) {
   1227   1.1  christos 			if (opcode == oLocalForward ||
   1228   1.1  christos 			    opcode == oDynamicForward)
   1229   1.1  christos 				add_local_forward(options, &fwd);
   1230   1.1  christos 			else if (opcode == oRemoteForward)
   1231   1.1  christos 				add_remote_forward(options, &fwd);
   1232   1.1  christos 		}
   1233   1.1  christos 		break;
   1234   1.1  christos 
   1235   1.1  christos 	case oClearAllForwardings:
   1236   1.1  christos 		intptr = &options->clear_forwardings;
   1237   1.1  christos 		goto parse_flag;
   1238   1.1  christos 
   1239   1.1  christos 	case oHost:
   1240  1.12  christos 		if (cmdline)
   1241  1.12  christos 			fatal("Host directive not supported as a command-line "
   1242  1.12  christos 			    "option");
   1243   1.1  christos 		*activep = 0;
   1244   1.6  christos 		arg2 = NULL;
   1245   1.6  christos 		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
   1246   1.6  christos 			negated = *arg == '!';
   1247   1.6  christos 			if (negated)
   1248   1.6  christos 				arg++;
   1249   1.1  christos 			if (match_pattern(host, arg)) {
   1250   1.6  christos 				if (negated) {
   1251   1.6  christos 					debug("%.200s line %d: Skipping Host "
   1252   1.6  christos 					    "block because of negated match "
   1253   1.6  christos 					    "for %.100s", filename, linenum,
   1254   1.6  christos 					    arg);
   1255   1.6  christos 					*activep = 0;
   1256   1.6  christos 					break;
   1257   1.6  christos 				}
   1258   1.6  christos 				if (!*activep)
   1259   1.6  christos 					arg2 = arg; /* logged below */
   1260   1.1  christos 				*activep = 1;
   1261   1.1  christos 			}
   1262   1.6  christos 		}
   1263   1.6  christos 		if (*activep)
   1264   1.6  christos 			debug("%.200s line %d: Applying options for %.100s",
   1265   1.6  christos 			    filename, linenum, arg2);
   1266   1.1  christos 		/* Avoid garbage check below, as strdelim is done. */
   1267   1.1  christos 		return 0;
   1268   1.1  christos 
   1269  1.12  christos 	case oMatch:
   1270  1.12  christos 		if (cmdline)
   1271  1.12  christos 			fatal("Host directive not supported as a command-line "
   1272  1.12  christos 			    "option");
   1273  1.12  christos 		value = match_cfg_line(options, &s, pw, host,
   1274  1.12  christos 		    filename, linenum);
   1275  1.12  christos 		if (value < 0)
   1276  1.12  christos 			fatal("%.200s line %d: Bad Match condition", filename,
   1277  1.12  christos 			    linenum);
   1278  1.12  christos 		*activep = value;
   1279  1.12  christos 		break;
   1280  1.12  christos 
   1281   1.1  christos 	case oEscapeChar:
   1282   1.1  christos 		intptr = &options->escape_char;
   1283   1.1  christos 		arg = strdelim(&s);
   1284   1.1  christos 		if (!arg || *arg == '\0')
   1285   1.1  christos 			fatal("%.200s line %d: Missing argument.", filename, linenum);
   1286   1.2  christos 		value = 0;	/* To avoid compiler warning... */
   1287   1.1  christos 		if (arg[0] == '^' && arg[2] == 0 &&
   1288   1.1  christos 		    (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
   1289   1.1  christos 			value = (u_char) arg[1] & 31;
   1290   1.1  christos 		else if (strlen(arg) == 1)
   1291   1.1  christos 			value = (u_char) arg[0];
   1292   1.1  christos 		else if (strcmp(arg, "none") == 0)
   1293   1.1  christos 			value = SSH_ESCAPECHAR_NONE;
   1294   1.1  christos 		else {
   1295   1.1  christos 			fatal("%.200s line %d: Bad escape character.",
   1296   1.1  christos 			    filename, linenum);
   1297   1.1  christos 			/* NOTREACHED */
   1298   1.1  christos 			value = 0;	/* Avoid compiler warning. */
   1299   1.1  christos 		}
   1300   1.1  christos 		if (*activep && *intptr == -1)
   1301   1.1  christos 			*intptr = value;
   1302   1.1  christos 		break;
   1303   1.1  christos 
   1304   1.1  christos 	case oAddressFamily:
   1305   1.1  christos 		intptr = &options->address_family;
   1306  1.12  christos 		multistate_ptr = multistate_addressfamily;
   1307  1.12  christos 		goto parse_multistate;
   1308   1.1  christos 
   1309   1.1  christos 	case oEnableSSHKeysign:
   1310   1.1  christos 		intptr = &options->enable_ssh_keysign;
   1311   1.1  christos 		goto parse_flag;
   1312   1.1  christos 
   1313   1.1  christos 	case oIdentitiesOnly:
   1314   1.1  christos 		intptr = &options->identities_only;
   1315   1.1  christos 		goto parse_flag;
   1316   1.1  christos 
   1317   1.1  christos 	case oServerAliveInterval:
   1318   1.1  christos 		intptr = &options->server_alive_interval;
   1319   1.1  christos 		goto parse_time;
   1320   1.1  christos 
   1321   1.1  christos 	case oServerAliveCountMax:
   1322   1.1  christos 		intptr = &options->server_alive_count_max;
   1323   1.1  christos 		goto parse_int;
   1324   1.1  christos 
   1325   1.1  christos 	case oSendEnv:
   1326   1.1  christos 		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
   1327   1.1  christos 			if (strchr(arg, '=') != NULL)
   1328   1.1  christos 				fatal("%s line %d: Invalid environment name.",
   1329   1.1  christos 				    filename, linenum);
   1330   1.1  christos 			if (!*activep)
   1331   1.1  christos 				continue;
   1332   1.1  christos 			if (options->num_send_env >= MAX_SEND_ENV)
   1333   1.1  christos 				fatal("%s line %d: too many send env.",
   1334   1.1  christos 				    filename, linenum);
   1335   1.1  christos 			options->send_env[options->num_send_env++] =
   1336   1.1  christos 			    xstrdup(arg);
   1337   1.1  christos 		}
   1338   1.1  christos 		break;
   1339   1.1  christos 
   1340   1.1  christos 	case oControlPath:
   1341   1.1  christos 		charptr = &options->control_path;
   1342   1.1  christos 		goto parse_string;
   1343   1.1  christos 
   1344   1.1  christos 	case oControlMaster:
   1345   1.1  christos 		intptr = &options->control_master;
   1346  1.12  christos 		multistate_ptr = multistate_controlmaster;
   1347  1.12  christos 		goto parse_multistate;
   1348   1.1  christos 
   1349   1.4      adam 	case oControlPersist:
   1350   1.4      adam 		/* no/false/yes/true, or a time spec */
   1351   1.4      adam 		intptr = &options->control_persist;
   1352   1.4      adam 		arg = strdelim(&s);
   1353   1.4      adam 		if (!arg || *arg == '\0')
   1354   1.4      adam 			fatal("%.200s line %d: Missing ControlPersist"
   1355   1.4      adam 			    " argument.", filename, linenum);
   1356   1.4      adam 		value = 0;
   1357   1.4      adam 		value2 = 0;	/* timeout */
   1358   1.4      adam 		if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
   1359   1.4      adam 			value = 0;
   1360   1.4      adam 		else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
   1361   1.4      adam 			value = 1;
   1362   1.4      adam 		else if ((value2 = convtime(arg)) >= 0)
   1363   1.4      adam 			value = 1;
   1364   1.4      adam 		else
   1365   1.4      adam 			fatal("%.200s line %d: Bad ControlPersist argument.",
   1366   1.4      adam 			    filename, linenum);
   1367   1.4      adam 		if (*activep && *intptr == -1) {
   1368   1.4      adam 			*intptr = value;
   1369   1.4      adam 			options->control_persist_timeout = value2;
   1370   1.4      adam 		}
   1371   1.4      adam 		break;
   1372   1.4      adam 
   1373   1.1  christos 	case oHashKnownHosts:
   1374   1.1  christos 		intptr = &options->hash_known_hosts;
   1375   1.1  christos 		goto parse_flag;
   1376   1.1  christos 
   1377   1.1  christos 	case oTunnel:
   1378   1.1  christos 		intptr = &options->tun_open;
   1379  1.12  christos 		multistate_ptr = multistate_tunnel;
   1380  1.12  christos 		goto parse_multistate;
   1381   1.1  christos 
   1382   1.1  christos 	case oTunnelDevice:
   1383   1.1  christos 		arg = strdelim(&s);
   1384   1.1  christos 		if (!arg || *arg == '\0')
   1385   1.1  christos 			fatal("%.200s line %d: Missing argument.", filename, linenum);
   1386   1.1  christos 		value = a2tun(arg, &value2);
   1387   1.1  christos 		if (value == SSH_TUNID_ERR)
   1388   1.1  christos 			fatal("%.200s line %d: Bad tun device.", filename, linenum);
   1389   1.1  christos 		if (*activep) {
   1390   1.1  christos 			options->tun_local = value;
   1391   1.1  christos 			options->tun_remote = value2;
   1392   1.1  christos 		}
   1393   1.1  christos 		break;
   1394   1.1  christos 
   1395   1.1  christos 	case oLocalCommand:
   1396   1.1  christos 		charptr = &options->local_command;
   1397   1.1  christos 		goto parse_command;
   1398   1.1  christos 
   1399   1.1  christos 	case oPermitLocalCommand:
   1400   1.1  christos 		intptr = &options->permit_local_command;
   1401   1.1  christos 		goto parse_flag;
   1402   1.1  christos 
   1403   1.1  christos 	case oVisualHostKey:
   1404   1.1  christos 		intptr = &options->visual_host_key;
   1405   1.1  christos 		goto parse_flag;
   1406   1.1  christos 
   1407   1.5  christos 	case oIPQoS:
   1408   1.5  christos 		arg = strdelim(&s);
   1409   1.5  christos 		if ((value = parse_ipqos(arg)) == -1)
   1410   1.5  christos 			fatal("%s line %d: Bad IPQoS value: %s",
   1411   1.5  christos 			    filename, linenum, arg);
   1412   1.5  christos 		arg = strdelim(&s);
   1413   1.5  christos 		if (arg == NULL)
   1414   1.5  christos 			value2 = value;
   1415   1.5  christos 		else if ((value2 = parse_ipqos(arg)) == -1)
   1416   1.5  christos 			fatal("%s line %d: Bad IPQoS value: %s",
   1417   1.5  christos 			    filename, linenum, arg);
   1418   1.5  christos 		if (*activep) {
   1419   1.5  christos 			options->ip_qos_interactive = value;
   1420   1.5  christos 			options->ip_qos_bulk = value2;
   1421   1.5  christos 		}
   1422   1.5  christos 		break;
   1423   1.5  christos 
   1424   1.3  christos 	case oUseRoaming:
   1425   1.3  christos 		intptr = &options->use_roaming;
   1426   1.3  christos 		goto parse_flag;
   1427   1.3  christos 
   1428   1.6  christos 	case oRequestTTY:
   1429   1.6  christos 		intptr = &options->request_tty;
   1430  1.12  christos 		multistate_ptr = multistate_requesttty;
   1431  1.12  christos 		goto parse_multistate;
   1432   1.6  christos 
   1433   1.7       tls 	case oSendVersionFirst:
   1434   1.7       tls 		intptr = &options->send_version_first;
   1435   1.7       tls 		goto parse_flag;
   1436   1.7       tls 
   1437  1.11  christos 	case oIgnoreUnknown:
   1438  1.11  christos 		charptr = &options->ignored_unknown;
   1439  1.11  christos 		goto parse_string;
   1440  1.11  christos 
   1441  1.12  christos 	case oProxyUseFdpass:
   1442  1.12  christos 		intptr = &options->proxy_use_fdpass;
   1443  1.12  christos 		goto parse_flag;
   1444  1.12  christos 
   1445  1.12  christos 	case oCanonicalDomains:
   1446  1.12  christos 		value = options->num_canonical_domains != 0;
   1447  1.12  christos 		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
   1448  1.12  christos 			valid_domain(arg, filename, linenum);
   1449  1.12  christos 			if (!*activep || value)
   1450  1.12  christos 				continue;
   1451  1.12  christos 			if (options->num_canonical_domains >= MAX_CANON_DOMAINS)
   1452  1.12  christos 				fatal("%s line %d: too many hostname suffixes.",
   1453  1.12  christos 				    filename, linenum);
   1454  1.12  christos 			options->canonical_domains[
   1455  1.12  christos 			    options->num_canonical_domains++] = xstrdup(arg);
   1456  1.12  christos 		}
   1457  1.12  christos 		break;
   1458  1.12  christos 
   1459  1.12  christos 	case oCanonicalizePermittedCNAMEs:
   1460  1.12  christos 		value = options->num_permitted_cnames != 0;
   1461  1.12  christos 		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
   1462  1.12  christos 			/* Either '*' for everything or 'list:list' */
   1463  1.12  christos 			if (strcmp(arg, "*") == 0)
   1464  1.12  christos 				arg2 = arg;
   1465  1.12  christos 			else {
   1466  1.12  christos 				lowercase(arg);
   1467  1.12  christos 				if ((arg2 = strchr(arg, ':')) == NULL ||
   1468  1.12  christos 				    arg2[1] == '\0') {
   1469  1.12  christos 					fatal("%s line %d: "
   1470  1.12  christos 					    "Invalid permitted CNAME \"%s\"",
   1471  1.12  christos 					    filename, linenum, arg);
   1472  1.12  christos 				}
   1473  1.12  christos 				*arg2 = '\0';
   1474  1.12  christos 				arg2++;
   1475  1.12  christos 			}
   1476  1.12  christos 			if (!*activep || value)
   1477  1.12  christos 				continue;
   1478  1.12  christos 			if (options->num_permitted_cnames >= MAX_CANON_DOMAINS)
   1479  1.12  christos 				fatal("%s line %d: too many permitted CNAMEs.",
   1480  1.12  christos 				    filename, linenum);
   1481  1.12  christos 			cname = options->permitted_cnames +
   1482  1.12  christos 			    options->num_permitted_cnames++;
   1483  1.12  christos 			cname->source_list = xstrdup(arg);
   1484  1.12  christos 			cname->target_list = xstrdup(arg2);
   1485  1.12  christos 		}
   1486  1.12  christos 		break;
   1487  1.12  christos 
   1488  1.12  christos 	case oCanonicalizeHostname:
   1489  1.12  christos 		intptr = &options->canonicalize_hostname;
   1490  1.12  christos 		multistate_ptr = multistate_canonicalizehostname;
   1491  1.12  christos 		goto parse_multistate;
   1492  1.12  christos 
   1493  1.12  christos 	case oCanonicalizeMaxDots:
   1494  1.12  christos 		intptr = &options->canonicalize_max_dots;
   1495  1.12  christos 		goto parse_int;
   1496  1.12  christos 
   1497  1.12  christos 	case oCanonicalizeFallbackLocal:
   1498  1.12  christos 		intptr = &options->canonicalize_fallback_local;
   1499  1.12  christos 		goto parse_flag;
   1500  1.12  christos 
   1501  1.12  christos 	case oStreamLocalBindMask:
   1502  1.12  christos 		arg = strdelim(&s);
   1503  1.12  christos 		if (!arg || *arg == '\0')
   1504  1.12  christos 			fatal("%.200s line %d: Missing StreamLocalBindMask argument.", filename, linenum);
   1505  1.12  christos 		/* Parse mode in octal format */
   1506  1.12  christos 		value = strtol(arg, &endofnumber, 8);
   1507  1.12  christos 		if (arg == endofnumber || value < 0 || value > 0777)
   1508  1.12  christos 			fatal("%.200s line %d: Bad mask.", filename, linenum);
   1509  1.12  christos 		options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
   1510  1.12  christos 		break;
   1511  1.12  christos 
   1512  1.12  christos 	case oStreamLocalBindUnlink:
   1513  1.12  christos 		intptr = &options->fwd_opts.streamlocal_bind_unlink;
   1514  1.12  christos 		goto parse_flag;
   1515  1.12  christos 
   1516   1.1  christos 	case oDeprecated:
   1517   1.1  christos 		debug("%s line %d: Deprecated option \"%s\"",
   1518   1.1  christos 		    filename, linenum, keyword);
   1519   1.1  christos 		return 0;
   1520   1.1  christos 
   1521   1.1  christos 	case oUnsupported:
   1522   1.1  christos 		error("%s line %d: Unsupported option \"%s\"",
   1523   1.1  christos 		    filename, linenum, keyword);
   1524   1.1  christos 		return 0;
   1525   1.1  christos 
   1526   1.1  christos 	default:
   1527   1.1  christos 		fatal("process_config_line: Unimplemented opcode %d", opcode);
   1528   1.1  christos 	}
   1529   1.1  christos 
   1530   1.1  christos 	/* Check that there is no garbage at end of line. */
   1531   1.1  christos 	if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
   1532   1.1  christos 		fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
   1533   1.1  christos 		    filename, linenum, arg);
   1534   1.1  christos 	}
   1535   1.1  christos 	return 0;
   1536   1.1  christos }
   1537   1.1  christos 
   1538   1.1  christos 
   1539   1.1  christos /*
   1540   1.1  christos  * Reads the config file and modifies the options accordingly.  Options
   1541   1.1  christos  * should already be initialized before this call.  This never returns if
   1542   1.1  christos  * there is an error.  If the file does not exist, this returns 0.
   1543   1.1  christos  */
   1544   1.1  christos 
   1545   1.1  christos int
   1546  1.12  christos read_config_file(const char *filename, struct passwd *pw, const char *host,
   1547  1.12  christos     Options *options, int flags)
   1548   1.1  christos {
   1549   1.1  christos 	FILE *f;
   1550   1.1  christos 	char line[1024];
   1551   1.1  christos 	int active, linenum;
   1552   1.1  christos 	int bad_options = 0;
   1553   1.1  christos 
   1554   1.1  christos 	if ((f = fopen(filename, "r")) == NULL)
   1555   1.1  christos 		return 0;
   1556   1.1  christos 
   1557   1.9   mlelstv 	if (flags & SSHCONF_CHECKPERM) {
   1558   1.1  christos 		struct stat sb;
   1559   1.1  christos 
   1560   1.1  christos 		if (fstat(fileno(f), &sb) == -1)
   1561   1.1  christos 			fatal("fstat %s: %s", filename, strerror(errno));
   1562   1.1  christos 		if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
   1563   1.1  christos 		    (sb.st_mode & 022) != 0))
   1564   1.1  christos 			fatal("Bad owner or permissions on %s", filename);
   1565   1.1  christos 	}
   1566   1.1  christos 
   1567   1.1  christos 	debug("Reading configuration data %.200s", filename);
   1568   1.1  christos 
   1569   1.1  christos 	/*
   1570   1.1  christos 	 * Mark that we are now processing the options.  This flag is turned
   1571   1.1  christos 	 * on/off by Host specifications.
   1572   1.1  christos 	 */
   1573   1.1  christos 	active = 1;
   1574   1.1  christos 	linenum = 0;
   1575   1.1  christos 	while (fgets(line, sizeof(line), f)) {
   1576   1.1  christos 		/* Update line number counter. */
   1577   1.1  christos 		linenum++;
   1578  1.12  christos 		if (process_config_line(options, pw, host, line, filename,
   1579  1.12  christos 		    linenum, &active, flags & SSHCONF_USERCONF) != 0)
   1580   1.1  christos 			bad_options++;
   1581   1.1  christos 	}
   1582   1.1  christos 	fclose(f);
   1583   1.1  christos 	if (bad_options > 0)
   1584   1.1  christos 		fatal("%s: terminating, %d bad configuration options",
   1585   1.1  christos 		    filename, bad_options);
   1586   1.1  christos 	return 1;
   1587   1.1  christos }
   1588   1.1  christos 
   1589  1.12  christos /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
   1590  1.12  christos int
   1591  1.12  christos option_clear_or_none(const char *o)
   1592  1.12  christos {
   1593  1.12  christos 	return o == NULL || strcasecmp(o, "none") == 0;
   1594  1.12  christos }
   1595  1.12  christos 
   1596   1.1  christos /*
   1597   1.1  christos  * Initializes options to special values that indicate that they have not yet
   1598   1.1  christos  * been set.  Read_config_file will only set options with this value. Options
   1599   1.1  christos  * are processed in the following order: command line, user config file,
   1600   1.1  christos  * system config file.  Last, fill_default_options is called.
   1601   1.1  christos  */
   1602   1.1  christos 
   1603   1.1  christos void
   1604   1.1  christos initialize_options(Options * options)
   1605   1.1  christos {
   1606   1.1  christos 	memset(options, 'X', sizeof(*options));
   1607   1.1  christos 	options->forward_agent = -1;
   1608   1.1  christos 	options->forward_x11 = -1;
   1609   1.1  christos 	options->forward_x11_trusted = -1;
   1610   1.4      adam 	options->forward_x11_timeout = -1;
   1611   1.1  christos 	options->exit_on_forward_failure = -1;
   1612   1.1  christos 	options->xauth_location = NULL;
   1613  1.12  christos 	options->fwd_opts.gateway_ports = -1;
   1614  1.12  christos 	options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
   1615  1.12  christos 	options->fwd_opts.streamlocal_bind_unlink = -1;
   1616   1.1  christos 	options->use_privileged_port = -1;
   1617   1.1  christos 	options->rsa_authentication = -1;
   1618   1.1  christos 	options->pubkey_authentication = -1;
   1619   1.1  christos 	options->challenge_response_authentication = -1;
   1620   1.2  christos #if defined(KRB4) || defined(KRB5)
   1621   1.2  christos 	options->kerberos_authentication = -1;
   1622   1.2  christos #endif
   1623   1.2  christos #if defined(AFS) || defined(KRB5)
   1624   1.2  christos 	options->kerberos_tgt_passing = -1;
   1625   1.2  christos #endif
   1626   1.2  christos #ifdef AFS
   1627   1.2  christos 	options->afs_token_passing = -1;
   1628   1.2  christos #endif
   1629   1.1  christos 	options->gss_authentication = -1;
   1630   1.1  christos 	options->gss_deleg_creds = -1;
   1631   1.1  christos 	options->password_authentication = -1;
   1632   1.1  christos 	options->kbd_interactive_authentication = -1;
   1633   1.1  christos 	options->kbd_interactive_devices = NULL;
   1634   1.1  christos 	options->rhosts_rsa_authentication = -1;
   1635   1.1  christos 	options->hostbased_authentication = -1;
   1636   1.1  christos 	options->batch_mode = -1;
   1637   1.1  christos 	options->check_host_ip = -1;
   1638   1.1  christos 	options->strict_host_key_checking = -1;
   1639   1.1  christos 	options->compression = -1;
   1640   1.1  christos 	options->tcp_keep_alive = -1;
   1641   1.1  christos 	options->compression_level = -1;
   1642   1.1  christos 	options->port = -1;
   1643   1.1  christos 	options->address_family = -1;
   1644   1.1  christos 	options->connection_attempts = -1;
   1645   1.1  christos 	options->connection_timeout = -1;
   1646   1.1  christos 	options->number_of_password_prompts = -1;
   1647   1.1  christos 	options->cipher = -1;
   1648   1.1  christos 	options->ciphers = NULL;
   1649   1.1  christos 	options->macs = NULL;
   1650   1.5  christos 	options->kex_algorithms = NULL;
   1651   1.1  christos 	options->hostkeyalgorithms = NULL;
   1652   1.1  christos 	options->protocol = SSH_PROTO_UNKNOWN;
   1653   1.1  christos 	options->num_identity_files = 0;
   1654   1.1  christos 	options->hostname = NULL;
   1655   1.1  christos 	options->host_key_alias = NULL;
   1656   1.1  christos 	options->proxy_command = NULL;
   1657   1.1  christos 	options->user = NULL;
   1658   1.1  christos 	options->escape_char = -1;
   1659   1.6  christos 	options->num_system_hostfiles = 0;
   1660   1.6  christos 	options->num_user_hostfiles = 0;
   1661   1.4      adam 	options->local_forwards = NULL;
   1662   1.1  christos 	options->num_local_forwards = 0;
   1663   1.4      adam 	options->remote_forwards = NULL;
   1664   1.1  christos 	options->num_remote_forwards = 0;
   1665   1.1  christos 	options->clear_forwardings = -1;
   1666   1.1  christos 	options->log_level = SYSLOG_LEVEL_NOT_SET;
   1667   1.1  christos 	options->preferred_authentications = NULL;
   1668   1.1  christos 	options->bind_address = NULL;
   1669   1.4      adam 	options->pkcs11_provider = NULL;
   1670   1.1  christos 	options->enable_ssh_keysign = - 1;
   1671   1.1  christos 	options->no_host_authentication_for_localhost = - 1;
   1672   1.1  christos 	options->identities_only = - 1;
   1673   1.1  christos 	options->rekey_limit = - 1;
   1674  1.11  christos 	options->rekey_interval = -1;
   1675   1.1  christos 	options->verify_host_key_dns = -1;
   1676   1.1  christos 	options->server_alive_interval = -1;
   1677   1.1  christos 	options->server_alive_count_max = -1;
   1678   1.1  christos 	options->num_send_env = 0;
   1679   1.1  christos 	options->control_path = NULL;
   1680   1.1  christos 	options->control_master = -1;
   1681   1.4      adam 	options->control_persist = -1;
   1682   1.4      adam 	options->control_persist_timeout = 0;
   1683   1.1  christos 	options->hash_known_hosts = -1;
   1684   1.1  christos 	options->tun_open = -1;
   1685   1.1  christos 	options->tun_local = -1;
   1686   1.1  christos 	options->tun_remote = -1;
   1687   1.1  christos 	options->local_command = NULL;
   1688   1.1  christos 	options->permit_local_command = -1;
   1689   1.3  christos 	options->use_roaming = -1;
   1690   1.1  christos 	options->visual_host_key = -1;
   1691   1.5  christos 	options->ip_qos_interactive = -1;
   1692   1.5  christos 	options->ip_qos_bulk = -1;
   1693   1.6  christos 	options->request_tty = -1;
   1694  1.12  christos 	options->proxy_use_fdpass = -1;
   1695  1.11  christos 	options->ignored_unknown = NULL;
   1696  1.12  christos 	options->num_canonical_domains = 0;
   1697  1.12  christos 	options->num_permitted_cnames = 0;
   1698  1.12  christos 	options->canonicalize_max_dots = -1;
   1699  1.12  christos 	options->canonicalize_fallback_local = -1;
   1700  1.12  christos 	options->canonicalize_hostname = -1;
   1701   1.2  christos 	options->none_switch = -1;
   1702   1.2  christos 	options->none_enabled = -1;
   1703   1.2  christos 	options->hpn_disabled = -1;
   1704   1.2  christos 	options->hpn_buffer_size = -1;
   1705   1.2  christos 	options->tcp_rcv_buf_poll = -1;
   1706   1.2  christos 	options->tcp_rcv_buf = -1;
   1707   1.7       tls 	options->send_version_first = -1;
   1708   1.1  christos }
   1709   1.1  christos 
   1710   1.1  christos /*
   1711  1.12  christos  * A petite version of fill_default_options() that just fills the options
   1712  1.12  christos  * needed for hostname canonicalization to proceed.
   1713  1.12  christos  */
   1714  1.12  christos void
   1715  1.12  christos fill_default_options_for_canonicalization(Options *options)
   1716  1.12  christos {
   1717  1.12  christos 	if (options->canonicalize_max_dots == -1)
   1718  1.12  christos 		options->canonicalize_max_dots = 1;
   1719  1.12  christos 	if (options->canonicalize_fallback_local == -1)
   1720  1.12  christos 		options->canonicalize_fallback_local = 1;
   1721  1.12  christos 	if (options->canonicalize_hostname == -1)
   1722  1.12  christos 		options->canonicalize_hostname = SSH_CANONICALISE_NO;
   1723  1.12  christos }
   1724  1.12  christos 
   1725  1.12  christos /*
   1726   1.1  christos  * Called after processing other sources of option data, this fills those
   1727   1.1  christos  * options for which no value has been specified with their default values.
   1728   1.1  christos  */
   1729   1.1  christos void
   1730   1.1  christos fill_default_options(Options * options)
   1731   1.1  christos {
   1732   1.1  christos 	if (options->forward_agent == -1)
   1733   1.1  christos 		options->forward_agent = 0;
   1734   1.1  christos 	if (options->forward_x11 == -1)
   1735   1.1  christos 		options->forward_x11 = 0;
   1736   1.1  christos 	if (options->forward_x11_trusted == -1)
   1737   1.1  christos 		options->forward_x11_trusted = 0;
   1738   1.4      adam 	if (options->forward_x11_timeout == -1)
   1739   1.4      adam 		options->forward_x11_timeout = 1200;
   1740   1.1  christos 	if (options->exit_on_forward_failure == -1)
   1741   1.1  christos 		options->exit_on_forward_failure = 0;
   1742   1.1  christos 	if (options->xauth_location == NULL)
   1743   1.5  christos 		options->xauth_location = __UNCONST(_PATH_XAUTH);
   1744  1.12  christos 	if (options->fwd_opts.gateway_ports == -1)
   1745  1.12  christos 		options->fwd_opts.gateway_ports = 0;
   1746  1.12  christos 	if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
   1747  1.12  christos 		options->fwd_opts.streamlocal_bind_mask = 0177;
   1748  1.12  christos 	if (options->fwd_opts.streamlocal_bind_unlink == -1)
   1749  1.12  christos 		options->fwd_opts.streamlocal_bind_unlink = 0;
   1750   1.1  christos 	if (options->use_privileged_port == -1)
   1751   1.1  christos 		options->use_privileged_port = 0;
   1752   1.1  christos 	if (options->rsa_authentication == -1)
   1753   1.1  christos 		options->rsa_authentication = 1;
   1754   1.1  christos 	if (options->pubkey_authentication == -1)
   1755   1.1  christos 		options->pubkey_authentication = 1;
   1756   1.1  christos 	if (options->challenge_response_authentication == -1)
   1757   1.1  christos 		options->challenge_response_authentication = 1;
   1758   1.2  christos #if defined(KRB4) || defined(KRB5)
   1759   1.2  christos 	if (options->kerberos_authentication == -1)
   1760   1.2  christos 		options->kerberos_authentication = 1;
   1761   1.2  christos #endif
   1762   1.2  christos #if defined(AFS) || defined(KRB5)
   1763   1.2  christos 	if (options->kerberos_tgt_passing == -1)
   1764   1.2  christos 		options->kerberos_tgt_passing = 1;
   1765   1.2  christos #endif
   1766   1.2  christos #ifdef AFS
   1767   1.2  christos 	if (options->afs_token_passing == -1)
   1768   1.2  christos 		options->afs_token_passing = 1;
   1769   1.2  christos #endif
   1770   1.1  christos 	if (options->gss_authentication == -1)
   1771   1.1  christos 		options->gss_authentication = 0;
   1772   1.1  christos 	if (options->gss_deleg_creds == -1)
   1773   1.1  christos 		options->gss_deleg_creds = 0;
   1774   1.1  christos 	if (options->password_authentication == -1)
   1775   1.1  christos 		options->password_authentication = 1;
   1776   1.1  christos 	if (options->kbd_interactive_authentication == -1)
   1777   1.1  christos 		options->kbd_interactive_authentication = 1;
   1778   1.1  christos 	if (options->rhosts_rsa_authentication == -1)
   1779   1.1  christos 		options->rhosts_rsa_authentication = 0;
   1780   1.1  christos 	if (options->hostbased_authentication == -1)
   1781   1.1  christos 		options->hostbased_authentication = 0;
   1782   1.1  christos 	if (options->batch_mode == -1)
   1783   1.1  christos 		options->batch_mode = 0;
   1784   1.1  christos 	if (options->check_host_ip == -1)
   1785   1.1  christos 		options->check_host_ip = 1;
   1786   1.1  christos 	if (options->strict_host_key_checking == -1)
   1787   1.1  christos 		options->strict_host_key_checking = 2;	/* 2 is default */
   1788   1.1  christos 	if (options->compression == -1)
   1789   1.1  christos 		options->compression = 0;
   1790   1.1  christos 	if (options->tcp_keep_alive == -1)
   1791   1.1  christos 		options->tcp_keep_alive = 1;
   1792   1.1  christos 	if (options->compression_level == -1)
   1793   1.1  christos 		options->compression_level = 6;
   1794   1.1  christos 	if (options->port == -1)
   1795   1.1  christos 		options->port = 0;	/* Filled in ssh_connect. */
   1796   1.1  christos 	if (options->address_family == -1)
   1797   1.1  christos 		options->address_family = AF_UNSPEC;
   1798   1.1  christos 	if (options->connection_attempts == -1)
   1799   1.1  christos 		options->connection_attempts = 1;
   1800   1.1  christos 	if (options->number_of_password_prompts == -1)
   1801   1.1  christos 		options->number_of_password_prompts = 3;
   1802   1.1  christos 	/* Selected in ssh_login(). */
   1803   1.1  christos 	if (options->cipher == -1)
   1804   1.1  christos 		options->cipher = SSH_CIPHER_NOT_SET;
   1805   1.1  christos 	/* options->ciphers, default set in myproposals.h */
   1806   1.1  christos 	/* options->macs, default set in myproposals.h */
   1807   1.5  christos 	/* options->kex_algorithms, default set in myproposals.h */
   1808   1.1  christos 	/* options->hostkeyalgorithms, default set in myproposals.h */
   1809   1.1  christos 	if (options->protocol == SSH_PROTO_UNKNOWN)
   1810   1.4      adam 		options->protocol = SSH_PROTO_2;
   1811   1.1  christos 	if (options->num_identity_files == 0) {
   1812   1.1  christos 		if (options->protocol & SSH_PROTO_1) {
   1813  1.10   mlelstv 			add_identity_file(options, "~/",
   1814  1.10   mlelstv 			    _PATH_SSH_CLIENT_IDENTITY, 0);
   1815   1.1  christos 		}
   1816   1.1  christos 		if (options->protocol & SSH_PROTO_2) {
   1817  1.10   mlelstv 			add_identity_file(options, "~/",
   1818  1.10   mlelstv 			    _PATH_SSH_CLIENT_ID_RSA, 0);
   1819  1.10   mlelstv 			add_identity_file(options, "~/",
   1820  1.10   mlelstv 			    _PATH_SSH_CLIENT_ID_DSA, 0);
   1821  1.10   mlelstv 			add_identity_file(options, "~/",
   1822  1.10   mlelstv 			    _PATH_SSH_CLIENT_ID_ECDSA, 0);
   1823  1.12  christos 			add_identity_file(options, "~/",
   1824  1.12  christos 			    _PATH_SSH_CLIENT_ID_ED25519, 0);
   1825   1.1  christos 		}
   1826   1.1  christos 	}
   1827   1.1  christos 	if (options->escape_char == -1)
   1828   1.1  christos 		options->escape_char = '~';
   1829   1.6  christos 	if (options->num_system_hostfiles == 0) {
   1830   1.6  christos 		options->system_hostfiles[options->num_system_hostfiles++] =
   1831   1.6  christos 		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
   1832   1.6  christos 		options->system_hostfiles[options->num_system_hostfiles++] =
   1833   1.6  christos 		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
   1834   1.6  christos 	}
   1835   1.6  christos 	if (options->num_user_hostfiles == 0) {
   1836   1.6  christos 		options->user_hostfiles[options->num_user_hostfiles++] =
   1837   1.6  christos 		    xstrdup(_PATH_SSH_USER_HOSTFILE);
   1838   1.6  christos 		options->user_hostfiles[options->num_user_hostfiles++] =
   1839   1.6  christos 		    xstrdup(_PATH_SSH_USER_HOSTFILE2);
   1840   1.6  christos 	}
   1841   1.1  christos 	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
   1842   1.1  christos 		options->log_level = SYSLOG_LEVEL_INFO;
   1843   1.1  christos 	if (options->clear_forwardings == 1)
   1844   1.1  christos 		clear_forwardings(options);
   1845   1.1  christos 	if (options->no_host_authentication_for_localhost == - 1)
   1846   1.1  christos 		options->no_host_authentication_for_localhost = 0;
   1847   1.1  christos 	if (options->identities_only == -1)
   1848   1.1  christos 		options->identities_only = 0;
   1849   1.1  christos 	if (options->enable_ssh_keysign == -1)
   1850   1.1  christos 		options->enable_ssh_keysign = 0;
   1851   1.1  christos 	if (options->rekey_limit == -1)
   1852   1.1  christos 		options->rekey_limit = 0;
   1853  1.11  christos 	if (options->rekey_interval == -1)
   1854  1.11  christos 		options->rekey_interval = 0;
   1855   1.1  christos 	if (options->verify_host_key_dns == -1)
   1856   1.1  christos 		options->verify_host_key_dns = 0;
   1857   1.1  christos 	if (options->server_alive_interval == -1)
   1858   1.1  christos 		options->server_alive_interval = 0;
   1859   1.1  christos 	if (options->server_alive_count_max == -1)
   1860   1.1  christos 		options->server_alive_count_max = 3;
   1861   1.2  christos 	if (options->none_switch == -1)
   1862   1.2  christos 	        options->none_switch = 0;
   1863   1.2  christos 	if (options->hpn_disabled == -1)
   1864   1.2  christos 	        options->hpn_disabled = 0;
   1865   1.2  christos 	if (options->hpn_buffer_size > -1)
   1866   1.2  christos 	{
   1867   1.2  christos 	  /* if a user tries to set the size to 0 set it to 1KB */
   1868   1.2  christos 		if (options->hpn_buffer_size == 0)
   1869   1.2  christos 		options->hpn_buffer_size = 1024;
   1870   1.2  christos 		/*limit the buffer to 64MB*/
   1871   1.2  christos 		if (options->hpn_buffer_size > 65536)
   1872   1.2  christos 		{
   1873   1.2  christos 			options->hpn_buffer_size = 65536*1024;
   1874   1.2  christos 			debug("User requested buffer larger than 64MB. Request reverted to 64MB");
   1875   1.2  christos 		}
   1876   1.2  christos 		debug("hpn_buffer_size set to %d", options->hpn_buffer_size);
   1877   1.2  christos 	}
   1878   1.2  christos 	if (options->tcp_rcv_buf == 0)
   1879   1.2  christos 		options->tcp_rcv_buf = 1;
   1880   1.2  christos 	if (options->tcp_rcv_buf > -1)
   1881   1.2  christos 		options->tcp_rcv_buf *=1024;
   1882   1.2  christos 	if (options->tcp_rcv_buf_poll == -1)
   1883   1.2  christos 		options->tcp_rcv_buf_poll = 1;
   1884   1.1  christos 	if (options->control_master == -1)
   1885   1.1  christos 		options->control_master = 0;
   1886   1.4      adam 	if (options->control_persist == -1) {
   1887   1.4      adam 		options->control_persist = 0;
   1888   1.4      adam 		options->control_persist_timeout = 0;
   1889   1.4      adam 	}
   1890   1.1  christos 	if (options->hash_known_hosts == -1)
   1891   1.1  christos 		options->hash_known_hosts = 0;
   1892   1.1  christos 	if (options->tun_open == -1)
   1893   1.1  christos 		options->tun_open = SSH_TUNMODE_NO;
   1894   1.1  christos 	if (options->tun_local == -1)
   1895   1.1  christos 		options->tun_local = SSH_TUNID_ANY;
   1896   1.1  christos 	if (options->tun_remote == -1)
   1897   1.1  christos 		options->tun_remote = SSH_TUNID_ANY;
   1898   1.1  christos 	if (options->permit_local_command == -1)
   1899   1.1  christos 		options->permit_local_command = 0;
   1900   1.3  christos 	if (options->use_roaming == -1)
   1901   1.3  christos 		options->use_roaming = 1;
   1902   1.1  christos 	if (options->visual_host_key == -1)
   1903   1.1  christos 		options->visual_host_key = 0;
   1904   1.5  christos 	if (options->ip_qos_interactive == -1)
   1905   1.5  christos 		options->ip_qos_interactive = IPTOS_LOWDELAY;
   1906   1.5  christos 	if (options->ip_qos_bulk == -1)
   1907   1.5  christos 		options->ip_qos_bulk = IPTOS_THROUGHPUT;
   1908   1.6  christos 	if (options->request_tty == -1)
   1909   1.6  christos 		options->request_tty = REQUEST_TTY_AUTO;
   1910  1.12  christos 	if (options->proxy_use_fdpass == -1)
   1911  1.12  christos 		options->proxy_use_fdpass = 0;
   1912  1.12  christos 	if (options->canonicalize_max_dots == -1)
   1913  1.12  christos 		options->canonicalize_max_dots = 1;
   1914  1.12  christos 	if (options->canonicalize_fallback_local == -1)
   1915  1.12  christos 		options->canonicalize_fallback_local = 1;
   1916  1.12  christos 	if (options->canonicalize_hostname == -1)
   1917  1.12  christos 		options->canonicalize_hostname = SSH_CANONICALISE_NO;
   1918   1.7       tls 	if (options->send_version_first == -1)
   1919   1.7       tls 		options->send_version_first = 1;
   1920  1.12  christos #define CLEAR_ON_NONE(v) \
   1921  1.12  christos 	do { \
   1922  1.12  christos 		if (option_clear_or_none(v)) { \
   1923  1.12  christos 			free(v); \
   1924  1.12  christos 			v = NULL; \
   1925  1.12  christos 		} \
   1926  1.12  christos 	} while(0)
   1927  1.12  christos 	CLEAR_ON_NONE(options->local_command);
   1928  1.12  christos 	CLEAR_ON_NONE(options->proxy_command);
   1929  1.12  christos 	CLEAR_ON_NONE(options->control_path);
   1930   1.1  christos 	/* options->user will be set in the main program if appropriate */
   1931   1.1  christos 	/* options->hostname will be set in the main program if appropriate */
   1932   1.1  christos 	/* options->host_key_alias should not be set by default */
   1933   1.1  christos 	/* options->preferred_authentications will be set in ssh */
   1934   1.1  christos }
   1935   1.1  christos 
   1936  1.12  christos struct fwdarg {
   1937  1.12  christos 	char *arg;
   1938  1.12  christos 	int ispath;
   1939  1.12  christos };
   1940  1.12  christos 
   1941  1.12  christos /*
   1942  1.12  christos  * parse_fwd_field
   1943  1.12  christos  * parses the next field in a port forwarding specification.
   1944  1.12  christos  * sets fwd to the parsed field and advances p past the colon
   1945  1.12  christos  * or sets it to NULL at end of string.
   1946  1.12  christos  * returns 0 on success, else non-zero.
   1947  1.12  christos  */
   1948  1.12  christos static int
   1949  1.12  christos parse_fwd_field(char **p, struct fwdarg *fwd)
   1950  1.12  christos {
   1951  1.12  christos 	char *ep, *cp = *p;
   1952  1.12  christos 	int ispath = 0;
   1953  1.12  christos 
   1954  1.12  christos 	if (*cp == '\0') {
   1955  1.12  christos 		*p = NULL;
   1956  1.12  christos 		return -1;	/* end of string */
   1957  1.12  christos 	}
   1958  1.12  christos 
   1959  1.12  christos 	/*
   1960  1.12  christos 	 * A field escaped with square brackets is used literally.
   1961  1.12  christos 	 * XXX - allow ']' to be escaped via backslash?
   1962  1.12  christos 	 */
   1963  1.12  christos 	if (*cp == '[') {
   1964  1.12  christos 		/* find matching ']' */
   1965  1.12  christos 		for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
   1966  1.12  christos 			if (*ep == '/')
   1967  1.12  christos 				ispath = 1;
   1968  1.12  christos 		}
   1969  1.12  christos 		/* no matching ']' or not at end of field. */
   1970  1.12  christos 		if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
   1971  1.12  christos 			return -1;
   1972  1.12  christos 		/* NUL terminate the field and advance p past the colon */
   1973  1.12  christos 		*ep++ = '\0';
   1974  1.12  christos 		if (*ep != '\0')
   1975  1.12  christos 			*ep++ = '\0';
   1976  1.12  christos 		fwd->arg = cp + 1;
   1977  1.12  christos 		fwd->ispath = ispath;
   1978  1.12  christos 		*p = ep;
   1979  1.12  christos 		return 0;
   1980  1.12  christos 	}
   1981  1.12  christos 
   1982  1.12  christos 	for (cp = *p; *cp != '\0'; cp++) {
   1983  1.12  christos 		switch (*cp) {
   1984  1.12  christos 		case '\\':
   1985  1.12  christos 			memmove(cp, cp + 1, strlen(cp + 1) + 1);
   1986  1.12  christos 			cp++;
   1987  1.12  christos 			break;
   1988  1.12  christos 		case '/':
   1989  1.12  christos 			ispath = 1;
   1990  1.12  christos 			break;
   1991  1.12  christos 		case ':':
   1992  1.12  christos 			*cp++ = '\0';
   1993  1.12  christos 			goto done;
   1994  1.12  christos 		}
   1995  1.12  christos 	}
   1996  1.12  christos done:
   1997  1.12  christos 	fwd->arg = *p;
   1998  1.12  christos 	fwd->ispath = ispath;
   1999  1.12  christos 	*p = cp;
   2000  1.12  christos 	return 0;
   2001  1.12  christos }
   2002  1.12  christos 
   2003   1.1  christos /*
   2004   1.1  christos  * parse_forward
   2005   1.1  christos  * parses a string containing a port forwarding specification of the form:
   2006   1.1  christos  *   dynamicfwd == 0
   2007  1.12  christos  *	[listenhost:]listenport|listenpath:connecthost:connectport|connectpath
   2008  1.12  christos  *	listenpath:connectpath
   2009   1.1  christos  *   dynamicfwd == 1
   2010   1.1  christos  *	[listenhost:]listenport
   2011   1.1  christos  * returns number of arguments parsed or zero on error
   2012   1.1  christos  */
   2013   1.1  christos int
   2014  1.12  christos parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
   2015   1.1  christos {
   2016  1.12  christos 	struct fwdarg fwdargs[4];
   2017  1.12  christos 	char *p, *cp;
   2018   1.1  christos 	int i;
   2019   1.1  christos 
   2020  1.12  christos 	memset(fwd, 0, sizeof(*fwd));
   2021  1.12  christos 	memset(fwdargs, 0, sizeof(fwdargs));
   2022   1.1  christos 
   2023   1.1  christos 	cp = p = xstrdup(fwdspec);
   2024   1.1  christos 
   2025   1.1  christos 	/* skip leading spaces */
   2026  1.12  christos 	while (isspace((u_char)*cp))
   2027   1.1  christos 		cp++;
   2028   1.1  christos 
   2029  1.12  christos 	for (i = 0; i < 4; ++i) {
   2030  1.12  christos 		if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
   2031   1.1  christos 			break;
   2032  1.12  christos 	}
   2033   1.1  christos 
   2034   1.1  christos 	/* Check for trailing garbage */
   2035  1.12  christos 	if (cp != NULL && *cp != '\0') {
   2036   1.1  christos 		i = 0;	/* failure */
   2037  1.12  christos 	}
   2038   1.1  christos 
   2039   1.1  christos 	switch (i) {
   2040   1.1  christos 	case 1:
   2041  1.12  christos 		if (fwdargs[0].ispath) {
   2042  1.12  christos 			fwd->listen_path = xstrdup(fwdargs[0].arg);
   2043  1.12  christos 			fwd->listen_port = PORT_STREAMLOCAL;
   2044  1.12  christos 		} else {
   2045  1.12  christos 			fwd->listen_host = NULL;
   2046  1.12  christos 			fwd->listen_port = a2port(fwdargs[0].arg);
   2047  1.12  christos 		}
   2048   1.1  christos 		fwd->connect_host = xstrdup("socks");
   2049   1.1  christos 		break;
   2050   1.1  christos 
   2051   1.1  christos 	case 2:
   2052  1.12  christos 		if (fwdargs[0].ispath && fwdargs[1].ispath) {
   2053  1.12  christos 			fwd->listen_path = xstrdup(fwdargs[0].arg);
   2054  1.12  christos 			fwd->listen_port = PORT_STREAMLOCAL;
   2055  1.12  christos 			fwd->connect_path = xstrdup(fwdargs[1].arg);
   2056  1.12  christos 			fwd->connect_port = PORT_STREAMLOCAL;
   2057  1.12  christos 		} else if (fwdargs[1].ispath) {
   2058  1.12  christos 			fwd->listen_host = NULL;
   2059  1.12  christos 			fwd->listen_port = a2port(fwdargs[0].arg);
   2060  1.12  christos 			fwd->connect_path = xstrdup(fwdargs[1].arg);
   2061  1.12  christos 			fwd->connect_port = PORT_STREAMLOCAL;
   2062  1.12  christos 		} else {
   2063  1.12  christos 			fwd->listen_host = xstrdup(fwdargs[0].arg);
   2064  1.12  christos 			fwd->listen_port = a2port(fwdargs[1].arg);
   2065  1.12  christos 			fwd->connect_host = xstrdup("socks");
   2066  1.12  christos 		}
   2067   1.1  christos 		break;
   2068   1.1  christos 
   2069   1.1  christos 	case 3:
   2070  1.12  christos 		if (fwdargs[0].ispath) {
   2071  1.12  christos 			fwd->listen_path = xstrdup(fwdargs[0].arg);
   2072  1.12  christos 			fwd->listen_port = PORT_STREAMLOCAL;
   2073  1.12  christos 			fwd->connect_host = xstrdup(fwdargs[1].arg);
   2074  1.12  christos 			fwd->connect_port = a2port(fwdargs[2].arg);
   2075  1.12  christos 		} else if (fwdargs[2].ispath) {
   2076  1.12  christos 			fwd->listen_host = xstrdup(fwdargs[0].arg);
   2077  1.12  christos 			fwd->listen_port = a2port(fwdargs[1].arg);
   2078  1.12  christos 			fwd->connect_path = xstrdup(fwdargs[2].arg);
   2079  1.12  christos 			fwd->connect_port = PORT_STREAMLOCAL;
   2080  1.12  christos 		} else {
   2081  1.12  christos 			fwd->listen_host = NULL;
   2082  1.12  christos 			fwd->listen_port = a2port(fwdargs[0].arg);
   2083  1.12  christos 			fwd->connect_host = xstrdup(fwdargs[1].arg);
   2084  1.12  christos 			fwd->connect_port = a2port(fwdargs[2].arg);
   2085  1.12  christos 		}
   2086   1.1  christos 		break;
   2087   1.1  christos 
   2088   1.1  christos 	case 4:
   2089  1.12  christos 		fwd->listen_host = xstrdup(fwdargs[0].arg);
   2090  1.12  christos 		fwd->listen_port = a2port(fwdargs[1].arg);
   2091  1.12  christos 		fwd->connect_host = xstrdup(fwdargs[2].arg);
   2092  1.12  christos 		fwd->connect_port = a2port(fwdargs[3].arg);
   2093   1.1  christos 		break;
   2094   1.1  christos 	default:
   2095   1.1  christos 		i = 0; /* failure */
   2096   1.1  christos 	}
   2097   1.1  christos 
   2098  1.11  christos 	free(p);
   2099   1.1  christos 
   2100   1.1  christos 	if (dynamicfwd) {
   2101   1.1  christos 		if (!(i == 1 || i == 2))
   2102   1.1  christos 			goto fail_free;
   2103   1.1  christos 	} else {
   2104  1.12  christos 		if (!(i == 3 || i == 4)) {
   2105  1.12  christos 			if (fwd->connect_path == NULL &&
   2106  1.12  christos 			    fwd->listen_path == NULL)
   2107  1.12  christos 				goto fail_free;
   2108  1.12  christos 		}
   2109  1.12  christos 		if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
   2110   1.1  christos 			goto fail_free;
   2111   1.1  christos 	}
   2112   1.1  christos 
   2113  1.12  christos 	if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
   2114  1.12  christos 	    (!remotefwd && fwd->listen_port == 0))
   2115   1.1  christos 		goto fail_free;
   2116   1.1  christos 	if (fwd->connect_host != NULL &&
   2117   1.1  christos 	    strlen(fwd->connect_host) >= NI_MAXHOST)
   2118   1.1  christos 		goto fail_free;
   2119  1.12  christos 	/* XXX - if connecting to a remote socket, max sun len may not match this host */
   2120  1.12  christos 	if (fwd->connect_path != NULL &&
   2121  1.12  christos 	    strlen(fwd->connect_path) >= PATH_MAX_SUN)
   2122  1.12  christos 		goto fail_free;
   2123   1.1  christos 	if (fwd->listen_host != NULL &&
   2124   1.1  christos 	    strlen(fwd->listen_host) >= NI_MAXHOST)
   2125   1.1  christos 		goto fail_free;
   2126  1.12  christos 	if (fwd->listen_path != NULL &&
   2127  1.12  christos 	    strlen(fwd->listen_path) >= PATH_MAX_SUN)
   2128  1.12  christos 		goto fail_free;
   2129   1.1  christos 
   2130   1.1  christos 	return (i);
   2131   1.1  christos 
   2132   1.1  christos  fail_free:
   2133  1.11  christos 	free(fwd->connect_host);
   2134  1.11  christos 	fwd->connect_host = NULL;
   2135  1.12  christos 	free(fwd->connect_path);
   2136  1.12  christos 	fwd->connect_path = NULL;
   2137  1.11  christos 	free(fwd->listen_host);
   2138  1.11  christos 	fwd->listen_host = NULL;
   2139  1.12  christos 	free(fwd->listen_path);
   2140  1.12  christos 	fwd->listen_path = NULL;
   2141   1.1  christos 	return (0);
   2142   1.1  christos }
   2143