if (m_priv) delete m_priv;
}
-void ShibTarget::init(ShibTargetConfig *config,
- string protocol, string hostname, int port,
- string uri, string content_type, string remote_host,
- string method)
+void ShibTarget::init(
+ ShibTargetConfig *config,
+ string protocol,
+ string hostname,
+ int port,
+ string uri,
+ string content_type,
+ string remote_host,
+ string method
+ )
{
#ifdef _DEBUG
saml::NDC ndc("ShibTarget::init");
ShibTarget::doCheckAuthN(bool requireSessionFlag, bool handleProfile)
{
#ifdef _DEBUG
- saml::NDC ndc("ShibTarget::doCheckAuthN");
+ saml::NDC ndc("ShibTarget::doCheckAuthN");
#endif
- const char *targetURL = NULL;
- const char *procState = "Process Initialization Error";
- ShibMLP mlp;
+ const char *targetURL = NULL;
+ const char *procState = "Request Setup Error";
+ ShibMLP mlp;
- try {
- if (! m_priv->m_app)
- throw ShibTargetException(SHIBRPC_OK, "ShibTarget Uninitialized. Application did not supply request information.");
-
- targetURL = m_priv->m_url.c_str();
- const char *shireURL = getShireURL(targetURL);
- if (! shireURL)
- throw ShibTargetException(SHIBRPC_OK, "Cannot map target URL to Shire URL. Check configuration");
+ try {
+ if (!m_priv->m_app)
+ throw SAMLException("System uninitialized, application did not supply request information.");
+
+ targetURL = m_priv->m_url.c_str();
+ const char *shireURL = getShireURL(targetURL);
+ if (!shireURL)
+ throw SAMLException("Cannot determine assertion consumer service from resource URL, check configuration.");
+
+ if (strstr(targetURL,shireURL)) {
+ if (handleProfile)
+ return doHandleProfile();
+ else
+ return pair<bool,void*>(true, returnOK());
+ }
- if (strstr(targetURL,shireURL)) {
- if (handleProfile)
- return doHandleProfile();
- else
- return pair<bool,void*>(true, returnOK());
- }
+ string auth_type = getAuthType();
+ if (strcasecmp(auth_type.c_str(),"shibboleth"))
+ return pair<bool,void*>(true,returnDecline());
- string auth_type = getAuthType();
- if (strcasecmp(auth_type.c_str(),"shibboleth"))
- return pair<bool,void*>(true,returnDecline());
+ pair<bool,bool> requireSession = m_priv->m_settings.first->getBool("requireSession");
+ if (!requireSession.first || !requireSession.second) {
+ // Web server might override.
+ if (requireSessionFlag)
+ requireSession.second=true;
+ }
- pair<bool,bool> requireSession =
- m_priv->m_settings.first->getBool("requireSession");
- if (!requireSession.first || !requireSession.second)
- if (requireSessionFlag)
- requireSession.second=true;
+ const char* session_id = m_priv->getSessionId(this);
+ if (!session_id || !*session_id) {
+ // No session. Maybe that's acceptable?
+ if (!requireSession.second)
+ return pair<bool,void*>(true,returnOK());
- const char* session_id = m_priv->getSessionId(this);
- if (!session_id || !*session_id) {
- // No session. Maybe that's acceptable?
+ // No cookie, but we require a session. Generate an AuthnRequest.
+ return pair<bool,void*>(true,sendRedirect(getAuthnRequest(targetURL)));
+ }
- if (!requireSession.second)
- return pair<bool,void*>(true,returnOK());
+ procState = "Session Processing Error";
+ try {
+ // Localized exception throw if the session isn't valid.
+ 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
+ );
+ }
+ catch (SAMLException& e) {
+ // If no session is required, bail now.
+ if (!requireSession.second)
+ // 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.
+ return pair<bool,void*>(true, returnOK());
+
+ // TODO: need to test this...may need an actual reference cast
+ if (typeid(e)==typeid(RetryableProfileException)) {
+ // Session is invalid but we can retry -- generate an AuthnRequest
+ return pair<bool,void*>(true,sendRedirect(getAuthnRequest(targetURL)));
+ }
+ throw; // send it to the outer handler
+ }
- // No cookie, but we require a session. Generate an AuthnRequest.
- return pair<bool,void*>(true,sendRedirect(getAuthnRequest(targetURL)));
+ // We're done. Everything is okay. Nothing to report. Nothing to do..
+ // Let the caller decide how to proceed.
+ log(LogLevelInfo, "doCheckAuthN succeeded");
+ return pair<bool,void*>(false,NULL);
}
-
- procState = "Session Processing Error";
- auto_ptr<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.
- else if (status->isRetryable()) {
- // Session is invalid but we can retry the auth -- generate an AuthnRequest
- return pair<bool,void*>(true,sendRedirect(getAuthnRequest(targetURL)));
-
- } else {
- string er = "Unretryable error: " ;
- er += status->getText();
- log(LogLevelError, er);
- mlp.insert(*status);
- goto out;
- }
+ catch (SAMLException& e) {
+ mlp.insert(e);
}
-
- // We're done. Everything is okay. Nothing to report. Nothing to do..
- // Let the caller decide how to proceed.
- log(LogLevelInfo, "doCheckAuthN Succeeded\n");
- return pair<bool,void*>(false,NULL);
-
- }
- catch (ShibTargetException &e) {
- mlp.insert("errorText", e.what());
- }
#ifndef _DEBUG
- catch (...) {
- mlp.insert("errorText", "Unexpected Exception");
- }
+ catch (...) {
+ mlp.insert("errorText", "Caught an unknown exception.");
+ }
#endif
- // If we get here then we've got an error.
- mlp.insert("errorType", procState);
- mlp.insert("errorDesc", "An error occurred while processing your request.");
+ // If we get here then we've got an error.
+ mlp.insert("errorType", procState);
+ if (targetURL)
+ mlp.insert("requestURL", targetURL);
- out:
- if (targetURL)
- mlp.insert("requestURL", targetURL);
-
- return pair<bool,void*>(true,m_priv->sendError(this, "session", mlp));
+ return pair<bool,void*>(true,m_priv->sendError(this, "session", mlp));
}
pair<bool,void*>
ShibTarget::doHandleProfile(void)
{
#ifdef _DEBUG
- saml::NDC ndc("ShibTarget::doHandleProfile");
+ saml::NDC ndc("ShibTarget::doHandleProfile");
#endif
- const char *targetURL = NULL;
- const char *procState = "Session Creation Service Error";
- ShibMLP mlp;
-
- try {
- if (! m_priv->m_app)
- throw ShibTargetException(SHIBRPC_OK, "ShibTarget Uninitialized. Application did not supply request information.");
+ const char *targetURL = NULL;
+ const char *procState = "Session Creation Service Error";
+ ShibMLP mlp;
- targetURL = m_priv->m_url.c_str();
- const char *shireURL = getShireURL(targetURL);
+ try {
+ if (!m_priv->m_app)
+ throw SAMLException("System uninitialized, application did not supply request information.");
- if (!shireURL)
- throw ShibTargetException(SHIBRPC_OK, "doHandleProfile() unable to map request to a proper shireURL setting. Check Configuration.");
+ targetURL = m_priv->m_url.c_str();
+ const char* shireURL = getShireURL(targetURL);
+ if (!shireURL)
+ throw SAMLException("Cannot determine assertion consumer service, check configuration.");
- // Make sure we only process the SHIRE requests.
- if (!strstr(targetURL, shireURL))
- return pair<bool,void*>(true, returnDecline());
+ // Make sure we only process the SHIRE requests.
+ if (!strstr(targetURL, shireURL))
+ return pair<bool,void*>(true, returnDecline());
- const IPropertySet* sessionProps=m_priv->m_app->getPropertySet("Sessions");
- if (!sessionProps)
- throw ShibTargetException(SHIBRPC_OK, "doHandleProfile() unable to map request to application session settings. Check configuration");
+ const IPropertySet* sessionProps=m_priv->m_app->getPropertySet("Sessions");
+ if (!sessionProps)
+ throw SAMLException("Unable to map request to application session settings, check configuration.");
- // Process SHIRE request
+ // Process incoming request.
+ pair<bool,bool> shireSSL=sessionProps->getBool("shireSSL");
- pair<bool,bool> shireSSL=sessionProps->getBool("shireSSL");
-
- // Make sure this is SSL, if it should be
- if ((!shireSSL.first || shireSSL.second) && m_priv->m_protocol == "https")
- throw ShibTargetException(SHIBRPC_OK, "blocked non-SSL access to session creation service");
-
- // If this is a GET, we see if it's a lazy session request, otherwise
- // assume it's a profile response and process it.
- string cgistr;
- if (!strcasecmp(m_priv->m_method.c_str(), "GET")) {
- cgistr = getArgs();
- string areq;
- if (!cgistr.empty())
- areq=getLazyAuthnRequest(cgistr.c_str());
- if (!areq.empty())
- return pair<bool,void*>(true, sendRedirect(areq));
- }
- else if (!strcasecmp(m_priv->m_method.c_str(), "POST")) {
- if (m_priv->m_content_type.empty() || strcasecmp(m_priv->m_content_type.c_str(),"application/x-www-form-urlencoded")) {
- string er = string("blocked invalid POST content-type to session creation service: ") + m_priv->m_content_type;
- throw ShibTargetException(SHIBRPC_OK, er.c_str());
+ // Make sure this is SSL, if it should be
+ if ((!shireSSL.first || shireSSL.second) && m_priv->m_protocol != "https")
+ throw FatalProfileException("Blocked non-SSL access to session creation service.");
+
+ // If this is a GET, we see if it's a lazy session request, otherwise
+ // assume it's a profile response and process it.
+ string cgistr;
+ if (!strcasecmp(m_priv->m_method.c_str(), "GET")) {
+ cgistr = getArgs();
+ string areq;
+ if (!cgistr.empty())
+ areq=getLazyAuthnRequest(cgistr.c_str());
+ if (!areq.empty())
+ return pair<bool,void*>(true, sendRedirect(areq));
+ }
+ else if (!strcasecmp(m_priv->m_method.c_str(), "POST")) {
+ if (m_priv->m_content_type.empty() || strcasecmp(m_priv->m_content_type.c_str(),"application/x-www-form-urlencoded")) {
+ throw FatalProfileException(
+ "Blocked invalid POST content-type ($1) to session creation service.",
+ params(1,m_priv->m_content_type)
+ );
+ }
+ // Read the POST Data
+ cgistr = getPostData();
}
- // Read the POST Data
- cgistr = getPostData();
- }
- // process the submission
- string cookie,target;
- auto_ptr<RPCError> status(
- sessionNew(
- SAML_11_POST | SAML_11_ARTIFACT,
- cgistr.c_str(),
- m_priv->m_remote_addr.c_str(),
- cookie,
- target
- )
- );
-
- if (status->isError()) {
- char buf[25];
- sprintf(buf, "(%d): ", status->getCode());
- string er = string("doHandleProfile() profile processing failed ") + buf + status->getText();
- log(LogLevelError, er);
-
- if (status->isRetryable()) {
- return pair<bool,void*>(true, sendRedirect(getAuthnRequest(target.c_str())));
- }
-
- // return this error to the user.
- mlp.insert(*status);
- goto out;
- }
+ // Process the submission
+ string cookie,target;
+ try {
+ sessionNew(
+ SAML11_POST | SAML11_ARTIFACT,
+ cgistr.c_str(),
+ m_priv->m_remote_addr.c_str(),
+ cookie,
+ target
+ );
+ }
+ catch (SAMLException& e) {
+ log(LogLevelError, string("profile processing failed: ") + e.what());
+
+ // TODO: need to test this...may need an actual reference cast
+ if (typeid(e)==typeid(RetryableProfileException)) {
+ return pair<bool,void*>(true, sendRedirect(getAuthnRequest(target.c_str())));
+ }
+ throw; // send it to the outer handler
+ }
- log(LogLevelDebug, string("doHandleProfile() profile processing succeeded, new session(") + cookie + ")");
+ log(LogLevelDebug, string("profile processing succeeded, new session created (") + cookie + ")");
- if (target=="default") {
- pair<bool,const char*> homeURL=m_priv->m_app->getString("homeURL");
- target=homeURL.first ? homeURL.second : "/";
- }
- else if (target=="42") {
- // Pull the target value from the "relay state" cookie.
- const char* relay_state = m_priv->getRelayState(this);
- if (!relay_state || !*relay_state) {
- // No apparent relay state value to use, so fall back on the default.
+ if (target=="default") {
pair<bool,const char*> homeURL=m_priv->m_app->getString("homeURL");
target=homeURL.first ? homeURL.second : "/";
}
- else {
- CgiParse::url_decode((char*)relay_state);
- target=relay_state;
+ else if (target=="cookie") {
+ // Pull the target value from the "relay state" cookie.
+ const char* relay_state = m_priv->getRelayState(this);
+ if (!relay_state || !*relay_state) {
+ // No apparent relay state value to use, so fall back on the default.
+ pair<bool,const char*> homeURL=m_priv->m_app->getString("homeURL");
+ target=homeURL.first ? homeURL.second : "/";
+ }
+ else {
+ CgiParse::url_decode((char*)relay_state);
+ target=relay_state;
+ }
}
+
+ // We've got a good session, set the cookie...
+ pair<string,const char*> shib_cookie=getCookieNameProps("_shibsession_");
+ cookie += shib_cookie.second;
+ setCookie(shib_cookie.first, cookie);
+
+ // ... and redirect to the target
+ return pair<bool,void*>(true, sendRedirect(target));
+ }
+ catch (SAMLException& e) {
+ mlp.insert(e);
}
-
- // We've got a good session, set the cookie...
- pair<string,const char*> shib_cookie=getCookieNameProps("_shibsession_");
- cookie += shib_cookie.second;
- setCookie(shib_cookie.first, cookie);
-
- // ... and redirect to the target
- return pair<bool,void*>(true, sendRedirect(target));
-
- }
- catch (ShibTargetException &e) {
- mlp.insert("errorText", e.what());
- }
#ifndef _DEBUG
- catch (...) {
- mlp.insert("errorText", "Unexpected Exception");
- }
+ catch (...) {
+ mlp.insert("errorText", "Caught an unknown exception.");
+ }
#endif
- // If we get here then we've got an error.
- mlp.insert("errorType", procState);
- mlp.insert("errorDesc", "An error occurred while processing your request.");
+ // If we get here then we've got an error.
+ mlp.insert("errorType", procState);
- out:
- if (targetURL)
- mlp.insert("requestURL", targetURL);
+ if (targetURL)
+ mlp.insert("requestURL", targetURL);
- return pair<bool,void*>(true,m_priv->sendError(this, "session", mlp));
+ return pair<bool,void*>(true,m_priv->sendError(this, "session", mlp));
}
pair<bool,void*>
ShibTarget::doCheckAuthZ(void)
{
#ifdef _DEBUG
- saml::NDC ndc("ShibTarget::doCheckAuthZ");
+ saml::NDC ndc("ShibTarget::doCheckAuthZ");
#endif
- ShibMLP mlp;
- const char *procState = "Authorization Processing Error";
- const char *targetURL = NULL;
- HTAccessInfo *ht = NULL;
- HTGroupTable* grpstatus = NULL;
-
- try {
- if (! m_priv->m_app)
- throw ShibTargetException(SHIBRPC_OK, "ShibTarget Uninitialized. Application did not supply request information.");
-
- targetURL = m_priv->m_url.c_str();
- const char *session_id = m_priv->getSessionId(this);
-
- // Do we have an access control plugin?
- 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_post_response ? m_priv->m_post_response->getAssertions() : EMPTY(SAMLAssertion*))) {
- log(LogLevelError, "doCheckAuthZ: access control provider denied access");
- goto out;
- }
- }
+ ShibMLP mlp;
+ const char *procState = "Authorization Processing Error";
+ const char *targetURL = NULL;
+ HTAccessInfo *ht = NULL;
+ HTGroupTable* grpstatus = NULL;
- // Perform HTAccess Checks
- ht = getAccessInfo();
+ try {
+ if (!m_priv->m_app)
+ throw SAMLException("System uninitialized, application did not supply request information.");
+
+ targetURL = m_priv->m_url.c_str();
+ const char *session_id = m_priv->getSessionId(this);
+
+ // Do we have an access control plugin?
+ 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_post_response ? m_priv->m_post_response->getAssertions() : EMPTY(SAMLAssertion*))) {
+ log(LogLevelError, "doCheckAuthZ() access control provider denied access");
+ if (targetURL)
+ mlp.insert("requestURL", targetURL);
+ // TODO: check setting and return 403
+ return pair<bool,void*>(true,m_priv->sendError(this, "access", mlp));
+ }
+ }
- // No Info means OK. Just return
- if (!ht)
- return pair<bool,void*>(false, NULL);
+ // Perform HTAccess Checks
+ ht = getAccessInfo();
- vector<bool> auth_OK(ht->elements.size(), false);
- bool method_restricted=false;
- string remote_user = getRemoteUser();
+ // No Info means OK. Just return
+ if (!ht)
+ return pair<bool,void*>(false, NULL);
+
+ vector<bool> auth_OK(ht->elements.size(), false);
+ bool method_restricted=false;
+ string remote_user = getRemoteUser();
#define CHECK_OK do { \
if (ht->requireAll) { \
continue; \
} while (0)
- for (int x = 0; x < ht->elements.size(); x++) {
- auth_OK[x] = false;
- HTAccessInfo::RequireLine *line = ht->elements[x];
- if (! line->use_line)
- continue;
- method_restricted = true;
-
- const char *w = line->tokens[0].c_str();
-
- if (!strcasecmp(w,"Shibboleth")) {
- // This is a dummy rule needed because Apache conflates authn and authz.
- // Without some require rule, AuthType is ignored and no check_user hooks run.
- CHECK_OK;
- }
- else if (!strcmp(w,"valid-user")) {
- log(LogLevelDebug, "doCheckAuthZ accepting valid-user");
- CHECK_OK;
- }
- else if (!strcmp(w,"user") && !remote_user.empty()) {
- bool regexp=false;
- for (int i = 1; i < line->tokens.size(); i++) {
- w = line->tokens[i].c_str();
- if (*w == '~') {
- regexp = true;
- continue;
- }
-
- if (regexp) {
- try {
- // To do regex matching, we have to convert from UTF-8.
- auto_ptr<XMLCh> trans(fromUTF8(w));
- RegularExpression re(trans.get());
- auto_ptr<XMLCh> trans2(fromUTF8(remote_user.c_str()));
- if (re.matches(trans2.get())) {
- log(LogLevelDebug, string("doCheckAuthZ accepting user: ") + w);
- CHECK_OK;
- }
- }
- catch (XMLException& ex) {
- auto_ptr_char tmp(ex.getMessage());
- log(LogLevelError, string("doCheckAuthZ caught exception while parsing regular expression (")
- + w + "): " + tmp.get());
- }
- }
- else if (!strcmp(remote_user.c_str(), w)) {
- log(LogLevelDebug, string("doCheckAuthZ accepting user: ") + w);
- CHECK_OK;
- }
- }
- }
- else if (!strcmp(w,"group")) {
- grpstatus = getGroupTable(remote_user);
+ for (int x = 0; x < ht->elements.size(); x++) {
+ auth_OK[x] = false;
+ HTAccessInfo::RequireLine *line = ht->elements[x];
+ if (! line->use_line)
+ continue;
+ method_restricted = true;
- if (!grpstatus) {
- delete ht;
- return pair<bool,void*>(true, returnDecline());
- }
-
- for (int i = 1; i < line->tokens.size(); i++) {
- w = line->tokens[i].c_str();
- if (grpstatus->lookup(w)) {
- log(LogLevelDebug, string("doCheckAuthZ accepting group: ") + w);
- CHECK_OK;
- }
- }
- delete grpstatus;
- grpstatus = NULL;
- }
- else {
- Iterator<IAAP*> provs = m_priv->m_app->getAAPProviders();
- AAP wrapper(provs, w);
- if (wrapper.fail()) {
- log(LogLevelWarn, string("doCheckAuthZ didn't recognize require rule: ") + w);
- continue;
- }
+ const char *w = line->tokens[0].c_str();
- bool regexp = false;
- string vals = getHeader(wrapper->getHeader());
- for (int i = 1; i < line->tokens.size() && !vals.empty(); i++) {
- w = line->tokens[i].c_str();
- if (*w == '~') {
- regexp = true;
- continue;
- }
-
- try {
- auto_ptr<RegularExpression> re;
- if (regexp) {
- delete re.release();
- auto_ptr<XMLCh> trans(fromUTF8(w));
- auto_ptr<RegularExpression> temp(new RegularExpression(trans.get()));
- re=temp;
+ if (!strcasecmp(w,"Shibboleth")) {
+ // This is a dummy rule needed because Apache conflates authn and authz.
+ // Without some require rule, AuthType is ignored and no check_user hooks run.
+ CHECK_OK;
}
-
- string vals_str(vals);
- int j = 0;
- for (int i = 0; i < vals_str.length(); i++) {
- if (vals_str.at(i) == ';') {
- if (i == 0) {
- log(LogLevelError, string("doCheckAuthZ invalid header encoding") +
- vals + ": starts with a semicolon");
- goto out;
- }
-
- if (vals_str.at(i-1) == '\\') {
- vals_str.erase(i-1, 1);
- i--;
- continue;
- }
-
- string val = vals_str.substr(j, i-j);
- j = i+1;
- if (regexp) {
- auto_ptr<XMLCh> trans(fromUTF8(val.c_str()));
- if (re->matches(trans.get())) {
- log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
- ", got " + val + ": authorization granted");
- CHECK_OK;
- }
- }
- else if ((wrapper->getCaseSensitive() && val==w) ||
- (!wrapper->getCaseSensitive() && !strcasecmp(val.c_str(),w))) {
- log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
- ", got " + val + ": authorization granted.");
- CHECK_OK;
- }
- else {
- log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
- ", got " + val + ": authoritzation not granted.");
+ else if (!strcmp(w,"valid-user")) {
+ log(LogLevelDebug, "doCheckAuthZ accepting valid-user");
+ CHECK_OK;
+ }
+ else if (!strcmp(w,"user") && !remote_user.empty()) {
+ bool regexp=false;
+ for (int i = 1; i < line->tokens.size(); i++) {
+ w = line->tokens[i].c_str();
+ if (*w == '~') {
+ regexp = true;
+ continue;
+ }
+
+ if (regexp) {
+ try {
+ // To do regex matching, we have to convert from UTF-8.
+ auto_ptr<XMLCh> trans(fromUTF8(w));
+ RegularExpression re(trans.get());
+ auto_ptr<XMLCh> trans2(fromUTF8(remote_user.c_str()));
+ if (re.matches(trans2.get())) {
+ log(LogLevelDebug, string("doCheckAuthZ accepting user: ") + w);
+ CHECK_OK;
+ }
+ }
+ catch (XMLException& ex) {
+ auto_ptr_char tmp(ex.getMessage());
+ log(LogLevelError, string("doCheckAuthZ caught exception while parsing regular expression (")
+ + w + "): " + tmp.get());
+ }
+ }
+ else if (!strcmp(remote_user.c_str(), w)) {
+ log(LogLevelDebug, string("doCheckAuthZ accepting user: ") + w);
+ CHECK_OK;
+ }
}
- }
}
+ else if (!strcmp(w,"group")) {
+ grpstatus = getGroupTable(remote_user);
+ if (!grpstatus) {
+ delete ht;
+ return pair<bool,void*>(true, returnDecline());
+ }
- string val = vals_str.substr(j, vals_str.length()-j);
- if (regexp) {
- auto_ptr<XMLCh> trans(fromUTF8(val.c_str()));
- if (re->matches(trans.get())) {
- log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
- ", got " + val + ": authorization granted.");
- CHECK_OK;
- }
- }
- else if ((wrapper->getCaseSensitive() && val==w) ||
- (!wrapper->getCaseSensitive() && !strcasecmp(val.c_str(),w))) {
- log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
- ", got " + val + ": authorization granted");
- CHECK_OK;
+ for (int i = 1; i < line->tokens.size(); i++) {
+ w = line->tokens[i].c_str();
+ if (grpstatus->lookup(w)) {
+ log(LogLevelDebug, string("doCheckAuthZ accepting group: ") + w);
+ CHECK_OK;
+ }
+ }
+ delete grpstatus;
+ grpstatus = NULL;
}
else {
- log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
- ", got " + val + ": authorization not granted");
- }
- }
- catch (XMLException& ex) {
- auto_ptr_char tmp(ex.getMessage());
- log(LogLevelError, string("doCheckAuthZ caught exception while parsing regular expression (")
- + w + "): " + tmp.get());
- }
- }
- }
- } // for x
+ Iterator<IAAP*> provs = m_priv->m_app->getAAPProviders();
+ AAP wrapper(provs, w);
+ if (wrapper.fail()) {
+ log(LogLevelWarn, string("doCheckAuthZ didn't recognize require rule: ") + w);
+ continue;
+ }
+ bool regexp = false;
+ string vals = getHeader(wrapper->getHeader());
+ for (int i = 1; i < line->tokens.size() && !vals.empty(); i++) {
+ w = line->tokens[i].c_str();
+ if (*w == '~') {
+ regexp = true;
+ continue;
+ }
+
+ try {
+ auto_ptr<RegularExpression> re;
+ if (regexp) {
+ delete re.release();
+ auto_ptr<XMLCh> trans(fromUTF8(w));
+ auto_ptr<RegularExpression> temp(new RegularExpression(trans.get()));
+ re=temp;
+ }
+
+ string vals_str(vals);
+ int j = 0;
+ for (int i = 0; i < vals_str.length(); i++) {
+ if (vals_str.at(i) == ';') {
+ if (i == 0) {
+ log(LogLevelError, string("doCheckAuthZ invalid header encoding") +
+ vals + ": starts with a semicolon");
+ throw SAMLException("Invalid information supplied to authorization module.");
+ }
+
+ if (vals_str.at(i-1) == '\\') {
+ vals_str.erase(i-1, 1);
+ i--;
+ continue;
+ }
+
+ string val = vals_str.substr(j, i-j);
+ j = i+1;
+ if (regexp) {
+ auto_ptr<XMLCh> trans(fromUTF8(val.c_str()));
+ if (re->matches(trans.get())) {
+ log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
+ ", got " + val + ": authorization granted");
+ CHECK_OK;
+ }
+ }
+ else if ((wrapper->getCaseSensitive() && val==w) ||
+ (!wrapper->getCaseSensitive() && !strcasecmp(val.c_str(),w))) {
+ log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
+ ", got " + val + ": authorization granted.");
+ CHECK_OK;
+ }
+ else {
+ log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
+ ", got " + val + ": authoritzation not granted.");
+ }
+ }
+ }
+
+ string val = vals_str.substr(j, vals_str.length()-j);
+ if (regexp) {
+ auto_ptr<XMLCh> trans(fromUTF8(val.c_str()));
+ if (re->matches(trans.get())) {
+ log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
+ ", got " + val + ": authorization granted.");
+ CHECK_OK;
+ }
+ }
+ else if ((wrapper->getCaseSensitive() && val==w) ||
+ (!wrapper->getCaseSensitive() && !strcasecmp(val.c_str(),w))) {
+ log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
+ ", got " + val + ": authorization granted");
+ CHECK_OK;
+ }
+ else {
+ log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
+ ", got " + val + ": authorization not granted");
+ }
+ }
+ catch (XMLException& ex) {
+ auto_ptr_char tmp(ex.getMessage());
+ log(LogLevelError, string("doCheckAuthZ caught exception while parsing regular expression (")
+ + w + "): " + tmp.get());
+ }
+ }
+ }
+ } // for x
- // check if all require directives are true
- bool auth_all_OK = true;
- for (int i = 0; i < ht->elements.size(); i++) {
- auth_all_OK &= auth_OK[i];
- }
- delete ht;
- if (grpstatus) delete grpstatus;
- if (auth_all_OK || !method_restricted)
- return pair<bool,void*>(false, NULL);
+ // check if all require directives are true
+ bool auth_all_OK = true;
+ for (int i = 0; i < ht->elements.size(); i++) {
+ auth_all_OK &= auth_OK[i];
+ }
- // If we get here there's an access error, so just fall through
+ delete ht;
+ if (grpstatus) delete grpstatus;
+ if (auth_all_OK || !method_restricted)
+ return pair<bool,void*>(false, NULL);
- }
- catch (ShibTargetException &e) {
- mlp.insert("errorText", e.what());
- }
+ // If we get here there's an access error, so just fall through
+ }
+ catch (SAMLException& e) {
+ mlp.insert(e);
+ }
#ifndef _DEBUG
- catch (...) {
- mlp.insert("errorText", "Unexpected Exception");
- }
+ catch (...) {
+ mlp.insert("errorText", "Caught an unknown exception.");
+ }
#endif
- // If we get here then we've got an error.
- mlp.insert("errorType", procState);
- mlp.insert("errorDesc", "An error occurred while processing your request.");
+ // If we get here then we've got an error.
+ mlp.insert("errorType", procState);
- out:
- if (targetURL)
- mlp.insert("requestURL", targetURL);
+ if (targetURL)
+ mlp.insert("requestURL", targetURL);
- if (ht)
delete ht;
- return pair<bool,void*>(true,m_priv->sendError(this, "access", mlp));
+ return pair<bool,void*>(true,m_priv->sendError(this, "access", mlp));
}
pair<bool,void*>
ShibTarget::doExportAssertions(bool exportAssertion)
{
#ifdef _DEBUG
- saml::NDC ndc("ShibTarget::doExportAssertions");
+ saml::NDC ndc("ShibTarget::doExportAssertions");
#endif
- ShibMLP mlp;
- const char *procState = "Attribute Processing Error";
- const char *targetURL = NULL;
- char *page = "rm";
-
- try {
- if (! m_priv->m_app)
- throw ShibTargetException(SHIBRPC_OK, "ShibTarget Uninitialized. Application did not supply request information.");
-
- targetURL = m_priv->m_url.c_str();
- const char *session_id = m_priv->getSessionId(this);
-
- 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_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 = "sessionGet failed: ";
- er += status->getText();
- log(ShibTarget::LogLevelError, er);
- mlp.insert(*status);
- delete status;
- goto out;
+ ShibMLP mlp;
+ const char *procState = "Attribute Processing Error";
+ const char *targetURL = NULL;
+ char *page = "rm";
+
+ try {
+ if (!m_priv->m_app)
+ throw SAMLException("System uninitialized, application did not supply request information.");
+
+ targetURL = m_priv->m_url.c_str();
+ const char *session_id = m_priv->getSessionId(this);
+
+ 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.
+ 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
+ );
}
- delete status;
- }
- // Get the AAP providers, which contain the attribute policy info.
- Iterator<IAAP*> provs=m_priv->m_app->getAAPProviders();
-
- // Clear out the list of mapped attributes
- while (provs.hasNext()) {
- IAAP* aap=provs.next();
- Locker locker(aap);
- Iterator<const IAttributeRule*> rules=aap->getAttributeRules();
- while (rules.hasNext()) {
- const char* header=rules.next()->getHeader();
- if (header)
- clearHeader(header);
- }
- }
-
- // Maybe export the first assertion.
- clearHeader("Shib-Attributes");
- pair<bool,bool> exp=m_priv->m_settings.first->getBool("exportAssertion");
- if (!exp.first || !exp.second)
- if (exportAssertion)
- exp.second=true;
- if (exp.second && m_priv->m_pre_response) {
- ostringstream os;
- os << *(m_priv->m_pre_response);
- unsigned int outlen;
- 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);
- }
+ // Get the AAP providers, which contain the attribute policy info.
+ Iterator<IAAP*> provs=m_priv->m_app->getAAPProviders();
- // Export the SAML AuthnMethod and the origin site name, and possibly the NameIdentifier.
- clearHeader("Shib-Origin-Site");
- clearHeader("Shib-Identity-Provider");
- clearHeader("Shib-Authentication-Method");
- clearHeader("Shib-NameIdentifier-Format");
- 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-Authentication-Method", am.get());
-
- // Export NameID?
- provs.reset();
- while (provs.hasNext()) {
- IAAP* aap=provs.next();
- Locker locker(aap);
- const IAttributeRule* rule=aap->lookup(m_priv->m_sso_statement->getSubject()->getNameIdentifier()->getFormat());
- if (rule && rule->getHeader()) {
- auto_ptr_char form(m_priv->m_sso_statement->getSubject()->getNameIdentifier()->getFormat());
- auto_ptr_char nameid(m_priv->m_sso_statement->getSubject()->getNameIdentifier()->getName());
- setHeader("Shib-NameIdentifier-Format", form.get());
- if (!strcmp(rule->getHeader(),"REMOTE_USER"))
- setRemoteUser(nameid.get());
- else
- setHeader(rule->getHeader(), nameid.get());
+ // Clear out the list of mapped attributes
+ while (provs.hasNext()) {
+ IAAP* aap=provs.next();
+ Locker locker(aap);
+ Iterator<const IAttributeRule*> rules=aap->getAttributeRules();
+ while (rules.hasNext()) {
+ const char* header=rules.next()->getHeader();
+ if (header)
+ clearHeader(header);
+ }
+ }
+
+ // Maybe export the first assertion.
+ clearHeader("Shib-Attributes");
+ pair<bool,bool> exp=m_priv->m_settings.first->getBool("exportAssertion");
+ if (!exp.first || !exp.second)
+ if (exportAssertion)
+ exp.second=true;
+ if (exp.second && m_priv->m_pre_response) {
+ ostringstream os;
+ os << *(m_priv->m_pre_response);
+ unsigned int outlen;
+ char* resp = (char*)os.str().c_str();
+ XMLByte* serialized = Base64::encode(reinterpret_cast<XMLByte*>(resp), os.str().length(), &outlen);
+ // TODO: strip linefeeds
+ setHeader("Shib-Attributes", reinterpret_cast<char*>(serialized));
+ XMLString::release(&serialized);
}
- }
- clearHeader("Shib-Application-ID");
- setHeader("Shib-Application-ID", m_priv->m_app->getId());
-
- // Export the attributes.
- 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();
- while (statements.hasNext()) {
- SAMLAttributeStatement* astate=dynamic_cast<SAMLAttributeStatement*>(statements.next());
- if (!astate)
- continue;
- Iterator<SAMLAttribute*> attrs=astate->getAttributes();
- while (attrs.hasNext()) {
- SAMLAttribute* attr=attrs.next();
+ // Export the SAML AuthnMethod and the origin site name, and possibly the NameIdentifier.
+ clearHeader("Shib-Origin-Site");
+ clearHeader("Shib-Identity-Provider");
+ clearHeader("Shib-Authentication-Method");
+ clearHeader("Shib-NameIdentifier-Format");
+ 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-Authentication-Method", am.get());
- // Are we supposed to export it?
- provs.reset();
- while (provs.hasNext()) {
+ // Export NameID?
+ provs.reset();
+ while (provs.hasNext()) {
IAAP* aap=provs.next();
Locker locker(aap);
- const IAttributeRule* rule=aap->lookup(attr->getName(),attr->getNamespace());
- if (!rule || !rule->getHeader()) {
- continue;
+ const IAttributeRule* rule=aap->lookup(m_priv->m_sso_statement->getSubject()->getNameIdentifier()->getFormat());
+ if (rule && rule->getHeader()) {
+ auto_ptr_char form(m_priv->m_sso_statement->getSubject()->getNameIdentifier()->getFormat());
+ auto_ptr_char nameid(m_priv->m_sso_statement->getSubject()->getNameIdentifier()->getName());
+ setHeader("Shib-NameIdentifier-Format", form.get());
+ if (!strcmp(rule->getHeader(),"REMOTE_USER"))
+ setRemoteUser(nameid.get());
+ else
+ setHeader(rule->getHeader(), nameid.get());
}
-
- Iterator<string> vals=attr->getSingleByteValues();
- if (!strcmp(rule->getHeader(),"REMOTE_USER") && vals.hasNext())
- setRemoteUser(vals.next());
- else {
- int it=0;
- string header = getHeader(rule->getHeader());
- if (!header.empty())
- it++;
- for (; vals.hasNext(); it++) {
- string value = vals.next();
- for (string::size_type pos = value.find_first_of(";", string::size_type(0));
- pos != string::npos;
- pos = value.find_first_of(";", pos)) {
- value.insert(pos, "\\");
- pos += 2;
- }
- if (it)
- header += ";";
- header += value;
+ }
+
+ clearHeader("Shib-Application-ID");
+ setHeader("Shib-Application-ID", m_priv->m_app->getId());
+
+ // Export the attributes.
+ 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();
+ while (statements.hasNext()) {
+ SAMLAttributeStatement* astate=dynamic_cast<SAMLAttributeStatement*>(statements.next());
+ if (!astate)
+ continue;
+ Iterator<SAMLAttribute*> attrs=astate->getAttributes();
+ while (attrs.hasNext()) {
+ SAMLAttribute* attr=attrs.next();
+
+ // Are we supposed to export it?
+ provs.reset();
+ while (provs.hasNext()) {
+ IAAP* aap=provs.next();
+ Locker locker(aap);
+ const IAttributeRule* rule=aap->lookup(attr->getName(),attr->getNamespace());
+ if (!rule || !rule->getHeader())
+ continue;
+
+ Iterator<string> vals=attr->getSingleByteValues();
+ if (!strcmp(rule->getHeader(),"REMOTE_USER") && vals.hasNext())
+ setRemoteUser(vals.next());
+ else {
+ int it=0;
+ string header = getHeader(rule->getHeader());
+ if (!header.empty())
+ it++;
+ for (; vals.hasNext(); it++) {
+ string value = vals.next();
+ for (string::size_type pos = value.find_first_of(";", string::size_type(0));
+ pos != string::npos;
+ pos = value.find_first_of(";", pos)) {
+ value.insert(pos, "\\");
+ pos += 2;
+ }
+ if (it)
+ header += ";";
+ header += value;
+ }
+ setHeader(rule->getHeader(), header);
+ }
+ }
}
- setHeader(rule->getHeader(), header);
}
- }
}
- }
+
+ return pair<bool,void*>(false,NULL);
+ }
+ catch (SAMLException& e) {
+ mlp.insert(e);
}
-
- return pair<bool,void*>(false,NULL);
- }
- catch (ShibTargetException &e) {
- mlp.insert("errorText", e.what());
- }
#ifndef _DEBUG
- catch (...) {
- mlp.insert("errorText", "Unexpected Exception");
- }
+ catch (...) {
+ mlp.insert("errorText", "Caught an unknown exception.");
+ }
#endif
- // If we get here then we've got an error.
- mlp.insert("errorType", procState);
- mlp.insert("errorDesc", "An error occurred while processing your request.");
+ // If we get here then we've got an error.
+ mlp.insert("errorType", procState);
- out:
- if (targetURL)
- mlp.insert("requestURL", targetURL);
+ if (targetURL)
+ mlp.insert("requestURL", targetURL);
- return pair<bool,void*>(true,m_priv->sendError(this, page, mlp));
+ return pair<bool,void*>(true,m_priv->sendError(this, page, mlp));
}
-// SHIRE APIs
+// Low level APIs
// Get the session cookie name and properties for the application
pair<string,const char*> ShibTarget::getCookieNameProps(const char* prefix) const
// value to the IdP so we can recognize it on the way back.
pair<string,const char*> shib_cookie=getCookieNameProps("_shibstate_");
setCookie(shib_cookie.first,m_priv->url_encode(resource) + shib_cookie.second);
- req += "&target=42";
+ req += "&target=cookie";
}
pair<bool,bool> old=m_priv->m_app->getBool("oldAuthnRequest");
return getAuthnRequest(target);
}
-RPCError* ShibTarget::sessionNew(
+void ShibTarget::sessionNew(
int supported_profiles,
const char* packet,
const char* ip,
) const
{
#ifdef _DEBUG
- saml::NDC ndc("sessionNew");
+ saml::NDC ndc("sessionNew");
#endif
- Category& log = Category::getInstance("shibtarget.ShibTarget");
+ Category& log = Category::getInstance("shibtarget.ShibTarget");
- if (!packet || !*packet) {
- log.error("Empty profile content");
- return new RPCError(SHIBRPC_RESPONSE_MISSING, "Empty profile content");
- }
+ if (!packet || !*packet) {
+ log.error("missing profile response");
+ throw FatalProfileException("Profile response missing.");
+ }
- if (!ip || !*ip) {
- log.error("Invalid IP address");
- return new RPCError(SHIBRPC_IPADDR_MISSING, "Invalid IP address");
- }
+ if (!ip || !*ip) {
+ log.error("missing client address");
+ throw FatalProfileException("Invalid client address.");
+ }
- if (supported_profiles <= 0) {
- log.error("No profile support indicated");
- return new RPCError(SHIBRPC_INTERNAL_ERROR, "No profile support indicated");
- }
+ if (supported_profiles <= 0) {
+ log.error("no profile support indicated");
+ throw FatalProfileException("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.supported_profiles = supported_profiles;
-
- log.info("create session for user at (%s) for application (%s)", ip, arg.application_id);
-
- shibrpc_new_session_ret_2 ret;
- memset(&ret, 0, sizeof(ret));
-
- // Loop on the RPC in case we lost contact the first time through
- int retry = 1;
- CLIENT* clnt;
- RPC rpc;
- do {
- clnt = rpc->connect();
- clnt_stat status = shibrpc_new_session_2 (&arg, &ret, clnt);
- if (status != RPC_SUCCESS) {
- // FAILED. Release, disconnect, and retry
- log.error("RPC Failure: %p (%p) (%d): %s", this, clnt, status, clnt_spcreateerror("shibrpc_new_session_2"));
- rpc->disconnect();
- if (retry)
- retry--;
- else
- return new RPCError(-1, "RPC Failure");
+ 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.supported_profiles = supported_profiles;
+
+ log.info("create session for user at (%s) for application (%s)", ip, arg.application_id);
+
+ shibrpc_new_session_ret_2 ret;
+ memset(&ret, 0, sizeof(ret));
+
+ // Loop on the RPC in case we lost contact the first time through
+ int retry = 1;
+ CLIENT* clnt;
+ RPC rpc;
+ do {
+ clnt = rpc->connect();
+ clnt_stat status = shibrpc_new_session_2 (&arg, &ret, clnt);
+ if (status != RPC_SUCCESS) {
+ // FAILED. Release, disconnect, and retry
+ log.error("RPC Failure: %p (%p) (%d): %s", this, clnt, status, clnt_spcreateerror("shibrpc_new_session_2"));
+ rpc->disconnect();
+ if (retry)
+ retry--;
+ else
+ throw ListenerException("Failure passing session setup information to listener.");
+ }
+ else {
+ // SUCCESS. Pool and continue
+ retry = -1;
+ }
+ } while (retry>=0);
+
+ if (ret.status && *ret.status)
+ log.debug("RPC completed with exception: %s", ret.status);
+ else
+ log.debug("RPC completed successfully");
+
+ SAMLException* except=NULL;
+ if (ret.status && *ret.status) {
+ // Reconstitute exception object.
+ try {
+ istringstream estr(ret.status);
+ except=SAMLException::getInstance(estr);
+ }
+ catch (SAMLException& e) {
+ log.error("caught SAML Exception while building the SAMLException: %s", e.what());
+ log.error("XML was: %s", ret.status);
+ clnt_freeres(clnt, (xdrproc_t)xdr_shibrpc_new_session_ret_2, (caddr_t)&ret);
+ rpc.pool();
+ throw FatalProfileException("An unrecoverable error occurred while creating your session.");
+ }
+#ifndef _DEBUG
+ catch (...) {
+ log.error("caught unknown exception building SAMLException");
+ log.error("XML was: %s", ret.status);
+ clnt_freeres(clnt, (xdrproc_t)xdr_shibrpc_new_session_ret_2, (caddr_t)&ret);
+ rpc.pool();
+ throw;
+ }
+#endif
}
else {
- // SUCCESS. Pool and continue
- retry = -1;
+ log.debug("new session cookie: %s", ret.cookie);
+ cookie = ret.cookie;
+ if (ret.target)
+ target = ret.target;
}
- } while (retry>=0);
-
- log.debug("RPC completed with status %d (%p)", ret.status.status, this);
-
- RPCError* retval;
- if (ret.status.status)
- retval = new RPCError(&ret.status);
- else {
- log.debug ("new session cookie: %s", ret.cookie);
- cookie = ret.cookie;
- if (ret.target)
- target = ret.target;
- retval = new RPCError();
- }
-
- clnt_freeres(clnt, (xdrproc_t)xdr_shibrpc_new_session_ret_2, (caddr_t)&ret);
- rpc.pool();
- return retval;
+ clnt_freeres(clnt, (xdrproc_t)xdr_shibrpc_new_session_ret_2, (caddr_t)&ret);
+ rpc.pool();
+ if (except) {
+ auto_ptr<SAMLException> wrapper(except);
+ throw *wrapper;
+ }
}
-RPCError* ShibTarget::sessionGet(
+void ShibTarget::sessionGet(
const char* cookie,
const char* ip,
ShibProfile& profile,
) const
{
#ifdef _DEBUG
- saml::NDC ndc("sessionGet");
+ saml::NDC ndc("sessionGet");
#endif
- Category& log = Category::getInstance("shibtarget.ShibTarget");
-
- if (!cookie || !*cookie) {
- 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.");
- 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");
- return new RPCError(SHIBRPC_IPADDR_MISSING, "Invalid IP Address");
- }
+ Category& log = Category::getInstance("shibtarget.ShibTarget");
- 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();
-
- shibrpc_get_session_ret_2 ret;
- memset (&ret, 0, sizeof(ret));
-
- // Loop on the RPC in case we lost contact the first time through
- int retry = 1;
- CLIENT *clnt;
- RPC rpc;
- do {
- clnt = rpc->connect();
- clnt_stat status = shibrpc_get_session_2(&arg, &ret, clnt);
- if (status != RPC_SUCCESS) {
- // FAILED. Release, disconnect, and try again...
- log.error("RPC Failure: %p (%p) (%d) %s", this, clnt, status, clnt_spcreateerror("shibrpc_get_session_2"));
- rpc->disconnect();
- if (retry)
- retry--;
- else
- return new RPCError(-1, "RPC Failure");
+ if (!cookie || !*cookie) {
+ log.error("no session key provided");
+ throw InvalidSessionException("No session key was provided.");
}
- else {
- // SUCCESS
- retry = -1;
+ else if (strchr(cookie,'=')) {
+ log.error("cookie value not extracted successfully, probably overlapping cookies across domains");
+ throw InvalidSessionException("The session key wasn't extracted successfully from the browser cookie.");
}
- } while (retry>=0);
- log.debug("RPC completed with status %d, %p", ret.status.status, this);
+ if (!ip || !*ip) {
+ log.error("invalid client Address");
+ throw FatalProfileException("Invalid client address.");
+ }
- RPCError* retval = NULL;
- if (ret.status.status)
- retval = new RPCError(&ret.status);
- else {
- try {
- try {
- 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);
+ 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();
+
+ shibrpc_get_session_ret_2 ret;
+ memset (&ret, 0, sizeof(ret));
+
+ // Loop on the RPC in case we lost contact the first time through
+ int retry = 1;
+ CLIENT *clnt;
+ RPC rpc;
+ do {
+ clnt = rpc->connect();
+ clnt_stat status = shibrpc_get_session_2(&arg, &ret, clnt);
+ if (status != RPC_SUCCESS) {
+ // FAILED. Release, disconnect, and try again...
+ log.error("RPC Failure: %p (%p) (%d) %s", this, clnt, status, clnt_spcreateerror("shibrpc_get_session_2"));
+ rpc->disconnect();
+ if (retry)
+ retry--;
+ else
+ throw ListenerException("Failure requesting session information from listener.");
}
-
- // return the unfiltered Response
- if (attr_response_pre) {
- istringstream prestream(ret.attr_response_pre);
-
- log.debugStream() << "Trying to decode unfiltered attribute response: "
- << ret.attr_response_pre << CategoryStream::ENDLINE;
- *attr_response_pre = new SAMLResponse(prestream);
+ else {
+ // SUCCESS
+ retry = -1;
}
+ } while (retry>=0);
- // 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);
+ if (ret.status && *ret.status)
+ log.debug("RPC completed with exception: %s", ret.status);
+ else
+ log.debug("RPC completed successfully");
+
+ SAMLException* except=NULL;
+ if (ret.status && *ret.status) {
+ // Reconstitute exception object.
+ try {
+ istringstream estr(ret.status);
+ except=SAMLException::getInstance(estr);
+ }
+ catch (SAMLException& e) {
+ log.error("caught SAML Exception while building the SAMLException: %s", e.what());
+ log.error("XML was: %s", ret.status);
+ clnt_freeres(clnt, (xdrproc_t)xdr_shibrpc_get_session_ret_2, (caddr_t)&ret);
+ rpc.pool();
+ throw FatalProfileException("An unrecoverable error occurred while accessing your session.");
+ }
+ catch (...) {
+ log.error("caught unknown exception building SAMLException");
+ log.error("XML was: %s", ret.status);
+ clnt_freeres(clnt, (xdrproc_t)xdr_shibrpc_get_session_ret_2, (caddr_t)&ret);
+ rpc.pool();
+ throw;
}
- }
- catch (SAMLException& e) {
- log.error ("SAML Exception: %s", e.what());
- ostringstream os;
- os << e;
- throw ShibTargetException(SHIBRPC_SAML_EXCEPTION, os.str().c_str());
- }
- catch (XMLException& e) {
- log.error ("XML Exception: %s", e.getMessage());
- auto_ptr_char msg(e.getMessage());
- throw ShibTargetException (SHIBRPC_XML_EXCEPTION, msg.get());
- }
}
- catch (ShibTargetException &e) {
- retval = new RPCError(e);
+ else {
+ try {
+ 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 unfiltered Response
+ if (attr_response_pre) {
+ istringstream prestream(ret.attr_response_pre);
+ 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) {
+ log.error("caught SAML exception while reconstituting session objects: %s", e.what());
+ clnt_freeres (clnt, (xdrproc_t)xdr_shibrpc_get_session_ret_2, (caddr_t)&ret);
+ rpc.pool();
+ throw;
+ }
+#ifndef _DEBUG
+ catch (...) {
+ log.error("caught unknown exception while reconstituting session objects");
+ clnt_freeres (clnt, (xdrproc_t)xdr_shibrpc_get_session_ret_2, (caddr_t)&ret);
+ rpc.pool();
+ throw;
+ }
+#endif
}
- if (!retval)
- retval = new RPCError();
- }
-
- clnt_freeres (clnt, (xdrproc_t)xdr_shibrpc_get_session_ret_2, (caddr_t)&ret);
- rpc.pool();
-
- return retval;
+ clnt_freeres (clnt, (xdrproc_t)xdr_shibrpc_get_session_ret_2, (caddr_t)&ret);
+ rpc.pool();
+ if (except) {
+ auto_ptr<SAMLException> wrapper(except);
+ throw *wrapper;
+ }
}
/*************************************************************************
m_mapper = NULL;
m_conf->unlock();
m_conf = NULL;
- throw ShibTargetException(SHIBRPC_OK, "unable to map request to application settings. Check configuration");
+ throw SAMLException("Unable to map request to application settings, check configuration.");
}
// Store the application for later use
void*
ShibTargetPriv::sendError(ShibTarget* st, string page, ShibMLP &mlp)
{
- const IPropertySet* props=m_app->getPropertySet("Errors");
- if (props) {
- pair<bool,const char*> p=props->getString(page.c_str());
- if (p.first) {
- ifstream infile(p.second);
- if (!infile.fail()) {
- const char* res = mlp.run(infile,props);
- if (res)
- return st->sendPage(res);
- }
+ const IPropertySet* props=m_app->getPropertySet("Errors");
+ if (props) {
+ pair<bool,const char*> p=props->getString(page.c_str());
+ if (p.first) {
+ ifstream infile(p.second);
+ if (!infile.fail()) {
+ const char* res = mlp.run(infile,props);
+ if (res)
+ return st->sendPage(res);
+ }
+ }
}
- }
- string errstr = "sendError could not process the error template for application ";
- errstr += m_app->getId();
- st->log(ShibTarget::LogLevelError, errstr);
- return st->sendPage("Internal Server Error. Please contact the server administrator.");
+ string errstr = "sendError could not process the error template for application (";
+ errstr += m_app->getId();
+ errstr += ")";
+ st->log(ShibTarget::LogLevelError, errstr);
+ return st->sendPage("Internal Server Error. Please contact the site administrator.");
}
const char* ShibTargetPriv::getSessionId(ShibTarget* st)