]> andersk Git - gssapi-openssh.git/blobdiff - openssh/readconf.c
update missing from merge of Simon's 20061220 patch
[gssapi-openssh.git] / openssh / readconf.c
index 81e9f934da2ec831003b4fe175f828d946a92b1d..de7635ebdfa2ca474b3a2bd5a6f482966e71a59e 100644 (file)
@@ -1,3 +1,4 @@
+/* $OpenBSD: readconf.c,v 1.159 2006/08/03 03:34:42 deraadt Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
  */
 
 #include "includes.h"
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: readconf.c,v 1.104 2003/04/01 10:22:21 markus Exp $");
 
 
-#include "ssh.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
 #include "xmalloc.h"
 #include "xmalloc.h"
+#include "ssh.h"
 #include "compat.h"
 #include "cipher.h"
 #include "pathnames.h"
 #include "log.h"
 #include "compat.h"
 #include "cipher.h"
 #include "pathnames.h"
 #include "log.h"
+#include "key.h"
 #include "readconf.h"
 #include "match.h"
 #include "misc.h"
 #include "readconf.h"
 #include "match.h"
 #include "misc.h"
+#include "buffer.h"
 #include "kex.h"
 #include "mac.h"
 
 #include "kex.h"
 #include "mac.h"
 
@@ -57,7 +74,6 @@ RCSID("$OpenBSD: readconf.c,v 1.104 2003/04/01 10:22:21 markus Exp $");
    Host fascist.blob.com
      Port 23123
      User tylonen
    Host fascist.blob.com
      Port 23123
      User tylonen
-     RhostsAuthentication no
      PasswordAuthentication no
 
    Host puukko.hut.fi
      PasswordAuthentication no
 
    Host puukko.hut.fi
@@ -71,16 +87,19 @@ RCSID("$OpenBSD: readconf.c,v 1.104 2003/04/01 10:22:21 markus Exp $");
      Cipher none
      PasswordAuthentication no
 
      Cipher none
      PasswordAuthentication no
 
+   Host vpn.fake.com
+     Tunnel yes
+     TunnelDevice 3
+
    # Defaults for various options
    Host *
      ForwardAgent no
      ForwardX11 no
    # Defaults for various options
    Host *
      ForwardAgent no
      ForwardX11 no
-     RhostsAuthentication yes
      PasswordAuthentication yes
      RSAAuthentication yes
      RhostsRSAAuthentication yes
      StrictHostKeyChecking yes
      PasswordAuthentication yes
      RSAAuthentication yes
      RhostsRSAAuthentication yes
      StrictHostKeyChecking yes
-     KeepAlives no
+     TcpKeepAlive no
      IdentityFile ~/.ssh/identity
      Port 22
      EscapeChar ~
      IdentityFile ~/.ssh/identity
      Port 22
      EscapeChar ~
@@ -91,37 +110,31 @@ RCSID("$OpenBSD: readconf.c,v 1.104 2003/04/01 10:22:21 markus Exp $");
 
 typedef enum {
        oBadOption,
 
 typedef enum {
        oBadOption,
-       oForwardAgent, oForwardX11, oGatewayPorts, oRhostsAuthentication,
+       oForwardAgent, oForwardX11, oForwardX11Trusted, oGatewayPorts,
+       oExitOnForwardFailure,
        oPasswordAuthentication, oRSAAuthentication,
        oChallengeResponseAuthentication, oXAuthLocation,
        oPasswordAuthentication, oRSAAuthentication,
        oChallengeResponseAuthentication, oXAuthLocation,
-#if defined(KRB4) || defined(KRB5)
-       oKerberosAuthentication,
-#endif
-#ifdef GSSAPI
-       oGssAuthentication, oGssKeyEx, oGssDelegateCreds,
-#ifdef GSI
-       oGssGlobusDelegateLimitedCreds,
-#endif /* GSI */
-#endif /* GSSAPI */
-#if defined(AFS) || defined(KRB5)
-       oKerberosTgtPassing,
-#endif
-#ifdef AFS
-       oAFSTokenPassing,
-#endif
        oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
        oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
        oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
        oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
        oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
        oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
        oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
        oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
-       oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts,
+       oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
        oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
        oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
        oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
        oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
        oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
        oClearAllForwardings, oNoHostAuthenticationForLocalhost,
        oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
        oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
        oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
        oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
        oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
        oClearAllForwardings, oNoHostAuthenticationForLocalhost,
-       oEnableSSHKeysign,
-       oDeprecated
+       oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
+       oAddressFamily, oGssAuthentication, oGssDelegateCreds,
+       oGssKeyEx,
+       oGssTrustDns,
+       oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
+       oSendEnv, oControlPath, oControlMaster, oHashKnownHosts,
+       oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
+       oNoneEnabled, oTcpRcvBufPoll, oTcpRcvBuf, oNoneSwitch, oHPNDisabled,
+       oHPNBufferSize,
+       oDeprecated, oUnsupported
 } OpCodes;
 
 /* Textual representations of the tokens. */
 } OpCodes;
 
 /* Textual representations of the tokens. */
@@ -132,10 +145,12 @@ static struct {
 } keywords[] = {
        { "forwardagent", oForwardAgent },
        { "forwardx11", oForwardX11 },
 } keywords[] = {
        { "forwardagent", oForwardAgent },
        { "forwardx11", oForwardX11 },
+       { "forwardx11trusted", oForwardX11Trusted },
+       { "exitonforwardfailure", oExitOnForwardFailure },
        { "xauthlocation", oXAuthLocation },
        { "gatewayports", oGatewayPorts },
        { "useprivilegedport", oUsePrivilegedPort },
        { "xauthlocation", oXAuthLocation },
        { "gatewayports", oGatewayPorts },
        { "useprivilegedport", oUsePrivilegedPort },
-       { "rhostsauthentication", oRhostsAuthentication },
+       { "rhostsauthentication", oDeprecated },
        { "passwordauthentication", oPasswordAuthentication },
        { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
        { "kbdinteractivedevices", oKbdInteractiveDevices },
        { "passwordauthentication", oPasswordAuthentication },
        { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
        { "kbdinteractivedevices", oKbdInteractiveDevices },
@@ -147,29 +162,25 @@ static struct {
        { "challengeresponseauthentication", oChallengeResponseAuthentication },
        { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
        { "tisauthentication", oChallengeResponseAuthentication },  /* alias */
        { "challengeresponseauthentication", oChallengeResponseAuthentication },
        { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
        { "tisauthentication", oChallengeResponseAuthentication },  /* alias */
-#if defined(KRB4) || defined(KRB5)
-       { "kerberosauthentication", oKerberosAuthentication },
-#endif
-#ifdef GSSAPI
+       { "kerberosauthentication", oUnsupported },
+       { "kerberostgtpassing", oUnsupported },
+       { "afstokenpassing", oUnsupported },
+#if defined(GSSAPI)
        { "gssapiauthentication", oGssAuthentication },
        { "gssapikeyexchange", oGssKeyEx },
        { "gssapidelegatecredentials", oGssDelegateCreds },
        { "gssapiauthentication", oGssAuthentication },
        { "gssapikeyexchange", oGssKeyEx },
        { "gssapidelegatecredentials", oGssDelegateCreds },
-#ifdef GSI
-       /* For backwards compatability with old 1.2.27 client code */
-       { "forwardgssapiglobusproxy", oGssDelegateCreds }, /* alias */
-       { "forwardgssapiglobuslimitedproxy", oGssGlobusDelegateLimitedCreds },
-#endif /* GSI */
-#endif /* GSSAPI */
-#if defined(AFS) || defined(KRB5)
-       { "kerberostgtpassing", oKerberosTgtPassing },
-#endif
-#ifdef AFS
-       { "afstokenpassing", oAFSTokenPassing },
+       { "gssapitrustdns", oGssTrustDns },
+#else
+       { "gssapiauthentication", oUnsupported },
+       { "gssapikeyexchange", oUnsupported },
+       { "gssapidelegatecredentials", oUnsupported },
+       { "gssapitrustdns", oUnsupported },
 #endif
        { "fallbacktorsh", oDeprecated },
        { "usersh", oDeprecated },
        { "identityfile", oIdentityFile },
        { "identityfile2", oIdentityFile },                     /* alias */
 #endif
        { "fallbacktorsh", oDeprecated },
        { "usersh", oDeprecated },
        { "identityfile", oIdentityFile },
        { "identityfile2", oIdentityFile },                     /* alias */
+       { "identitiesonly", oIdentitiesOnly },
        { "hostname", oHostName },
        { "hostkeyalias", oHostKeyAlias },
        { "proxycommand", oProxyCommand },
        { "hostname", oHostName },
        { "hostkeyalias", oHostKeyAlias },
        { "proxycommand", oProxyCommand },
@@ -193,17 +204,42 @@ static struct {
        { "stricthostkeychecking", oStrictHostKeyChecking },
        { "compression", oCompression },
        { "compressionlevel", oCompressionLevel },
        { "stricthostkeychecking", oStrictHostKeyChecking },
        { "compression", oCompression },
        { "compressionlevel", oCompressionLevel },
-       { "keepalive", oKeepAlives },
+       { "tcpkeepalive", oTCPKeepAlive },
+       { "keepalive", oTCPKeepAlive },                         /* obsolete */
        { "numberofpasswordprompts", oNumberOfPasswordPrompts },
        { "loglevel", oLogLevel },
        { "dynamicforward", oDynamicForward },
        { "preferredauthentications", oPreferredAuthentications },
        { "hostkeyalgorithms", oHostKeyAlgorithms },
        { "bindaddress", oBindAddress },
        { "numberofpasswordprompts", oNumberOfPasswordPrompts },
        { "loglevel", oLogLevel },
        { "dynamicforward", oDynamicForward },
        { "preferredauthentications", oPreferredAuthentications },
        { "hostkeyalgorithms", oHostKeyAlgorithms },
        { "bindaddress", oBindAddress },
+#ifdef SMARTCARD
        { "smartcarddevice", oSmartcardDevice },
        { "smartcarddevice", oSmartcardDevice },
+#else
+       { "smartcarddevice", oUnsupported },
+#endif
        { "clearallforwardings", oClearAllForwardings },
        { "enablesshkeysign", oEnableSSHKeysign },
        { "clearallforwardings", oClearAllForwardings },
        { "enablesshkeysign", oEnableSSHKeysign },
+       { "verifyhostkeydns", oVerifyHostKeyDNS },
        { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
        { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
+       { "rekeylimit", oRekeyLimit },
+       { "connecttimeout", oConnectTimeout },
+       { "addressfamily", oAddressFamily },
+       { "serveraliveinterval", oServerAliveInterval },
+       { "serveralivecountmax", oServerAliveCountMax },
+       { "sendenv", oSendEnv },
+       { "controlpath", oControlPath },
+       { "controlmaster", oControlMaster },
+       { "hashknownhosts", oHashKnownHosts },
+       { "tunnel", oTunnel },
+       { "tunneldevice", oTunnelDevice },
+       { "localcommand", oLocalCommand },
+       { "permitlocalcommand", oPermitLocalCommand },
+        { "noneenabled", oNoneEnabled },
+        { "tcprcvbufpoll", oTcpRcvBufPoll },
+        { "tcprcvbuf", oTcpRcvBuf },
+        { "noneswitch", oNoneSwitch },
+       { "hpndisabled", oHPNDisabled },
+       { "hpnbuffersize", oHPNBufferSize },
        { NULL, oBadOption }
 };
 
        { NULL, oBadOption }
 };
 
@@ -213,21 +249,23 @@ static struct {
  */
 
 void
  */
 
 void
-add_local_forward(Options *options, u_short port, const char *host,
-                 u_short host_port)
+add_local_forward(Options *options, const Forward *newfwd)
 {
        Forward *fwd;
 #ifndef NO_IPPORT_RESERVED_CONCEPT
        extern uid_t original_real_uid;
 {
        Forward *fwd;
 #ifndef NO_IPPORT_RESERVED_CONCEPT
        extern uid_t original_real_uid;
-       if (port < IPPORT_RESERVED && original_real_uid != 0)
+       if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0)
                fatal("Privileged ports can only be forwarded by root.");
 #endif
        if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
                fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
        fwd = &options->local_forwards[options->num_local_forwards++];
                fatal("Privileged ports can only be forwarded by root.");
 #endif
        if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
                fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
        fwd = &options->local_forwards[options->num_local_forwards++];
-       fwd->port = port;
-       fwd->host = xstrdup(host);
-       fwd->host_port = host_port;
+
+       fwd->listen_host = (newfwd->listen_host == NULL) ?
+           NULL : xstrdup(newfwd->listen_host);
+       fwd->listen_port = newfwd->listen_port;
+       fwd->connect_host = xstrdup(newfwd->connect_host);
+       fwd->connect_port = newfwd->connect_port;
 }
 
 /*
 }
 
 /*
@@ -236,17 +274,19 @@ add_local_forward(Options *options, u_short port, const char *host,
  */
 
 void
  */
 
 void
-add_remote_forward(Options *options, u_short port, const char *host,
-                  u_short host_port)
+add_remote_forward(Options *options, const Forward *newfwd)
 {
        Forward *fwd;
        if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
                fatal("Too many remote forwards (max %d).",
                    SSH_MAX_FORWARDS_PER_DIRECTION);
        fwd = &options->remote_forwards[options->num_remote_forwards++];
 {
        Forward *fwd;
        if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
                fatal("Too many remote forwards (max %d).",
                    SSH_MAX_FORWARDS_PER_DIRECTION);
        fwd = &options->remote_forwards[options->num_remote_forwards++];
-       fwd->port = port;
-       fwd->host = xstrdup(host);
-       fwd->host_port = host_port;
+
+       fwd->listen_host = (newfwd->listen_host == NULL) ?
+           NULL : xstrdup(newfwd->listen_host);
+       fwd->listen_port = newfwd->listen_port;
+       fwd->connect_host = xstrdup(newfwd->connect_host);
+       fwd->connect_port = newfwd->connect_port;
 }
 
 static void
 }
 
 static void
@@ -254,12 +294,19 @@ clear_forwardings(Options *options)
 {
        int i;
 
 {
        int i;
 
-       for (i = 0; i < options->num_local_forwards; i++)
-               xfree(options->local_forwards[i].host);
+       for (i = 0; i < options->num_local_forwards; i++) {
+               if (options->local_forwards[i].listen_host != NULL)
+                       xfree(options->local_forwards[i].listen_host);
+               xfree(options->local_forwards[i].connect_host);
+       }
        options->num_local_forwards = 0;
        options->num_local_forwards = 0;
-       for (i = 0; i < options->num_remote_forwards; i++)
-               xfree(options->remote_forwards[i].host);
+       for (i = 0; i < options->num_remote_forwards; i++) {
+               if (options->remote_forwards[i].listen_host != NULL)
+                       xfree(options->remote_forwards[i].listen_host);
+               xfree(options->remote_forwards[i].connect_host);
+       }
        options->num_remote_forwards = 0;
        options->num_remote_forwards = 0;
+       options->tun_open = SSH_TUNMODE_NO;
 }
 
 /*
 }
 
 /*
@@ -291,15 +338,23 @@ process_config_line(Options *options, const char *host,
                    char *line, const char *filename, int linenum,
                    int *activep)
 {
                    char *line, const char *filename, int linenum,
                    int *activep)
 {
-       char buf[256], *s, **charptr, *endofnumber, *keyword, *arg;
-       int opcode, *intptr, value;
+       char *s, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256];
+       int opcode, *intptr, value, value2, scale;
+       long long orig, val64;
        size_t len;
        size_t len;
-       u_short fwd_port, fwd_host_port;
-       char sfwd_host_port[6];
+       Forward fwd;
+
+       /* Strip trailing whitespace */
+       for (len = strlen(line) - 1; len > 0; len--) {
+               if (strchr(WHITESPACE, line[len]) == NULL)
+                       break;
+               line[len] = '\0';
+       }
 
        s = line;
        /* Get the keyword. (Each line is supposed to begin with a keyword). */
 
        s = line;
        /* Get the keyword. (Each line is supposed to begin with a keyword). */
-       keyword = strdelim(&s);
+       if ((keyword = strdelim(&s)) == NULL)
+               return 0;
        /* Ignore leading whitespace. */
        if (*keyword == '\0')
                keyword = strdelim(&s);
        /* Ignore leading whitespace. */
        if (*keyword == '\0')
                keyword = strdelim(&s);
@@ -313,6 +368,20 @@ process_config_line(Options *options, const char *host,
                /* don't panic, but count bad options */
                return -1;
                /* NOTREACHED */
                /* don't panic, but count bad options */
                return -1;
                /* NOTREACHED */
+       case oConnectTimeout:
+               intptr = &options->connection_timeout;
+parse_time:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing time value.",
+                           filename, linenum);
+               if ((value = convtime(arg)) == -1)
+                       fatal("%s line %d: invalid time value.",
+                           filename, linenum);
+               if (*intptr == -1)
+                       *intptr = value;
+               break;
+
        case oForwardAgent:
                intptr = &options->forward_agent;
 parse_flag:
        case oForwardAgent:
                intptr = &options->forward_agent;
 parse_flag:
@@ -334,16 +403,20 @@ parse_flag:
                intptr = &options->forward_x11;
                goto parse_flag;
 
                intptr = &options->forward_x11;
                goto parse_flag;
 
+       case oForwardX11Trusted:
+               intptr = &options->forward_x11_trusted;
+               goto parse_flag;
+
        case oGatewayPorts:
                intptr = &options->gateway_ports;
                goto parse_flag;
 
        case oGatewayPorts:
                intptr = &options->gateway_ports;
                goto parse_flag;
 
-       case oUsePrivilegedPort:
-               intptr = &options->use_privileged_port;
+       case oExitOnForwardFailure:
+               intptr = &options->exit_on_forward_failure;
                goto parse_flag;
 
                goto parse_flag;
 
-       case oRhostsAuthentication:
-               intptr = &options->rhosts_authentication;
+       case oUsePrivilegedPort:
+               intptr = &options->use_privileged_port;
                goto parse_flag;
 
        case oPasswordAuthentication:
                goto parse_flag;
 
        case oPasswordAuthentication:
@@ -377,16 +450,11 @@ parse_flag:
        case oChallengeResponseAuthentication:
                intptr = &options->challenge_response_authentication;
                goto parse_flag;
        case oChallengeResponseAuthentication:
                intptr = &options->challenge_response_authentication;
                goto parse_flag;
-#if defined(KRB4) || defined(KRB5)
-       case oKerberosAuthentication:
-               intptr = &options->kerberos_authentication;
-               goto parse_flag;
-#endif
-#ifdef GSSAPI
+
        case oGssAuthentication:
                intptr = &options->gss_authentication;
                goto parse_flag;
        case oGssAuthentication:
                intptr = &options->gss_authentication;
                goto parse_flag;
-      
+
        case oGssKeyEx:
                intptr = &options->gss_keyex;
                goto parse_flag;
        case oGssKeyEx:
                intptr = &options->gss_keyex;
                goto parse_flag;
@@ -394,25 +462,11 @@ parse_flag:
        case oGssDelegateCreds:
                intptr = &options->gss_deleg_creds;
                goto parse_flag;
        case oGssDelegateCreds:
                intptr = &options->gss_deleg_creds;
                goto parse_flag;
-#ifdef GSI
-       case oGssGlobusDelegateLimitedCreds:
-               intptr = &options->gss_globus_deleg_limited_proxy;
-               goto parse_flag;
-#endif /* GSI */
-
-#endif /* GSSAPI */
 
 
-#if defined(AFS) || defined(KRB5)
-       case oKerberosTgtPassing:
-               intptr = &options->kerberos_tgt_passing;
+       case oGssTrustDns:
+               intptr = &options->gss_trust_dns;
                goto parse_flag;
                goto parse_flag;
-#endif
-#ifdef AFS
-       case oAFSTokenPassing:
-               intptr = &options->afs_token_passing;
-               goto parse_flag;
-#endif
+
        case oBatchMode:
                intptr = &options->batch_mode;
                goto parse_flag;
        case oBatchMode:
                intptr = &options->batch_mode;
                goto parse_flag;
@@ -421,8 +475,34 @@ parse_flag:
                intptr = &options->check_host_ip;
                goto parse_flag;
 
                intptr = &options->check_host_ip;
                goto parse_flag;
 
+       case oNoneEnabled:
+               intptr = &options->none_enabled;
+               goto parse_flag;
+
+       case oNoneSwitch:
+               intptr = &options->none_switch;
+               goto parse_flag;
+
+       case oHPNDisabled:
+               intptr = &options->hpn_disabled;
+               goto parse_flag;
+
+       case oHPNBufferSize:
+               intptr = &options->hpn_buffer_size;
+               goto parse_int;
+
+       case oTcpRcvBufPoll:
+               intptr = &options->tcp_rcv_buf_poll;
+               goto parse_flag;
+
+       case oVerifyHostKeyDNS:
+               intptr = &options->verify_host_key_dns;
+               goto parse_yesnoask;
+
+
        case oStrictHostKeyChecking:
                intptr = &options->strict_host_key_checking;
        case oStrictHostKeyChecking:
                intptr = &options->strict_host_key_checking;
+parse_yesnoask:
                arg = strdelim(&s);
                if (!arg || *arg == '\0')
                        fatal("%.200s line %d: Missing yes/no/ask argument.",
                arg = strdelim(&s);
                if (!arg || *arg == '\0')
                        fatal("%.200s line %d: Missing yes/no/ask argument.",
@@ -444,8 +524,8 @@ parse_flag:
                intptr = &options->compression;
                goto parse_flag;
 
                intptr = &options->compression;
                goto parse_flag;
 
-       case oKeepAlives:
-               intptr = &options->keepalives;
+       case oTCPKeepAlive:
+               intptr = &options->tcp_keep_alive;
                goto parse_flag;
 
        case oNoHostAuthenticationForLocalhost:
                goto parse_flag;
 
        case oNoHostAuthenticationForLocalhost:
@@ -460,6 +540,45 @@ parse_flag:
                intptr = &options->compression_level;
                goto parse_int;
 
                intptr = &options->compression_level;
                goto parse_int;
 
+       case oRekeyLimit:
+               intptr = &options->rekey_limit;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (arg[0] < '0' || arg[0] > '9')
+                       fatal("%.200s line %d: Bad number.", filename, linenum);
+               orig = val64 = strtoll(arg, &endofnumber, 10);
+               if (arg == endofnumber)
+                       fatal("%.200s line %d: Bad number.", filename, linenum);
+               switch (toupper(*endofnumber)) {
+               case '\0':
+                       scale = 1;
+                       break;
+               case 'K':
+                       scale = 1<<10;
+                       break;
+               case 'M':
+                       scale = 1<<20;
+                       break;
+               case 'G':
+                       scale = 1<<30;
+                       break;
+               default:
+                       fatal("%.200s line %d: Invalid RekeyLimit suffix",
+                           filename, linenum);
+               }
+               val64 *= scale;
+               /* detect integer wrap and too-large limits */
+               if ((val64 / scale) != orig || val64 > INT_MAX)
+                       fatal("%.200s line %d: RekeyLimit too large",
+                           filename, linenum);
+               if (val64 < 16)
+                       fatal("%.200s line %d: RekeyLimit too small",
+                           filename, linenum);
+               if (*activep && *intptr == -1)
+                       *intptr = (int)val64;
+               break;
+
        case oIdentityFile:
                arg = strdelim(&s);
                if (!arg || *arg == '\0')
        case oIdentityFile:
                arg = strdelim(&s);
                if (!arg || *arg == '\0')
@@ -527,6 +646,9 @@ parse_string:
 
        case oProxyCommand:
                charptr = &options->proxy_command;
 
        case oProxyCommand:
                charptr = &options->proxy_command;
+parse_command:
+               if (s == NULL)
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
                len = strspn(s, WHITESPACE "=");
                if (*activep && *charptr == NULL)
                        *charptr = xstrdup(s + len);
                len = strspn(s, WHITESPACE "=");
                if (*activep && *charptr == NULL)
                        *charptr = xstrdup(s + len);
@@ -553,6 +675,10 @@ parse_int:
                intptr = &options->connection_attempts;
                goto parse_int;
 
                intptr = &options->connection_attempts;
                goto parse_int;
 
+       case oTcpRcvBuf:
+               intptr = &options->tcp_rcv_buf;
+               goto parse_int;
+
        case oCipher:
                intptr = &options->cipher;
                arg = strdelim(&s);
        case oCipher:
                intptr = &options->cipher;
                arg = strdelim(&s);
@@ -626,30 +752,26 @@ parse_int:
        case oLocalForward:
        case oRemoteForward:
                arg = strdelim(&s);
        case oLocalForward:
        case oRemoteForward:
                arg = strdelim(&s);
-               if (!arg || *arg == '\0')
+               if (arg == NULL || *arg == '\0')
                        fatal("%.200s line %d: Missing port argument.",
                            filename, linenum);
                        fatal("%.200s line %d: Missing port argument.",
                            filename, linenum);
-               if ((fwd_port = a2port(arg)) == 0)
-                       fatal("%.200s line %d: Bad listen port.",
-                           filename, linenum);
-               arg = strdelim(&s);
-               if (!arg || *arg == '\0')
-                       fatal("%.200s line %d: Missing second argument.",
+               arg2 = strdelim(&s);
+               if (arg2 == NULL || *arg2 == '\0')
+                       fatal("%.200s line %d: Missing target argument.",
                            filename, linenum);
                            filename, linenum);
-               if (sscanf(arg, "%255[^:]:%5[0-9]", buf, sfwd_host_port) != 2 &&
-                   sscanf(arg, "%255[^/]/%5[0-9]", buf, sfwd_host_port) != 2)
+
+               /* construct a string for parse_forward */
+               snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
+
+               if (parse_forward(&fwd, fwdarg) == 0)
                        fatal("%.200s line %d: Bad forwarding specification.",
                            filename, linenum);
                        fatal("%.200s line %d: Bad forwarding specification.",
                            filename, linenum);
-               if ((fwd_host_port = a2port(sfwd_host_port)) == 0)
-                       fatal("%.200s line %d: Bad forwarding port.",
-                           filename, linenum);
+
                if (*activep) {
                        if (opcode == oLocalForward)
                if (*activep) {
                        if (opcode == oLocalForward)
-                               add_local_forward(options, fwd_port, buf,
-                                   fwd_host_port);
+                               add_local_forward(options, &fwd);
                        else if (opcode == oRemoteForward)
                        else if (opcode == oRemoteForward)
-                               add_remote_forward(options, fwd_port, buf,
-                                   fwd_host_port);
+                               add_remote_forward(options, &fwd);
                }
                break;
 
                }
                break;
 
@@ -658,12 +780,25 @@ parse_int:
                if (!arg || *arg == '\0')
                        fatal("%.200s line %d: Missing port argument.",
                            filename, linenum);
                if (!arg || *arg == '\0')
                        fatal("%.200s line %d: Missing port argument.",
                            filename, linenum);
-               fwd_port = a2port(arg);
-               if (fwd_port == 0)
+               memset(&fwd, '\0', sizeof(fwd));
+               fwd.connect_host = "socks";
+               fwd.listen_host = hpdelim(&arg);
+               if (fwd.listen_host == NULL ||
+                   strlen(fwd.listen_host) >= NI_MAXHOST)
+                       fatal("%.200s line %d: Bad forwarding specification.",
+                           filename, linenum);
+               if (arg) {
+                       fwd.listen_port = a2port(arg);
+                       fwd.listen_host = cleanhostname(fwd.listen_host);
+               } else {
+                       fwd.listen_port = a2port(fwd.listen_host);
+                       fwd.listen_host = NULL;
+               }
+               if (fwd.listen_port == 0)
                        fatal("%.200s line %d: Badly formatted port number.",
                            filename, linenum);
                if (*activep)
                        fatal("%.200s line %d: Badly formatted port number.",
                            filename, linenum);
                if (*activep)
-                       add_local_forward(options, fwd_port, "socks4", 0);
+                       add_local_forward(options, &fwd);
                break;
 
        case oClearAllForwardings:
                break;
 
        case oClearAllForwardings:
@@ -703,15 +838,140 @@ parse_int:
                        *intptr = value;
                break;
 
                        *intptr = value;
                break;
 
+       case oAddressFamily:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing address family.",
+                           filename, linenum);
+               intptr = &options->address_family;
+               if (strcasecmp(arg, "inet") == 0)
+                       value = AF_INET;
+               else if (strcasecmp(arg, "inet6") == 0)
+                       value = AF_INET6;
+               else if (strcasecmp(arg, "any") == 0)
+                       value = AF_UNSPEC;
+               else
+                       fatal("Unsupported AddressFamily \"%s\"", arg);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
        case oEnableSSHKeysign:
                intptr = &options->enable_ssh_keysign;
                goto parse_flag;
 
        case oEnableSSHKeysign:
                intptr = &options->enable_ssh_keysign;
                goto parse_flag;
 
+       case oIdentitiesOnly:
+               intptr = &options->identities_only;
+               goto parse_flag;
+
+       case oServerAliveInterval:
+               intptr = &options->server_alive_interval;
+               goto parse_time;
+
+       case oServerAliveCountMax:
+               intptr = &options->server_alive_count_max;
+               goto parse_int;
+
+       case oSendEnv:
+               while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+                       if (strchr(arg, '=') != NULL)
+                               fatal("%s line %d: Invalid environment name.",
+                                   filename, linenum);
+                       if (!*activep)
+                               continue;
+                       if (options->num_send_env >= MAX_SEND_ENV)
+                               fatal("%s line %d: too many send env.",
+                                   filename, linenum);
+                       options->send_env[options->num_send_env++] =
+                           xstrdup(arg);
+               }
+               break;
+
+       case oControlPath:
+               charptr = &options->control_path;
+               goto parse_string;
+
+       case oControlMaster:
+               intptr = &options->control_master;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing ControlMaster argument.",
+                           filename, linenum);
+               value = 0;      /* To avoid compiler warning... */
+               if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
+                       value = SSHCTL_MASTER_YES;
+               else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
+                       value = SSHCTL_MASTER_NO;
+               else if (strcmp(arg, "auto") == 0)
+                       value = SSHCTL_MASTER_AUTO;
+               else if (strcmp(arg, "ask") == 0)
+                       value = SSHCTL_MASTER_ASK;
+               else if (strcmp(arg, "autoask") == 0)
+                       value = SSHCTL_MASTER_AUTO_ASK;
+               else
+                       fatal("%.200s line %d: Bad ControlMaster argument.",
+                           filename, linenum);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oHashKnownHosts:
+               intptr = &options->hash_known_hosts;
+               goto parse_flag;
+
+       case oTunnel:
+               intptr = &options->tun_open;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing yes/point-to-point/"
+                           "ethernet/no argument.", filename, linenum);
+               value = 0;      /* silence compiler */
+               if (strcasecmp(arg, "ethernet") == 0)
+                       value = SSH_TUNMODE_ETHERNET;
+               else if (strcasecmp(arg, "point-to-point") == 0)
+                       value = SSH_TUNMODE_POINTOPOINT;
+               else if (strcasecmp(arg, "yes") == 0)
+                       value = SSH_TUNMODE_DEFAULT;
+               else if (strcasecmp(arg, "no") == 0)
+                       value = SSH_TUNMODE_NO;
+               else
+                       fatal("%s line %d: Bad yes/point-to-point/ethernet/"
+                           "no argument: %s", filename, linenum, arg);
+               if (*activep)
+                       *intptr = value;
+               break;
+
+       case oTunnelDevice:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               value = a2tun(arg, &value2);
+               if (value == SSH_TUNID_ERR)
+                       fatal("%.200s line %d: Bad tun device.", filename, linenum);
+               if (*activep) {
+                       options->tun_local = value;
+                       options->tun_remote = value2;
+               }
+               break;
+
+       case oLocalCommand:
+               charptr = &options->local_command;
+               goto parse_command;
+
+       case oPermitLocalCommand:
+               intptr = &options->permit_local_command;
+               goto parse_flag;
+
        case oDeprecated:
                debug("%s line %d: Deprecated option \"%s\"",
                    filename, linenum, keyword);
                return 0;
 
        case oDeprecated:
                debug("%s line %d: Deprecated option \"%s\"",
                    filename, linenum, keyword);
                return 0;
 
+       case oUnsupported:
+               error("%s line %d: Unsupported option \"%s\"",
+                   filename, linenum, keyword);
+               return 0;
+
        default:
                fatal("process_config_line: Unimplemented opcode %d", opcode);
        }
        default:
                fatal("process_config_line: Unimplemented opcode %d", opcode);
        }
@@ -719,7 +979,7 @@ parse_int:
        /* Check that there is no garbage at end of line. */
        if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
                fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
        /* Check that there is no garbage at end of line. */
        if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
                fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
-                    filename, linenum, arg);
+                   filename, linenum, arg);
        }
        return 0;
 }
        }
        return 0;
 }
@@ -732,7 +992,8 @@ parse_int:
  */
 
 int
  */
 
 int
-read_config_file(const char *filename, const char *host, Options *options)
+read_config_file(const char *filename, const char *host, Options *options,
+    int checkperm)
 {
        FILE *f;
        char line[1024];
 {
        FILE *f;
        char line[1024];
@@ -740,10 +1001,19 @@ read_config_file(const char *filename, const char *host, Options *options)
        int bad_options = 0;
 
        /* Open the file. */
        int bad_options = 0;
 
        /* Open the file. */
-       f = fopen(filename, "r");
-       if (!f)
+       if ((f = fopen(filename, "r")) == NULL)
                return 0;
 
                return 0;
 
+       if (checkperm) {
+               struct stat sb;
+
+               if (fstat(fileno(f), &sb) == -1)
+                       fatal("fstat %s: %s", filename, strerror(errno));
+               if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
+                   (sb.st_mode & 022) != 0))
+                       fatal("Bad owner or permissions on %s", filename);
+       }
+
        debug("Reading configuration data %.200s", filename);
 
        /*
        debug("Reading configuration data %.200s", filename);
 
        /*
@@ -778,31 +1048,18 @@ initialize_options(Options * options)
        memset(options, 'X', sizeof(*options));
        options->forward_agent = -1;
        options->forward_x11 = -1;
        memset(options, 'X', sizeof(*options));
        options->forward_agent = -1;
        options->forward_x11 = -1;
+       options->forward_x11_trusted = -1;
+       options->exit_on_forward_failure = -1;
        options->xauth_location = NULL;
        options->gateway_ports = -1;
        options->use_privileged_port = -1;
        options->xauth_location = NULL;
        options->gateway_ports = -1;
        options->use_privileged_port = -1;
-       options->rhosts_authentication = -1;
        options->rsa_authentication = -1;
        options->pubkey_authentication = -1;
        options->challenge_response_authentication = -1;
        options->rsa_authentication = -1;
        options->pubkey_authentication = -1;
        options->challenge_response_authentication = -1;
-#ifdef GSSAPI
-        options->gss_authentication = -1;
+       options->gss_authentication = -1;
        options->gss_keyex = -1;
        options->gss_keyex = -1;
-        options->gss_deleg_creds = -1;
-#ifdef GSI
-        options->gss_globus_deleg_limited_proxy = -1;
-#endif /* GSI */
-#endif /* GSSAPI */
-
-#if defined(KRB4) || defined(KRB5)
-       options->kerberos_authentication = -1;
-#endif
-#if defined(AFS) || defined(KRB5)
-       options->kerberos_tgt_passing = -1;
-#endif
-#ifdef AFS
-       options->afs_token_passing = -1;
-#endif
+       options->gss_deleg_creds = -1;
+       options->gss_trust_dns = -1;
        options->password_authentication = -1;
        options->kbd_interactive_authentication = -1;
        options->kbd_interactive_devices = NULL;
        options->password_authentication = -1;
        options->kbd_interactive_authentication = -1;
        options->kbd_interactive_devices = NULL;
@@ -812,10 +1069,12 @@ initialize_options(Options * options)
        options->check_host_ip = -1;
        options->strict_host_key_checking = -1;
        options->compression = -1;
        options->check_host_ip = -1;
        options->strict_host_key_checking = -1;
        options->compression = -1;
-       options->keepalives = -1;
+       options->tcp_keep_alive = -1;
        options->compression_level = -1;
        options->port = -1;
        options->compression_level = -1;
        options->port = -1;
+       options->address_family = -1;
        options->connection_attempts = -1;
        options->connection_attempts = -1;
+       options->connection_timeout = -1;
        options->number_of_password_prompts = -1;
        options->cipher = -1;
        options->ciphers = NULL;
        options->number_of_password_prompts = -1;
        options->cipher = -1;
        options->ciphers = NULL;
@@ -841,6 +1100,26 @@ initialize_options(Options * options)
        options->smartcard_device = NULL;
        options->enable_ssh_keysign = - 1;
        options->no_host_authentication_for_localhost = - 1;
        options->smartcard_device = NULL;
        options->enable_ssh_keysign = - 1;
        options->no_host_authentication_for_localhost = - 1;
+       options->identities_only = - 1;
+       options->rekey_limit = - 1;
+       options->verify_host_key_dns = -1;
+       options->server_alive_interval = -1;
+       options->server_alive_count_max = -1;
+       options->num_send_env = 0;
+       options->control_path = NULL;
+       options->control_master = -1;
+       options->hash_known_hosts = -1;
+       options->tun_open = -1;
+       options->tun_local = -1;
+       options->tun_remote = -1;
+       options->local_command = NULL;
+       options->permit_local_command = -1;
+       options->none_switch = -1;
+       options->none_enabled = -1;
+       options->hpn_disabled = -1;
+       options->hpn_buffer_size = -1;
+       options->tcp_rcv_buf_poll = -1;
+       options->tcp_rcv_buf = -1;
 }
 
 /*
 }
 
 /*
@@ -857,44 +1136,30 @@ fill_default_options(Options * options)
                options->forward_agent = 0;
        if (options->forward_x11 == -1)
                options->forward_x11 = 0;
                options->forward_agent = 0;
        if (options->forward_x11 == -1)
                options->forward_x11 = 0;
+       if (options->forward_x11_trusted == -1)
+               options->forward_x11_trusted = 0;
+       if (options->exit_on_forward_failure == -1)
+               options->exit_on_forward_failure = 0;
        if (options->xauth_location == NULL)
                options->xauth_location = _PATH_XAUTH;
        if (options->gateway_ports == -1)
                options->gateway_ports = 0;
        if (options->use_privileged_port == -1)
                options->use_privileged_port = 0;
        if (options->xauth_location == NULL)
                options->xauth_location = _PATH_XAUTH;
        if (options->gateway_ports == -1)
                options->gateway_ports = 0;
        if (options->use_privileged_port == -1)
                options->use_privileged_port = 0;
-       if (options->rhosts_authentication == -1)
-               options->rhosts_authentication = 0;
        if (options->rsa_authentication == -1)
                options->rsa_authentication = 1;
        if (options->pubkey_authentication == -1)
                options->pubkey_authentication = 1;
        if (options->challenge_response_authentication == -1)
                options->challenge_response_authentication = 1;
        if (options->rsa_authentication == -1)
                options->rsa_authentication = 1;
        if (options->pubkey_authentication == -1)
                options->pubkey_authentication = 1;
        if (options->challenge_response_authentication == -1)
                options->challenge_response_authentication = 1;
-#ifdef GSSAPI
        if (options->gss_authentication == -1)
                options->gss_authentication = 1;
        if (options->gss_keyex == -1)
                options->gss_keyex = 1;
        if (options->gss_deleg_creds == -1)
                options->gss_deleg_creds = 1;
        if (options->gss_authentication == -1)
                options->gss_authentication = 1;
        if (options->gss_keyex == -1)
                options->gss_keyex = 1;
        if (options->gss_deleg_creds == -1)
                options->gss_deleg_creds = 1;
-#ifdef GSI
-       if (options->gss_globus_deleg_limited_proxy == -1)
-               options->gss_globus_deleg_limited_proxy = 0;
-#endif /* GSI */
-#endif /* GSSAPI */
-#if defined(KRB4) || defined(KRB5)
-       if (options->kerberos_authentication == -1)
-               options->kerberos_authentication = 1;
-#endif
-#if defined(AFS) || defined(KRB5)
-       if (options->kerberos_tgt_passing == -1)
-               options->kerberos_tgt_passing = 1;
-#endif
-#ifdef AFS
-       if (options->afs_token_passing == -1)
-               options->afs_token_passing = 1;
-#endif
+       if (options->gss_trust_dns == -1)
+               options->gss_trust_dns = 1;
        if (options->password_authentication == -1)
                options->password_authentication = 1;
        if (options->kbd_interactive_authentication == -1)
        if (options->password_authentication == -1)
                options->password_authentication = 1;
        if (options->kbd_interactive_authentication == -1)
@@ -911,12 +1176,14 @@ fill_default_options(Options * options)
                options->strict_host_key_checking = 2;  /* 2 is default */
        if (options->compression == -1)
                options->compression = 0;
                options->strict_host_key_checking = 2;  /* 2 is default */
        if (options->compression == -1)
                options->compression = 0;
-       if (options->keepalives == -1)
-               options->keepalives = 1;
+       if (options->tcp_keep_alive == -1)
+               options->tcp_keep_alive = 1;
        if (options->compression_level == -1)
                options->compression_level = 6;
        if (options->port == -1)
                options->port = 0;      /* Filled in ssh_connect. */
        if (options->compression_level == -1)
                options->compression_level = 6;
        if (options->port == -1)
                options->port = 0;      /* Filled in ssh_connect. */
+       if (options->address_family == -1)
+               options->address_family = AF_UNSPEC;
        if (options->connection_attempts == -1)
                options->connection_attempts = 1;
        if (options->number_of_password_prompts == -1)
        if (options->connection_attempts == -1)
                options->connection_attempts = 1;
        if (options->number_of_password_prompts == -1)
@@ -967,11 +1234,120 @@ fill_default_options(Options * options)
                clear_forwardings(options);
        if (options->no_host_authentication_for_localhost == - 1)
                options->no_host_authentication_for_localhost = 0;
                clear_forwardings(options);
        if (options->no_host_authentication_for_localhost == - 1)
                options->no_host_authentication_for_localhost = 0;
+       if (options->identities_only == -1)
+               options->identities_only = 0;
        if (options->enable_ssh_keysign == -1)
                options->enable_ssh_keysign = 0;
        if (options->enable_ssh_keysign == -1)
                options->enable_ssh_keysign = 0;
+       if (options->rekey_limit == -1)
+               options->rekey_limit = 0;
+       if (options->verify_host_key_dns == -1)
+               options->verify_host_key_dns = 0;
+       if (options->server_alive_interval == -1)
+               options->server_alive_interval = 0;
+       if (options->server_alive_count_max == -1)
+               options->server_alive_count_max = 3;
+       if (options->none_switch == -1)
+               options->none_switch = 0;
+       if (options->hpn_disabled == -1)
+               options->hpn_disabled = 0;
+       if (options->hpn_buffer_size > -1)
+       {
+               if (options->hpn_buffer_size == 0)
+               options->hpn_buffer_size = 1;
+               /*limit the buffer to 7MB*/
+                       if (options->hpn_buffer_size > 7168)
+               {
+                       options->hpn_buffer_size = 7168;
+                       debug("User requested buffer larger than 7MB. Request reverted to 7MB");
+               }
+               options->hpn_buffer_size *=1024;
+               debug("hpn_buffer_size set to %d", options->hpn_buffer_size);
+       }
+       if (options->tcp_rcv_buf == 0)
+               options->tcp_rcv_buf = 1;
+       if (options->tcp_rcv_buf > -1) 
+               options->tcp_rcv_buf *=1024;
+       if (options->control_master == -1)
+               options->control_master = 0;
+       if (options->hash_known_hosts == -1)
+               options->hash_known_hosts = 0;
+       if (options->tun_open == -1)
+               options->tun_open = SSH_TUNMODE_NO;
+       if (options->tun_local == -1)
+               options->tun_local = SSH_TUNID_ANY;
+       if (options->tun_remote == -1)
+               options->tun_remote = SSH_TUNID_ANY;
+       if (options->permit_local_command == -1)
+               options->permit_local_command = 0;
+       /* options->local_command should not be set by default */
        /* options->proxy_command should not be set by default */
        /* options->user will be set in the main program if appropriate */
        /* options->hostname will be set in the main program if appropriate */
        /* options->host_key_alias should not be set by default */
        /* options->preferred_authentications will be set in ssh */
 }
        /* options->proxy_command should not be set by default */
        /* options->user will be set in the main program if appropriate */
        /* options->hostname will be set in the main program if appropriate */
        /* options->host_key_alias should not be set by default */
        /* options->preferred_authentications will be set in ssh */
 }
+
+/*
+ * parse_forward
+ * parses a string containing a port forwarding specification of the form:
+ *     [listenhost:]listenport:connecthost:connectport
+ * returns number of arguments parsed or zero on error
+ */
+int
+parse_forward(Forward *fwd, const char *fwdspec)
+{
+       int i;
+       char *p, *cp, *fwdarg[4];
+
+       memset(fwd, '\0', sizeof(*fwd));
+
+       cp = p = xstrdup(fwdspec);
+
+       /* skip leading spaces */
+       while (*cp && isspace(*cp))
+               cp++;
+
+       for (i = 0; i < 4; ++i)
+               if ((fwdarg[i] = hpdelim(&cp)) == NULL)
+                       break;
+
+       /* Check for trailing garbage in 4-arg case*/
+       if (cp != NULL)
+               i = 0;  /* failure */
+
+       switch (i) {
+       case 3:
+               fwd->listen_host = NULL;
+               fwd->listen_port = a2port(fwdarg[0]);
+               fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
+               fwd->connect_port = a2port(fwdarg[2]);
+               break;
+
+       case 4:
+               fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
+               fwd->listen_port = a2port(fwdarg[1]);
+               fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
+               fwd->connect_port = a2port(fwdarg[3]);
+               break;
+       default:
+               i = 0; /* failure */
+       }
+
+       xfree(p);
+
+       if (fwd->listen_port == 0 && fwd->connect_port == 0)
+               goto fail_free;
+
+       if (fwd->connect_host != NULL &&
+           strlen(fwd->connect_host) >= NI_MAXHOST)
+               goto fail_free;
+
+       return (i);
+
+ fail_free:
+       if (fwd->connect_host != NULL)
+               xfree(fwd->connect_host);
+       if (fwd->listen_host != NULL)
+               xfree(fwd->listen_host);
+       return (0);
+}
This page took 0.076584 seconds and 4 git commands to generate.