Add name-based API to GSSRequest
[shibboleth/cpp-sp-resolver.git] / src / shibresolver / resolver.cpp
index d14600a..dd7bbbf 100644 (file)
@@ -49,6 +49,7 @@
 #include <xmltooling/XMLToolingConfig.h>
 #include <xmltooling/impl/AnyElement.h>
 #include <xmltooling/util/ParserPool.h>
+#include <xmltooling/util/Threads.h>
 #include <xmltooling/util/XMLHelper.h>
 #include <xercesc/util/Base64.hpp>
 
@@ -109,6 +110,9 @@ namespace shibresolver {
     };
 
     static RemotedResolver g_Remoted;
+
+    static int g_initCount = 0;
+    static auto_ptr<Mutex> g_lock(Mutex::create());
 };
 
 ShibbolethResolver* ShibbolethResolver::create()
@@ -140,9 +144,16 @@ void ShibbolethResolver::setRequest(const SPRequest* request)
     if (request) {
         const GSSRequest* gss = dynamic_cast<const GSSRequest*>(request);
         if (gss) {
-            // TODO: fix API to prevent destruction of contexts
+#ifdef SHIBRESOLVER_HAVE_GSSAPI_NAMINGEXTS
+            gss_name_t name = gss->getGSSName();
+            if (name != GSS_C_NO_NAME) {
+                addToken(name);
+                return;
+            }
+#endif
             gss_ctx_id_t ctx = gss->getGSSContext();
-            addToken(&ctx);
+            if (ctx != GSS_C_NO_CONTEXT)
+                addToken(&ctx);
         }
     }
 #endif
@@ -587,14 +598,26 @@ const RoleDescriptor* RemotedResolver::lookup(
 
 bool ShibbolethResolver::init(unsigned long features, const char* config, bool rethrow)
 {
-    if (features && SPConfig::OutOfProcess) {
+    Lock initLock(g_lock.get());
+
+    if (g_initCount == INT_MAX) {
+        Category::getInstance(SHIBRESOLVER_LOGCAT".Config").crit("library initialized too many times");
+        return false;
+    }
+
+    if (g_initCount >= 1) {
+        ++g_initCount;
+        return true;
+    }
+
+    if (features & SPConfig::OutOfProcess) {
 #ifndef SHIBSP_LITE
         features = features | SPConfig::AttributeResolution | SPConfig::Metadata | SPConfig::Trust | SPConfig::Credentials;
 #endif
-        if (!(features && SPConfig::InProcess))
+        if (!(features & SPConfig::InProcess))
             features |= SPConfig::Listener;
     }
-    else if (features && SPConfig::InProcess) {
+    else if (features & SPConfig::InProcess) {
         features |= SPConfig::Listener;
     }
     SPConfig::getConfig().setFeatures(features);
@@ -602,16 +625,22 @@ bool ShibbolethResolver::init(unsigned long features, const char* config, bool r
         return false;
     if (!SPConfig::getConfig().instantiate(config, rethrow))
         return false;
+
+    ++g_initCount;
     return true;
 }
 
-/**
-    * Shuts down runtime.
-    *
-    * Each process using the library SHOULD call this function exactly once before terminating itself.
-    */
 void ShibbolethResolver::term()
 {
+    Lock initLock(g_lock.get());
+    if (g_initCount == 0) {
+        Category::getInstance(SHIBRESOLVER_LOGCAT".Config").crit("term without corresponding init");
+        return;
+    }
+    else if (--g_initCount > 0) {
+        return;
+    }
+
     SPConfig::getConfig().term();
 }