Add name-based API to GSSRequest
authorScott Cantor <cantor.2@osu.edu>
Tue, 3 Apr 2012 21:37:50 +0000 (21:37 +0000)
committerScott Cantor <cantor.2@osu.edu>
Tue, 3 Apr 2012 21:37:50 +0000 (21:37 +0000)
apache/mod_shib.cpp
shibsp/AbstractSPRequest.cpp
shibsp/GSSRequest.h
shibsp/handler/impl/RemotedHandler.cpp

index 1da37e2..422673c 100644 (file)
@@ -19,7 +19,7 @@
  */
 
 /**
- * mod_apache.cpp
+ * mod_shib.cpp
  *
  * Apache module implementation.
  */
@@ -324,6 +324,9 @@ class ShibTargetApache : public AbstractSPRequest
   mutable bool m_gotBody,m_firsttime;
   mutable vector<string> m_certs;
   set<string> m_allhttp;
+#if defined(SHIBSP_HAVE_GSSAPI) && !defined(SHIB_APACHE_13)
+  mutable gss_name_t m_gssname;
+#endif
 
 public:
   bool m_handler;
@@ -333,9 +336,20 @@ public:
   shib_request_config* m_rc;
 
   ShibTargetApache(request_rec* req) : AbstractSPRequest(SHIBSP_LOGCAT".Apache"),
-        m_gotBody(false),m_firsttime(true), m_handler(false), m_req(req), m_dc(nullptr), m_sc(nullptr), m_rc(nullptr) {
+        m_gotBody(false),m_firsttime(true),
+#if defined(SHIBSP_HAVE_GSSAPI) && !defined(SHIB_APACHE_13)
+        m_gssname(GSS_C_NO_NAME),
+#endif
+        m_handler(false), m_req(req), m_dc(nullptr), m_sc(nullptr), m_rc(nullptr) {
+  }
+  virtual ~ShibTargetApache() {
+#if defined(SHIBSP_HAVE_GSSAPI) && !defined(SHIB_APACHE_13)
+    if (m_gssname != GSS_C_NO_NAME) {
+        OM_uint32 minor;
+        gss_release_name(&minor, &m_gssname);
+    }
+#endif
   }
-  virtual ~ShibTargetApache() {}
 
   bool isInitialized() const {
       return (m_sc != nullptr);
@@ -634,7 +648,19 @@ public:
     apr_pool_userdata_get((void**)&ctx, g_szGSSContextKey, m_req->pool);
     return ctx;
   }
-#endif
+  gss_name_t getGSSName() const {
+      if (m_gssname == GSS_C_NO_NAME) {
+          gss_ctx_id_t ctx = getGSSContext();
+          if (ctx != GSS_C_NO_CONTEXT) {
+              OM_uint32 minor;
+              OM_uint32 major = gss_inquire_context(&minor, ctx, &m_gssname, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
+              if (major != GSS_S_COMPLETE)
+                  m_gssname = GSS_C_NO_NAME;
+          }
+      }
+      return m_gssname;
+  }
+  #endif
 };
 
 /********************************************************************************/
index e0ccdcc..fe0de14 100644 (file)
@@ -65,6 +65,11 @@ GSSRequest::GSSRequest()
 GSSRequest::~GSSRequest()
 {
 }
+
+gss_name_t GSSRequest::getGSSName() const
+{
+    return GSS_C_NO_NAME;
+}
 #endif
 
 AbstractSPRequest::AbstractSPRequest(const char* category)
index a140f0b..a703e58 100644 (file)
@@ -58,6 +58,14 @@ namespace shibsp {
          * @return  a GSS-API context handle, or GSS_C_NO_CONTEXT
          */
         virtual gss_ctx_id_t getGSSContext() const=0;
+
+        /**
+         * Returns the GSS-API initiator name established for this request, or
+         * GSS_C_NO_NAME if none is available.
+         *
+         * @return  a GSS-API name, or GSS_C_NO_NAME
+         */
+        virtual gss_name_t getGSSName() const;
     };
 };
 
index fe5ce22..d92a4c1 100644 (file)
 # include <xsec/framework/XSECProvider.hpp>
 #endif
 
+#ifdef HAVE_GSSAPI_NAMINGEXTS
+# ifdef SHIBSP_HAVE_GSSMIT
+#  include <gssapi/gssapi_ext.h>
+# endif
+#endif
+
 using namespace shibsp;
 using namespace opensaml;
 using namespace xmltooling;
@@ -64,12 +70,13 @@ namespace shibsp {
         mutable scoped_ptr<CGIParser> m_parser;
         mutable vector<XSECCryptoX509*> m_certs;
 #ifdef SHIBSP_HAVE_GSSAPI
-        mutable gss_ctx_id_t m_gss;
+        mutable gss_ctx_id_t m_gssctx;
+        mutable gss_name_t m_gssname;
 #endif
     public:
         RemotedRequest(DDF& input) : m_input(input), m_parser(nullptr)
 #ifdef SHIBSP_HAVE_GSSAPI
-            , m_gss(GSS_C_NO_CONTEXT)
+            , m_gssctx(GSS_C_NO_CONTEXT), m_gssname(GSS_C_NO_NAME)
 #endif
         {
         }
@@ -77,10 +84,11 @@ namespace shibsp {
         virtual ~RemotedRequest() {
             for_each(m_certs.begin(), m_certs.end(), xmltooling::cleanup<XSECCryptoX509>());
 #ifdef SHIBSP_HAVE_GSSAPI
-            if (m_gss != GSS_C_NO_CONTEXT) {
-                OM_uint32 minor;
-                gss_delete_sec_context(&minor, &m_gss, GSS_C_NO_BUFFER);
-            }
+            OM_uint32 minor;
+            if (m_gssctx != GSS_C_NO_CONTEXT)
+                gss_delete_sec_context(&minor, &m_gssctx, GSS_C_NO_BUFFER);
+            if (m_gssname != GSS_C_NO_NAME)
+                gss_release_name(&minor, &m_gssname);
 #endif
         }
 
@@ -125,6 +133,7 @@ namespace shibsp {
 #ifdef SHIBSP_HAVE_GSSAPI
         // GSSRequest
         gss_ctx_id_t getGSSContext() const;
+        gss_name_t getGSSName() const;
 #endif
 
         // HTTPRequest
@@ -215,19 +224,19 @@ const std::vector<XSECCryptoX509*>& RemotedRequest::getClientCertificates() cons
 #ifdef SHIBSP_HAVE_GSSAPI
 gss_ctx_id_t RemotedRequest::getGSSContext() const
 {
-    if (m_gss == GSS_C_NO_CONTEXT) {
+    if (m_gssctx == GSS_C_NO_CONTEXT) {
         const char* encoded = m_input["gss_context"].string();
         if (encoded) {
             xsecsize_t x;
-            XMLByte* decoded=Base64::decode(reinterpret_cast<const XMLByte*>(encoded), &x);
+            XMLByte* decoded = Base64::decode(reinterpret_cast<const XMLByte*>(encoded), &x);
             if (decoded) {
                 gss_buffer_desc importbuf;
                 importbuf.length = x;
                 importbuf.value = decoded;
                 OM_uint32 minor;
-                OM_uint32 major = gss_import_sec_context(&minor, &importbuf, &m_gss);
+                OM_uint32 major = gss_import_sec_context(&minor, &importbuf, &m_gssctx);
                 if (major != GSS_S_COMPLETE)
-                    m_gss = GSS_C_NO_CONTEXT;
+                    m_gssctx = GSS_C_NO_CONTEXT;
 #ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
                 XMLString::release(&decoded);
 #else
@@ -236,7 +245,45 @@ gss_ctx_id_t RemotedRequest::getGSSContext() const
             }
         }
     }
-    return m_gss;
+    return m_gssctx;
+}
+
+gss_name_t RemotedRequest::getGSSName() const
+{
+    if (m_gssname == GSS_C_NO_NAME) {
+        const char* encoded = m_input["gss_name"].string();
+        if (encoded) {
+            xsecsize_t x;
+            XMLByte* decoded = Base64::decode(reinterpret_cast<const XMLByte*>(encoded), &x);
+            gss_buffer_desc importbuf;
+            importbuf.length = x;
+            importbuf.value = decoded;
+            OM_uint32 major,minor;
+#ifdef HAVE_GSSAPI_COMPOSITE_NAME
+            major = gss_import_name(&minor, &importbuf, GSS_C_NT_EXPORT_NAME_COMPOSITE, &m_gssname);
+#else
+            major = gss_import_name(&minor, &importbuf, GSS_C_NT_EXPORT_NAME, &m_gssname);
+#endif
+            if (major != GSS_S_COMPLETE)
+                m_gssname = GSS_C_NO_NAME;
+#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
+            XMLString::release(&decoded);
+#else
+            XMLString::release((char**)&decoded);
+#endif
+        }
+
+        if (m_gssname == GSS_C_NO_NAME) {
+            gss_ctx_id_t ctx = getGSSContext();
+             if (ctx != GSS_C_NO_CONTEXT) {
+                 OM_uint32 minor;
+                 OM_uint32 major = gss_inquire_context(&minor, ctx, &m_gssname, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
+                 if (major != GSS_S_COMPLETE)
+                     m_gssname = GSS_C_NO_NAME;
+             }
+         }
+    }
+    return m_gssname;
 }
 #endif
 
@@ -372,13 +419,12 @@ DDF RemotedHandler::wrap(const SPRequest& request, const vector<string>* headers
         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;
+            gss_buffer_desc contextbuf = GSS_C_EMPTY_BUFFER;
             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);
+                xsecsize_t len = 0;
+                XMLByte* out = Base64::encode(reinterpret_cast<const XMLByte*>(contextbuf.value), contextbuf.length, &len);
+                gss_release_buffer(&minor, &contextbuf);
                 if (out) {
                     string ctx;
                     ctx.append(reinterpret_cast<char*>(out), len);
@@ -397,6 +443,37 @@ DDF RemotedHandler::wrap(const SPRequest& request, const vector<string>* headers
                 request.log(SPRequest::SPError, "error while exporting GSS context");
             }
         }
+#ifdef HAVE_GSSAPI_NAMINGEXTS
+        else {
+            gss_name_t name = gss->getGSSName();
+            if (name != GSS_C_NO_NAME) {
+                OM_uint32 minor;
+                gss_buffer_desc namebuf = GSS_C_EMPTY_BUFFER;
+                OM_uint32 major = gss_export_name_composite(&minor, name, &namebuf);
+                if (major == GSS_S_COMPLETE) {
+                    xsecsize_t len = 0;
+                    XMLByte* out = Base64::encode(reinterpret_cast<const XMLByte*>(namebuf.value), namebuf.length, &len);
+                    gss_release_buffer(&minor, &namebuf);
+                    if (out) {
+                        string nm;
+                        nm.append(reinterpret_cast<char*>(out), len);
+#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
+                        XMLString::release(&out);
+#else
+                        XMLString::release((char**)&out);
+#endif
+                        in.addmember("gss_name").string(nm.c_str());
+                    }
+                    else {
+                        request.log(SPRequest::SPError, "error while base64-encoding GSS name");
+                    }
+                }
+                else {
+                    request.log(SPRequest::SPError, "error while exporting GSS name");
+                }
+            }
+        }
+#endif
     }
 #endif