Pārlūkot izejas kodu

HPCC-9663 Dynamically start/stop scope scans

Currently, to enable or disable scope scans, the admin has to bring down Dali,
modify the configuration file, and restart dali. This is awkward, and can
cause production to be down resulting in lost revenue.
This change allows scope scan status to be queried, and allows it to be
enabled/disabled dynamically by sending a new request from ESP to Dali in
response to the admin clicking a new button on the permissions page of ECLWatch.
If the configured Dali is downlevel (a version that does not support this feature)
then the button is not displayed

Signed-off-by: William Whitehead <william.whitehead@lexisnexis.com>
William Whitehead 12 gadi atpakaļ
vecāks
revīzija
be8f3268ee

+ 1 - 2
dali/base/dacoven.cpp

@@ -37,7 +37,7 @@ extern void closedownDFS();
 // base is saved in store whenever block exhausted, so replacement coven servers can restart 
 
 // server side versioning.
-#define ServerVersion    "3.9"
+#define ServerVersion    "3.10"
 #define MinClientVersion "1.5"
 
 
@@ -327,7 +327,6 @@ public:
         if (comm)
             comm->cancel(srcrank,tag);
     }
-
 };
 
 

+ 0 - 1
dali/base/dacoven.hpp

@@ -50,7 +50,6 @@ interface ICoven: extends ICommunicator // ICoven can be used to communicate wit
     virtual rank_t          chooseServer(DALI_UID uid, int tag=0)=0;    // choose a server deterministically based on UID and tag
 
     inline ICommunicator &queryComm() { return *this; }
-
 };
 
 class da_decl CDaliVersion

+ 204 - 2
dali/base/dasess.cpp

@@ -85,6 +85,8 @@ interface ISessionManagerServer: implements IConnectionMonitor
     virtual void start() = 0;
     virtual void ready() = 0;
     virtual void stop() = 0;
+    virtual bool queryScopeScansEnabled(IUserDescriptor *udesc, int * err, StringBuffer &retMsg) = 0;
+    virtual bool enableScopeScans(IUserDescriptor *udesc, bool enable, int * err, StringBuffer &retMsg) = 0;
 };
 
 
@@ -366,7 +368,53 @@ enum MSessionRequestKind {
     MSR_IMPORT_CAPABILITIES,
     MSR_LOOKUP_LDAP_PERMISSIONS,
     MSR_CLEAR_PERMISSIONS_CACHE,
-    MSR_EXIT // TBD
+    MSR_EXIT, // TBD
+    MSR_QUERY_SCOPE_SCANS_ENABLED,
+    MSR_ENABLE_SCOPE_SCANS
+};
+
+class CQueryScopeScansEnabledReq : implements IMessageWrapper
+{
+public:
+    bool enabled;
+    Linked<IUserDescriptor> udesc;
+
+    CQueryScopeScansEnabledReq(IUserDescriptor *_udesc) : udesc(_udesc) {}
+    CQueryScopeScansEnabledReq() {}
+
+    void serializeReq(CMessageBuffer &mb)
+    {
+        mb.append(MSR_QUERY_SCOPE_SCANS_ENABLED);
+        udesc->serialize(mb);
+    }
+
+    void deserializeReq(CMessageBuffer &mb)
+    {
+        udesc.setown(createUserDescriptor(mb));
+    }
+};
+
+class CEnableScopeScansReq : implements IMessageWrapper
+{
+public:
+    bool doEnable;
+    Linked<IUserDescriptor> udesc;
+
+    CEnableScopeScansReq(IUserDescriptor *_udesc, bool _doEnable) : udesc(_udesc), doEnable(_doEnable) {}
+    CEnableScopeScansReq() {}
+
+    void serializeReq(CMessageBuffer &mb)
+    {
+        mb.append(MSR_ENABLE_SCOPE_SCANS);
+        udesc->serialize(mb);
+        mb.append(doEnable);
+    }
+
+    void deserializeReq(CMessageBuffer &mb)
+    {
+        udesc.setown(createUserDescriptor(mb));
+        mb.read(doEnable);
+    }
 };
 
 class CSessionRequestServer: public Thread
@@ -537,6 +585,41 @@ public:
                 coven.reply(mb);
             }
             break;
+        case MSR_QUERY_SCOPE_SCANS_ENABLED:{
+                CQueryScopeScansEnabledReq req;
+                req.deserializeReq(mb);
+                int err;
+                StringBuffer retMsg;
+                bool enabled = manager.queryScopeScansEnabled(req.udesc, &err, retMsg);
+                mb.clear().append(err);
+                mb.append(enabled);
+                mb.append(retMsg.str());
+                if (err != 0 || retMsg.length())
+                {
+                    StringBuffer user;
+                    req.udesc->getUserName(user);
+                    DBGLOG("Error %d querying scope scan status for %s : %s", err, user.str(), retMsg.str());
+                }
+                coven.reply(mb);
+            }
+            break;
+        case MSR_ENABLE_SCOPE_SCANS:{
+                CEnableScopeScansReq req;
+                req.deserializeReq(mb);
+                int err;
+                StringBuffer retMsg;
+                bool ok = manager.enableScopeScans(req.udesc, req.doEnable, &err, retMsg);
+                mb.clear().append(err);
+                mb.append(retMsg.str());
+                if (err != 0 || retMsg.length())
+                {
+                    StringBuffer user;
+                    req.udesc->getUserName(user);
+                    DBGLOG("Error %d %sing Scope Scan Status for %s: %s", err, req.doEnable?"Enabl":"Disabl", user.str(), retMsg.str());
+                }
+                coven.reply(mb);
+            }
+            break;
         }
     }
 
@@ -823,6 +906,89 @@ public:
         udesc->serialize(mb);
         return queryCoven().sendRecv(mb,RANK_RANDOM,MPTAG_DALI_SESSION_REQUEST,SESSIONREPLYTIMEOUT);
     }
+
+    bool queryScopeScansEnabled(IUserDescriptor *udesc, int * err, StringBuffer &retMsg)
+    {
+        if (queryDaliServerVersion().compare("3.10") < 0)
+        {
+            *err = -1;
+            StringBuffer ver;
+            queryDaliServerVersion().toString(ver);
+            retMsg.appendf("Scope Scan status feature requires Dali V3.10 or newer, current Dali version %s",ver.str());
+            return false;
+        }
+        if (securitydisabled)
+        {
+            *err = -1;
+            retMsg.append("Security not enabled");
+            return false;
+        }
+        if (queryDaliServerVersion().compare("1.8") < 0) {
+            *err = -1;
+            retMsg.append("Security not enabled");
+            securitydisabled = true;
+            return false;
+        }
+        CMessageBuffer mb;
+        CQueryScopeScansEnabledReq req(udesc);
+        req.serializeReq(mb);
+        if (!queryCoven().sendRecv(mb,RANK_RANDOM,MPTAG_DALI_SESSION_REQUEST,SESSIONREPLYTIMEOUT))
+        {
+            *err = -1;
+            retMsg.append("DALI Send/Recv error");
+            return false;
+        }
+        int rc;
+        bool enabled;
+        mb.read(rc).read(enabled).read(retMsg);
+        *err = rc;
+        return enabled;
+    }
+
+    bool enableScopeScans(IUserDescriptor *udesc, bool enable, int * err, StringBuffer &retMsg)
+    {
+        if (queryDaliServerVersion().compare("3.10") < 0)
+        {
+            *err = -1;
+            StringBuffer ver;
+            queryDaliServerVersion().toString(ver);
+            retMsg.appendf("Scope Scan enable/disable feature requires Dali V3.10 or newer, current Dali version %s",ver.str());
+            return false;
+        }
+
+        if (securitydisabled)
+        {
+            *err = -1;
+            retMsg.append("Security not enabled");
+            return false;
+        }
+        if (queryDaliServerVersion().compare("1.8") < 0) {
+            *err = -1;
+            retMsg.append("Security not enabled");
+            securitydisabled = true;
+            return false;
+        }
+        CMessageBuffer mb;
+        CEnableScopeScansReq req(udesc,enable);
+        req.serializeReq(mb);
+        if (!queryCoven().sendRecv(mb,RANK_RANDOM,MPTAG_DALI_SESSION_REQUEST,SESSIONREPLYTIMEOUT))
+        {
+            *err = -1;
+            retMsg.append("DALI Send/Recv error");
+            return false;
+        }
+        int rc;
+        mb.read(rc).read(retMsg);
+        *err = rc;
+        if (rc == 0)
+        {
+            StringBuffer user;
+            udesc->getUserName(user);
+            DBGLOG("Scope Scans %sabled by %s",enable ? "En" : "Dis", user.str());
+        }
+        return rc == 0;
+    }
+
     bool checkScopeScansLDAP()
     {
         assertex(!"checkScopeScansLDAP called on client");
@@ -1299,6 +1465,37 @@ public:
 #endif
         return ok;
     }
+
+    virtual bool queryScopeScansEnabled(IUserDescriptor *udesc, int * err, StringBuffer &retMsg)
+    {
+#ifdef _NO_LDAP
+        *err = -1;
+        retMsg.append("LDAP not enabled");
+        return false;
+#else
+        *err = 0;
+        return checkScopeScansLDAP();
+#endif
+    }
+
+    virtual bool enableScopeScans(IUserDescriptor *udesc, bool enable, int * err, StringBuffer &retMsg)
+    {
+#ifdef _NO_LDAP
+        *err = -1;
+        retMsg.append("LDAP not supporteded");
+        return false;
+#else
+        if (!ldapconn)
+        {
+            *err = -1;
+            retMsg.append("LDAP not connected");
+            return false;
+        }
+
+        return ldapconn->enableScopeScans(udesc, enable, err);
+#endif
+    }
+
     virtual bool checkScopeScansLDAP()
     {
 #ifdef _NO_LDAP
@@ -1756,7 +1953,12 @@ IUserDescriptor *createUserDescriptor()
     return new CUserDescriptor;
 }
 
-
+IUserDescriptor *createUserDescriptor(MemoryBuffer &mb)
+{
+    IUserDescriptor * udesc = createUserDescriptor();
+    udesc->deserialize(mb);
+    return udesc;
+}
 
 MODULE_INIT(INIT_PRIORITY_DALI_DASESS)
 {

+ 9 - 2
dali/base/dasess.hpp

@@ -78,6 +78,7 @@ interface IUserDescriptor: extends serializable
 };
 
 extern da_decl IUserDescriptor *createUserDescriptor();
+extern da_decl IUserDescriptor *createUserDescriptor(MemoryBuffer &mb);
 
 const static IUserDescriptor * unknownUser = NULL;//use of this should be avoided
 #define UNKNOWN_USER (IUserDescriptor*)unknownUser
@@ -111,7 +112,8 @@ interface ISessionManager: extends IInterface
     virtual unsigned getLDAPflags()=0;
     virtual void setLDAPflags(unsigned flags)=0;
     virtual bool clearPermissionsCache(IUserDescriptor *udesc)=0;
-
+    virtual bool queryScopeScansEnabled(IUserDescriptor *udesc, int * err, StringBuffer &retMsg)=0;
+    virtual bool enableScopeScans(IUserDescriptor *udesc, bool enable, int * err, StringBuffer &retMsg)=0;
 };
 
 // the following are getPermissionsLDAP input flags for audit reporting
@@ -127,7 +129,12 @@ extern da_decl ISessionManager &querySessionManager();
 
 #define myProcessSession() (querySessionManager().lookupProcessSession())
 
-
+interface IMessageWrapper
+{
+public:
+    virtual void serializeReq(CMessageBuffer &mb) = 0;
+    virtual void deserializeReq(CMessageBuffer &mb) = 0;
+};
 
 // for server use
 interface IDaliServer;

+ 31 - 0
dali/server/daldap.cpp

@@ -187,6 +187,37 @@ public:
         user->credentials().setPassword(password);
         return ldapsecurity->clearPermissionsCache(*user);
     }
+
+    bool enableScopeScans(IUserDescriptor *udesc, bool enable, int * err)
+    {
+        bool superUser;
+        StringBuffer username;
+        StringBuffer password;
+        udesc->getUserName(username);
+        udesc->getPassword(password);
+        Owned<ISecUser> user = ldapsecurity->createUser(username);
+        user->credentials().setPassword(password);
+        if (!ldapsecurity->authenticateUser(*user,superUser) || !superUser)
+        {
+            *err = -1;
+            return false;
+        }
+        unsigned flags = getLDAPflags();
+        if (enable)
+        {
+            DBGLOG("Scope Scans Enabled by user %s",username.str());
+            flags |= (unsigned)DLF_SCOPESCANS;
+        }
+        else
+        {
+            DBGLOG("Scope Scans Disabled by user %s",username.str());
+            flags &= ~(unsigned)DLF_SCOPESCANS;
+        }
+        setLDAPflags(flags);
+        *err = 0;
+        return true;
+    }
+
     bool checkScopeScans()
     {
         return (ldapflags&DLF_SCOPESCANS)!=0;

+ 1 - 0
dali/server/daldap.hpp

@@ -31,6 +31,7 @@ interface IDaliLdapConnection: extends IInterface
     virtual unsigned getLDAPflags() = 0;
     virtual void setLDAPflags(unsigned flags) = 0;
     virtual bool clearPermissionsCache(IUserDescriptor *udesc) = 0;
+    virtual bool enableScopeScans(IUserDescriptor *udesc, bool enable, int *err) = 0;
 };
 
 extern IDaliLdapConnection *createDaliLdapConnection(IPropertyTree *proptree);

+ 2 - 0
esp/eclwatch/ws_XSLT/CMakeLists.txt

@@ -139,6 +139,8 @@ FOREACH ( iFILES
     ${CMAKE_CURRENT_SOURCE_DIR}/access_adduser.xslt
     ${CMAKE_CURRENT_SOURCE_DIR}/access_basedns.xslt
     ${CMAKE_CURRENT_SOURCE_DIR}/access_clearpermissionscache.xslt
+    ${CMAKE_CURRENT_SOURCE_DIR}/access_enablescopescans.xslt
+    ${CMAKE_CURRENT_SOURCE_DIR}/access_disablescopescans.xslt
     ${CMAKE_CURRENT_SOURCE_DIR}/access_filepermission.xslt
     ${CMAKE_CURRENT_SOURCE_DIR}/access_groupadd.xslt
     ${CMAKE_CURRENT_SOURCE_DIR}/access_groupdelete.xslt

+ 57 - 0
esp/eclwatch/ws_XSLT/access_disablescopescans.xslt

@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
+  <xsl:output method="html"/>
+  <xsl:template match="/">
+    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+      <head>
+        <script type="text/javascript" src="/esp/files/scripts/espdefault.js">&#160;</script>
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+        <title>Scope Scanning</title>
+      </head>
+      <body class="yui-skin-sam" onload="nof5();">
+        <xsl:apply-templates/>
+      </body>
+    </html>
+  </xsl:template>
+  
+  <xsl:template match="DisableScopeScansResponse/scopeScansStatus">
+    <table>
+      <tbody>
+        <th align="left">
+          <h2>Disable Scope Scans Result</h2>
+        </th>
+        <tr>
+          <td>
+            <xsl:choose>
+              <xsl:when test="retcode=0">
+                Scope Scans Disabled
+              </xsl:when>
+              <xsl:otherwise>
+                Scope Scans Disable failed :
+              </xsl:otherwise>
+            </xsl:choose>
+            <xsl:value-of select="retmsg"/>
+          </td>
+        </tr>
+      </tbody>
+    </table>
+    
+  </xsl:template>
+</xsl:stylesheet>

+ 57 - 0
esp/eclwatch/ws_XSLT/access_enablescopescans.xslt

@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
+  <xsl:output method="html"/>
+  <xsl:template match="/">
+    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+      <head>
+        <script type="text/javascript" src="/esp/files/scripts/espdefault.js">&#160;</script>
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+        <title>Scope Scanning</title>
+      </head>
+      <body class="yui-skin-sam" onload="nof5();">
+        <xsl:apply-templates/>
+      </body>
+    </html>
+  </xsl:template>
+  
+  <xsl:template match="EnableScopeScansResponse/scopeScansStatus">
+    <table>
+      <tbody>
+        <th align="left">
+          <h2>Enable Scope Scans Result</h2>
+        </th>
+        <tr>
+          <td>
+            <xsl:choose>
+              <xsl:when test="retcode=0">
+                Scope Scans Enabled
+              </xsl:when>
+              <xsl:otherwise>
+                Scope Scans Enable failed :
+              </xsl:otherwise>
+            </xsl:choose>
+            <xsl:value-of select="retmsg"/>
+          </td>
+        </tr>
+      </tbody>
+    </table>
+    
+  </xsl:template>
+</xsl:stylesheet>

+ 18 - 0
esp/eclwatch/ws_XSLT/access_resources.xslt

@@ -193,6 +193,24 @@
                   <input id="clearPermissionsCacheBtn" class="sbutton" type="submit" name="action" value="Clear Permissions Cache" onclick="return confirm('Are you sure you want to clear the DALI and ESP permissions caches? Running workunit performance might degrade significantly until the caches have been refreshed.')"/>
                 </form>
             </td>
+
+            <xsl:if test="scopeScansStatus/retcode=0">
+              <xsl:if test="scopeScansStatus/isEnabled=0">
+                <td>
+                  <form action="/ws_access/EnableScopeScans">
+                    <input id="EnableScopeScansBtn" class="sbutton" type="submit"  name="action" value="Enable Scope Scans" onclick="return confirm('Are you sure you want to enable Scope Scans?')"/>
+                  </form>
+                </td>
+              </xsl:if>
+              <xsl:if test="scopeScansStatus/isEnabled=1">
+                <td>
+                  <form action="/ws_access/DisableScopeScans">
+                    <input id="DisableScopeScansBtn" class="sbutton" type="submit"  name="action" value="Disable Scope Scans" onclick="return confirm('Are you sure you want to disable Scope Scans?')"/>
+                  </form>
+                </td>
+              </xsl:if>
+            </xsl:if>
+
                 </tr>
             </table>
       <form action="/ws_access/ResourceAddInput" id="addform">

+ 40 - 1
esp/scm/ws_access.ecm

@@ -362,6 +362,13 @@ ESPstruct Resource
     bool isSpecial;
 };
 
+ESPstruct ScopeScanStatusStruct
+{
+    bool    isEnabled;
+    int     retcode;
+    string  retmsg;
+};
+
 ESPresponse ResourcesResponse
 {
     string basedn;
@@ -373,6 +380,7 @@ ESPresponse ResourcesResponse
     string default_name;
     string prefix;
     [min_ver("1.05")] bool toomany;
+    [min_ver("1.08")] ESPstruct ScopeScanStatusStruct scopeScansStatus;
 };
 
 ESPrequest ResourceAddInputRequest
@@ -561,6 +569,34 @@ ESPresponse ClearPermissionsCacheResponse
 {
     int retcode;
 };
+
+ESPrequest QueryScopeScansEnabledRequest
+{
+};
+
+ESPresponse QueryScopeScansEnabledResponse
+{
+    [min_ver("1.08")] ESPstruct ScopeScanStatusStruct scopeScansStatus;
+};
+
+ESPrequest EnableScopeScansRequest
+{
+};
+
+ESPresponse EnableScopeScansResponse
+{
+    [min_ver("1.08")] ESPstruct ScopeScanStatusStruct scopeScansStatus;
+};
+
+ESPrequest DisableScopeScansRequest
+{
+};
+
+ESPresponse DisableScopeScansResponse
+{
+    [min_ver("1.08")] ESPstruct ScopeScanStatusStruct scopeScansStatus;
+};
+
 ESPrequest PermissionActionRequest
 {
     string basedn;
@@ -655,7 +691,7 @@ ESPresponse [nil_remove] UserAccountExportResponse
 };
 
 
-ESPservice [version("1.07"), default_client_version("1.07"), exceptions_inline("./smc_xslt/exceptions.xslt")] ws_access
+ESPservice [version("1.08"), default_client_version("1.08"), exceptions_inline("./smc_xslt/exceptions.xslt")] ws_access
 {
     ESPmethod [client_xslt("/esp/xslt/access_users.xslt")] Users(UserRequest, UserResponse);
     ESPmethod [client_xslt("/esp/xslt/access_useredit.xslt")] UserEdit(UserEditRequest, UserEditResponse);
@@ -690,6 +726,9 @@ ESPservice [version("1.07"), default_client_version("1.07"), exceptions_inline("
     ESPmethod [client_xslt("/esp/xslt/access_permissionresetinput.xslt")] PermissionsResetInput(PermissionsResetInputRequest, PermissionsResetInputResponse);
     ESPmethod [client_xslt("/esp/xslt/access_permissionsreset.xslt")] PermissionsReset(PermissionsResetRequest, PermissionsResetResponse);
     ESPmethod [client_xslt("/esp/xslt/access_clearpermissionscache.xslt")] ClearPermissionsCache(ClearPermissionsCacheRequest, ClearPermissionsCacheResponse);
+    ESPmethod QueryScopeScansEnabled(QueryScopeScansEnabledRequest, QueryScopeScansEnabledResponse);
+    ESPmethod [client_xslt("/esp/xslt/access_enablescopescans.xslt")] EnableScopeScans(EnableScopeScansRequest, EnableScopeScansResponse);
+    ESPmethod [client_xslt("/esp/xslt/access_disablescopescans.xslt")] DisableScopeScans(DisableScopeScansRequest, DisableScopeScansResponse);
     //ESPmethod [client_xslt("/esp/xslt/access_useraccountexport.xslt")] UserAccountExport(UserAccountExportRequest, UserAccountExportResponse);
     ESPmethod UserAccountExport(UserAccountExportRequest, UserAccountExportResponse);
 

+ 72 - 0
esp/services/ws_access/ws_accessService.cpp

@@ -1436,6 +1436,20 @@ bool Cws_accessEx::onResources(IEspContext &context, IEspResourcesRequest &req,
 
             rarray.append(*oneresource.getLink());
         }
+        if (version >= 1.08)
+        {
+            Owned<IUserDescriptor> userdesc;
+            userdesc.setown(createUserDescriptor());
+            userdesc->set(context.queryUserId(), context.queryPassword());
+            int retCode;
+            StringBuffer retMsg;
+            bool isEnabled = querySessionManager().queryScopeScansEnabled(userdesc, &retCode, retMsg);
+            if (retCode != 0)
+                DBGLOG("Error %d querying scope scan status : %s", retCode, retMsg.str());
+            resp.updateScopeScansStatus().setIsEnabled(isEnabled);
+            resp.updateScopeScansStatus().setRetcode(retCode);
+            resp.updateScopeScansStatus().setRetmsg(retMsg.str());
+        }
         resp.setResources(rarray);
     }
     catch(IException* e)
@@ -1918,6 +1932,64 @@ bool Cws_accessEx::onClearPermissionsCache(IEspContext &context, IEspClearPermis
     resp.setRetcode(ok ? 0 : -1);
     return true;
 }
+
+bool Cws_accessEx::onQueryScopeScansEnabled(IEspContext &context, IEspQueryScopeScansEnabledRequest &req, IEspQueryScopeScansEnabledResponse &resp)
+{
+    ISecManager* secmgr = context.querySecManager();
+    if(secmgr == NULL)
+        throw MakeStringException(ECLWATCH_INVALID_SEC_MANAGER, MSG_SEC_MANAGER_IS_NULL);
+
+    Owned<IUserDescriptor> userdesc;
+    userdesc.setown(createUserDescriptor());
+    userdesc->set(context.queryUserId(), context.queryPassword());
+    int retCode;
+    StringBuffer retMsg;
+    bool isEnabled = querySessionManager().queryScopeScansEnabled(userdesc, &retCode, retMsg);
+    if (retCode != 0)
+        throw MakeStringException(ECLWATCH_OLD_CLIENT_VERSION, "Error %d querying scope scan status : %s", retCode, retMsg.str());
+    resp.updateScopeScansStatus().setIsEnabled(isEnabled);
+    resp.updateScopeScansStatus().setRetcode(retCode);
+    resp.updateScopeScansStatus().setRetmsg(retMsg.str());
+    return true;
+
+}
+
+bool Cws_accessEx::onEnableScopeScans(IEspContext &context, IEspEnableScopeScansRequest &req, IEspEnableScopeScansResponse &resp)
+{
+    StringBuffer retMsg;
+    int rc = enableDisableScopeScans(context, true, retMsg);
+    resp.updateScopeScansStatus().setIsEnabled(rc == 0);
+    resp.updateScopeScansStatus().setRetcode(rc);
+    resp.updateScopeScansStatus().setRetmsg(retMsg.str());
+    return true;
+}
+
+bool Cws_accessEx::onDisableScopeScans(IEspContext &context, IEspDisableScopeScansRequest &req, IEspDisableScopeScansResponse &resp)
+{
+    StringBuffer retMsg;
+    int rc = enableDisableScopeScans(context, false, retMsg);
+    resp.updateScopeScansStatus().setIsEnabled(rc != 0);
+    resp.updateScopeScansStatus().setRetcode(rc);
+    resp.updateScopeScansStatus().setRetmsg(retMsg.str());
+    return true;
+}
+
+int Cws_accessEx::enableDisableScopeScans(IEspContext &context, bool doEnable, StringBuffer &retMsg)
+{
+    ISecManager* secmgr = context.querySecManager();
+    if(secmgr == NULL)
+        throw MakeStringException(ECLWATCH_INVALID_SEC_MANAGER, MSG_SEC_MANAGER_IS_NULL);
+
+    Owned<IUserDescriptor> userdesc;
+    userdesc.setown(createUserDescriptor());
+    userdesc->set(context.queryUserId(), context.queryPassword());
+    int retCode;
+    bool rc = querySessionManager().enableScopeScans(userdesc, doEnable, &retCode, retMsg);
+    if (!rc || retCode != 0)
+        DBGLOG("Error %d enabling Scope Scans : %s", retCode, retMsg.str());
+    return retCode;
+}
+
 bool Cws_accessEx::permissionsReset(CLdapSecManager* ldapsecmgr, const char* basedn, const char* rtype0, const char* prefix,
         const char* resourceName, ACT_TYPE accountType, const char* accountName,
         bool allow_access, bool allow_read, bool allow_write, bool allow_full,

+ 4 - 0
esp/services/ws_access/ws_accessService.hpp

@@ -77,6 +77,7 @@ class Cws_accessEx : public Cws_access
         bool deny_access, bool deny_read, bool deny_write, bool deny_full);
     void getBaseDNsForAddingPermssionToAccount(CLdapSecManager* secmgr, const char* prefix, const char* accountName, 
         int accountType, StringArray& basednNames);
+    int enableDisableScopeScans(IEspContext &context, bool doEnable, StringBuffer &retMsg);
 
 public:
     IMPLEMENT_IINTERFACE;
@@ -117,6 +118,9 @@ public:
     virtual bool onPermissionsReset(IEspContext &context, IEspPermissionsResetRequest &req, IEspPermissionsResetResponse &resp);
     virtual bool onUserAccountExport(IEspContext &context, IEspUserAccountExportRequest &req, IEspUserAccountExportResponse &resp);
     virtual bool onClearPermissionsCache(IEspContext &context, IEspClearPermissionsCacheRequest &req, IEspClearPermissionsCacheResponse &resp);
+    virtual bool onQueryScopeScansEnabled(IEspContext &context, IEspQueryScopeScansEnabledRequest &req, IEspQueryScopeScansEnabledResponse &resp);
+    virtual bool onEnableScopeScans(IEspContext &context, IEspEnableScopeScansRequest &req, IEspEnableScopeScansResponse &resp);
+    virtual bool onDisableScopeScans(IEspContext &context, IEspDisableScopeScansRequest &req, IEspDisableScopeScansResponse &resp);
 };
 
 #endif //_ESPWIZ_ws_access_HPP__

+ 7 - 0
system/security/LdapSecurity/ldapsecurity.cpp

@@ -1273,6 +1273,13 @@ bool CLdapSecManager::clearPermissionsCache(ISecUser& user)
     }
     return true;
 }
+bool CLdapSecManager::authenticateUser(ISecUser & user, bool &superUser)
+{
+    if (!authenticate(&user))
+        return false;
+    superUser = isSuperUser(&user);
+    return true;
+}
 
 extern "C"
 {

+ 1 - 0
system/security/LdapSecurity/ldapsecurity.ipp

@@ -441,6 +441,7 @@ public:
     virtual aindex_t getManagedFileScopes(IArrayOf<ISecResource>& scopes);
     virtual int queryDefaultPermission(ISecUser& user);
     virtual bool clearPermissionsCache(ISecUser &user);
+    virtual bool authenticateUser(ISecUser & user, bool &superUser);
 };
 
 #endif

+ 1 - 0
system/security/shared/basesecurity.hpp

@@ -288,6 +288,7 @@ public:
     virtual aindex_t getManagedFileScopes(IArrayOf<ISecResource>& scopes) {UNIMPLEMENTED; }
     virtual int queryDefaultPermission(ISecUser& user) {UNIMPLEMENTED; }
     virtual bool clearPermissionsCache(ISecUser& user) {return false;}
+    virtual bool authenticateUser(ISecUser & user, bool &superUser) {return false;}
 protected:
     const char* getServer(){return m_dbserver.toCharArray();}
     const char* getUser(){return m_dbuser.toCharArray();}

+ 1 - 0
system/security/shared/seclib.hpp

@@ -299,6 +299,7 @@ interface ISecManager : extends IInterface
     virtual aindex_t getManagedFileScopes(IArrayOf<ISecResource>& scopes) = 0;
     virtual int queryDefaultPermission(ISecUser& user) = 0;
     virtual bool clearPermissionsCache(ISecUser & user) = 0;
+    virtual bool authenticateUser(ISecUser & user, bool &superUser) = 0;
 };
 
 interface IExtSecurityManager