[cpp-sp] branch main updated: Copy in extension lib support from xmltooling.

Scott Cantor cantor.2 at osu.edu
Tue Dec 3 14:57:44 UTC 2024


This is an automated email from the git hooks/post-receive script.

scantor pushed a commit to branch main
in repository cpp-sp.

View the commit online:
http://git.shibboleth.net/view/?p=cpp-sp.git;a=commit;h=71fc57ddae3d2f40002cd4c060a6baaf94264d68

The following commit(s) were added to refs/heads/main by this push:
     new 71fc57dd Copy in extension lib support from xmltooling.
71fc57dd is described below

commit 71fc57ddae3d2f40002cd4c060a6baaf94264d68
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue Dec 3 09:57:36 2024 -0500

    Copy in extension lib support from xmltooling.
---
 configure.ac                |  9 +++++
 shibsp.pc.in                |  2 +-
 shibsp/AgentConfig.h        | 15 ++++++++
 shibsp/impl/AgentConfig.cpp | 92 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 117 insertions(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index 771c93c0..d126a9c9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -41,6 +41,15 @@ AC_CHECK_HEADERS([sys/socket.h], [AC_DEFINE([SHIBSP_HAVE_SYS_SOCKET_H],[1],[Defi
 AC_CHECK_FUNCS([strchr strdup strstr timegm gmtime_r localtime_r strtok_r strcasecmp getpwnam getgrnam initgroups])
 AC_CHECK_TYPES([struct sockaddr_storage], [], [], [[#include <sys/socket.h>]])
 AC_CHECK_MEMBERS([struct sockaddr.sa_len], [], [], [[#include <sys/socket.h>]])
+AC_CHECK_HEADERS([dlfcn.h])
+
+# Check for dlopen.
+AX_SAVE_FLAGS
+LIBS=""
+AC_SEARCH_LIBS([dlopen],[dl],,[AC_MSG_ERROR([cannot find dlopen() function])])
+AC_SUBST([dlopen_LIBS],[$LIBS])
+AX_RESTORE_FLAGS
+
 
 AC_CACHE_CHECK([for SOCK_CLOEXEC support], [shib_cv_sock_cloexec],
 [AC_TRY_RUN([
diff --git a/shibsp.pc.in b/shibsp.pc.in
index 2c718bb1..1d1c25d1 100644
--- a/shibsp.pc.in
+++ b/shibsp.pc.in
@@ -7,7 +7,7 @@ Name: @PACKAGE_NAME@
 Description: Shibboleth Service Provider library
 Version: @PACKAGE_VERSION@
 Libs: -L${libdir} -lshibsp
-Libs.private: @PTHREAD_LIBS@
+Libs.private: @dlopen_LIBS @PTHREAD_LIBS@
 Cflags: -I${includedir} @BOOST_CPPFLAGS@ @PTHREAD_CFLAGS@
 Requires: @SHIBSP_REQUIRES@
 Requires.private: @SHIBSP_REQUIRES_PRIVATE@
diff --git a/shibsp/AgentConfig.h b/shibsp/AgentConfig.h
index 845987ca..f4dbff24 100644
--- a/shibsp/AgentConfig.h
+++ b/shibsp/AgentConfig.h
@@ -76,6 +76,21 @@ namespace shibsp {
          */
         virtual void term()=0;
 
+        /**
+         * Loads a shared/dynamic library extension.
+         *
+         * <p>Extension libraries are managed using a pair of "C" linkage functions:<br>
+         *      extern "C" int shibsp_extension_init(void* context);<br>
+         *      extern "C" void shibsp_extension_term();
+         *
+         * <p>This method is internally synchronized.</p>
+         *
+         * @param path      pathname of shared library to load into process
+         * @param context   arbitrary data to pass to library initialization hook
+         * @return true iff library was loaded successfully
+         */
+        virtual bool load_library(const char* path, void* context=nullptr)=0;
+
         /**
          * Manages factories for LoggingService plugins.
          */
diff --git a/shibsp/impl/AgentConfig.cpp b/shibsp/impl/AgentConfig.cpp
index beab11aa..89c33f42 100644
--- a/shibsp/impl/AgentConfig.cpp
+++ b/shibsp/impl/AgentConfig.cpp
@@ -30,9 +30,14 @@
 #include <ctime>
 #include <stdexcept>
 #include <thread>
+#include <vector>
 #include <boost/property_tree/ptree.hpp>
 #include <boost/property_tree/ini_parser.hpp>
 
+#ifdef HAVE_DLFCN_H
+# include <dlfcn.h>
+#endif
+
 using namespace shibsp;
 using namespace xmltooling;
 using namespace boost::property_tree;
@@ -48,6 +53,7 @@ namespace shibsp {
 
         bool init(const char* inst_prefix=nullptr, const char* config_file=nullptr, bool rethrow=false);
         void term();
+        bool load_library(const char* path, void* context=nullptr);
 
         const PathResolver& getPathResolver() const {
             return m_pathResolver;
@@ -71,6 +77,7 @@ namespace shibsp {
         ptree m_config;
         PathResolver m_pathResolver;
         URLEncoder m_urlEncoder;
+        vector<void*> m_libhandles;
         unique_ptr<LoggingService> m_logging;
         //unique_ptr<Agent> m_agent;
     };
@@ -278,6 +285,23 @@ void AgentInternalConfig::_term()
 
     LoggingServiceManager.deregisterFactories();
 
+    for (vector<void*>::reverse_iterator i=m_libhandles.rbegin(); i!=m_libhandles.rend(); i++) {
+#if defined(WIN32)
+        FARPROC fn=GetProcAddress(static_cast<HMODULE>(*i),"xmltooling_extension_term");
+        if (fn)
+            fn();
+        FreeLibrary(static_cast<HMODULE>(*i));
+#elif defined(HAVE_DLFCN_H)
+        void (*fn)()=(void (*)())dlsym(*i,"shibsp_extension_term");
+        if (fn)
+            fn();
+        dlclose(*i);
+#else
+# error "Don't know about dynamic loading on this platform!"
+#endif
+    }
+    m_libhandles.clear();
+
     log.info("%s agent shutdown complete", PACKAGE_STRING);
 
     m_logging->term();
@@ -311,3 +335,71 @@ void AgentInternalConfig::_term()
         SessionCacheManager.deregisterFactories();
     */
 }
+
+bool AgentInternalConfig::load_library(const char* path, void* context)
+{
+#ifdef _DEBUG
+    xmltooling::NDC ndc("LoadLibrary");
+#endif
+    Category& log=Category::getInstance(SHIBSP_LOGCAT ".Config");
+    log.info("loading extension: %s", path);
+
+    lock_guard<mutex> locker(m_lock);
+
+    string resolved(path);
+    m_pathResolver.resolve(resolved, PathResolver::SHIBSP_LIB_FILE);
+
+#if defined(WIN32)
+    HMODULE handle=nullptr;
+    for (string::iterator i = resolved.begin(); i != resolved.end(); ++i)
+        if (*i == '/')
+            *i = '\\';
+
+    UINT em=SetErrorMode(SEM_FAILCRITICALERRORS);
+    try {
+        handle=LoadLibraryEx(resolved.c_str(),nullptr,LOAD_WITH_ALTERED_SEARCH_PATH);
+        if (!handle)
+             handle=LoadLibraryEx(resolved.c_str(),nullptr,0);
+        if (!handle)
+            throw runtime_error(string("unable to load extension library: ") + resolved);
+        FARPROC fn=GetProcAddress(handle,"shibsp_extension_init");
+        if (!fn)
+            throw runtime_error(string("unable to locate shibsp_extension_init entry point: ") + resolved);
+        if (reinterpret_cast<int(*)(void*)>(fn)(context)!=0)
+            throw runtime_error(string("detected error in shibsp_extension_init: ") + resolved);
+        SetErrorMode(em);
+    }
+    catch(std::exception&) {
+        if (handle)
+            FreeLibrary(handle);
+        SetErrorMode(em);
+        throw;
+    }
+#elif defined(HAVE_DLFCN_H)
+    void* handle=dlopen(resolved.c_str(),RTLD_LAZY);
+    if (!handle)
+        throw runtime_error(string("unable to load extension library '") + resolved + "': " + dlerror());
+    int (*fn)(void*)=(int (*)(void*))(dlsym(handle,"shibsp_extension_init"));
+    if (!fn) {
+        dlclose(handle);
+        throw runtime_error(
+            string("unable to locate shibsp_extension_init entry point in '") + resolved + "': " +
+                (dlerror() ? dlerror() : "unknown error")
+            );
+    }
+    try {
+        if (fn(context)!=0)
+            throw runtime_error(string("detected error in shibsp_extension_init in ") + resolved);
+    }
+    catch(std::exception&) {
+        if (handle)
+            dlclose(handle);
+        throw;
+    }
+#else
+# error "Don't know about dynamic loading on this platform!"
+#endif
+    m_libhandles.push_back(handle);
+    log.info("loaded extension: %s", resolved.c_str());
+    return true;
+}

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list