Support for GSS-API contexts attached to requests.
authorcantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Fri, 15 Oct 2010 23:46:04 +0000 (23:46 +0000)
committercantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Fri, 15 Oct 2010 23:46:04 +0000 (23:46 +0000)
git-svn-id: https://svn.middleware.georgetown.edu/cpp-sp/branches/REL_2@3345 cb58f699-b61c-0410-a6fe-9272a202ed29

apache/mod_apache.cpp
shibsp/AbstractSPRequest.cpp
shibsp/GSSRequest.h [new file with mode: 0644]
shibsp/Makefile.am
shibsp/handler/impl/RemotedHandler.cpp
shibsp/shibsp-lite.vcxproj
shibsp/shibsp-lite.vcxproj.filters
shibsp/shibsp.vcxproj
shibsp/shibsp.vcxproj.filters

index 13d817e..64d16a9 100644 (file)
 # define _CRT_SECURE_NO_DEPRECATE 1
 #endif
 
+#include <shibsp/exceptions.h>
 #include <shibsp/AbstractSPRequest.h>
 #include <shibsp/AccessControl.h>
-#include <shibsp/exceptions.h>
+#include <shibsp/GSSRequest.h>
 #include <shibsp/RequestMapper.h>
 #include <shibsp/SPConfig.h>
 #include <shibsp/ServiceProvider.h>
 #include <shibsp/SessionCache.h>
 #include <shibsp/attribute/Attribute.h>
+
 #include <xercesc/util/XMLUniDefs.hpp>
 #include <xercesc/util/regx/RegularExpression.hpp>
 #include <xmltooling/XMLToolingConfig.h>
@@ -95,6 +97,9 @@ namespace {
     string g_unsetHeaderValue,g_spoofKey;
     bool g_checkSpoofing = true;
     bool g_catchAll = false;
+#ifndef SHIB_APACHE_13
+    char* g_szGSSContextKey = "mod_auth_gssapi:gss_ctx";
+#endif
     static const char* g_UserDataKey = "urn:mace:shibboleth:Apache:shib_check_user";
 }
 
@@ -294,10 +299,11 @@ extern "C" const char* shib_table_set(cmd_parms* parms, shib_dir_config* dc, con
     return nullptr;
 }
 
-/********************************************************************************/
-// Apache ShibTarget subclass(es) here.
 
 class ShibTargetApache : public AbstractSPRequest
+#if defined(HAVE_GSSAPI) && !defined(SHIB_APACHE_13)
+    , public GSSRequest
+#endif
 {
   bool m_handler;
   mutable string m_body;
@@ -574,6 +580,13 @@ public:
   }
   long returnDecline(void) { return DECLINED; }
   long returnOK(void) { return OK; }
+#if defined(HAVE_GSSAPI) && !defined(SHIB_APACHE_13)
+  gss_ctx_id_t getGSSContext() const {
+    gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
+    apr_pool_userdata_get((void**)&ctx, g_szGSSContextKey, m_req->pool);
+    return ctx;
+  }
+#endif
 };
 
 /********************************************************************************/
@@ -1536,6 +1549,8 @@ static command_rec shib_cmds[] = {
         RSRC_CONF, "Path to shibboleth2.xml config file"),
     AP_INIT_TAKE1("ShibCatalogs", (config_fn_t)ap_set_global_string_slot, &g_szSchemaDir,
         RSRC_CONF, "Paths of XML schema catalogs"),
+    AP_INIT_TAKE1("ShibGSSKey", (config_fn_t)ap_set_global_string_slot, &g_szGSSContextKey,
+        RSRC_CONF, "Name of user data key containing GSS context established by GSS module"),
 
     AP_INIT_TAKE1("ShibURLScheme", (config_fn_t)shib_set_server_string_slot,
         (void *) offsetof (shib_server_config, szScheme),
index b6c5e80..6f9b005 100644 (file)
@@ -50,6 +50,16 @@ void SPRequest::setAuthType(const char* authtype)
 {
 }
 
+#ifdef HAVE_GSSAPI
+GSSRequest::GSSRequest()
+{
+}
+
+GSSRequest::~GSSRequest()
+{
+}
+#endif
+
 AbstractSPRequest::AbstractSPRequest(const char* category)
     : m_sp(nullptr), m_mapper(nullptr), m_app(nullptr), m_sessionTried(false), m_session(nullptr),
         m_log(&Category::getInstance(category)), m_parser(nullptr)
diff --git a/shibsp/GSSRequest.h b/shibsp/GSSRequest.h
new file mode 100644 (file)
index 0000000..a58cc51
--- /dev/null
@@ -0,0 +1,60 @@
+/*\r
+ *  Copyright 2010 Internet2\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * @file shibsp/GSSRequest.h\r
+ *\r
+ * Interface to a GSS-authenticated request.\r
+ */\r
+\r
+#if !defined(__shibsp_gssreq_h__) && defined(HAVE_GSSAPI)\r
+#define __shibsp_gssreq_h__\r
+\r
+#include <shibsp/base.h>\r
+#include <xmltooling/io/GenericRequest.h>\r
+\r
+#ifdef HAVE_GSSGNU\r
+# include <gss.h>\r
+#elif defined HAVE_GSSMIT\r
+# include <gssapi/gssapi.h>\r
+# include <gssapi/gssapi_generic.h>\r
+#else\r
+# include <gssapi.h>\r
+#endif\r
+\r
+namespace shibsp {\r
+\r
+    /**\r
+     * Interface to a GSS-authenticated request.\r
+     */\r
+    class SHIBSP_API GSSRequest : public virtual xmltooling::GenericRequest\r
+    {\r
+    protected:\r
+        GSSRequest();\r
+    public:\r
+        virtual ~GSSRequest();\r
+\r
+        /**\r
+         * Returns the GSS-API context established for this request, or\r
+         * GSS_C_NO_CONTEXT if none is available.\r
+         *\r
+         * @return  a GSS-API context handle, or GSS_C_NO_CONTEXT\r
+         */\r
+        virtual gss_ctx_id_t getGSSContext() const=0;\r
+    };\r
+};\r
+\r
+#endif /* __shibsp_gssreq_h__ */\r
index 55072f9..7681b5e 100644 (file)
@@ -31,6 +31,7 @@ libshibspinclude_HEADERS = \
        base.h \
        exceptions.h \
        paths.h \
+       GSSRequest.h \
        RequestMapper.h \
        ServiceProvider.h \
        SessionCache.h \
index e7ca6d7..a843751 100644 (file)
  */
 
 #include "internal.h"
-#include "Application.h"
 #include "exceptions.h"
+#include "Application.h"
+#include "GSSRequest.h"
 #include "ServiceProvider.h"
 #include "SPRequest.h"
 #include "handler/RemotedHandler.h"
 
 #include <algorithm>
 #include <xmltooling/unicode.h>
+#include <xercesc/util/Base64.hpp>
 
 #ifndef SHIBSP_LITE
 # include "util/CGIParser.h"
@@ -46,16 +48,35 @@ using namespace std;
 
 #ifndef SHIBSP_LITE
 namespace shibsp {
-    class SHIBSP_DLLLOCAL RemotedRequest : public virtual HTTPRequest 
+    class SHIBSP_DLLLOCAL RemotedRequest : 
+#ifdef HAVE_GSSAPI
+        public virtual GSSRequest,
+#endif
+        public virtual HTTPRequest
     {
         DDF& m_input;
         mutable CGIParser* m_parser;
         mutable vector<XSECCryptoX509*> m_certs;
+#ifdef HAVE_GSSAPI
+        mutable gss_ctx_id_t m_gss;
+#endif
     public:
-        RemotedRequest(DDF& input) : m_input(input), m_parser(nullptr) {}
+        RemotedRequest(DDF& input) : m_input(input), m_parser(nullptr)
+#ifdef HAVE_GSSAPI
+            , m_ctx(GSS_C_NO_CONTEXT)
+#endif
+        {
+        }
+
         virtual ~RemotedRequest() {
             for_each(m_certs.begin(), m_certs.end(), xmltooling::cleanup<XSECCryptoX509>());
             delete m_parser;
+#ifdef HAVE_GSSAPI
+            if (m_ctx != GSS_C_NO_CONTEXT) {
+                OM_uint32 minor;
+                gss_delete_sec_context(&minor, &m_ctx, GSS_C_NO_BUFFER);
+            }
+#endif
         }
 
         // GenericRequest
@@ -93,6 +114,11 @@ namespace shibsp {
 
         const std::vector<XSECCryptoX509*>& getClientCertificates() const;
         
+#ifdef HAVE_GSSAPI
+        // GSSRequest
+        gss_ctx_id_t getGSSContext() const;
+#endif
+
         // HTTPRequest
         const char* getMethod() const {
             return m_input["method"].string();
@@ -177,6 +203,34 @@ const std::vector<XSECCryptoX509*>& RemotedRequest::getClientCertificates() cons
     return m_certs;
 }
 
+#ifdef HAVE_GSSAPI
+gss_ctx_id_t RemotedRequest::getGSSContext() const
+{
+    if (m_ctx == GSS_C_NO_CONTEXT) {
+        const char* encoded = m_input["gss_context"];
+        if (encoded) {
+            xsecsize_t x;
+            XMLByte* decoded=Base64::decode(reinterpret_cast<const XMLByte*>(encoded), &x);
+            if (decoded) {
+                gss_buffer_desc importbuf;
+                importbuf.length = x;
+                importbuf.data = decoded;
+                OM_uint32 minor;
+                OM_uint32 major = gss_import_sec_context(&minor, &importbuf, &m_ctx);
+                if (major != GSS_S_COMPLETE)
+                    m_ctx = GSS_C_NO_CONTEXT;
+#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
+                XMLString::release(&decoded);
+#else
+                XMLString::release((char**)&decoded);
+#endif
+            }
+        }
+    }
+    return m_ctx;
+}
+#endif
+
 long RemotedResponse::sendResponse(std::istream& in, long status)
 {
     string msg;
@@ -289,6 +343,40 @@ DDF RemotedHandler::wrap(const SPRequest& request, const vector<string>* headers
 #endif
     }
 
+#ifdef HAVE_GSSAPI
+    const GSSRequest* gss = dynamic_cast<const GSSRequest*>(&request);
+    if (gss) {
+        gss_ctx_id_t ctx = gss->getGSSContext();
+        if (ctx != GSS_C_NO_CONTEXT) {
+            OM_uint32 minor;
+            gss_buffer_desc contextbuf;
+            contextbuf.length = 0;
+            contextbuf.value = nullptr;
+            OM_uint32 major = gss_export_sec_context(&minor, &ctx, &contextbuf);
+            if (major == GSS_S_COMPLETE) {
+                xsecsize_t len=0;
+                XMLByte* out=Base64::encode(reinterpret_cast<const XMLByte*>(contextbuf.value), contextbuf.length, &len);
+                if (out) {
+                    string ctx;
+                    ctx.append(reinterpret_cast<char*>(out), len);
+#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
+                    XMLString::release(&out);
+#else
+                    XMLString::release((char**)&out);
+#endif
+                    in.addmember("gss_context").string(ctx.c_str());
+                }
+                else {
+                    request.log(SPRequest::SPError, "error while base64-encoding GSS context");
+                }
+            }
+            else {
+                request.log(SPRequest::SPError, "error while exporting GSS context");
+            }
+        }
+    }
+#endif
+
     return in;
 }
 
index 81a331c..ade8cb9 100644 (file)
   </ItemGroup>\r
   <ItemGroup>\r
     <ClInclude Include="binding\ProtocolProvider.h" />\r
+    <ClInclude Include="GSSRequest.h" />\r
     <ClInclude Include="handler\LogoutInitiator.h" />\r
     <ClInclude Include="remoting\impl\SocketListener.h" />\r
     <ClInclude Include="AbstractSPRequest.h" />\r
index 2eff898..654a364 100644 (file)
     <ClInclude Include="binding\ProtocolProvider.h">\r
       <Filter>Header Files\binding</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="GSSRequest.h">\r
+      <Filter>Header Files</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ResourceCompile Include="shibsp.rc">\r
index cd56309..58cb9a6 100644 (file)
   </ItemGroup>\r
   <ItemGroup>\r
     <ClInclude Include="binding\ProtocolProvider.h" />\r
+    <ClInclude Include="GSSRequest.h" />\r
     <ClInclude Include="handler\LogoutInitiator.h" />\r
     <ClInclude Include="remoting\impl\SocketListener.h" />\r
     <ClInclude Include="AbstractSPRequest.h" />\r
index f1da19e..a9d09ff 100644 (file)
     <ClInclude Include="binding\ProtocolProvider.h">\r
       <Filter>Header Files\binding</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="GSSRequest.h">\r
+      <Filter>Header Files</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ResourceCompile Include="shibsp.rc">\r