Selaa lähdekoodia

HPCC-14940 Limited, read-only, context information for security managers

Define IEspSecureContext interface to provide security manager plug-ins with
access to required information about the request being handled without allowing
the plug-in to affect the nature of the request. The goals of the interface
include:

 - Incur minimal overhead cost when interacting with security managers that do
   not need any information from the context. The concrete class holds a
   reference to the data it needs, and only accesses values on demand.

 - Allow each protocol to define the types of data values it supports without
   affecting the interface for existing implementations. The getProp method
   accepts any type and name values to identify a requested value.

 - Provide a uniform method to convert non-textual values to their intrinsic
   types, including checks for over- and under-flow. The interface declares and
   implements a template wrapper of getProp to support conversions. The default
   conversions are numeric, but the signature allows callers to supply custom
   converters to override or extend this behavior.

Define the TokenDeserializer class as a counterpart to the existing
TokenSerializer. This class attempts to convert a character array into a
primitive data type for which std::is_arithmetic is true.

Update the ISecManager interface to accept a pointer to IEspSecureContext for
authorization requests, and any others for which a known need exists. Update
existing security managers to accept the ISecManager changes.

Change the HTTP protocol stack to construct an HTTP-specific subclass of
IEspSecureContext, associate it with the existing IEspContext instance, and
pass it to the ISecManager instance as needed.

Signed-off-by: Tim Klemm <Tim.Klemm@lexisnexis.com>
Klemm 9 vuotta sitten
vanhempi
commit
0f24530644

+ 1 - 0
esp/bindings/SOAP/soaplib/CMakeLists.txt

@@ -37,6 +37,7 @@ set (    SRCS
          ../../http/platform/htmlpage.cpp 
          ../../http/platform/httpbinding.cpp 
          ../../http/platform/httpprot.cpp 
+         ../../http/platform/httpsecurecontext.cpp
          ../../http/platform/httpservice.cpp 
          ../../http/platform/httptransport.cpp 
          ../../http/platform/mime.cpp 

+ 3 - 2
esp/bindings/http/platform/httpbinding.cpp

@@ -45,6 +45,7 @@
 #include  "../../SOAP/Platform/soapmessage.hpp"
 #include "xmlvalidator.hpp"
 #include "xsdparser.hpp"
+#include "espsecurecontext.hpp"
 
 #define FILE_UPLOAD     "FileUploadAccess"
 
@@ -492,7 +493,7 @@ bool EspHttpBinding::basicAuth(IEspContext* ctx)
     if(rlist == NULL)
         return false;
 
-    bool authenticated = m_secmgr->authorize(*user, rlist);
+    bool authenticated = m_secmgr->authorize(*user, rlist, ctx->querySecureContext());
     if(!authenticated)
     {
         if (user->getAuthenticateStatus() == AS_PASSWORD_EXPIRED || user->getAuthenticateStatus() == AS_PASSWORD_VALID_BUT_EXPIRED)
@@ -527,7 +528,7 @@ bool EspHttpBinding::basicAuth(IEspContext* ctx)
     if(securitySettings == NULL)
         return authorized;
 
-    m_secmgr->updateSettings(*user,securitySettings);
+    m_secmgr->updateSettings(*user,securitySettings, ctx->querySecureContext());
 
     ctx->addTraceSummaryTimeStamp("basicAuth");
     return authorized;

+ 85 - 0
esp/bindings/http/platform/httpsecurecontext.cpp

@@ -0,0 +1,85 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2016 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.
+############################################################################## */
+
+#include "httpsecurecontext.hpp"
+
+class CHttpSecureContext : extends CEspBaseSecureContext
+{
+private:
+    CHttpRequest* m_request;
+
+protected:
+    IEspContext* queryContext() const
+    {
+        return (m_request ? m_request->queryContext() : NULL);
+    }
+
+public:
+    CHttpSecureContext(CHttpRequest* request)
+        : m_request(request)
+    {
+    }
+
+    virtual ~CHttpSecureContext()
+    {
+    }
+
+    virtual const char* getProtocol() const override
+    {
+        return "http";
+    }
+
+    virtual bool getProp(int type, const char* name, StringBuffer& value) override
+    {
+        bool result = false;
+
+        switch (type)
+        {
+        case HTTP_PROPERTY_TYPE_COOKIE:
+            result = getCookie(name, value);
+            break;
+        default:
+            break;
+        }
+
+        return result;
+    }
+
+private:
+    bool getCookie(const char* name, StringBuffer& value)
+    {
+        bool result = false;
+
+        if (name && *name)
+        {
+            CEspCookie* cookie = m_request->queryCookie(name);
+
+            if (cookie)
+            {
+                value.set(cookie->getValue());
+                result = true;
+            }
+        }
+
+        return result;
+    }
+};
+
+IEspSecureContext* createHttpSecureContext(CHttpRequest* request)
+{
+    return new CHttpSecureContext(request);
+}

+ 32 - 0
esp/bindings/http/platform/httpsecurecontext.hpp

@@ -0,0 +1,32 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2016 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.
+############################################################################## */
+
+#ifndef HTTPSECURECONTEXT_HPP
+#define HTTPSECURECONTEXT_HPP
+
+#include "espbasesecurecontext.hpp"
+#include "http/platform/httptransport.ipp"
+#include "esphttp.hpp"
+
+enum HttpPropertyType
+{
+    HTTP_PROPERTY_TYPE_COOKIE,
+};
+
+ESPHTTP_API IEspSecureContext* createHttpSecureContext(CHttpRequest* request);
+
+#endif // HTTPSECURECONTEXT_HPP

+ 3 - 2
esp/bindings/http/platform/httpservice.cpp

@@ -30,6 +30,7 @@
 #include "esphttp.hpp"
 
 //ESP Bindings
+#include "http/platform/httpsecurecontext.hpp"
 #include "http/platform/httpservice.hpp"
 #include "http/platform/httptransport.hpp"
 
@@ -40,8 +41,8 @@
  ***************************************************************************/
 CEspHttpServer::CEspHttpServer(ISocket& sock, bool viewConfig, int maxRequestEntityLength):m_socket(sock), m_MaxRequestEntityLength(maxRequestEntityLength)
 {
-    IEspContext* ctx = createEspContext();
     m_request.setown(new CHttpRequest(sock));
+    IEspContext* ctx = createEspContext(createHttpSecureContext(m_request.get()));
     m_request->setMaxRequestEntityLength(maxRequestEntityLength);
     m_response.setown(new CHttpResponse(sock));
     m_request->setOwnContext(ctx);
@@ -51,8 +52,8 @@ CEspHttpServer::CEspHttpServer(ISocket& sock, bool viewConfig, int maxRequestEnt
 
 CEspHttpServer::CEspHttpServer(ISocket& sock, CEspApplicationPort* apport, bool viewConfig, int maxRequestEntityLength):m_socket(sock), m_MaxRequestEntityLength(maxRequestEntityLength)
 {
-    IEspContext* ctx = createEspContext();
     m_request.setown(new CHttpRequest(sock));
+    IEspContext* ctx = createEspContext(createHttpSecureContext(m_request.get()));
     m_request->setMaxRequestEntityLength(maxRequestEntityLength);
     m_response.setown(new CHttpResponse(sock));
     m_request->setOwnContext(ctx);

+ 45 - 0
esp/platform/espbasesecurecontext.hpp

@@ -0,0 +1,45 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2016 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.
+############################################################################## */
+
+#ifndef ESPBASESECURECONTEXT_HPP
+#define ESPBASESECURECONTEXT_HPP
+
+#include "espsecurecontext.hpp"
+#include "jexcept.hpp"
+#include "esp.hpp"
+
+// Concrete implementation of IEspSecureContext interface that is abstract, with
+// subclasses required to provide access to key protocol-independent data.
+// Handles protocol-independent requests, such as accessing the TxSummary
+// instance. Requests for protocol-dependent data raise exceptions.
+class CEspBaseSecureContext : extends CInterface, implements IEspSecureContext
+{
+public:
+    IMPLEMENT_IINTERFACE;
+
+    virtual const char* getProtocol() const override { UNIMPLEMENTED; }
+
+    virtual CTxSummary* getTxSummary() const override { return (queryContext() ? queryContext()->getTxSummary() : NULL); }
+
+    virtual bool getProp(int type, const char* name, StringBuffer& value) override { UNIMPLEMENTED; }
+
+protected:
+    // Abstract method providing internal access to the full ESP context.
+    virtual IEspContext* queryContext() const = 0;
+};
+
+#endif // ESPBASESECURECONTEXT_HPP

+ 12 - 3
esp/platform/espcontext.cpp

@@ -29,6 +29,7 @@
 #include "http/platform/httptransport.ipp"
 #include "sechandler.hpp"
 #include "espprotocol.hpp"
+#include "espsecurecontext.hpp"
 
 class CEspContext : public CInterface, implements IEspContext
 {
@@ -78,10 +79,12 @@ private:
 
     ESPSerializationFormat respSerializationFormat;
 
+    Owned<IEspSecureContext> m_secureContext;
+
 public:
     IMPLEMENT_IINTERFACE;
 
-    CEspContext()
+    CEspContext(IEspSecureContext* secureContext)
     : m_servPort(0)
     , m_bindingValue(0)
     , m_serviceValue(0)
@@ -98,6 +101,8 @@ public:
     {
         m_txSummary.setown(new CTxSummary(m_creationTime));
         updateTraceSummaryHeader();
+        m_secureContext.setown(secureContext);
+        m_SecurityHandler.setSecureContext(secureContext);
     }
 
     ~CEspContext()
@@ -454,6 +459,10 @@ public:
     virtual void setResponseFormat(ESPSerializationFormat fmt){respSerializationFormat = fmt;}
 
     void updateTraceSummaryHeader();
+    IEspSecureContext* querySecureContext() override
+    {
+        return m_secureContext.get();
+    }
 };
 
 //---------------------------------------------------------
@@ -546,9 +555,9 @@ void CEspContext::updateTraceSummaryHeader()
     }
 }
 
-IEspContext* createEspContext()
+IEspContext* createEspContext(IEspSecureContext* secureContext)
 {
-    return new CEspContext;
+    return new CEspContext(secureContext);
 }
 
 bool getUrlParams(IProperties *props, StringBuffer& params)

+ 3 - 1
esp/platform/espcontext.hpp

@@ -31,7 +31,9 @@
 #include "esp.hpp"
 #include "esphttp.hpp"
 
-ESPHTTP_API IEspContext* createEspContext();
+interface IEspSecureContext;
+
+ESPHTTP_API IEspContext* createEspContext(IEspSecureContext* secureContext = NULL);
 
 // Get URL parameters (include these from Content)
 // Return: a=b&c=d format. 

+ 104 - 0
esp/platform/espsecurecontext.hpp

@@ -0,0 +1,104 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2016 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.
+############################################################################## */
+
+#ifndef ESPSECURECONTEXT_HPP
+#define ESPSECURECONTEXT_HPP
+
+#include "jiface.hpp"
+#include "tokenserialization.hpp"
+
+class CTxSummary;
+
+// Declares a protocol-independent interface to give security managers read
+// access to protocol-dependent data values. Subclasses determine the types
+// of data to which they will provide access. Callers are assumed to know
+// which data types they may request.
+//
+// For example, consider an HTTP request. A caller may need access to HTTP
+// cookies. In such a case, the caller may call getProtocol() to confirm that
+// the supported protocol is "http" and then may assume that a property type
+// of "cookie" will be supported.
+interface IEspSecureContext : extends IInterface
+{
+    // Return a protocol-specific identifier. Callers may use this value to
+    // confirm availability of required data types.
+    virtual const char* getProtocol() const = 0;
+
+    // Returns the TxSummary object to be used for a request.
+    virtual CTxSummary* getTxSummary() const = 0;
+
+    // Fetches a data value based on a given type and name. If the requested
+    // value exists it is stored in the supplied value buffer and true is
+    // returned. If the requested value does not exist, the value buffer is
+    // unchanged and false is returned.
+    //
+    // Acceptable values of the 'type' parameter are defined by protocol-
+    // specific subclasses. E.g., an HTTP specific subclass might support
+    // cookie data.
+    //
+    // Acceptable values of the 'name' parameter are dependent on the caller.
+    virtual bool getProp(int type, const char* name, StringBuffer& value) = 0;
+
+    // Implementation-independent wrapper of the abstract getProp method
+    // providing convenient access to non-string values. Non-string means
+    // numeric (including Boolean) values by default, but callers do have
+    // the option to replace the default deserializer with one capable of
+    // supporting more complex types.
+    //
+    // True is returned if the requested property exists and its value is
+    // convertible to TValue. False is returned in all other cases. The
+    // caller may request the conversion result code to understand why a
+    // request failed.
+    //
+    // Template Parameters
+    // - TValue: a type supported by of TDeserializer
+    // - TDefault[TValue]: a type from which TValue can be initialized
+    // - TDeserializer[TokenDeserializer]: a callback function, lambda, or
+    //       functor with signature:
+    //           DeserializationResult (*pfn)(const char*, TValue&)
+    template <typename TValue, typename TDefault = TValue, class TDeserializer = TokenDeserializer>
+    bool getProp(int type, const char* name, TValue& value, const TDefault dflt = TDefault(), DeserializationResult* deserializationResult = NULL, TDeserializer& deserializer = TDeserializer());
+};
+
+template <typename TValue, typename TDefault, class TDeserializer>
+inline bool IEspSecureContext::getProp(int type, const char* name, TValue& value, const TDefault dflt, DeserializationResult* deserializationResult, TDeserializer& deserializer)
+{
+    DeserializationResult result = Deserialization_UNKNOWN;
+    StringBuffer prop;
+    bool found = getProp(type, name, prop);
+
+    if (found)
+    {
+        result = deserializer(prop, value);
+        found = (Deserialization_SUCCESS == result);
+    }
+
+    if (!found)
+    {
+        value = TValue(dflt);
+    }
+
+    if (deserializationResult)
+    {
+        *deserializationResult = result;
+    }
+
+    return found;
+}
+
+#endif // ESPSECURECONTEXT_HPP
+

+ 6 - 1
esp/platform/sechandler.cpp

@@ -61,6 +61,11 @@ void SecHandler::setFeatureAuthMap(IAuthMap * map)
         m_feature_authmap.set(map);
 }
 
+void SecHandler::setSecureContext(IEspSecureContext* secureContext)
+{
+    m_secureContext.set(secureContext);
+}
+
 bool SecHandler::authorizeSecFeature(const char * pszFeatureUrl, const char* UserID, const char* CompanyID, SecAccessFlags & required_access,bool bCheckTrial,int DebitUnits, SecUserStatus & user_status)
 {
     if(m_user.get()==0)
@@ -220,7 +225,7 @@ bool SecHandler::authorizeSecReqFeatures(StringArray & features, IEspStringIntMa
     bool auth_ok = false;
     try
     {
-        auth_ok = m_secmgr->authorize(*m_user.get(), plist);
+        auth_ok = m_secmgr->authorize(*m_user.get(), plist, m_secureContext.get());
     }
     catch(IException* e)
     {

+ 3 - 1
esp/platform/sechandler.hpp

@@ -23,7 +23,7 @@
 #include "seclib.hpp"
 #include "esp.hpp"
 #include "sechandler.hpp"
-
+#include "espsecurecontext.hpp"
 
 class SecHandler : public CInterface
 {
@@ -31,6 +31,7 @@ class SecHandler : public CInterface
     Owned<ISecResourceList> m_resources;
     Owned<ISecUser> m_user;
     Owned<IAuthMap> m_feature_authmap;
+    Owned<IEspSecureContext> m_secureContext;
 private:
     bool authorizeTrial(ISecUser& user,const char* pszFeatureUrl, SecAccessFlags & required_access);
     void AuditMessage(AuditType type, const char *filterType, const char *title, const char *parms, ...) __attribute__((format(printf, 5, 6)));
@@ -52,6 +53,7 @@ public:
     void setResources(ISecResourceList* rlist);
     void setUser(ISecUser* user);
     void setFeatureAuthMap(IAuthMap * map);
+    void setSecureContext(IEspSecureContext* secureContext);
 };
 
 

+ 394 - 0
esp/platform/tokenserialization.hpp

@@ -18,7 +18,30 @@
 #ifndef TOKENSERIALIZATION_HPP
 #define TOKENSERIALIZATION_HPP
 
+#include "jlog.hpp"
 #include "jstring.hpp"
+#include <cmath>
+#include <cerrno>
+#include <limits>
+#include <type_traits>
+
+#if !defined(ERANGE)
+# define ERANGE    34    /* Math result not representable.  */
+#endif
+
+// The template methods in TokenDeserializer must be redefined by each subclass
+// to dispatch requests correctly.
+#define EXTEND_TOKENDESERIALIZER(base) \
+    template <typename TValue> \
+    DeserializationResult operator () (const char* buffer, TValue& value) \
+    { \
+        return deserialize(buffer, value); \
+    } \
+    template <typename TValue> \
+    DeserializationResult deserialize(const char* buffer, TValue& value) const \
+    { \
+        return base::deserialize(buffer, value); \
+    }
 
 class TokenSerializer
 {
@@ -51,4 +74,375 @@ public:
     }
 };
 
+enum DeserializationResult
+{
+    Deserialization_UNKNOWN = -1,  // no deserialization attempted
+    Deserialization_SUCCESS,
+    Deserialization_BAD_TYPE,      // receiving value cannot be const
+    Deserialization_UNSUPPORTED,   // receiving value type not handled
+    Deserialization_INVALID_TOKEN, // token cannot be NULL, empty, or all whitespace
+    Deserialization_NOT_A_NUMBER,  // non-numeric characters found in numeric conversion
+    Deserialization_OVERFLOW,      // number too large to be represented by receiving value
+    Deserialization_UNDERFLOW,     // number too small to be represented by receiving value
+};
+
+class TokenDeserializer
+{
+public:
+    // Convert the contents of buffer from text to the requested numeric type.
+    // The conversion fails if:
+    //  - value is a const type
+    //  - value is not a numeric type
+    //  - buffer is NULL, empty or entirely whitespace characters
+    //  - buffer contains any character not valid for the receiving type
+    //  - buffer contains a number too large for the receiving type
+    //  - buffer contains a number too small for the receiving type
+    template <typename TValue>
+    DeserializationResult deserialize(const char* buffer, TValue& value) const
+    {
+        DeserializationResult result = Deserialization_UNKNOWN;
+
+        if (std::is_const<TValue>())
+        {
+            result = Deserialization_BAD_TYPE;
+        }
+        else if (std::is_arithmetic<TValue>())
+        {
+            const char* ptr = buffer;
+
+            skipWhitespace(ptr);
+            if (!*ptr)
+            {
+                result = Deserialization_INVALID_TOKEN;
+            }
+            else
+            {
+                if (std::is_integral<TValue>())
+                {
+                    if (std::is_signed<TValue>())
+                    {
+                        result = deserializeSigned(ptr, value);
+                    }
+                    else
+                    {
+                        result = deserializeUnsigned(ptr, value);
+                    }
+                }
+                else if (std::is_floating_point<TValue>())
+                {
+                    result = deserializeFloatingPoint(ptr, value);
+                }
+            }
+        }
+        else
+        {
+            result = Deserialization_UNSUPPORTED;
+        }
+
+        logResult<TValue>(buffer, result);
+
+        return result;
+    }
+
+    // Convert the contents of buffer from text to the bool data type. The
+    // conversion fails if buffer contains any character that is not a valid
+    // Boolean representation.
+    //
+    // Supported representations:
+    //     true: "true"|"yes"|"on"|non-zero integer
+    //     false: "false"|"no"|"off"|zero
+    DeserializationResult deserialize(const char* buffer, bool& value) const
+    {
+        const char* ptr = buffer;
+        DeserializationResult result = Deserialization_UNKNOWN;
+
+        skipWhitespace(ptr);
+        if (!*ptr)
+        {
+            result = Deserialization_INVALID_TOKEN;
+        }
+        else
+        {
+            result = deserializeBool(ptr, value);
+        }
+
+        logResult<bool>(buffer, result);
+
+        return result;
+    }
+
+    // Allow an instance of this class to be used as a functor.
+    template <typename TValue>
+    DeserializationResult operator () (const char* buffer, TValue& value)
+    {
+        return deserialize(buffer, value);
+    }
+
+private:
+    DeserializationResult deserializeBool(const char* buffer, bool& value) const
+    {
+        const char* ptr = buffer;
+        bool tmp = false;
+        DeserializationResult result = Deserialization_UNKNOWN;
+
+        switch (*ptr)
+        {
+        case 't': case 'T':
+            if (memicmp(ptr + 1, "rue", 3) == 0)
+            {
+                result = Deserialization_SUCCESS;
+                tmp = true;
+                ptr += 4;
+            }
+            break;
+        case 'f': case 'F':
+            if (memicmp(ptr + 1, "alse", 4) == 0)
+            {
+                result = Deserialization_SUCCESS;
+                ptr += 5;
+            }
+            break;
+
+        case 'y': case 'Y':
+            if (memicmp(ptr + 1, "es", 2) == 0)
+            {
+                result = Deserialization_SUCCESS;
+                tmp = true;
+                ptr += 3;
+            }
+            break;
+        case 'n': case 'N':
+            if (('o' == ptr[1]) || ('O' == ptr[1]))
+            {
+                result = Deserialization_SUCCESS;
+                ptr += 2;
+            }
+            break;
+
+        case 'o': case 'O':
+            switch (ptr[1])
+            {
+            case 'n': case 'N':
+                result = Deserialization_SUCCESS;
+                tmp = true;
+                ptr += 2;
+                break;
+            case 'f': case 'F':
+                if (('f' == ptr[2]) || ('F' == ptr[2]))
+                {
+                    result = Deserialization_SUCCESS;
+                    ptr += 3;
+                }
+                break;
+            default:
+                break;
+            }
+            break;
+
+        case '0':
+        case '1':
+        case '2':
+        case '3':
+        case '4':
+        case '5':
+        case '6':
+        case '7':
+        case '8':
+        case '9':
+            result = Deserialization_SUCCESS;
+            do
+            {
+                if (*ptr != '0')
+                    tmp = true;
+            }
+            while (isdigit(*++ptr));
+            break;
+
+        default:
+            break;
+        }
+
+        if (Deserialization_SUCCESS == result && !isEmptyOrWhitespace(ptr))
+            result = Deserialization_NOT_A_NUMBER;
+        if (Deserialization_SUCCESS == result)
+            value = tmp;
+
+        return result;
+    }
+    template <typename TValue>
+    DeserializationResult deserializeSigned(const char* buffer, TValue& value) const
+    {
+        char* end = NULL;
+        long long tmp = strtoll(buffer, &end, 0);
+        DeserializationResult result = Deserialization_UNKNOWN;
+
+        if (end == buffer)
+        {
+            result = Deserialization_NOT_A_NUMBER;
+        }
+        else if (LLONG_MIN == tmp && ERANGE == errno)
+        {
+            result = Deserialization_UNDERFLOW;
+        }
+        else if (LLONG_MAX == tmp && ERANGE == errno)
+        {
+            result = Deserialization_OVERFLOW;
+        }
+        else if (!isEmptyOrWhitespace(end))
+        {
+            result = Deserialization_NOT_A_NUMBER;
+        }
+#if defined(_WIN32)
+// VS2015 generates this sign mismatch warning when TValue is unsigned, and
+// unsigned values are not process here.
+#pragma warning(suppress:4018)
+#endif
+        else if (tmp < std::numeric_limits<TValue>::min())
+        {
+            result = Deserialization_UNDERFLOW;
+        }
+#if defined(_WIN32)
+// VS2015 generates this sign mismatch warning when TValue is unsigned, and
+// unsigned values are not process here.
+#pragma warning(suppress:4018)
+#endif
+        else if (tmp > std::numeric_limits<TValue>::max())
+        {
+            result = Deserialization_OVERFLOW;
+        }
+        else
+        {
+            value = TValue(tmp);
+            result = Deserialization_SUCCESS;
+        }
+
+        return result;
+    }
+    template <typename TValue>
+    DeserializationResult deserializeUnsigned(const char* buffer, TValue& value) const
+    {
+        char* end = NULL;
+        unsigned long long tmp = strtoull(buffer, &end, 0);
+        DeserializationResult result = Deserialization_UNKNOWN;
+
+        if (end == buffer)
+        {
+            result = Deserialization_NOT_A_NUMBER;
+        }
+        else if (ULLONG_MAX == tmp && ERANGE == errno)
+        {
+            result = Deserialization_OVERFLOW;
+        }
+        else if (!isEmptyOrWhitespace(end))
+        {
+            result = Deserialization_NOT_A_NUMBER;
+        }
+        else if ('-' == buffer[0])
+        {
+            result = Deserialization_UNDERFLOW;
+        }
+#if defined(_WIN32)
+// VS2015 generates this sign mismatch warning when TValue is unsigned, and tmp
+// is always unsigned.
+#pragma warning(suppress:4018)
+#endif
+        else if (tmp > std::numeric_limits<TValue>::max())
+        {
+            result = Deserialization_OVERFLOW;
+        }
+        else
+        {
+            value = TValue(tmp);
+            result = Deserialization_SUCCESS;
+        }
+
+        return result;
+    }
+    template <typename TValue>
+    DeserializationResult deserializeFloatingPoint(const char* buffer, TValue& value) const
+    {
+        char* end = NULL;
+        long double tmp = strtold(buffer, &end);
+        DeserializationResult result = Deserialization_UNKNOWN;
+
+        if (0 == tmp && end == buffer)
+        {
+            result = Deserialization_NOT_A_NUMBER;
+        }
+        else if (0 == tmp && ERANGE == errno)
+        {
+            result = Deserialization_UNDERFLOW;
+        }
+        else if ((-HUGE_VALL == tmp || HUGE_VALL == tmp) && ERANGE == errno)
+        {
+            result = Deserialization_OVERFLOW;
+        }
+        else if (!isEmptyOrWhitespace(end))
+        {
+            result = Deserialization_NOT_A_NUMBER;
+        }
+#if defined(_WIN32)
+// VS2015 generates this warning (as an error) with unsigned integral types,
+// even though this method does not process integral types.
+#pragma warning(suppress:4146)
+#endif
+        else if (tmp < -std::numeric_limits<TValue>::max())
+        {
+            result = Deserialization_OVERFLOW;
+        }
+        else if (tmp > std::numeric_limits<TValue>::max())
+        {
+            result = Deserialization_OVERFLOW;
+        }
+        else
+        {
+            value = TValue(tmp);
+            result = Deserialization_SUCCESS;
+        }
+
+        return result;
+    }
+    template <typename TValue>
+    void logResult(const char* buffer, DeserializationResult result) const
+    {
+        bool success = false;
+        if (Deserialization_SUCCESS == result)
+#if !defined(_DEBUG)
+            return;
+#else
+            success = true;
+#endif
+
+        const char* typeStr = typeid(TValue).name();
+        const char* resultStr = NULL;
+
+        switch (result)
+        {
+        case Deserialization_UNKNOWN:       resultStr = "unknown"; break;
+        case Deserialization_SUCCESS:       resultStr = "success"; break;
+        case Deserialization_BAD_TYPE:      resultStr = "bad type"; break;
+        case Deserialization_UNSUPPORTED:   resultStr = "unsupported"; break;
+        case Deserialization_INVALID_TOKEN: resultStr = "invalid token"; break;
+        case Deserialization_NOT_A_NUMBER:  resultStr = "not a number"; break;
+        case Deserialization_OVERFLOW:      resultStr = "overflow"; break;
+        case Deserialization_UNDERFLOW:     resultStr = "underflow"; break;
+        default:                            resultStr = "unexpected"; break;
+        }
+
+        if (success)
+            DBGLOG("Result of deserializing '%s' to type '%s': %s", buffer, typeStr, resultStr);
+        else
+            ERRLOG("Result of deserializing '%s' to type '%s': %s", buffer, typeStr, resultStr);
+    }
+    bool isEmptyOrWhitespace(const char* buffer) const
+    {
+        skipWhitespace(buffer);
+        return (!*buffer);
+    }
+    void skipWhitespace(const char*& buffer) const
+    {
+        while (isspace(*buffer)) buffer++;
+    }
+};
+
 #endif // TOKENSERIALIZATION_HPP

+ 1 - 0
esp/protocols/http/CMakeLists.txt

@@ -32,6 +32,7 @@ set (    SRCS
          ../../bindings/http/platform/htmlpage.cpp 
          ../../bindings/http/platform/httpbinding.cpp 
          ../../bindings/http/platform/httpprot.cpp 
+         ../../bindings/http/platform/httpsecurecontext.cpp
          ../../bindings/http/platform/httpservice.cpp 
          ../../bindings/http/platform/httptransport.cpp 
          ../../bindings/http/platform/mime.cpp 

+ 3 - 0
esp/scm/esp.ecm

@@ -61,6 +61,7 @@ typedef enum ESPSerializationFormat_
 #define ESPCTX_ALL_ANNOTATION   0x00010000
 
 class CTxSummary;
+interface IEspSecureContext;
 
 interface IEspContext : extends IInterface
 {
@@ -155,6 +156,8 @@ interface IEspContext : extends IInterface
 
     virtual void setAcceptLanguage(const char * acceptLanguage) = 0;
     virtual StringBuffer& getAcceptLanguage(StringBuffer& acceptLanguage) = 0;
+
+    virtual IEspSecureContext* querySecureContext() = 0;
 };
 
 

+ 5 - 5
system/security/LdapSecurity/ldapsecurity.cpp

@@ -602,7 +602,7 @@ bool CLdapSecManager::authenticate(ISecUser* user)
     return ok;
 }
 
-bool CLdapSecManager::authorizeEx(SecResourceType rtype, ISecUser& sec_user, ISecResourceList * Resources)
+bool CLdapSecManager::authorizeEx(SecResourceType rtype, ISecUser& sec_user, ISecResourceList * Resources, IEspSecureContext* secureContext)
 {
     if(!authenticate(&sec_user))
     {
@@ -661,7 +661,7 @@ bool CLdapSecManager::authorizeEx(SecResourceType rtype, ISecUser& sec_user, ISe
     return rc;
 }
 
-int CLdapSecManager::authorizeEx(SecResourceType rtype, ISecUser & user, const char * resourcename)
+int CLdapSecManager::authorizeEx(SecResourceType rtype, ISecUser & user, const char * resourcename, IEspSecureContext* secureContext)
 {
     if(!resourcename || !*resourcename)
         return SecAccess_Full;
@@ -670,7 +670,7 @@ int CLdapSecManager::authorizeEx(SecResourceType rtype, ISecUser & user, const c
     rlist.setown(createResourceList("resources"));
     rlist->addResource(resourcename);
     
-    bool ok = authorizeEx(rtype, user, rlist.get());
+    bool ok = authorizeEx(rtype, user, rlist.get(), secureContext);
     if(ok)
         return rlist->queryResource(0)->getAccessFlags();
     else
@@ -818,9 +818,9 @@ int CLdapSecManager::getAccessFlagsEx(SecResourceType rtype, ISecUser & user, co
         return -1;
 }
 
-bool CLdapSecManager::authorize(ISecUser& sec_user, ISecResourceList * Resources)
+bool CLdapSecManager::authorize(ISecUser& sec_user, ISecResourceList * Resources, IEspSecureContext* secureContext)
 {
-    return authorizeEx(RT_DEFAULT, sec_user, Resources);
+    return authorizeEx(RT_DEFAULT, sec_user, Resources, secureContext);
 }
 
 

+ 4 - 4
system/security/LdapSecurity/ldapsecurity.ipp

@@ -354,9 +354,9 @@ public:
     ISecResourceList * createResourceList(const char * rlname);
     bool subscribe(ISecAuthenticEvents & events);
     bool unsubscribe(ISecAuthenticEvents & events);
-    bool authorize(ISecUser& sec_user, ISecResourceList * Resources);
-    bool authorizeEx(SecResourceType rtype, ISecUser& sec_user, ISecResourceList * Resources);
-    int authorizeEx(SecResourceType rtype, ISecUser& sec_user, const char* resourcename);
+    bool authorize(ISecUser& sec_user, ISecResourceList * Resources, IEspSecureContext* secureContext);
+    bool authorizeEx(SecResourceType rtype, ISecUser& sec_user, ISecResourceList * Resources, IEspSecureContext* secureContext = NULL);
+    int authorizeEx(SecResourceType rtype, ISecUser& sec_user, const char* resourcename, IEspSecureContext* secureContext = NULL);
     virtual int authorizeFileScope(ISecUser & user, const char * filescope);
     virtual bool authorizeFileScope(ISecUser & user, ISecResourceList * resources);
     virtual int authorizeWorkunitScope(ISecUser & user, const char * wuscope);
@@ -377,7 +377,7 @@ public:
     virtual IAuthMap * createAuthMap(IPropertyTree * authconfig);
     virtual IAuthMap * createFeatureMap(IPropertyTree * authconfig);
     virtual IAuthMap * createSettingMap(struct IPropertyTree *){return 0;}
-    virtual bool updateSettings(ISecUser & User,ISecPropertyList * settings){return false;}
+    virtual bool updateSettings(ISecUser & User,ISecPropertyList * settings, IEspSecureContext* secureContext){return false;}
     virtual bool updateUserPassword(ISecUser& user, const char* newPassword, const char* currPassword = 0);
     virtual bool updateUser(const char* type, ISecUser& user);
     virtual bool updateUserPassword(const char* username, const char* newPassword);

+ 1 - 1
system/security/htpasswdSecurity/htpasswdSecurity.cpp

@@ -130,7 +130,7 @@ protected:
         return -2;//never expires
     }
 
-    int authorizeEx(SecResourceType rtype, ISecUser & user, const char * resourcename)
+    int authorizeEx(SecResourceType rtype, ISecUser & user, const char * resourcename, IEspSecureContext* secureContext)
     {
         return SecAccess_Full;//grant full access to authenticated users
     }

+ 4 - 4
system/security/shared/basesecurity.hpp

@@ -70,19 +70,19 @@ public:
         return false;
     }
 
-    bool authorize(ISecUser & user, ISecResourceList * resources)
+    bool authorize(ISecUser & user, ISecResourceList * resources, IEspSecureContext* secureContext)
     {
         UNIMPLEMENTED;
         return false;
     }
 
-    bool authorizeEx(SecResourceType rtype, ISecUser & user, ISecResourceList * resources)
+    bool authorizeEx(SecResourceType rtype, ISecUser & user, ISecResourceList * resources, IEspSecureContext* secureContext)
     {
         UNIMPLEMENTED;
         return false;
     }
 
-    int authorizeEx(SecResourceType rtype, ISecUser & user, const char * resourcename)
+    int authorizeEx(SecResourceType rtype, ISecUser & user, const char * resourcename, IEspSecureContext* secureContext)
     {
         UNIMPLEMENTED;
         return 0;
@@ -136,7 +136,7 @@ public:
         return false;
     }
 
-    bool updateSettings(ISecUser & user, ISecPropertyList * resources)
+    bool updateSettings(ISecUser & user, ISecPropertyList * resources, IEspSecureContext* secureContext)
     {
         UNIMPLEMENTED;
         return false;

+ 5 - 4
system/security/shared/seclib.hpp

@@ -268,15 +268,16 @@ enum secManagerType
     SMT_HTPasswd,
     SMT_HTPluggable
 };
+interface IEspSecureContext;
 interface ISecManager : extends IInterface
 {
     virtual ISecUser * createUser(const char * user_name) = 0;
     virtual ISecResourceList * createResourceList(const char * rlname) = 0;
     virtual bool subscribe(ISecAuthenticEvents & events) = 0;
     virtual bool unsubscribe(ISecAuthenticEvents & events) = 0;
-    virtual bool authorize(ISecUser & user, ISecResourceList * resources) = 0;
-    virtual bool authorizeEx(SecResourceType rtype, ISecUser & user, ISecResourceList * resources) = 0;
-    virtual int authorizeEx(SecResourceType rtype, ISecUser & user, const char * resourcename) = 0;
+    virtual bool authorize(ISecUser & user, ISecResourceList * resources, IEspSecureContext* secureContext) = 0;
+    virtual bool authorizeEx(SecResourceType rtype, ISecUser & user, ISecResourceList * resources, IEspSecureContext* secureContext = NULL) = 0;
+    virtual int authorizeEx(SecResourceType rtype, ISecUser & user, const char * resourcename, IEspSecureContext* secureContext = NULL) = 0;
     virtual int getAccessFlagsEx(SecResourceType rtype, ISecUser & user, const char * resourcename) = 0;
     virtual int authorizeFileScope(ISecUser & user, const char * filescope) = 0;
     virtual bool authorizeFileScope(ISecUser & user, ISecResourceList * resources) = 0;
@@ -285,7 +286,7 @@ interface ISecManager : extends IInterface
     virtual bool addResourceEx(SecResourceType rtype, ISecUser & user, const char * resourcename, SecPermissionType ptype, const char * basedn) = 0;
     virtual bool getResources(SecResourceType rtype, const char * basedn, IResourceArray & resources) = 0;
     virtual bool updateResources(ISecUser & user, ISecResourceList * resources) = 0;
-    virtual bool updateSettings(ISecUser & user, ISecPropertyList * resources) = 0;
+    virtual bool updateSettings(ISecUser & user, ISecPropertyList * resources, IEspSecureContext* secureContext) = 0;
     virtual bool addUser(ISecUser & user) = 0;
     virtual ISecUser * findUser(const char * username) = 0;
     virtual ISecUser * lookupUser(unsigned uid) = 0;