using namespace shibtarget;
using namespace log4cpp;
-#define PLUGIN_VER_MAJOR 1
+#define PLUGIN_VER_MAJOR 2
#define PLUGIN_VER_MINOR 0
+#define STATE_TABLE \
+ "CREATE TABLE state (cookie VARCHAR(64) PRIMARY KEY, " \
+ "application_id VARCHAR(255)," \
+ "atime DATETIME," \
+ "addr VARCHAR(128)," \
+ "profile INT," \
+ "provider VARCHAR(256)," \
+ "statement TEXT," \
+ "response TEXT)" \
+
static const XMLCh Argument[] =
{ chLatin_A, chLatin_r, chLatin_g, chLatin_u, chLatin_m, chLatin_e, chLatin_n, chLatin_t, chNull };
static const XMLCh cleanupInterval[] =
{ chLatin_c, chLatin_a, chLatin_c, chLatin_h, chLatin_e, chLatin_T, chLatin_i, chLatin_m, chLatin_e, chLatin_o, chLatin_u, chLatin_t, chNull };
static const XMLCh mysqlTimeout[] =
{ chLatin_m, chLatin_y, chLatin_s, chLatin_q, chLatin_l, chLatin_T, chLatin_i, chLatin_m, chLatin_e, chLatin_o, chLatin_u, chLatin_t, chNull };
+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 };
class ShibMySQLCCache;
class ShibMySQLCCacheEntry : public ISessionCacheEntry
virtual void unlock() { m_cacheEntry->unlock(); delete this; }
virtual bool isValid(time_t lifetime, time_t timeout) const;
virtual const char* getClientAddress() const { return m_cacheEntry->getClientAddress(); }
+ virtual ShibProfile getProfile() const { return m_cacheEntry->getProfile(); }
+ virtual const char* getProviderId() const { return m_cacheEntry->getProviderId(); }
virtual const SAMLAuthenticationStatement* getAuthnStatement() const { return m_cacheEntry->getAuthnStatement(); }
- virtual Iterator<SAMLAssertion*> getAssertions() { return m_cacheEntry->getAssertions(); }
+ virtual const SAMLResponse* getResponse(bool filtered=true) { return m_cacheEntry->getResponse(filtered); }
private:
bool touch() const;
virtual string generateKey() const {return m_cache->generateKey();}
virtual ISessionCacheEntry* find(const char* key, const IApplication* application);
virtual void insert(
- const char* key,
- const IApplication* application,
- SAMLAuthenticationStatement *s,
- const char *client_addr,
- SAMLResponse* r=NULL,
- const IRoleDescriptor* source=NULL);
+ const char* key,
+ const IApplication* application,
+ const char* client_addr,
+ ShibProfile profile,
+ const char* providerId,
+ saml::SAMLAuthenticationStatement* s,
+ saml::SAMLResponse* r=NULL,
+ const shibboleth::IRoleDescriptor* source=NULL
+ );
virtual void remove(const char* key);
void cleanup();
private:
ISessionCache* m_cache;
ThreadKey* m_mysql;
+ bool m_storeAttributes;
const DOMElement* m_root; // can only use this during initialization
static void* cleanup_fcn(void*); // XXX Assumed an ShibMySQLCCache
if (major != PLUGIN_VER_MAJOR || minor != PLUGIN_VER_MINOR) {
// If we're capable, try upgrading on the fly...
- if (major == 0 && minor == 0) {
+ if (major == 0 || major == 1) {
upgradeDatabase(mysql);
}
else {
mysql_close(mysql);
- log->crit("Invalid database version: %d.%d", major, minor);
- throw SAMLException("ShibMySQLCCache::thread_init(): Invalid database version");
+ log->crit("Unknown database version: %d.%d", major, minor);
+ throw SAMLException("ShibMySQLCCache::thread_init(): Unknown database version");
}
}
m_mysql->setData(mysql);
}
-ShibMySQLCCache::ShibMySQLCCache(const DOMElement* e)
+ShibMySQLCCache::ShibMySQLCCache(const DOMElement* e) : m_root(e), m_storeAttributes(false)
{
#ifdef _DEBUG
saml::NDC ndc("shibmysql::ShibMySQLCCache");
m_mysql = ThreadKey::create(&shib_mysql_destroy_handle);
log = &(Category::getInstance("shibmysql::ShibMySQLCCache"));
- m_root=e;
initialized = false;
mysqlInit(e,*log);
thread_init();
"edu.internet2.middleware.shibboleth.sp.provider.MemorySessionCacheProvider", e
)
);
+
+ // Load our configuration details...
+ const XMLCh* tag=m_root->getAttributeNS(NULL,storeAttributes);
+ if (tag && *tag && (*tag==chLatin_t || *tag==chDigit_1))
+ m_storeAttributes=true;
// Initialize the cleanup thread
shutdown_wait = CondWait::create();
log->debug("Looking in database...");
// nothing cached; see if this exists in the database
- string q = string("SELECT application_id,addr,statement FROM state WHERE cookie='") + key + "' LIMIT 1";
+ string q = string("SELECT application_id,addr,profile,provider,statement,response FROM state WHERE cookie='") + key + "' LIMIT 1";
MYSQL_RES* rows;
MYSQL* mysql = getMYSQL();
}
log->debug("Match found. Parsing...");
+
+ /* Columns in query:
+ 0: application_id
+ 1: address
+ 2: profile
+ 3: provider
+ 4: statement
+ 5: response
+ */
// Pull apart the row and process the results
MYSQL_ROW row = mysql_fetch_row(rows);
- IConfig* conf=ShibTargetConfig::getConfig().getINI();
- Locker locker(conf);
- const IApplication* application=conf->getApplication(row[0]);
- if (!application) {
+ if (strcmp(application->getId(),row[0])) {
+ log->crit("An application (%s) attempted to access another application's (%s) session!", application->getId(), row[0]);
mysql_free_result(rows);
- throw ShibTargetException(SHIBRPC_INTERNAL_ERROR,"unable to locate application for session, deleted?");
+ return NULL;
}
- else if (strcmp(row[0],application->getId())) {
- log->crit("An application (%s) attempted to access another application's (%s) session!", application->getId(), row[0]);
+
+ Metadata m(application->getMetadataProviders());
+ const IEntityDescriptor* provider=m.lookup(row[3]);
+ if (!provider) {
+ log->crit("no metadata found for identity provider (%s) responsible for the session.", row[3]);
mysql_free_result(rows);
return NULL;
}
- istringstream str(row[2]);
- SAMLAuthenticationStatement *s = NULL;
+ SAMLAuthenticationStatement* s=NULL;
+ SAMLResponse* r=NULL;
+ const IRoleDescriptor* role=provider->getIDPSSODescriptor(saml::XML::SAML11_PROTOCOL_ENUM);
+ if (!role) {
+ log->crit("no SAML 1.1 IdP role found for identity provider (%s) responsible for the session.", row[3]);
+ mysql_free_result(rows);
+ return NULL;
+ }
- // Try to parse the AuthStatement
+ // Try to parse the SAML data
try {
- s = new SAMLAuthenticationStatement(str);
- } catch (...) {
+ istringstream istr(row[4]);
+ s = new SAMLAuthenticationStatement(istr);
+ if (row[5]) {
+ istr.str(row[5]);
+ r = new SAMLResponse(istr);
+ }
+ }
+ catch (...) {
mysql_free_result(rows);
throw;
}
// Insert it into the memory cache
- if (s)
- m_cache->insert(key, application, s, row[1]);
+ if (s) {
+ m_cache->insert(key, application, row[1], static_cast<ShibProfile>(atoi(row[2])), row[3], s, r, role);
+ }
// Free the results, and then re-run the 'find' query
mysql_free_result(rows);
void ShibMySQLCCache::insert(
const char* key,
const IApplication* application,
- saml::SAMLAuthenticationStatement *s,
- const char *client_addr,
+ const char* client_addr,
+ ShibProfile profile,
+ const char* providerId,
+ saml::SAMLAuthenticationStatement* s,
saml::SAMLResponse* r,
- const IRoleDescriptor* source)
+ const shibboleth::IRoleDescriptor* source
+ )
{
#ifdef _DEBUG
saml::NDC ndc("ShibMySQLCCache::insert");
#endif
- ostringstream os;
- os << *s;
-
- string q = string("INSERT INTO state VALUES('") + key + "','" + application->getId() + "',NOW(),'" + client_addr + "','" + os.str() + "')";
+
+ ostringstream q;
+ q << "INSERT INTO state VALUES('" << key << "','" << application->getId() << "',NOW(),'" << client_addr << "'," << profile
+ << ",'" << providerId << "','" << *s << "',";
+ if (m_storeAttributes)
+ q << "'" << *r << "')";
+ else
+ q << "null)";
- log->debug("Query: %s", q.c_str());
+ log->debug("Query: %s", q.str().c_str());
// then add it to the database
MYSQL* mysql = getMYSQL();
- if (mysql_query(mysql, q.c_str())) {
+ if (mysql_query(mysql, q.str().c_str())) {
const char* err=mysql_error(mysql);
log->error("Error inserting %s: %s", key, err);
if (isCorrupt(err) && repairTable(mysql,"state")) {
// Try again...
- if (mysql_query(mysql, q.c_str()))
+ if (mysql_query(mysql, q.str().c_str()))
log->error("Error inserting %s: %s", key, mysql_error(mysql));
throw SAMLException("ShibMySQLCCache::insert(): inset failed");
}
}
// Add it to the memory cache
- m_cache->insert(key, application, s, client_addr, r, source);
+ m_cache->insert(key, application, client_addr, profile, providerId, s, r, source);
}
void ShibMySQLCCache::remove(const char* key)
throw SAMLException("ShibMySQLCCache::createDatabase(): create table cmd failed");
}
- if (mysql_query(mysql,
- "CREATE TABLE state (cookie VARCHAR(64) PRIMARY KEY, application_id VARCHAR(255),"
- "atime DATETIME, addr VARCHAR(128), statement TEXT)")) {
+ if (mysql_query(mysql,STATE_TABLE)) {
log->error ("Error creating state: %s", mysql_error(mysql));
throw SAMLException("ShibMySQLCCache::createDatabase(): create table cmd failed");
}
log->error("Error dropping old session state table: %s", mysql_error(mysql));
}
- if (mysql_query(mysql,
- "CREATE TABLE state (cookie VARCHAR(64) PRIMARY KEY, application_id VARCHAR(255),"
- "atime DATETIME, addr VARCHAR(128), statement TEXT)")) {
+ if (mysql_query(mysql,STATE_TABLE)) {
log->error ("Error creating state table: %s", mysql_error(mysql));
throw SAMLException("ShibMySQLCCache::upgradeDatabase(): error creating state table");
}
{
public:
InternalCCacheEntry(
- const char* id,
+ const char* key,
const IApplication* application,
+ const char* client_addr,
+ ShibProfile profile,
+ const char* providerId,
SAMLAuthenticationStatement* s,
- const char *client_addr,
SAMLResponse* r=NULL,
const IRoleDescriptor* source=NULL
);
bool isValid(time_t lifetime, time_t timeout) const;
const char* getClientAddress() const { return m_clientAddress.c_str(); }
- const SAMLAuthenticationStatement* getAuthnStatement() const { return p_auth; }
- Iterator<SAMLAssertion*> getAssertions();
+ ShibProfile getProfile() const { return m_profile; }
+ const char* getProviderId() const { return m_provider_id.c_str(); }
+ const SAMLAuthenticationStatement* getAuthnStatement() const { return m_auth_statement; }
+ const SAMLResponse* getResponse(bool filtered=true);
void setCache(InternalCCache *cache) { m_cache = cache; }
time_t lastAccess() const { return m_lastAccess; }
private:
void populate(); // wraps process of checking cache, and repopulating if need be
bool responseValid(); // checks validity of existing response
- SAMLResponse* getNewResponse(); // wraps an actual query
+ pair<SAMLResponse*,SAMLResponse*> getNewResponse(); // wraps an actual query
void filter(SAMLResponse* r, const IApplication* application, const IRoleDescriptor* source);
string m_id;
string m_application_id;
- string m_originSite;
+ string m_provider_id;
string m_clientAddress;
time_t m_sessionCreated;
time_t m_responseCreated;
mutable time_t m_lastAccess;
time_t m_lastRetry;
- const SAMLNameIdentifier* m_nameid;
- SAMLAuthenticationStatement* p_auth;
- SAMLResponse* m_response;
+ ShibProfile m_profile;
+ SAMLAuthenticationStatement* m_auth_statement;
+ SAMLResponse* m_response_pre;
+ SAMLResponse* m_response_post;
InternalCCache *m_cache;
log4cpp::Category* log;
string generateKey() const;
ISessionCacheEntry* find(const char* key, const IApplication* application);
void insert(
- const char* key, const IApplication* application, SAMLAuthenticationStatement* s, const char *client_addr, SAMLResponse* r=NULL, const IRoleDescriptor* source=NULL
+ const char* key,
+ const IApplication* application,
+ const char* client_addr,
+ ShibProfile profile,
+ const char* providerId,
+ SAMLAuthenticationStatement* s,
+ SAMLResponse* r=NULL,
+ const IRoleDescriptor* source=NULL
);
void remove(const char* key);
log4cpp::Category* log;
- static void* cleanup_fcn(void*); // XXX Assumed an InternalCCache
+ static void* cleanup_fcn(void*); // Assumes an InternalCCache
bool shutdown;
CondWait* shutdown_wait;
Thread* cleanup_thread;
// assumes a lock is held..
InternalCCacheEntry* InternalCCache::findi(const char* key)
{
- log->debug("findI: \"%s\"", key);
-
map<string,InternalCCacheEntry*>::const_iterator i=m_hashtable.find(key);
if (i==m_hashtable.end()) {
- log->debug("No Match found");
+ log->debug("No match found");
return NULL;
}
- log->debug("Match Found.");
+ log->debug("Match found");
return i->second;
}
ISessionCacheEntry* InternalCCache::find(const char* key, const IApplication* application)
{
- log->debug("Find: \"%s\"", key);
+ log->debug("searching memory cache for key (%s)", key);
ReadLock rwlock(lock);
InternalCCacheEntry* entry = findi(key);
}
void InternalCCache::insert(
- const char* key, const IApplication* application, SAMLAuthenticationStatement* s, const char* client_addr, SAMLResponse* r, const IRoleDescriptor* source
+ const char* key,
+ const IApplication* application,
+ const char* client_addr,
+ ShibProfile profile,
+ const char* providerId,
+ SAMLAuthenticationStatement* s,
+ SAMLResponse* r,
+ const IRoleDescriptor* source
)
{
log->debug("caching new entry for application %s: \"%s\"", application->getId(), key);
- InternalCCacheEntry* entry = new InternalCCacheEntry(key, application, s, client_addr, r, source);
+ InternalCCacheEntry* entry = new InternalCCacheEntry(key, application, client_addr, profile, providerId, s, r, source);
entry->setCache(this);
lock->wrlock();
// remove the entry from the database and then destroy the cacheentry
void InternalCCache::remove(const char* key)
{
- log->debug("removing cache entry \"key\"", key);
+ log->debug("removing cache entry with key (%s)", key);
// lock the cache for writing, which means we know nobody is sitting in find()
lock->wrlock();
/******************************************************************************/
InternalCCacheEntry::InternalCCacheEntry(
- const char* id,
+ const char* key,
const IApplication* application,
- SAMLAuthenticationStatement *s,
const char* client_addr,
+ ShibProfile profile,
+ const char* providerId,
+ SAMLAuthenticationStatement* s,
SAMLResponse* r,
const IRoleDescriptor* source
- ) : m_response(r), m_responseCreated(r ? time(NULL) : 0), m_lastRetry(0),
- log(&Category::getInstance("shibtarget::InternalCCacheEntry"))
+ ) : m_application_id(application->getId()), m_profile(profile), m_auth_statement(s), m_response_pre(r), m_response_post(NULL),
+ m_responseCreated(r ? time(NULL) : 0), m_lastRetry(0), log(&Category::getInstance("shibtarget::InternalCCacheEntry"))
{
- if (!id || !s) {
- log->error("NULL session ID or auth statement");
- throw SAMLException("InternalCCacheEntry() passed an empty session ID or SAML Statement");
+ if (!key || !s || !client_addr || !providerId) {
+ log->error("missing required cache entry details");
+ throw SAMLException("InternalCCacheEntry() missing required cache entry details");
}
- m_id=id;
- m_application_id=application->getId();
-
- m_nameid = s->getSubject()->getNameIdentifier();
- auto_ptr_char d(m_nameid->getNameQualifier());
- m_originSite = d.get();
-
+ m_id=key;
m_clientAddress = client_addr;
+ m_provider_id = providerId;
m_sessionCreated = m_lastAccess = time(NULL);
- // Save for later.
- p_auth = s;
-
// If pushing attributes, filter the response.
- if (r)
- filter(r, application, source);
+ if (r) {
+ log->debug("filtering attribute information");
+ m_response_post=static_cast<SAMLResponse*>(r->clone());
+ filter(m_response_post, application, source);
+ }
m_lock = Mutex::create();
- log->info("new session created (ID: %s)", id);
+ log->info("new session created with session ID (%s)", key);
if (log->isDebugEnabled()) {
- auto_ptr_char h(m_nameid->getName());
- log->debug("Handle: \"%s\", Origin: \"%s\", Address: %s", h.get(), d.get(), client_addr);
+ auto_ptr_char h(s->getSubject()->getNameIdentifier()->getName());
+ log->debug("NameID (%s), IdP (%s), Address (%s)", h.get(), providerId, client_addr);
}
}
InternalCCacheEntry::~InternalCCacheEntry()
{
log->debug("deleting session (ID: %s)", m_id.c_str());
- delete m_response;
- delete p_auth;
+ delete m_response_pre;
+ delete m_response_post;
+ delete m_auth_statement;
delete m_lock;
}
return true;
}
-Iterator<SAMLAssertion*> InternalCCacheEntry::getAssertions()
+const SAMLResponse* InternalCCacheEntry::getResponse(bool filtered)
{
#ifdef _DEBUG
saml::NDC ndc("getAssertions");
#endif
populate();
- return (m_response) ? m_response->getAssertions() : EMPTY(SAMLAssertion*);
+ return filtered ? m_response_post : m_response_pre;
}
bool InternalCCacheEntry::responseValid()
time_t now=time(NULL) - SAMLConfig::getConfig().clock_skew_secs;
int count = 0;
- Iterator<SAMLAssertion*> iter = m_response->getAssertions();
+ Iterator<SAMLAssertion*> iter = m_response_pre->getAssertions();
while (iter.hasNext()) {
SAMLAssertion* assertion = iter.next();
log->debug("populating attributes for session (ID: %s)", m_id.c_str());
// Do we have any data cached?
- if (m_response) {
+ if (m_response_pre) {
// Can we use what we have?
if (responseValid())
return;
// If we're being strict, dump what we have and reset timestamps.
if (m_cache->m_strictValidity) {
log->info("strictly enforcing attribute validity, dumping expired data");
- delete m_response;
- m_response=NULL;
+ delete m_response_pre;
+ delete m_response_post;
+ m_response_pre=m_response_post=NULL;
m_responseCreated=0;
m_lastRetry=0;
}
") on (applicationId: " <<
m_application_id <<
") for principal from (IdP: " <<
- m_originSite <<
+ m_provider_id <<
")";
stc.releaseTransactionLog();
- SAMLResponse* new_response=getNewResponse();
- if (new_response) {
- delete m_response;
- m_response=new_response;
+ pair<SAMLResponse*,SAMLResponse*> new_responses=getNewResponse();
+ if (new_responses.first) {
+ delete m_response_pre;
+ delete m_response_post;
+ m_response_pre=new_responses.first;
+ m_response_post=new_responses.second;
m_responseCreated=time(NULL);
m_lastRetry=0;
log->debug("fetched and stored new response");
}
}
-SAMLResponse* InternalCCacheEntry::getNewResponse()
+pair<SAMLResponse*,SAMLResponse*> InternalCCacheEntry::getNewResponse()
{
#ifdef _DEBUG
saml::NDC ndc("getNewResponse");
// The retryInterval determines how often to poll an AA that might be down.
time_t now=time(NULL);
if ((now - m_lastRetry) < m_cache->m_retryInterval)
- return NULL;
+ return pair<SAMLResponse*,SAMLResponse*>(NULL,NULL);
if (m_lastRetry)
log->debug("retry interval exceeded, so trying again");
m_lastRetry=now;
// Try this request.
Metadata m(application->getMetadataProviders());
- const IEntityDescriptor* site=m.lookup(m_nameid->getNameQualifier());
+ const IEntityDescriptor* site=m.lookup(m_provider_id.c_str());
if (!site) {
log->error("unable to locate identity provider's metadata during attribute query");
throw ShibTargetException(SHIBRPC_INTERNAL_ERROR,"Unable to locate identity provider's metadata during attribute query.");
try {
// Build a SAML Request....
SAMLAttributeQuery* q=new SAMLAttributeQuery(
- new SAMLSubject(static_cast<SAMLNameIdentifier*>(m_nameid->clone())),
+ new SAMLSubject(static_cast<SAMLNameIdentifier*>(m_auth_statement->getSubject()->getNameIdentifier()->clone())),
providerID.second,
application->getAttributeDesignators().clone()
);
}
}
- if (signedResponse.first && signedResponse.second && !response->isSigned()) {
+ if (response && signedResponse.first && signedResponse.second && !response->isSigned()) {
delete response;
response=NULL;
log->error("unsigned response obtained, but we were told it must be signed.");
}
- else {
- // Run it through the filter. Note that we could end up with an empty response.
- filter(response,application,AA);
+
+ if (response) {
+ // Run a copy through the filter. Note that we could end up with an empty response.
+ SAMLResponse* copy = static_cast<SAMLResponse*>(response->clone());
+ filter(copy,application,AA);
+ return make_pair(response,copy);
}
}
catch (SAMLException& e) {
throw ShibTargetException(SHIBRPC_SAML_EXCEPTION, os.str().c_str(), AA);
}
- // See if we got a response.
- if (!response) {
- log->error("no response obtained");
- throw ShibTargetException(SHIBRPC_INTERNAL_ERROR,"Unable to obtain attributes from user's identity provider.",AA);
- }
- return response;
+ log->error("no response obtained");
+ throw ShibTargetException(SHIBRPC_INTERNAL_ERROR,"Unable to obtain attributes from user's identity provider.",AA);
}
void InternalCCacheEntry::filter(SAMLResponse* r, const IApplication* application, const IRoleDescriptor* source)
Trust t(application->getTrustProviders());
// Examine each new assertion...
+ r->toDOM();
Iterator<SAMLAssertion*> assertions=r->getAssertions();
for (unsigned long i=0; i < assertions.size();) {
try {
const char *session_id;
string m_cookies;
- vector<SAMLAssertion*> m_assertions;
+ ShibProfile m_sso_profile;
+ string m_provider_id;
SAMLAuthenticationStatement* m_sso_statement;
+ SAMLResponse* m_pre_response;
+ SAMLResponse* m_post_response;
// These are the actual request parameters set via the init method.
string m_url;
string uri, string content_type, string remote_host,
string method)
{
+#ifdef _DEBUG
saml::NDC ndc("ShibTarget::init");
+#endif
if (m_priv->m_app)
throw runtime_error("ShibTarget Already Initialized");
}
procState = "Session Processing Error";
- RPCError *status = sessionGet(session_id, m_priv->m_remote_addr.c_str(), m_priv->m_assertions, &m_priv->m_sso_statement);
+ RPCError* status = sessionGet(
+ session_id,
+ m_priv->m_remote_addr.c_str(),
+ m_priv->m_sso_profile,
+ m_priv->m_provider_id,
+ &m_priv->m_sso_statement,
+ &m_priv->m_pre_response,
+ &m_priv->m_post_response
+ );
if (status->isError()) {
// If no session is required, bail now.
if (!requireSession.second)
return pair<bool,void*>(true, returnOK());
- // XXX: Or should this be DECLINED?
- // Has to be OK because DECLINED will just cause Apache
- // to fail when it can't locate anything to process the
- // AuthType. No session plus requireSession false means
- // do not authenticate the user at this time.
+ // XXX: Or should this be DECLINED?
+ // Has to be OK because DECLINED will just cause Apache
+ // to fail when it can't locate anything to process the
+ // AuthType. No session plus requireSession false means
+ // do not authenticate the user at this time.
else if (status->isRetryable()) {
// Session is invalid but we can retry the auth -- generate an AuthnRequest
delete status;
}
// process the submission
- string cookie,target;
- RPCError* status = sessionNew(cgistr.c_str(), m_priv->m_remote_addr.c_str(),cookie,target);
+ string cookie,target,statemgr_packet;
+ RPCError* status = sessionNew(
+ SAML_11_POST | SAML_11_ARTIFACT,
+ cgistr.c_str(),
+ NULL, // XXX: no state token yet
+ m_priv->m_remote_addr.c_str(),
+ cookie,
+ target,
+ statemgr_packet
+ );
if (status->isError()) {
char buf[25];
if (m_priv->m_settings.second) {
Locker acllock(m_priv->m_settings.second);
if (!m_priv->m_settings.second->authorized(*m_priv->m_sso_statement,
- m_priv->m_assertions)) {
+ m_priv->m_post_response ? m_priv->m_post_response->getAssertions() : EMPTY(SAMLAssertion*))) {
log(LogLevelError, "doCheckAuthZ: access control provider denied access");
goto out;
}
pair<bool,void*>
ShibTarget::doExportAssertions(bool exportAssertion)
{
+#ifdef _DEBUG
saml::NDC ndc("ShibTarget::doExportAssertions");
+#endif
ShibMLP mlp;
const char *procState = "Attribute Processing Error";
if (!m_priv->m_sso_statement) {
// No data yet, so we need to get the session. This can only happen
// if the call to doCheckAuthn doesn't happen in the same object lifetime.
- RPCError* status = sessionGet(session_id, m_priv->m_remote_addr.c_str(), m_priv->m_assertions, &m_priv->m_sso_statement);
+ RPCError* status = sessionGet(
+ session_id,
+ m_priv->m_remote_addr.c_str(),
+ m_priv->m_sso_profile,
+ m_priv->m_provider_id,
+ &m_priv->m_sso_statement,
+ &m_priv->m_pre_response,
+ &m_priv->m_post_response
+ );
if (status->isError()) {
- string er = "getAssertions failed: ";
+ string er = "sessionGet failed: ";
er += status->getText();
log(ShibTarget::LogLevelError, er);
mlp.insert(*status);
if (!exp.first || !exp.second)
if (exportAssertion)
exp.second=true;
- if (exp.second && m_priv->m_assertions.size()) {
+ if (exp.second && m_priv->m_pre_response) {
ostringstream os;
- os << *(m_priv->m_assertions[0]);
+ os << *(m_priv->m_pre_response);
unsigned int outlen;
- char* assn = (char*)os.str().c_str();
- XMLByte* serialized = Base64::encode(reinterpret_cast<XMLByte*>(assn), os.str().length(), &outlen);
- string assertion = (char*)serialized;
- XMLString::release(&serialized);
- setHeader("Shib-Attributes", assertion.c_str());
+ char* resp = (char*)os.str().c_str();
+ XMLByte* serialized = Base64::encode(reinterpret_cast<XMLByte*>(resp), os.str().length(), &outlen);
+ setHeader("Shib-Attributes", reinterpret_cast<char*>(serialized));
+ XMLString::release(&serialized);
}
// Export the SAML AuthnMethod and the origin site name, and possibly the NameIdentifier.
clearHeader("Shib-Identity-Provider");
clearHeader("Shib-Authentication-Method");
clearHeader("Shib-NameIdentifier-Format");
- auto_ptr_char os(m_priv->m_sso_statement->getSubject()->getNameIdentifier()->getNameQualifier());
+ setHeader("Shib-Origin-Site", m_priv->m_provider_id.c_str());
+ setHeader("Shib-Identity-Provider", m_priv->m_provider_id.c_str());
auto_ptr_char am(m_priv->m_sso_statement->getAuthMethod());
- setHeader("Shib-Origin-Site", os.get());
- setHeader("Shib-Identity-Provider", os.get());
setHeader("Shib-Authentication-Method", am.get());
// Export NameID?
setHeader("Shib-Application-ID", m_priv->m_app->getId());
// Export the attributes.
- Iterator<SAMLAssertion*> a_iter(m_priv->m_assertions);
+ Iterator<SAMLAssertion*> a_iter(m_priv->m_post_response ? m_priv->m_post_response->getAssertions() : EMPTY(SAMLAssertion*));
while (a_iter.hasNext()) {
SAMLAssertion* assert=a_iter.next();
Iterator<SAMLStatement*> statements=assert->getStatements();
return getAuthnRequest(target);
}
-RPCError*
-ShibTarget::sessionNew(const char* packet, const char* ip, string& cookie, string& target)
- const
+RPCError* ShibTarget::sessionNew(
+ int supported_profiles,
+ const char* packet,
+ const char* statemgr_cookie,
+ const char* ip,
+ string& cookie,
+ string& target,
+ string& statemgr_packet
+ ) const
{
#ifdef _DEBUG
- saml::NDC ndc("sessionCreate");
+ saml::NDC ndc("sessionNew");
#endif
Category& log = Category::getInstance("shibtarget.ShibTarget");
if (!packet || !*packet) {
- log.error ("Empty SAML response content");
- return new RPCError(SHIBRPC_RESPONSE_MISSING, "Empty SAML response content");
+ log.error("Empty profile content");
+ return new RPCError(SHIBRPC_RESPONSE_MISSING, "Empty profile content");
}
if (!ip || !*ip) {
- log.error ("Invalid IP address");
+ log.error("Invalid IP address");
return new RPCError(SHIBRPC_IPADDR_MISSING, "Invalid IP address");
}
+ if (supported_profiles <= 0) {
+ log.error("No profile support indicated");
+ return new RPCError(SHIBRPC_INTERNAL_ERROR, "No profile support indicated");
+ }
+
shibrpc_new_session_args_2 arg;
arg.recipient = (char*) m_priv->m_shireURL.c_str();
arg.application_id = (char*) m_priv->m_app->getId();
arg.packet = (char*)packet;
arg.client_addr = (char*)ip;
- arg.checkIPAddress = true;
-
- log.info ("create session for user at %s for application %s", ip, arg.application_id);
+ arg.supported_profiles = supported_profiles;
+ if (statemgr_cookie)
+ arg.cookie = (char*)statemgr_cookie;
+ else
+ arg.cookie = "";
- const IPropertySet* props=m_priv->m_app->getPropertySet("Sessions");
- if (props) {
- pair<bool,bool> pcheck=props->getBool("checkAddress");
- if (pcheck.first)
- arg.checkIPAddress = pcheck.second;
- }
+ log.info("create session for user at (%s) for application (%s) with state token (%s)",
+ ip, arg.application_id, statemgr_cookie);
shibrpc_new_session_ret_2 ret;
- memset (&ret, 0, sizeof(ret));
+ memset(&ret, 0, sizeof(ret));
// Loop on the RPC in case we lost contact the first time through
int retry = 1;
if (ret.status.status)
retval = new RPCError(&ret.status);
else {
- log.debug ("new cookie: %s", ret.cookie);
+ log.debug ("new session cookie: %s", ret.cookie);
cookie = ret.cookie;
if (ret.target)
target = ret.target;
+ if (ret.packet)
+ statemgr_packet = ret.packet;
retval = new RPCError();
}
return retval;
}
-RPCError*
-ShibTarget::sessionGet(
+RPCError* ShibTarget::sessionGet(
const char* cookie,
const char* ip,
- std::vector<saml::SAMLAssertion*>& assertions,
- saml::SAMLAuthenticationStatement **statement
+ ShibProfile& profile,
+ string& provider_id,
+ SAMLAuthenticationStatement** auth_statement,
+ SAMLResponse** attr_response_pre,
+ SAMLResponse** attr_response_post
) const
{
#ifdef _DEBUG
Category& log = Category::getInstance("shibtarget.ShibTarget");
if (!cookie || !*cookie) {
- log.error ("No cookie value was provided");
+ log.error("No cookie value was provided");
return new RPCError(SHIBRPC_NO_SESSION, "No cookie value was provided");
}
else if (strchr(cookie,'=')) {
- log.error ("The cookie value wasn't extracted successfully, use a more unique cookie name for your installation.");
+ log.error("The cookie value wasn't extracted successfully, use a more unique cookie name for your installation.");
return new RPCError(SHIBRPC_INTERNAL_ERROR, "The cookie value wasn't extracted successfully, use a more unique cookie name for your installation.");
}
if (!ip || !*ip) {
- log.error ("Invalid IP Address");
+ log.error("Invalid IP Address");
return new RPCError(SHIBRPC_IPADDR_MISSING, "Invalid IP Address");
}
- log.info ("get session for client address (%s)", ip);
- log.debug ("session cookie (%s)", cookie);
+ log.info("getting session for client at (%s)", ip);
+ log.debug("session cookie (%s)", cookie);
shibrpc_get_session_args_2 arg;
arg.cookie = (char*)cookie;
arg.client_addr = (char*)ip;
arg.application_id = (char*)m_priv->m_app->getId();
-
- // Get rest of input from the application Session properties.
- arg.lifetime = 3600;
- arg.timeout = 1800;
- arg.checkIPAddress = true;
- const IPropertySet* props=m_priv->m_app->getPropertySet("Sessions");
- if (props) {
- pair<bool,unsigned int> p=props->getUnsignedInt("lifetime");
- if (p.first)
- arg.lifetime = p.second;
- p=props->getUnsignedInt("timeout");
- if (p.first)
- arg.timeout = p.second;
- pair<bool,bool> pcheck=props->getBool("checkAddress");
- if (pcheck.first)
- arg.checkIPAddress = pcheck.second;
- }
-
+
shibrpc_get_session_ret_2 ret;
memset (&ret, 0, sizeof(ret));
else {
try {
try {
- for (u_int i = 0; i < ret.assertions.assertions_len; i++) {
- istringstream attrstream(ret.assertions.assertions_val[i].xml_string);
- SAMLAssertion *as = NULL;
- log.debugStream() << "Trying to decode assertion " << i << ": " <<
- ret.assertions.assertions_val[i].xml_string << CategoryStream::ENDLINE;
- assertions.push_back(new SAMLAssertion(attrstream));
+ profile = ret.profile;
+ provider_id = ret.provider_id;
+
+ // return the Authentication Statement
+ if (auth_statement) {
+ istringstream authstream(ret.auth_statement);
+
+ log.debugStream() << "Trying to decode authentication statement: "
+ << ret.auth_statement << CategoryStream::ENDLINE;
+ *auth_statement = new SAMLAuthenticationStatement(authstream);
}
- // return the Authentication Statement
- if (statement) {
- istringstream authstream(ret.auth_statement.xml_string);
- SAMLAuthenticationStatement *auth = NULL;
+ // return the unfiltered Response
+ if (attr_response_pre) {
+ istringstream prestream(ret.attr_response_pre);
- log.debugStream() << "Trying to decode authentication statement: " <<
- ret.auth_statement.xml_string << CategoryStream::ENDLINE;
- auth = new SAMLAuthenticationStatement(authstream);
-
- // Save off the statement
- *statement = auth;
+ log.debugStream() << "Trying to decode unfiltered attribute response: "
+ << ret.attr_response_pre << CategoryStream::ENDLINE;
+ *attr_response_pre = new SAMLResponse(prestream);
+ }
+
+ // return the filtered Response
+ if (attr_response_post) {
+ istringstream poststream(ret.attr_response_post);
+
+ log.debugStream() << "Trying to decode filtered attribute response: "
+ << ret.attr_response_post << CategoryStream::ENDLINE;
+ *attr_response_post = new SAMLResponse(poststream);
}
}
catch (SAMLException& e) {
* Shib Target Private implementation
*/
-ShibTargetPriv::ShibTargetPriv()
- : m_app(NULL), m_mapper(NULL), m_conf(NULL), m_Config(NULL), session_id(NULL), m_sso_statement(NULL) {}
+ShibTargetPriv::ShibTargetPriv() : m_app(NULL), m_mapper(NULL), m_conf(NULL), m_Config(NULL), session_id(NULL),
+ m_sso_profile(PROFILE_UNSPECIFIED), m_sso_statement(NULL), m_pre_response(NULL), m_post_response(NULL) {}
ShibTargetPriv::~ShibTargetPriv()
{
delete m_sso_statement;
m_sso_statement = NULL;
- for (int k = 0; k < m_assertions.size(); k++)
- delete m_assertions[k];
- m_assertions.clear();
+ delete m_pre_response;
+ m_pre_response = NULL;
+
+ delete m_post_response;
+ m_post_response = NULL;
if (m_mapper) {
m_mapper->unlock();
{
virtual bool isValid(time_t lifetime, time_t timeout) const=0;
virtual const char* getClientAddress() const=0;
+ virtual ShibProfile getProfile() const=0;
+ virtual const char* getProviderId() const=0;
virtual const saml::SAMLAuthenticationStatement* getAuthnStatement() const=0;
- virtual saml::Iterator<saml::SAMLAssertion*> getAssertions()=0;
+ virtual const saml::SAMLResponse* getResponse(bool filtered=true)=0;
virtual ~ISessionCacheEntry() {}
};
virtual void insert(
const char* key,
const IApplication* application,
- saml::SAMLAuthenticationStatement *s,
const char* client_addr,
+ ShibProfile profile,
+ const char* providerId,
+ saml::SAMLAuthenticationStatement* s,
saml::SAMLResponse* r=NULL,
const shibboleth::IRoleDescriptor* source=NULL
)=0;
// Currently wraps remoted interface.
// TODO: Move this functionality behind ISessionCache
+ RPCError* stateMgr(
+ const char* packet,
+ const char* ip,
+ std::string& cookie
+ ) const;
+
RPCError* sessionNew(
- const char* packet,
- const char* ip,
- std::string& cookie,
- std::string& target
- ) const;
+ int supported_profiles,
+ const char* packet,
+ const char* statemgr_cookie,
+ const char* ip,
+ std::string& cookie,
+ std::string& target,
+ std::string& statemgr_packet
+ ) const;
RPCError* sessionGet(
- const char* cookie,
- const char* ip,
- std::vector<saml::SAMLAssertion*>& assertions,
- saml::SAMLAuthenticationStatement **statement = NULL
- ) const;
+ const char* cookie,
+ const char* ip,
+ ShibProfile& profile,
+ std::string& provider_id,
+ saml::SAMLAuthenticationStatement** auth_statement=NULL,
+ saml::SAMLResponse** attr_response_pre=NULL,
+ saml::SAMLResponse** attr_response_post=NULL
+ ) const;
// Initialize the request from the parsed URL
// protocol == http, https, etc
(xdrproc_t) xdr_shibrpc_get_session_ret_2, (caddr_t) clnt_res,
TIMEOUT));
}
+
+enum clnt_stat
+shibrpc_statemgr_2(shibrpc_statemgr_args_2 *argp, shibrpc_statemgr_ret_2 *clnt_res, CLIENT *clnt)
+{
+ return (clnt_call(clnt, shibrpc_statemgr,
+ (xdrproc_t) xdr_shibrpc_statemgr_args_2, (caddr_t) argp,
+ (xdrproc_t) xdr_shibrpc_statemgr_ret_2, (caddr_t) clnt_res,
+ TIMEOUT));
+}
return retval;
}
+bool_t
+shibrpc_statemgr_2_svc(shibrpc_statemgr_args_2 *argp, shibrpc_statemgr_ret_2 *result, struct svc_req *rqstp)
+{
+ bool_t retval;
+
+ /*
+ * insert server code here
+ */
+
+ return retval;
+}
+
int
shibrpc_prog_2_freeresult (SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result)
{
}
memset (result, 0, sizeof (*result));
- result->auth_statement.xml_string = strdup("");
-
- log.debug ("checking: %s@%s (checkAddr=%s)",
- argp->cookie, argp->client_addr, argp->checkIPAddress ? "true" : "false");
+ result->provider_id = strdup("");
+ result->auth_statement = strdup("");
+ result->attr_response_pre = strdup("");
+ result->attr_response_post = strdup("");
+
+ log.debug ("checking: %s@%s", argp->cookie, argp->client_addr);
// See if the session exists...
return TRUE;
}
+ bool checkIPAddress=true;
+ int lifetime=0,timeout=0;
+ const IPropertySet* props=app->getPropertySet("Sessions");
+ if (props) {
+ pair<bool,unsigned int> p=props->getUnsignedInt("lifetime");
+ if (p.first)
+ lifetime = p.second;
+ p=props->getUnsignedInt("timeout");
+ if (p.first)
+ timeout = p.second;
+ pair<bool,bool> pcheck=props->getBool("checkAddress");
+ if (pcheck.first)
+ checkIPAddress = pcheck.second;
+ }
+
ISessionCacheEntry* entry = conf->getSessionCache()->find(argp->cookie,app);
// If not, leave now..
// TEST the session...
try {
// Verify the address is the same
- if (argp->checkIPAddress) {
- log.debug ("Checking address against %s", entry->getClientAddress());
- if (strcmp (argp->client_addr, entry->getClientAddress())) {
+ if (checkIPAddress) {
+ log.debug("Checking address against %s", entry->getClientAddress());
+ if (strcmp(argp->client_addr, entry->getClientAddress())) {
log.debug ("IP Address mismatch");
Metadata m(app->getMetadataProviders());
throw ShibTargetException(SHIBRPC_IPADDR_MISMATCH,
"Your IP address does not match the address recorded at the time the session was established.",
- m.lookup(entry->getAuthnStatement()->getSubject()->getNameIdentifier()->getNameQualifier()));
+ m.lookup(entry->getProviderId()));
}
}
// and that the session is still valid...
- if (!entry->isValid(argp->lifetime, argp->timeout)) {
+ if (!entry->isValid(lifetime,timeout)) {
log.debug ("Session expired");
Metadata m(app->getMetadataProviders());
throw ShibTargetException(SHIBRPC_SESSION_EXPIRED,
"Your session has expired, and you must re-authenticate.",
- m.lookup(entry->getAuthnStatement()->getSubject()->getNameIdentifier()->getNameQualifier()));
+ m.lookup(entry->getProviderId()));
}
try {
- // Now grab the serialized authentication statement
+ // Set profile and provider
+ result->profile = entry->getProfile();
+ free(result->provider_id);
+ result->provider_id = strdup(entry->getProviderId());
+
+ // Now grab the serialized authentication statement and responses
ostringstream os;
os << *(entry->getAuthnStatement());
- free(result->auth_statement.xml_string);
- result->auth_statement.xml_string = strdup(os.str().c_str());
-
- // grab the attributes for this session
- Iterator<SAMLAssertion*> iter = entry->getAssertions();
- u_int size = iter.size();
-
- // if we have assertions...
- if (size) {
- // Build the response section
- ShibRpcXML* av = (ShibRpcXML*) malloc (size * sizeof (ShibRpcXML));
-
- // and then serialize them all...
- u_int i = 0;
- while (iter.hasNext()) {
- SAMLAssertion* as = iter.next();
- ostringstream os2;
- os2 << *as;
- av[i++].xml_string = strdup(os2.str().c_str());
- }
-
- // Set the results, once we know we've succeeded.
- result->assertions.assertions_len = size;
- result->assertions.assertions_val = av;
- }
+ free(result->auth_statement);
+ result->auth_statement = strdup(os.str().c_str());
+
+ os.str("");
+ os << *(entry->getResponse(false));
+ free(result->attr_response_pre);
+ result->attr_response_pre = strdup(os.str().c_str());
+
+ os.str("");
+ os << *(entry->getResponse(true));
+ free(result->attr_response_post);
+ result->attr_response_post = strdup(os.str().c_str());
}
catch (SAMLException &e) {
log.error ("caught SAML exception: %s", e.what());
ostringstream os;
os << e;
Metadata m(app->getMetadataProviders());
- throw ShibTargetException(SHIBRPC_SAML_EXCEPTION, os.str().c_str(),
- m.lookup(entry->getAuthnStatement()->getSubject()->getNameIdentifier()->getNameQualifier()));
+ throw ShibTargetException(SHIBRPC_SAML_EXCEPTION, os.str().c_str(), m.lookup(entry->getProviderId()));
}
}
catch (ShibTargetException &e) {
memset (result, 0, sizeof(*result));
result->cookie = strdup ("");
result->target = strdup ("");
+ result->packet = strdup ("");
log.debug ("creating session for %s", argp->client_addr);
log.debug ("recipient: %s", argp->recipient);
return TRUE;
}
- // TODO: Sub in call to getReplayCache() as the determinant.
- // For now, we always have a cache and use the flag...
- pair<bool,bool> checkReplay=pair<bool,bool>(false,false);
+ bool checkIPAddress=true;
const IPropertySet* props=app->getPropertySet("Sessions");
+ if (props) {
+ pair<bool,bool> pcheck=props->getBool("checkAddress");
+ if (pcheck.first)
+ checkIPAddress = pcheck.second;
+ }
+
+ pair<bool,bool> checkReplay=pair<bool,bool>(false,false);
+ props=app->getPropertySet("Sessions");
if (props)
checkReplay=props->getBool("checkReplay");
"Unable to locate role-specific metadata for identity provider", provider);
// Maybe verify the origin address....
- if (argp->checkIPAddress) {
+ if (checkIPAddress) {
log.debug ("verify client address");
// Verify the client address exists
}
// Insertion into cache might fail.
+ auto_ptr_char oname(origin);
SAMLAuthenticationStatement* as=NULL;
try {
as=static_cast<SAMLAuthenticationStatement*>(bpr.authnStatement->clone());
conf->getSessionCache()->insert(
cookie.c_str(),
app,
- as,
argp->client_addr,
+ SAML_11_POST, // TODO: need to vary this
+ oname.get(),
+ as,
(attributesPushed ? bpr.response : NULL),
role
);
// Transaction Logging
STConfig& stc=static_cast<STConfig&>(ShibTargetConfig::getConfig());
- auto_ptr_char oname(origin);
auto_ptr_char hname(as->getSubject()->getNameIdentifier()->getName());
stc.getTransactionLog().infoStream() <<
"New session (ID: " <<
return TRUE;
}
+extern "C" bool_t
+shibrpc_statemgr_2_svc(
+ shibrpc_statemgr_args_2 *argp,
+ shibrpc_statemgr_ret_2 *result,
+ struct svc_req *rqstp
+ )
+{
+ return FALSE;
+}
+
extern "C" int
shibrpc_prog_2_freeresult (SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result)
{
#include <rpc/pmap_clnt.h>
#include <string.h>
#include <memory.h>
-
#ifdef WIN32
# include <winsock.h>
#else
int shibrpc_ping_2_arg;
shibrpc_new_session_args_2 shibrpc_new_session_2_arg;
shibrpc_get_session_args_2 shibrpc_get_session_2_arg;
+ shibrpc_statemgr_args_2 shibrpc_statemgr_2_arg;
} argument;
union {
int shibrpc_ping_2_res;
shibrpc_new_session_ret_2 shibrpc_new_session_2_res;
shibrpc_get_session_ret_2 shibrpc_get_session_2_res;
+ shibrpc_statemgr_ret_2 shibrpc_statemgr_2_res;
} result;
bool_t retval;
xdrproc_t _xdr_argument, _xdr_result;
local = (bool_t (*) (char *, void *, struct svc_req *))shibrpc_get_session_2_svc;
break;
+ case shibrpc_statemgr:
+ _xdr_argument = (xdrproc_t) xdr_shibrpc_statemgr_args_2;
+ _xdr_result = (xdrproc_t) xdr_shibrpc_statemgr_ret_2;
+ local = (bool_t (*) (char *, void *, struct svc_req *))shibrpc_statemgr_2_svc;
+ break;
+
default:
svcerr_noproc (transp);
return;
}
bool_t
-xdr_ShibRpcXML (XDR *xdrs, ShibRpcXML *objp)
+xdr_ShibProfile (XDR *xdrs, ShibProfile *objp)
{
register int32_t *buf;
- if (!xdr_string (xdrs, &objp->xml_string, ~0))
+ if (!xdr_enum (xdrs, (enum_t *) objp))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_shibrpc_statemgr_args_2 (XDR *xdrs, shibrpc_statemgr_args_2 *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_string (xdrs, &objp->application_id, ~0))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->packet, ~0))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->client_addr, ~0))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_shibrpc_statemgr_ret_2 (XDR *xdrs, shibrpc_statemgr_ret_2 *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_ShibRpcError (xdrs, &objp->status))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->cookie, ~0))
return FALSE;
return TRUE;
}
{
register int32_t *buf;
+ if (!xdr_int (xdrs, &objp->supported_profiles))
+ return FALSE;
if (!xdr_string (xdrs, &objp->application_id, ~0))
return FALSE;
if (!xdr_string (xdrs, &objp->packet, ~0))
return FALSE;
+ if (!xdr_string (xdrs, &objp->cookie, ~0))
+ return FALSE;
if (!xdr_string (xdrs, &objp->recipient, ~0))
return FALSE;
if (!xdr_string (xdrs, &objp->client_addr, ~0))
return FALSE;
- if (!xdr_bool (xdrs, &objp->checkIPAddress))
- return FALSE;
return TRUE;
}
return FALSE;
if (!xdr_string (xdrs, &objp->target, ~0))
return FALSE;
+ if (!xdr_string (xdrs, &objp->packet, ~0))
+ return FALSE;
if (!xdr_string (xdrs, &objp->cookie, ~0))
return FALSE;
return TRUE;
return FALSE;
if (!xdr_string (xdrs, &objp->client_addr, ~0))
return FALSE;
- if (!xdr_bool (xdrs, &objp->checkIPAddress))
- return FALSE;
- if (!xdr_long (xdrs, &objp->lifetime))
- return FALSE;
- if (!xdr_long (xdrs, &objp->timeout))
- return FALSE;
return TRUE;
}
if (!xdr_ShibRpcError (xdrs, &objp->status))
return FALSE;
- if (!xdr_ShibRpcXML (xdrs, &objp->auth_statement))
+ if (!xdr_ShibProfile (xdrs, &objp->profile))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->provider_id, ~0))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->auth_statement, ~0))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->attr_response_pre, ~0))
return FALSE;
- if (!xdr_array (xdrs, (char **)&objp->assertions.assertions_val, (u_int *) &objp->assertions.assertions_len, ~0,
- sizeof (ShibRpcXML), (xdrproc_t) xdr_ShibRpcXML))
+ if (!xdr_string (xdrs, &objp->attr_response_post, ~0))
return FALSE;
return TRUE;
}
};
typedef struct ShibRpcError ShibRpcError;
-struct ShibRpcXML {
- char *xml_string;
+enum ShibProfile {
+ PROFILE_UNSPECIFIED = 0,
+ SAML_10_POST = 1,
+ SAML_10_ARTIFACT = 2,
+ SAML_11_POST = 4,
+ SAML_11_ARTIFACT = 8,
+ SAML_20_SSO = 16,
};
-typedef struct ShibRpcXML ShibRpcXML;
+typedef enum ShibProfile ShibProfile;
+
+struct shibrpc_statemgr_args_2 {
+ char *application_id;
+ char *packet;
+ char *client_addr;
+};
+typedef struct shibrpc_statemgr_args_2 shibrpc_statemgr_args_2;
+
+struct shibrpc_statemgr_ret_2 {
+ ShibRpcError status;
+ char *cookie;
+};
+typedef struct shibrpc_statemgr_ret_2 shibrpc_statemgr_ret_2;
struct shibrpc_new_session_args_2 {
+ int supported_profiles;
char *application_id;
char *packet;
+ char *cookie;
char *recipient;
char *client_addr;
- bool_t checkIPAddress;
};
typedef struct shibrpc_new_session_args_2 shibrpc_new_session_args_2;
struct shibrpc_new_session_ret_2 {
ShibRpcError status;
char *target;
+ char *packet;
char *cookie;
};
typedef struct shibrpc_new_session_ret_2 shibrpc_new_session_ret_2;
char *application_id;
char *cookie;
char *client_addr;
- bool_t checkIPAddress;
- long lifetime;
- long timeout;
};
typedef struct shibrpc_get_session_args_2 shibrpc_get_session_args_2;
struct shibrpc_get_session_ret_2 {
ShibRpcError status;
- ShibRpcXML auth_statement;
- struct {
- u_int assertions_len;
- ShibRpcXML *assertions_val;
- } assertions;
+ ShibProfile profile;
+ char *provider_id;
+ char *auth_statement;
+ char *attr_response_pre;
+ char *attr_response_post;
};
typedef struct shibrpc_get_session_ret_2 shibrpc_get_session_ret_2;
#define shibrpc_get_session 2
extern enum clnt_stat shibrpc_get_session_2(shibrpc_get_session_args_2 *, shibrpc_get_session_ret_2 *, CLIENT *);
extern bool_t shibrpc_get_session_2_svc(shibrpc_get_session_args_2 *, shibrpc_get_session_ret_2 *, struct svc_req *);
+#define shibrpc_statemgr 3
+extern enum clnt_stat shibrpc_statemgr_2(shibrpc_statemgr_args_2 *, shibrpc_statemgr_ret_2 *, CLIENT *);
+extern bool_t shibrpc_statemgr_2_svc(shibrpc_statemgr_args_2 *, shibrpc_statemgr_ret_2 *, struct svc_req *);
extern int shibrpc_prog_2_freeresult (SVCXPRT *, xdrproc_t, caddr_t);
#else /* K&R C */
#define shibrpc_get_session 2
extern enum clnt_stat shibrpc_get_session_2();
extern bool_t shibrpc_get_session_2_svc();
+#define shibrpc_statemgr 3
+extern enum clnt_stat shibrpc_statemgr_2();
+extern bool_t shibrpc_statemgr_2_svc();
extern int shibrpc_prog_2_freeresult ();
#endif /* K&R C */
extern bool_t xdr_ShibRpcStatus (XDR *, ShibRpcStatus*);
extern bool_t xdr_ShibRpcErr (XDR *, ShibRpcErr*);
extern bool_t xdr_ShibRpcError (XDR *, ShibRpcError*);
-extern bool_t xdr_ShibRpcXML (XDR *, ShibRpcXML*);
+extern bool_t xdr_ShibProfile (XDR *, ShibProfile*);
+extern bool_t xdr_shibrpc_statemgr_args_2 (XDR *, shibrpc_statemgr_args_2*);
+extern bool_t xdr_shibrpc_statemgr_ret_2 (XDR *, shibrpc_statemgr_ret_2*);
extern bool_t xdr_shibrpc_new_session_args_2 (XDR *, shibrpc_new_session_args_2*);
extern bool_t xdr_shibrpc_new_session_ret_2 (XDR *, shibrpc_new_session_ret_2*);
extern bool_t xdr_shibrpc_get_session_args_2 (XDR *, shibrpc_get_session_args_2*);
extern bool_t xdr_ShibRpcStatus ();
extern bool_t xdr_ShibRpcErr ();
extern bool_t xdr_ShibRpcError ();
-extern bool_t xdr_ShibRpcXML ();
+extern bool_t xdr_ShibProfile ();
+extern bool_t xdr_shibrpc_statemgr_args_2 ();
+extern bool_t xdr_shibrpc_statemgr_ret_2 ();
extern bool_t xdr_shibrpc_new_session_args_2 ();
extern bool_t xdr_shibrpc_new_session_ret_2 ();
extern bool_t xdr_shibrpc_get_session_args_2 ();
ShibRpcErr e;
};
-struct ShibRpcXML {
- string xml_string<>;
+/* enumerate profiles/bindings to support */
+enum ShibProfile {
+ PROFILE_UNSPECIFIED = 0,
+ SAML_10_POST = 1,
+ SAML_10_ARTIFACT = 2,
+ SAML_11_POST = 4,
+ SAML_11_ARTIFACT = 8,
+ SAML_20_SSO = 16
};
/* function argument and response structures */
+struct shibrpc_statemgr_args_2 {
+ string application_id<>;
+ string packet<>; /* opaque state to manage */
+ string client_addr<>;
+};
+
+struct shibrpc_statemgr_ret_2 {
+ ShibRpcError status;
+ string cookie<>; /* state token returned to caller */
+};
+
struct shibrpc_new_session_args_2 {
+ int supported_profiles; /* bitmask of supported profiles */
string application_id<>;
- string packet<>;
- string recipient<>;
+ string packet<>; /* profile input packet from client */
+ string cookie<>; /* statemgr token, if any */
+ string recipient<>; /* endpoint that received packet */
string client_addr<>;
- bool checkIPAddress;
};
struct shibrpc_new_session_ret_2 {
ShibRpcError status;
- string target<>;
- string cookie<>;
+ string target<>; /* profile-specific state token from client */
+ string packet<>; /* state token recovered by statemgr, if any */
+ string cookie<>; /* session key manufactured for client */
};
struct shibrpc_get_session_args_2 {
string application_id<>;
- string cookie<>;
+ string cookie<>; /* session key provided by client */
string client_addr<>;
- bool checkIPAddress;
- long lifetime;
- long timeout;
};
struct shibrpc_get_session_ret_2 {
ShibRpcError status;
- ShibRpcXML auth_statement;
- ShibRpcXML assertions<>;
+ ShibProfile profile; /* profile used in creating session */
+ string provider_id<>; /* authenticating IdP */
+ string auth_statement<>; /* SAML authn statement */
+ string attr_response_pre<>; /* SAML attr assertions as received */
+ string attr_response_post<>; /* SAML attr assertions post-filtering */
};
/* Create a new session for this user (SAML Browser Profile Consumer) */
shibrpc_new_session_ret_2 shibrpc_new_session (shibrpc_new_session_args_2) = 1;
- /* Validate and access data associated with existing session.
- * Returns 0 for TRUE, a non-zero error code for FALSE */
+ /* Validate and access data associated with existing session */
shibrpc_get_session_ret_2 shibrpc_get_session (shibrpc_get_session_args_2) = 2;
+ /* Post managed state information for later retrieval during session creation */
+ shibrpc_statemgr_ret_2 shibrpc_statemgr (shibrpc_statemgr_args_2) = 3;
+
} = 2;
} = 123456; /* Arbitrary RPC Program Number */