# include <unistd.h>
#endif
-#include <shib/shib-threads.h>
#include <shib-target/shib-target.h>
+
#include <log4cpp/Category.hh>
+#include <xmltooling/util/NDC.h>
+#include <xmltooling/util/Threads.h>
+#include <xmltooling/util/XMLHelper.h>
+#include <shibsp/SPConfig.h>
+using xmltooling::XMLHelper;
#include <sstream>
#include <dmalloc.h>
#endif
-using namespace std;
-using namespace saml;
-using namespace shibboleth;
+using namespace shibsp;
using namespace shibtarget;
+using namespace opensaml::saml2md;
+using namespace saml;
using namespace log4cpp;
+using namespace std;
#define PLUGIN_VER_MAJOR 3
#define PLUGIN_VER_MINOR 0
static const XMLCh storeAttributes[] =
{ chLatin_s, chLatin_t, chLatin_o, chLatin_r, chLatin_e, chLatin_A, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e, chLatin_s, chNull };
+static bool g_MySQLInitialized = false;
+
class MySQLBase : public virtual saml::IPlugIn
{
public:
log4cpp::Category* log;
protected:
- ThreadKey* m_mysql;
+ xmltooling::ThreadKey* m_mysql;
const DOMElement* m_root; // can only use this during initialization
bool initialized;
+ bool handleShutdown;
void createDatabase(MYSQL*, int major, int minor);
void upgradeDatabase(MYSQL*);
MySQLBase::MySQLBase(const DOMElement* e) : m_root(e)
{
#ifdef _DEBUG
- saml::NDC ndc("MySQLBase");
+ xmltooling::NDC ndc("MySQLBase");
#endif
- log = &(Category::getInstance("shibmysql.MySQLBase"));
+ log = &(Category::getInstance("shibtarget.SessionCache.MySQL"));
- m_mysql = ThreadKey::create(&shib_mysql_destroy_handle);
+ m_mysql = xmltooling::ThreadKey::create(&shib_mysql_destroy_handle);
initialized = false;
mysqlInit(e,*log);
MYSQL* MySQLBase::getMYSQL()
{
#ifdef _DEBUG
- saml::NDC ndc("getMYSQL");
+ xmltooling::NDC ndc("getMYSQL");
#endif
// Do we already have a handle?
pair<int,int> MySQLBase::getVersion(MYSQL* mysql)
{
// grab the version number from the database
- if (mysql_query(mysql, "SELECT * FROM version"))
- log->error ("Error reading version: %s", mysql_error(mysql));
+ if (mysql_query(mysql, "SELECT * FROM version")) {
+ log->error("error reading version: %s", mysql_error(mysql));
+ throw SAMLException("MySQLBase::getVersion(): error reading version");
+ }
MYSQL_RES* rows = mysql_store_result(mysql);
if (rows) {
log->debug("opening database version %d.%d", major, minor);
mysql_free_result(rows);
return make_pair(major,minor);
- } else {
+ }
+ else {
// Wrong number of rows or wrong number of fields...
log->crit("Houston, we've got a problem with the database...");
- mysql_free_result (rows);
- throw SAMLException("ShibMySQLCCache::getVersion(): version verification failed");
+ mysql_free_result(rows);
+ throw SAMLException("MySQLBase::getVersion(): version verification failed");
}
}
log->crit("MySQL Read Failed in version verification");
- throw SAMLException("ShibMySQLCCache::getVersion(): error reading version");
+ throw SAMLException("MySQLBase::getVersion(): error reading version");
}
static void mysqlInit(const DOMElement* e, Category& log)
{
- static bool done = false;
- if (done) {
+ if (g_MySQLInitialized) {
log.info("MySQL embedded server already initialized");
return;
}
arg_array.push_back("shibboleth");
// grab any MySQL parameters from the config file
- e=saml::XML::getFirstChildElement(e,shibtarget::XML::SHIBTARGET_NS,Argument);
+ e=XMLHelper::getFirstChildElement(e,Argument);
while (e) {
auto_ptr_char arg(e->getFirstChild()->getNodeValue());
if (arg.get())
arg_array.push_back(arg.get());
- e=saml::XML::getNextSiblingElement(e,shibtarget::XML::SHIBTARGET_NS,Argument);
+ e=XMLHelper::getNextSiblingElement(e,Argument);
}
// Compute the argument array
mysql_server_init(arg_count, (char **)args, NULL);
delete[] args;
- done = true;
+ g_MySQLInitialized = true;
}
class ShibMySQLCCache : public MySQLBase, virtual public ISessionCache, virtual public ISessionCacheStore
// Delegate all the ISessionCache methods.
string insert(
const IApplication* application,
- const IEntityDescriptor* source,
+ const RoleDescriptor* role,
const char* client_addr,
const SAMLSubject* subject,
const char* authnContext,
const SAMLResponse* tokens
)
- { return m_cache->insert(application,source,client_addr,subject,authnContext,tokens); }
+ { return m_cache->insert(application,role,client_addr,subject,authnContext,tokens); }
ISessionCacheEntry* find(const char* key, const IApplication* application, const char* client_addr)
{ return m_cache->find(key,application,client_addr); }
void remove(const char* key, const IApplication* application, const char* client_addr)
private:
bool m_storeAttributes;
ISessionCache* m_cache;
- CondWait* shutdown_wait;
+ xmltooling::CondWait* shutdown_wait;
bool shutdown;
- Thread* cleanup_thread;
+ xmltooling::Thread* cleanup_thread;
static void* cleanup_fcn(void*); // XXX Assumed an ShibMySQLCCache
};
ShibMySQLCCache::ShibMySQLCCache(const DOMElement* e) : MySQLBase(e), m_storeAttributes(false)
{
#ifdef _DEBUG
- saml::NDC ndc("ShibMySQLCCache");
+ xmltooling::NDC ndc("ShibMySQLCCache");
#endif
- log = &(Category::getInstance("shibmysql.SessionCache"));
m_cache = dynamic_cast<ISessionCache*>(
- SAMLConfig::getConfig().getPlugMgr().newPlugin(shibtarget::XML::MemorySessionCacheType, e)
+ SAMLConfig::getConfig().getPlugMgr().newPlugin(MEMORY_SESSIONCACHE, e)
);
if (!m_cache->setBackingStore(this)) {
delete m_cache;
throw SAMLException("Unable to register MySQL cache plugin as a cache store.");
}
- shutdown_wait = CondWait::create();
+ shutdown_wait = xmltooling::CondWait::create();
shutdown = false;
// Load our configuration details...
m_storeAttributes=true;
// Initialize the cleanup thread
- cleanup_thread = Thread::create(&cleanup_fcn, (void*)this);
+ cleanup_thread = xmltooling::Thread::create(&cleanup_fcn, (void*)this);
}
ShibMySQLCCache::~ShibMySQLCCache()
)
{
#ifdef _DEBUG
- saml::NDC ndc("onCreate");
+ xmltooling::NDC ndc("onCreate");
#endif
// Get XML data from entry. Default is not to return SAML objects.
)
{
#ifdef _DEBUG
- saml::NDC ndc("onRead");
+ xmltooling::NDC ndc("onRead");
#endif
log->debug("searching MySQL database...");
MYSQL_RES* rows = mysql_store_result(mysql);
// Nope, doesn't exist.
- if (!rows)
+ if (!rows || mysql_num_rows(rows)==0) {
+ log->debug("not found in database");
+ if (rows)
+ mysql_free_result(rows);
return S_FALSE;
+ }
- // Make sure we got 1 and only 1 rows.
- if (mysql_num_rows(rows) != 1) {
- log->error("Database select returned wrong number of rows: %d", mysql_num_rows(rows));
+ // Make sure we got 1 and only 1 row.
+ if (mysql_num_rows(rows) > 1) {
+ log->error("database select returned %d rows!", mysql_num_rows(rows));
mysql_free_result(rows);
- return S_FALSE;
+ return E_FAIL;
}
- log->debug("match found, tranfering data back into memory");
+ log->debug("session found, tranfering data back into memory");
/* Columns in query:
0: application_id
HRESULT ShibMySQLCCache::onRead(const char* key, time_t& accessed)
{
#ifdef _DEBUG
- saml::NDC ndc("onRead");
+ xmltooling::NDC ndc("onRead");
#endif
log->debug("reading last access time from MySQL database");
MYSQL_RES* rows = mysql_store_result(mysql);
// Nope, doesn't exist.
- if (!rows)
+ if (!rows || mysql_num_rows(rows)==0) {
+ log->warn("session expected, but not found in database");
+ if (rows)
+ mysql_free_result(rows);
return S_FALSE;
+ }
- // Make sure we got 1 and only 1 rows.
+ // Make sure we got 1 and only 1 row.
if (mysql_num_rows(rows) != 1) {
- log->error("database select returned wrong number of rows: %d", mysql_num_rows(rows));
+ log->error("database select returned %d rows!", mysql_num_rows(rows));
mysql_free_result(rows);
- return S_FALSE;
+ return E_FAIL;
}
MYSQL_ROW row = mysql_fetch_row(rows);
HRESULT ShibMySQLCCache::onRead(const char* key, string& tokens)
{
#ifdef _DEBUG
- saml::NDC ndc("onRead");
+ xmltooling::NDC ndc("onRead");
#endif
if (!m_storeAttributes)
MYSQL_RES* rows = mysql_store_result(mysql);
// Nope, doesn't exist.
- if (!rows)
+ if (!rows || mysql_num_rows(rows)==0) {
+ log->warn("session expected, but not found in database");
+ if (rows)
+ mysql_free_result(rows);
return S_FALSE;
+ }
- // Make sure we got 1 and only 1 rows.
+ // Make sure we got 1 and only 1 row.
if (mysql_num_rows(rows) != 1) {
- log->error("database select returned wrong number of rows: %d", mysql_num_rows(rows));
+ log->error("database select returned %d rows!", mysql_num_rows(rows));
mysql_free_result(rows);
- return S_FALSE;
+ return E_FAIL;
}
MYSQL_ROW row = mysql_fetch_row(rows);
HRESULT ShibMySQLCCache::onUpdate(const char* key, const char* tokens, time_t lastAccess)
{
#ifdef _DEBUG
- saml::NDC ndc("onUpdate");
+ xmltooling::NDC ndc("onUpdate");
#endif
ostringstream q;
HRESULT ShibMySQLCCache::onDelete(const char* key)
{
#ifdef _DEBUG
- saml::NDC ndc("onDelete");
+ xmltooling::NDC ndc("onDelete");
#endif
// Remove from the database
void ShibMySQLCCache::cleanup()
{
#ifdef _DEBUG
- saml::NDC ndc("cleanup");
+ xmltooling::NDC ndc("cleanup");
#endif
- Mutex* mutex = Mutex::create();
+ xmltooling::Mutex* mutex = xmltooling::Mutex::create();
int rerun_timer = 0;
int timeout_life = 0;
mutex->unlock();
delete mutex;
- Thread::exit(NULL);
+ xmltooling::Thread::exit(NULL);
}
void* ShibMySQLCCache::cleanup_fcn(void* cache_p)
{
ShibMySQLCCache* cache = (ShibMySQLCCache*)cache_p;
- // First, let's block all signals
- Thread::mask_all_signals();
+#ifndef WIN32
+ // First, let'block all signals
+ xmltooling::Thread::mask_all_signals();
+#endif
// Now run the cleanup process.
cache->cleanup();
bool check(const char* str, time_t expires);
};
-MySQLReplayCache::MySQLReplayCache(const DOMElement* e) : MySQLBase(e)
-{
-#ifdef _DEBUG
- saml::NDC ndc("MySQLReplayCache");
-#endif
-
- log = &(Category::getInstance("shibmysql.ReplayCache"));
-}
+MySQLReplayCache::MySQLReplayCache(const DOMElement* e) : MySQLBase(e) {}
bool MySQLReplayCache::check(const char* str, time_t expires)
{
#ifdef _DEBUG
- saml::NDC ndc("check");
+ xmltooling::NDC ndc("check");
#endif
// Remove expired entries
* The registration functions here...
*/
-IPlugIn* new_mysql_ccache(const DOMElement* e)
+SessionCache* new_mysql_ccache(const DOMElement* const & e)
{
return new ShibMySQLCCache(e);
}
extern "C" int SHIBMYSQL_EXPORTS saml_extension_init(void*)
{
// register this ccache type
- SAMLConfig::getConfig().getPlugMgr().regFactory(shibtarget::XML::MySQLReplayCacheType, &new_mysql_replay);
- SAMLConfig::getConfig().getPlugMgr().regFactory(shibtarget::XML::MySQLSessionCacheType, &new_mysql_ccache);
+ SAMLConfig::getConfig().getPlugMgr().regFactory(MYSQL_REPLAYCACHE, &new_mysql_replay);
+ SPConfig::getConfig().SessionCacheManager.registerFactory(MYSQL_SESSIONCACHE, &new_mysql_ccache);
return 0;
}
extern "C" void SHIBMYSQL_EXPORTS saml_extension_term()
{
// Shutdown MySQL
- mysql_server_end();
- SAMLConfig::getConfig().getPlugMgr().unregFactory(shibtarget::XML::MySQLReplayCacheType);
- SAMLConfig::getConfig().getPlugMgr().unregFactory(shibtarget::XML::MySQLSessionCacheType);
+ if (g_MySQLInitialized)
+ mysql_server_end();
+ SAMLConfig::getConfig().getPlugMgr().unregFactory(MYSQL_REPLAYCACHE);
}