Browse Source

Merge pull request #10277 from mckellyln/hpcc-18007

HPCC-18007 Dfuplus spray to dafilesrv with SSLFirst problem

Reviewed-By: Anthony Fishbeck <anthony.fishbeck@lexisnexis.com>
Reviewed-By: Jake Smith <jake.smith@lexisnexis.com>
Reviewed-By: Richard Chapman <rchapman@hpccsystems.com>
Richard Chapman 7 years ago
parent
commit
579d9270b3

+ 7 - 8
common/remote/rmtfile.cpp

@@ -308,27 +308,26 @@ public:
     }
 } *DaliServixIntercept = NULL;
 
-bool testDaliServixPresent(const SocketEndpoint &_ep)
+unsigned short getActiveDaliServixPort(const IpAddress &ip)
 {
-    SocketEndpoint ep(_ep);
+    if (ip.isNull())
+        return 0;
+    SocketEndpoint ep(0, ip);
     setDafsEndpointPort(ep);
-    if (ep.isNull())
-        return false;
     try {
         Owned<ISocket> socket = connectDafs(ep, 10000);
-        return true;
+        return ep.port;
     }
     catch (IException *e)
     {
         e->Release();
     }
-    return false;
+    return 0;
 }
 
 bool testDaliServixPresent(const IpAddress &ip)
 {
-    SocketEndpoint ep(0,ip);
-    return testDaliServixPresent(ep);
+    return getActiveDaliServixPort(ip) != 0;
 }
 
 unsigned getDaliServixVersion(const SocketEndpoint &_ep,StringBuffer &ver)

+ 1 - 1
common/remote/rmtfile.hpp

@@ -54,7 +54,7 @@ extern REMOTE_API void setDaliServixSocketCaching(bool set);
 extern REMOTE_API bool canAccessDirectly(const RemoteFilename & file);
 extern REMOTE_API IFile *createDaliServixFile(const RemoteFilename & file);
 extern REMOTE_API bool testDaliServixPresent(const IpAddress &ip);
-extern REMOTE_API bool testDaliServixPresent(const SocketEndpoint &ep);
+extern REMOTE_API unsigned short getActiveDaliServixPort(const IpAddress &ip);
 extern REMOTE_API unsigned getDaliServixVersion(const IpAddress &ip,StringBuffer &ver);
 extern REMOTE_API unsigned getDaliServixVersion(const SocketEndpoint &ep,StringBuffer &ver);
 extern REMOTE_API DAFS_OS getDaliServixOs(const SocketEndpoint &ep);

+ 76 - 31
common/remote/sockfile.cpp

@@ -1042,7 +1042,7 @@ class CRemoteBase: public CInterface
                         ssock.setown(createSecureSocket(socket.getClear(), ClientSocket));
                         int status = ssock->secure_connect();
                         if (status < 0)
-                            throw MakeStringException(-1, "Failure to establish secure connection");
+                            throw createDafsException(DAFSERR_connection_failed, "Failure to establish secure connection");
                         socket.setown(ssock.getLink());
                     }
                     catch (IException *e)
@@ -2701,13 +2701,26 @@ ISocket *checkSocketSecure(ISocket *socket)
 
     if ( (pport == securitySettings.daFileSrvSSLPort) && (!socket->isSecure()) )
     {
-        Owned<ISecureSocket> ssock;
 #ifdef _USE_OPENSSL
-        ssock.setown(createSecureSocket(LINK(socket), ClientSocket));
-        int status = ssock->secure_connect();
-        if (status < 0)
-            throw createDafsException(DAFSERR_connection_failed,"Failure to establish secure connection");
-        return ssock.getClear();
+        Owned<ISecureSocket> ssock;
+        try
+        {
+            ssock.setown(createSecureSocket(LINK(socket), ClientSocket));
+            int status = ssock->secure_connect();
+            if (status < 0)
+                throw createDafsException(DAFSERR_connection_failed, "Failure to establish secure connection");
+            return ssock.getClear();
+        }
+        catch (IException *e)
+        {
+            cleanupSocket(ssock);
+            ssock.clear();
+            cleanupSocket(socket);
+            StringBuffer eMsg;
+            e->errorMessage(eMsg);
+            e->Release();
+            throw createDafsException(DAFSERR_connection_failed, eMsg.str());
+        }
 #else
         throw createDafsException(DAFSERR_connection_failed,"Failure to establish secure connection: OpenSSL disabled in build");
 #endif
@@ -2723,42 +2736,74 @@ ISocket *connectDafs(SocketEndpoint &ep, unsigned timeoutms)
     if ( (securitySettings.connectMethod == SSLNone) || (securitySettings.connectMethod == SSLOnly) )
     {
         socket.setown(ISocket::connect_timeout(ep, timeoutms));
-        return socket.getClear();
+        return checkSocketSecure(socket);
     }
 
+    // SSLFirst or UnsecureFirst ...
+
     unsigned newtimeout = timeoutms;
     if (newtimeout > 5000)
         newtimeout = 5000;
 
-    bool tryAgain = false;
-    try
+    int conAttempts = 2;
+    while (conAttempts > 0)
     {
-        socket.setown(ISocket::connect_timeout(ep, newtimeout));
-    }
-    catch (IJSOCK_Exception *e)
-    {
-        if (e->errorCode() == JSOCKERR_connection_failed)
+        conAttempts--;
+        bool connected = false;
+        try
+        {
+            socket.setown(ISocket::connect_timeout(ep, newtimeout));
+            connected = true;
+            newtimeout = timeoutms;
+        }
+        catch (IJSOCK_Exception *e)
+        {
+            if (e->errorCode() == JSOCKERR_connection_failed)
+            {
+                e->Release();
+                if (ep.port == securitySettings.daFileSrvSSLPort)
+                    ep.port = securitySettings.daFileSrvPort;
+                else
+                    ep.port = securitySettings.daFileSrvSSLPort;
+                if (!conAttempts)
+                    throw;
+            }
+            else
+                throw;
+        }
+
+        if (connected)
         {
-            unsigned prevPort = ep.port;
-            if (prevPort == securitySettings.daFileSrvSSLPort)
-                ep.port = securitySettings.daFileSrvPort;
+            if (ep.port == securitySettings.daFileSrvSSLPort)
+            {
+                try
+                {
+                    return checkSocketSecure(socket);
+                }
+                catch (IDAFS_Exception *e)
+                {
+                    connected = false;
+                    if (e->errorCode() == DAFSERR_connection_failed)
+                    {
+                        // worth logging to help identify any ssl config issues ...
+                        StringBuffer errmsg;
+                        e->errorMessage(errmsg);
+                        WARNLOG("%s", errmsg.str());
+                        e->Release();
+                        ep.port = securitySettings.daFileSrvPort;
+                        if (!conAttempts)
+                            throw;
+                    }
+                    else
+                        throw;
+                }
+            }
             else
-                ep.port = securitySettings.daFileSrvSSLPort;
-            WARNLOG("Connect failed on port %d, retrying on port %d", prevPort, ep.port);
-            tryAgain = true;
-            e->Release();
+                return socket.getClear();
         }
-        else
-            throw e;
     }
 
-    if (tryAgain)
-        socket.setown(ISocket::connect_timeout(ep, timeoutms));
-
-    if (socket)
-        return checkSocketSecure(socket);
-    else
-        return nullptr;
+    throw createDafsException(DAFSERR_connection_failed, "Failed to establish connection with DaFileSrv");
 }
 
 unsigned getRemoteVersion(CRemoteFileIO &remoteFileIO, StringBuffer &ver)

+ 1 - 1
common/remote/sockfile.hpp

@@ -78,7 +78,7 @@ extern void remoteExtractBlobElements(const SocketEndpoint &ep, const char * pre
 extern int getDafsInfo(ISocket * socket, unsigned level, StringBuffer &retstr);
 extern void setDafsEndpointPort(SocketEndpoint &ep);
 extern void setDafsLocalMountRedirect(const IpAddress &ip,const char *dir,const char *mountdir);
-extern REMOTE_API ISocket *connectDafs(SocketEndpoint &ep, unsigned timeoutms);
+extern REMOTE_API ISocket *connectDafs(SocketEndpoint &ep, unsigned timeoutms); // NOTE: might alter ep.port if configured for multiple ports ...
 extern REMOTE_API ISocket *checkSocketSecure(ISocket *socket);
 
 // client only

+ 4 - 3
dali/dfuXRefLib/dfuxreflib.cpp

@@ -335,10 +335,11 @@ static unsigned short getDafsPort(const SocketEndpoint &ep,unsigned &numfails,Cr
     }
     else if (numfails>5)
         return 0;
-    if (testDaliServixPresent(ep)) 
-        return ep.port?ep.port:getDaliServixPort();
+    unsigned short nPort = getActiveDaliServixPort(ep);
+    if (nPort)
+        return nPort;
     StringBuffer err("Failed to connect to DaFileSrv on ");
-    ep.getUrlStr(err);
+    ep.getIpText(err);
 #ifdef _WIN32
     ERRLOG("%s",err.str());
     if (sect) {

+ 45 - 15
dali/dfuplus/dfuplus.cpp

@@ -116,10 +116,7 @@ bool CDfuPlusHelper::runLocalDaFileSvr(SocketEndpoint &listenep,bool requireauth
     if (!thr->ok())
         return false;
 
-    unsigned port = listenep.port;
-    if (!port)
-        port = securitySettings.queryDaliServixPort();
-
+    unsigned port = securitySettings.queryDaliServixPort();
     unsigned sslport = securitySettings.queryDaliServixSSLPort();
 
     DAFSConnectCfg connectMethod = securitySettings.queryDAFSConnectCfg();
@@ -129,14 +126,14 @@ bool CDfuPlusHelper::runLocalDaFileSvr(SocketEndpoint &listenep,bool requireauth
     if (printep.isNull())
     {
         if (connectMethod == SSLNone)
-            addlPort.appendf("%u", port);
+            addlPort.appendf("port %u", port);
         else if (connectMethod == SSLOnly)
-            addlPort.appendf("%u", sslport);
+            addlPort.appendf("port %u", sslport);
         else if (connectMethod == SSLFirst)
-            addlPort.appendf("%u:%u", sslport, port);
+            addlPort.appendf("ports %u:%u", sslport, port);
         else
-            addlPort.appendf("%u:%u", port, sslport);
-        progress("Started local Dali file server on port %s\n", addlPort.str());
+            addlPort.appendf("ports %u:%u", port, sslport);
+        progress("Started local Dali file server on %s\n", addlPort.str());
     }
     else
     {
@@ -178,17 +175,50 @@ bool CDfuPlusHelper::runLocalDaFileSvr(SocketEndpoint &listenep,bool requireauth
 
 bool CDfuPlusHelper::checkLocalDaFileSvr(const char *eps,SocketEndpoint &epout)
 {
+    unsigned port = securitySettings.queryDaliServixPort();
+    unsigned sslport = securitySettings.queryDaliServixSSLPort();
+
+    DAFSConnectCfg connectMethod = securitySettings.queryDAFSConnectCfg();
+
+    unsigned dafsPort;
+    StringBuffer addlPort;
+    if (connectMethod == SSLNone)
+    {
+        dafsPort = port;
+        addlPort.appendf("port %u", port);
+    }
+    else if (connectMethod == SSLOnly)
+    {
+        dafsPort = sslport;
+        addlPort.appendf("port %u", sslport);
+    }
+    else if (connectMethod == SSLFirst)
+    {
+        dafsPort = sslport;
+        addlPort.appendf("ports %u:%u", sslport, port);
+    }
+    else
+    {
+        dafsPort = port;
+        addlPort.appendf("ports %u:%u", port, sslport);
+    }
     if (!eps||!*eps)
-        epout.setLocalHost(securitySettings.queryDaliServixPort());
+        epout.setLocalHost(dafsPort);
     else {
-        epout.set(eps,securitySettings.queryDaliServixPort());
+        epout.set(eps,dafsPort);
         if (!epout.isLocal())
             return false;
     }
-    progress("Checking for local Dali File Server\n");
-    if (!testDaliServixPresent(epout)) // only lookup local
-        runLocalDaFileSvr(epout,false,0);
-    return true;
+    progress("Checking for local Dali File Server on %s\n", addlPort.str());
+
+    unsigned short nPort = getActiveDaliServixPort(epout);
+    if (nPort)
+    {
+        epout.port = nPort;
+        return true;
+    }
+
+    return runLocalDaFileSvr(epout,false,0);
 }
 
 #else