*/
#include <time.h>
-#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#define SHIB_INSTANTIATE
#include "internal.h"
-#include <log4cpp/Category.hh>
+#include "shib-threads.h"
+
+#include <openssl/err.h>
using namespace saml;
using namespace shibboleth;
+using namespace log4cpp;
+using namespace std;
-SAML_EXCEPTION_FACTORY(UnsupportedProtocolException);
-SAML_EXCEPTION_FACTORY(OriginSiteMapperException);
+SAML_EXCEPTION_FACTORY(MetadataException);
+SAML_EXCEPTION_FACTORY(CredentialException);
+SAML_EXCEPTION_FACTORY(InvalidHandleException);
namespace {
- ShibInternalConfig g_config;
+ ShibConfig g_config;
+ vector<Mutex*> g_openssl_locks;
}
-ShibConfig::~ShibConfig() {}
-
-bool ShibInternalConfig::init()
+extern "C" void openssl_locking_callback(int mode,int n,const char *file,int line)
{
- saml::NDC ndc("init");
-
- REGISTER_EXCEPTION_FACTORY(edu.internet2.middleware.shibboleth.common,UnsupportedProtocolException);
- REGISTER_EXCEPTION_FACTORY(edu.internet2.middleware.shibboleth.common,OriginSiteMapperException);
-
- // Register extension schema.
- saml::XML::registerSchema(XML::SHIB_NS,XML::SHIB_SCHEMA_ID);
-
- if (!aapURL.empty())
- {
- try
- {
- m_AAP=new AAP(aapURL.c_str());
- }
- catch(SAMLException& e)
- {
- log4cpp::Category::getInstance(SHIB_LOGCAT".ShibConfig").fatal("init: failed to initialize AAP: %s", e.what());
- return false;
- }
- }
-
- m_lock=RWLock::create();
- m_shutdown_wait = CondWait::create();
- if (!m_lock || !m_shutdown_wait)
- {
- log4cpp::Category::getInstance(SHIB_LOGCAT".ShibConfig").fatal("init: failed to create mapper locks");
- delete m_lock;
- delete m_shutdown_wait;
- delete m_AAP;
- return false;
- }
+ if (mode & CRYPTO_LOCK)
+ g_openssl_locks[n]->lock();
+ else
+ g_openssl_locks[n]->unlock();
+}
- try
- {
- m_mapper=new XMLOriginSiteMapper(mapperURL.c_str(),SAMLConfig::getConfig().ssl_calist.c_str(),mapperCert);
- }
- catch(SAMLException& e)
- {
- log4cpp::Category::getInstance(SHIB_LOGCAT".ShibConfig").fatal("init: failed to initialize origin site mapper: %s", e.what());
- delete m_lock;
- delete m_shutdown_wait;
- delete m_AAP;
- return false;
- }
+#ifndef WIN32
+extern "C" unsigned long openssl_thread_id(void)
+{
+ return (unsigned long)(pthread_self());
+}
+#endif
- m_manager=xmlSecSimpleKeysMngrCreate();
- const char* roots=m_mapper->getTrustedRoots();
- if (roots && *roots && xmlSecSimpleKeysMngrLoadPemCert(m_manager,roots,true) < 0)
- {
- log4cpp::Category::getInstance(SHIB_LOGCAT".ShibConfig").fatal("init: failed to load CAs into simple key manager");
- xmlSecSimpleKeysMngrDestroy(m_manager);
- delete m_mapper;
- delete m_lock;
- delete m_shutdown_wait;
- delete m_AAP;
- return false;
- }
- SAMLConfig::getConfig().xmlsig_ptr=m_manager;
- if (mapperRefreshInterval)
- m_refresh_thread = Thread::create(&refresh_fn, (void*)this);
+bool ShibConfig::init()
+{
+ REGISTER_EXCEPTION_FACTORY(MetadataException);
+ REGISTER_EXCEPTION_FACTORY(CredentialException);
+ REGISTER_EXCEPTION_FACTORY(InvalidHandleException);
+
+ // Set up OpenSSL locking.
+ for (int i=0; i<CRYPTO_num_locks(); i++)
+ g_openssl_locks.push_back(Mutex::create());
+ CRYPTO_set_locking_callback(openssl_locking_callback);
+#ifndef WIN32
+ CRYPTO_set_id_callback(openssl_thread_id);
+#endif
return true;
}
-void ShibInternalConfig::term()
+void ShibConfig::term()
{
- // Shut down the refresh thread and let it know...
- if (m_refresh_thread)
- {
- m_shutdown = true;
- m_shutdown_wait->signal();
- m_refresh_thread->join(NULL);
- }
-
- delete m_mapper;
- if (m_manager)
- xmlSecSimpleKeysMngrDestroy(m_manager);
- delete mapperCert;
- delete m_lock;
- delete m_shutdown_wait;
- delete m_AAP;
+ CRYPTO_set_locking_callback(NULL);
+ for (vector<Mutex*>::iterator i=g_openssl_locks.begin(); i!=g_openssl_locks.end(); i++)
+ delete (*i);
+ g_openssl_locks.clear();
}
-IOriginSiteMapper* ShibInternalConfig::getMapper()
+void PlugManager::regFactory(const char* type, Factory* factory)
{
- m_lock->rdlock();
- return m_mapper;
+ if (type && factory)
+ m_map[type]=factory;
}
-void ShibInternalConfig::releaseMapper(IOriginSiteMapper* mapper)
+IPlugIn* PlugManager::newPlugin(const char* type, const DOMElement* source)
{
- m_lock->unlock();
+ FactoryMap::const_iterator i=m_map.find(type);
+ if (i==m_map.end())
+ throw saml::UnsupportedExtensionException(std::string("unable to build plugin of type '") + type + "'");
+ return i->second(source);
}
-ShibConfig& ShibConfig::getConfig()
+void PlugManager::unregFactory(const char* type)
{
- return g_config;
+ if (type)
+ m_map.erase(type);
}
-void* ShibInternalConfig::refresh_fn(void* config_p)
+ShibConfig& ShibConfig::getConfig()
{
- ShibInternalConfig* config = reinterpret_cast<ShibInternalConfig*>(config_p);
-
- // First, let's block all signals
- sigset_t sigmask;
- sigfillset(&sigmask);
- Thread::mask_signals(SIG_BLOCK, &sigmask, NULL);
-
- // Now run the refresh process.
- config->refresh();
+ return g_config;
}
-void ShibInternalConfig::refresh()
+void shibboleth::log_openssl()
{
- Mutex* mutex = Mutex::create();
- saml::NDC ndc("refresh");
- log4cpp::Category& log=log4cpp::Category::getInstance(SHIB_LOGCAT".ShibConfig");
-
- mutex->lock();
+ const char* file;
+ const char* data;
+ int flags,line;
- log.debug("XMLMapper refresh thread started...");
-
- while (!m_shutdown)
+ unsigned long code=ERR_get_error_line_data(&file,&line,&data,&flags);
+ while (code)
{
- struct timespec ts;
- memset (&ts, 0, sizeof(ts));
- ts.tv_sec = time(NULL) + mapperRefreshInterval;
-
- m_shutdown_wait->timedwait(mutex, &ts);
-
- if (m_shutdown)
- break;
-
- log.info("Refresh thread running...");
-
- // To refresh the mapper, we basically build a new one in the background and if it works,
- // we grab the write lock and replace the official pointer with the new one.
- try
- {
- IOriginSiteMapper* new_mapper=new XMLOriginSiteMapper(mapperURL.c_str(),SAMLConfig::getConfig().ssl_calist.c_str(),mapperCert);
- m_lock->wrlock();
- delete m_mapper;
- m_mapper=new_mapper;
- m_lock->unlock();
- }
- catch(SAMLException& e)
- {
- log.error("failed to build a refreshed origin site mapper, sticking with what we have: %s", e.what());
- }
- catch(...)
- {
- log.error("caught an unknown exception, sticking with what we have");
- }
+ Category& log=Category::getInstance("OpenSSL");
+ log.errorStream() << "error code: " << code << " in " << file << ", line " << line << CategoryStream::ENDLINE;
+ if (data && (flags & ERR_TXT_STRING))
+ log.errorStream() << "error data: " << data << CategoryStream::ENDLINE;
+ code=ERR_get_error_line_data(&file,&line,&data,&flags);
}
-
- mutex->unlock();
- delete mutex;
- Thread::exit(NULL);
}