char* szAuthGrpFile; // Auth GroupFile name
int bRequireAll; // all require directives must match, otherwise OR logic
- // SHIRE Configuration
+ // Content Configuration
int bBasicHijack; // activate for AuthType Basic?
int bRequireSession; // require a session?
int bExportAssertion; // export SAML assertion to the environment?
}
/********************************************************************************/
-// Some other useful helper function(s)
-
-static SH_AP_TABLE* groups_for_user(request_rec* r, const char* user, char* grpfile)
-{
- SH_AP_CONFIGFILE* f;
- SH_AP_TABLE* grps=ap_make_table(r->pool,15);
- char l[MAX_STRING_LEN];
- const char *group_name, *ll, *w;
-
-#ifdef SHIB_APACHE_13
- if (!(f=ap_pcfg_openfile(r->pool,grpfile))) {
-#else
- if (ap_pcfg_openfile(&f,r->pool,grpfile) != APR_SUCCESS) {
-#endif
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG,SH_AP_R(r),"groups_for_user() could not open group file: %s\n",grpfile);
- return NULL;
- }
-
- SH_AP_POOL* sp;
-#ifdef SHIB_APACHE_13
- sp=ap_make_sub_pool(r->pool);
-#else
- if (apr_pool_create(&sp,r->pool) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,
- "groups_for_user() could not create a subpool");
- return NULL;
- }
-#endif
-
- while (!(ap_cfg_getline(l,MAX_STRING_LEN,f))) {
- if ((*l=='#') || (!*l))
- continue;
- ll = l;
- ap_clear_pool(sp);
-
- group_name=ap_getword(sp,&ll,':');
-
- while (*ll) {
- w=ap_getword_conf(sp,&ll);
- if (!strcmp(w,user)) {
- ap_table_setn(grps,ap_pstrdup(r->pool,group_name),"in");
- break;
- }
- }
- }
- ap_cfg_closefile(f);
- ap_destroy_pool(sp);
- return grps;
-}
-
-/********************************************************************************/
// Apache ShibTarget subclass(es) here.
-class HTGroupTableApache : public HTGroupTable
-{
-public:
- HTGroupTableApache(request_rec* r, const char *user, char *grpfile) {
- groups = groups_for_user(r, user, grpfile);
- if (!groups)
- throw ResourceAccessException("Unable to access group file ($1) for user ($2)",params(2,grpfile,user));
- }
- ~HTGroupTableApache() {}
- bool lookup(const char *entry) { return (ap_table_get(groups, entry)!=NULL); }
- SH_AP_TABLE* groups;
-};
-
class ShibTargetApache : public ShibTarget
{
public:
}
return string(auth_type);
}
- // Override this function because we want to add the Apache Directory override
- virtual pair<bool,bool> getRequireSession(IRequestMapper::Settings &settings) {
- pair<bool,bool> requireSession = settings.first->getBool("requireSession");
- if (!requireSession.first || !requireSession.second)
- if (m_dc->bRequireSession == 1)
- requireSession.second=true;
-
- return requireSession;
- }
-
- virtual HTAccessInfo* getAccessInfo(void) {
- int m = m_req->method_number;
- const array_header* reqs_arr = ap_requires(m_req);
- if (!reqs_arr)
- return NULL;
-
- require_line* reqs = (require_line*) reqs_arr->elts;
-
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(m_req),
- "REQUIRE nelts: %d", reqs_arr->nelts);
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(m_req),
- "REQUIRE all: %d", m_dc->bRequireAll);
-
- HTAccessInfo* ht = new HTAccessInfo();
- ht->requireAll = (m_dc->bRequireAll == 1);
- ht->elements.reserve(reqs_arr->nelts);
- for (int x = 0; x < reqs_arr->nelts; x++) {
- HTAccessInfo::RequireLine* rline = new HTAccessInfo::RequireLine();
- rline->use_line = (reqs[x].method_mask & (1 << m));
- rline->tokens.reserve(6); // No reason to reserve specifically 6 tokens
- const char* t = reqs[x].requirement;
- const char* w = ap_getword_white(m_req->pool, &t);
- rline->tokens.push_back(w);
- while (*t) {
- w = ap_getword_conf(m_req->pool, &t);
- rline->tokens.push_back(w);
- }
- ht->elements.push_back(rline);
- }
- return ht;
- }
- virtual HTGroupTable* getGroupTable(string& user) {
- if (m_dc->szAuthGrpFile && !user.empty()) {
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(m_req),
- "getGroupTable() using groups file: %s\n",
- m_dc->szAuthGrpFile);
- try {
- HTGroupTableApache *gt = new HTGroupTableApache(m_req, user.c_str(),
- m_dc->szAuthGrpFile);
- return gt;
- } catch (...) { }
- }
- return NULL;
- }
virtual void* sendPage(
const string& msg,
ShibTargetApache sta(r);
// Check user authentication, the set the handler bypass
- pair<bool,void*> res = sta.doCheckAuthN((sta.m_dc->bRequireSession == 1), true);
+ pair<bool,void*> res = sta.doCheckAuthN(true);
apr_pool_userdata_setn((const void*)42,g_UserDataKey,NULL,r->pool);
if (res.first) return (int)res.second;
// user auth was okay -- export the assertions now
- res = sta.doExportAssertions((sta.m_dc->bExportAssertion == 1));
+ res = sta.doExportAssertions();
if (res.first) return (int)res.second;
// export happened successfully.. this user is ok.
#endif
}
-#if 0
-static char* shib_get_targeturl(request_rec* r, const char* scheme=NULL)
+// Access control plugin that enforces htaccess rules
+class htAccessControl : virtual public IAccessControl
{
- // On 1.3, this is always canonical, but on 2.0, UseCanonicalName comes into play.
- // However, we also have a setting to forcibly replace the scheme for esoteric cases.
- if (scheme) {
- unsigned port = ap_get_server_port(r);
- if ((!strcmp(scheme,"http") && port==80) || (!strcmp(scheme,"https") && port==443)) {
- return ap_pstrcat(r->pool, scheme, "://", ap_get_server_name(r), r->unparsed_uri, NULL);
- }
- return ap_psprintf(r->pool, "%s://%s:%u%s", scheme, ap_get_server_name(r), port, r->unparsed_uri);
- }
- return ap_construct_url(r->pool,r->unparsed_uri,r);
-}
+public:
+ htAccessControl() {}
+ ~htAccessControl() {}
+ void lock() {}
+ void unlock() {}
+ bool authorized(
+ ShibTarget* st,
+ const char* providerId,
+ const saml::SAMLAuthenticationStatement* authn,
+ const saml::SAMLResponse* attrs
+ ) const;
+};
-extern "C" int shib_check_user(request_rec* r)
+IPlugIn* htAccessFactory(const DOMElement* e)
{
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),"shib_check_user: ENTER");
- shib_dir_config* dc=(shib_dir_config*)ap_get_module_config(r->per_dir_config,&mod_shib);
- shib_server_config* sc=(shib_server_config*)ap_get_module_config(r->server->module_config,&mod_shib);
-
- ostringstream threadid;
- threadid << "[" << getpid() << "] shib_check_user" << '\0';
- saml::NDC ndc(threadid.str().c_str());
-
- const char* targeturl=shib_get_targeturl(r,sc->szScheme);
+ return new htAccessControl();
+}
- // We lock the configuration system for the duration.
- IConfig* conf=g_Config->getINI();
- Locker locker(conf);
-
- // Map request to application and content settings.
- IRequestMapper* mapper=conf->getRequestMapper();
- Locker locker2(mapper);
- IRequestMapper::Settings settings=mapper->getSettingsFromParsedURL(
- (sc-> szScheme ? sc-> szScheme : ap_http_method(r)), ap_get_server_name(r), ap_get_server_port(r), r->unparsed_uri
- );
- pair<bool,const char*> application_id=settings.first->getString("applicationId");
- const IApplication* application=conf->getApplication(application_id.second);
- if (!application) {
- ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,SH_AP_R(r),
- "shib_check_user: unable to map request to application settings, check configuration");
- return SERVER_ERROR;
- }
-
- // Declare SHIRE object for this request.
- SHIRE shire(application);
-
- const char* shireURL=shire.getShireURL(targeturl);
- if (!shireURL) {
- ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,SH_AP_R(r),
- "shib_check_user: unable to map request to proper shireURL setting, check configuration");
- return SERVER_ERROR;
- }
+class ApacheRequestMapper : public virtual IRequestMapper, public virtual IPropertySet
+{
+public:
+ struct ApacheRequestMapperSettings {
+ ApacheRequestMapperSettings(ShibTargetApache* sta, const IPropertySet* p) : m_sta(sta), m_props(p) {}
+ ShibTargetApache* m_sta;
+ const IPropertySet* m_props;
+ };
+
+ ApacheRequestMapper(const DOMElement* e);
+ ~ApacheRequestMapper() { delete m_mapper; delete m_htaccess; delete m_key; }
+ void lock() { m_mapper->lock(); }
+ void unlock() { delete (ApacheRequestMapperSettings*)(m_key->getData()); m_key->setData(NULL); m_mapper->unlock(); }
+ Settings getSettings(ShibTarget* st) const;
- // Get location of this application's assertion consumer service and see if this is it.
- if (strstr(targeturl,shireURL)) {
- return shib_handler(r,application,shire);
- }
-
- // We can short circuit the handler if we run this...
- apr_pool_userdata_setn((const void*)42,g_UserDataKey,NULL,r->pool);
-
- // Regular access to arbitrary resource...check AuthType
- const char *auth_type=ap_auth_type(r);
- if (!auth_type)
- return DECLINED;
-
- if (strcasecmp(auth_type,"shibboleth")) {
- if (!strcasecmp(auth_type,"basic") && dc->bBasicHijack==1) {
- core_dir_config* conf=
- (core_dir_config*)ap_get_module_config(r->per_dir_config,
- ap_find_linked_module("http_core.c"));
- conf->ap_auth_type="shibboleth";
- }
- else
- return DECLINED;
- }
-
- pair<bool,bool> requireSession = settings.first->getBool("requireSession");
- if (!requireSession.first || !requireSession.second)
- if (dc->bRequireSession==1)
- requireSession.second=true;
-
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),"shib_check_user: session check for %s",targeturl);
-
- pair<const char*,const char*> shib_cookie=shire.getCookieNameProps(); // always returns *something*
-
- // We're in charge, so check for cookie.
- const char* session_id=NULL;
- const char* cookies=ap_table_get(r->headers_in,"Cookie");
-
- if (cookies) {
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),"shib_check_user: cookies found: %s",cookies);
- if (session_id=strstr(cookies,shib_cookie.first)) {
- // Yep, we found a cookie -- pull it out (our session_id)
- session_id+=strlen(shib_cookie.first) + 1; /* Skip over the '=' */
- char* cookiebuf = ap_pstrdup(r->pool,session_id);
- char* cookieend = strchr(cookiebuf,';');
- if (cookieend)
- *cookieend = '\0'; /* Ignore anyting after a ; */
- session_id=cookiebuf;
- }
- }
-
- if (!session_id || !*session_id) {
- // If no session required, bail now.
- if (!requireSession.second)
- return OK;
-
- // No acceptable cookie, and we require a session. Generate an AuthnRequest.
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),"shib_check_user: no cookie found -- redirecting to WAYF");
- ap_table_setn(r->headers_out,"Location",ap_pstrdup(r->pool,shire.getAuthnRequest(targeturl)));
- return REDIRECT;
- }
-
- // Make sure this session is still valid.
- RPCError* status = NULL;
- ShibMLP markupProcessor;
- markupProcessor.insert("requestURL", targeturl);
-
- try {
- status = shire.sessionIsValid(session_id, r->connection->remote_ip);
- }
- catch (ShibTargetException &e) {
- ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,SH_AP_R(r),"shib_check_user(): %s", e.what());
- markupProcessor.insert("errorType", "Session Processing Error");
- markupProcessor.insert("errorText", e.what());
- markupProcessor.insert("errorDesc", "An error occurred while processing your request.");
- return shib_error_page(r, application, "shire", markupProcessor);
- }
-#ifndef _DEBUG
- catch (...) {
- ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,SH_AP_R(r),"shib_check_user(): caught unexpected error");
- markupProcessor.insert("errorType", "Session Processing Error");
- markupProcessor.insert("errorText", "Unexpected Exception");
- markupProcessor.insert("errorDesc", "An error occurred while processing your request.");
- return shib_error_page(r, application, "shire", markupProcessor);
- }
-#endif
-
- // Check the status
- if (status->isError()) {
- ap_log_rerror(APLOG_MARK,APLOG_INFO|APLOG_NOERRNO,SH_AP_R(r),
- "shib_check_user() session invalid: %s", status->getText());
-
- // If no session required, bail now.
- if (!requireSession.second)
- return OK; // 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.
- else if (status->isRetryable()) {
- // Oops, session is invalid. Generate AuthnRequest.
- ap_table_setn(r->headers_out,"Location",ap_pstrdup(r->pool,shire.getAuthnRequest(targeturl)));
- delete status;
- return REDIRECT;
- }
- else {
- // return the error page to the user
- markupProcessor.insert(*status);
- delete status;
- return shib_error_page(r, application, "shire", markupProcessor);
- }
- }
-
- delete status;
- // set the authtype
-#ifdef SHIB_APACHE_13
- if (r->connection)
- r->connection->ap_auth_type = "shibboleth";
-#else
- r->ap_auth_type = "shibboleth";
-#endif
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),"shib_check_user: session successfully verified");
-
- // This is code transferred in from the auth check to export the attributes.
- // We could even combine the isSessionValid/getAssertions API...?
-
- RM rm(application);
- vector<SAMLAssertion*> assertions;
- SAMLAuthenticationStatement* sso_statement=NULL;
-
- try {
- status = rm.getAssertions(session_id, r->connection->remote_ip, assertions, &sso_statement);
- }
- catch (ShibTargetException &e) {
- ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,SH_AP_R(r),"shib_check_user(): %s", e.what());
- markupProcessor.insert("errorType", "Attribute Processing Error");
- markupProcessor.insert("errorText", e.what());
- markupProcessor.insert("errorDesc", "An error occurred while processing your request.");
- return shib_error_page(r, application, "rm", markupProcessor);
- }
-#ifndef _DEBUG
- catch (...) {
- ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,SH_AP_R(r),"shib_check_user(): caught unexpected error");
- markupProcessor.insert("errorType", "Attribute Processing Error");
- markupProcessor.insert("errorText", "Unexpected Exception");
- markupProcessor.insert("errorDesc", "An error occurred while processing your request.");
- return shib_error_page(r, application, "rm", markupProcessor);
- }
-#endif
+ pair<bool,bool> getBool(const char* name, const char* ns=NULL) const;
+ pair<bool,const char*> getString(const char* name, const char* ns=NULL) const;
+ pair<bool,const XMLCh*> getXMLString(const char* name, const char* ns=NULL) const;
+ pair<bool,unsigned int> getUnsignedInt(const char* name, const char* ns=NULL) const;
+ pair<bool,int> getInt(const char* name, const char* ns=NULL) const;
+ const IPropertySet* getPropertySet(const char* name, const char* ns="urn:mace:shibboleth:target:config:1.0") const;
+ const DOMElement* getElement() const;
+
+private:
+ IRequestMapper* m_mapper;
+ ThreadKey* m_key;
+ IAccessControl* m_htaccess;
+};
- if (status->isError()) {
- ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,SH_AP_R(r),
- "shib_check_user() getAssertions failed: %s", status->getText());
+IPlugIn* ApacheRequestMapFactory(const DOMElement* e)
+{
+ return new ApacheRequestMapper(e);
+}
- markupProcessor.insert(*status);
- delete status;
- return shib_error_page(r, application, "rm", markupProcessor);
- }
- delete status;
-
- // Do we have an access control plugin?
- if (settings.second) {
- Locker acllock(settings.second);
- if (!settings.second->authorized(*sso_statement,assertions)) {
- for (int k = 0; k < assertions.size(); k++)
- delete assertions[k];
- delete sso_statement;
- ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,SH_AP_R(r),"shib_check_user(): access control provider denied access");
- return shib_error_page(r, application, "access", markupProcessor);
- }
+ApacheRequestMapper::ApacheRequestMapper(const DOMElement* e) : m_mapper(NULL), m_htaccess(NULL), m_key(NULL)
+{
+ IPlugIn* p=SAMLConfig::getConfig().getPlugMgr().newPlugin(
+ "edu.internet2.middleware.shibboleth.sp.provider.XMLRequestMapProvider", e
+ );
+ m_mapper=dynamic_cast<IRequestMapper*>(p);
+ if (!m_mapper) {
+ delete p;
+ throw UnsupportedExtensionException("Embedded request mapper plugin was not of correct type.");
}
+ m_htaccess=new htAccessControl();
+ m_key=ThreadKey::create(NULL);
+}
- // Get the AAP providers, which contain the attribute policy info.
- Iterator<IAAP*> provs=application->getAAPProviders();
-
- // Clear out the list of mapped attributes
- while (provs.hasNext()) {
- IAAP* aap=provs.next();
- aap->lock();
- try {
- Iterator<const IAttributeRule*> rules=aap->getAttributeRules();
- while (rules.hasNext()) {
- const char* header=rules.next()->getHeader();
- if (header)
- ap_table_unset(r->headers_in,header);
- }
- }
- catch(...) {
- aap->unlock();
- for (int k = 0; k < assertions.size(); k++)
- delete assertions[k];
- delete sso_statement;
- ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,SH_AP_R(r),
- "shib_check_user(): caught unexpected error while clearing headers");
- markupProcessor.insert("errorType", "Attribute Processing Error");
- markupProcessor.insert("errorText", "Unexpected Exception");
- markupProcessor.insert("errorDesc", "An error occurred while processing your request.");
- return shib_error_page(r, application, "rm", markupProcessor);
- }
- aap->unlock();
- }
- provs.reset();
-
- // Maybe export the first assertion.
- ap_table_unset(r->headers_in,"Shib-Attributes");
- pair<bool,bool> exp=settings.first->getBool("exportAssertion");
- if (!exp.first || !exp.second)
- if (dc->bExportAssertion==1)
- exp.second=true;
- if (exp.second && assertions.size()) {
- string assertion;
- RM::serialize(*(assertions[0]), assertion);
- ap_table_set(r->headers_in,"Shib-Attributes", assertion.c_str());
- }
+IRequestMapper::Settings ApacheRequestMapper::getSettings(ShibTarget* st) const
+{
+ Settings s=m_mapper->getSettings(st);
+ m_key->setData(new ApacheRequestMapperSettings(dynamic_cast<ShibTargetApache*>(st),s.first));
+ return pair<const IPropertySet*,IAccessControl*>(this,s.second ? s.second : m_htaccess);
+}
- // Export the SAML AuthnMethod and the origin site name, and possibly the NameIdentifier.
- ap_table_unset(r->headers_in,"Shib-Origin-Site");
- ap_table_unset(r->headers_in,"Shib-Authentication-Method");
- ap_table_unset(r->headers_in,"Shib-NameIdentifier-Format");
- auto_ptr_char os(sso_statement->getSubject()->getNameIdentifier()->getNameQualifier());
- auto_ptr_char am(sso_statement->getAuthMethod());
- ap_table_set(r->headers_in,"Shib-Origin-Site", os.get());
- ap_table_set(r->headers_in,"Shib-Authentication-Method", am.get());
-
- // Export NameID?
- AAP wrapper(provs,sso_statement->getSubject()->getNameIdentifier()->getFormat(),Constants::SHIB_ATTRIBUTE_NAMESPACE_URI);
- if (!wrapper.fail() && wrapper->getHeader()) {
- auto_ptr_char form(sso_statement->getSubject()->getNameIdentifier()->getFormat());
- auto_ptr_char nameid(sso_statement->getSubject()->getNameIdentifier()->getName());
- ap_table_set(r->headers_in,"Shib-NameIdentifier-Format",form.get());
- if (!strcmp(wrapper->getHeader(),"REMOTE_USER"))
- SH_AP_USER(r)=ap_pstrdup(r->pool,nameid.get());
- else
- ap_table_set(r->headers_in,wrapper->getHeader(),nameid.get());
- }
-
- ap_table_unset(r->headers_in,"Shib-Application-ID");
- ap_table_set(r->headers_in,"Shib-Application-ID",application_id.second);
-
- // Export the attributes.
- Iterator<SAMLAssertion*> a_iter(assertions);
- 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?
- AAP wrapper(provs,attr->getName(),attr->getNamespace());
- if (wrapper.fail() || !wrapper->getHeader())
- continue;
-
- Iterator<string> vals=attr->getSingleByteValues();
- if (!strcmp(wrapper->getHeader(),"REMOTE_USER") && vals.hasNext())
- SH_AP_USER(r)=ap_pstrdup(r->pool,vals.next().c_str());
- else {
- int it=0;
- char* header = (char*)ap_table_get(r->headers_in, wrapper->getHeader());
- if (header) {
- header=ap_pstrdup(r->pool, header);
- it++;
- }
- else
- header = ap_pstrdup(r->pool, "");
- 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;
- }
- header=ap_pstrcat(r->pool, header, (it ? ";" : ""), value.c_str(), NULL);
- }
- ap_table_setn(r->headers_in, wrapper->getHeader(), header);
- }
- }
+pair<bool,bool> ApacheRequestMapper::getBool(const char* name, const char* ns) const
+{
+ ApacheRequestMapperSettings* arms=(ApacheRequestMapperSettings*)m_key->getData();
+ if (arms) {
+ if (!ns) {
+ // Override Apache-settable boolean properties.
+ if (name && !strcmp(name,"requireSession") && arms->m_sta->m_dc->bRequireSession==1)
+ return make_pair(true,true);
+ else if (name && !strcmp(name,"exportAssertion") && arms->m_sta->m_dc->bExportAssertion==1)
+ return make_pair(true,true);
}
+ return arms->m_props->getBool(name,ns);
}
-
- // clean up memory
- for (int k = 0; k < assertions.size(); k++)
- delete assertions[k];
- delete sso_statement;
-
- return OK;
+ return make_pair(false,false);
}
-extern "C" int shib_post_handler(request_rec* r)
+pair<bool,const char*> ApacheRequestMapper::getString(const char* name, const char* ns) const
{
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),
- "shib_post_handler(%d): ENTER", (int)getpid());
- shib_server_config* sc=(shib_server_config*)ap_get_module_config(r->server->module_config,&mod_shib);
-
-#ifndef SHIB_APACHE_13
- // With 2.x, this handler always runs, though last.
- // We check if shib_check_user ran, because it will detect a SHIRE request
- // and dispatch it directly.
- void* data;
- apr_pool_userdata_get(&data,g_UserDataKey,r->pool);
- if (data==(const void*)42) {
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),"shib_post_handler skipped since check_user ran");
- return DECLINED;
- }
-#endif
-
- ostringstream threadid;
- threadid << "[" << getpid() << "] shib_post_handler" << '\0';
- saml::NDC ndc(threadid.str().c_str());
+ ApacheRequestMapperSettings* arms=(ApacheRequestMapperSettings*)m_key->getData();
+ return arms ? arms->m_props->getString(name,ns) : pair<bool,const char*>(false,NULL);
+}
- // We lock the configuration system for the duration.
- IConfig* conf=g_Config->getINI();
- Locker locker(conf);
-
- // Map request to application and content settings.
- IRequestMapper* mapper=conf->getRequestMapper();
- Locker locker2(mapper);
- IRequestMapper::Settings settings=mapper->getSettingsFromParsedURL(
- (sc->szScheme ? sc->szScheme : ap_http_method(r)), ap_get_server_name(r), ap_get_server_port(r), r->unparsed_uri
- );
- pair<bool,const char*> application_id=settings.first->getString("applicationId");
- const IApplication* application=conf->getApplication(application_id.second);
- if (!application) {
- ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,SH_AP_R(r),
- "shib_post_handler: unable to map request to application settings, check configuration");
- return SERVER_ERROR;
- }
-
- // Declare SHIRE object for this request.
- SHIRE shire(application);
-
- return shib_handler(r, application, shire);
+pair<bool,const XMLCh*> ApacheRequestMapper::getXMLString(const char* name, const char* ns) const
+{
+ ApacheRequestMapperSettings* arms=(ApacheRequestMapperSettings*)m_key->getData();
+ return arms ? arms->m_props->getXMLString(name,ns) : pair<bool,const XMLCh*>(false,NULL);
}
-int shib_handler(request_rec* r, const IApplication* application, SHIRE& shire)
+pair<bool,unsigned int> ApacheRequestMapper::getUnsignedInt(const char* name, const char* ns) const
{
- shib_server_config* sc=(shib_server_config*)ap_get_module_config(r->server->module_config,&mod_shib);
+ ApacheRequestMapperSettings* arms=(ApacheRequestMapperSettings*)m_key->getData();
+ return arms ? arms->m_props->getUnsignedInt(name,ns) : make_pair(false,0);
+}
- const char* targeturl=shib_get_targeturl(r,sc->szScheme);
+pair<bool,int> ApacheRequestMapper::getInt(const char* name, const char* ns) const
+{
+ ApacheRequestMapperSettings* arms=(ApacheRequestMapperSettings*)m_key->getData();
+ return arms ? arms->m_props->getInt(name,ns) : make_pair(false,0);
+}
- const char* shireURL=shire.getShireURL(targeturl);
- if (!shireURL) {
- ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,SH_AP_R(r),
- "shib_post_handler: unable to map request to proper shireURL setting, check configuration");
- return SERVER_ERROR;
- }
+const IPropertySet* ApacheRequestMapper::getPropertySet(const char* name, const char* ns) const
+{
+ ApacheRequestMapperSettings* arms=(ApacheRequestMapperSettings*)m_key->getData();
+ return arms ? arms->m_props->getPropertySet(name,ns) : NULL;
+}
- // Make sure we only process the SHIRE requests.
- if (!strstr(targeturl,shireURL))
- return DECLINED;
+const DOMElement* ApacheRequestMapper::getElement() const
+{
+ ApacheRequestMapperSettings* arms=(ApacheRequestMapperSettings*)m_key->getData();
+ return arms ? arms->m_props->getElement() : NULL;
+}
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),"shib_handler() running");
+static SH_AP_TABLE* groups_for_user(request_rec* r, const char* user, char* grpfile)
+{
+ SH_AP_CONFIGFILE* f;
+ SH_AP_TABLE* grps=ap_make_table(r->pool,15);
+ char l[MAX_STRING_LEN];
+ const char *group_name, *ll, *w;
- const IPropertySet* sessionProps=application->getPropertySet("Sessions");
- if (!sessionProps) {
- ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,SH_AP_R(r),
- "shib_post_handler: unable to map request to application session settings, check configuration");
- return SERVER_ERROR;
+#ifdef SHIB_APACHE_13
+ if (!(f=ap_pcfg_openfile(r->pool,grpfile))) {
+#else
+ if (ap_pcfg_openfile(&f,r->pool,grpfile) != APR_SUCCESS) {
+#endif
+ ap_log_rerror(APLOG_MARK,APLOG_DEBUG,SH_AP_R(r),"groups_for_user() could not open group file: %s\n",grpfile);
+ return NULL;
}
- pair<const char*,const char*> shib_cookie=shire.getCookieNameProps(); // always returns something
-
- ShibMLP markupProcessor;
- markupProcessor.insert("requestURL", targeturl);
-
- // Process SHIRE request
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r), "shib_handler() Beginning SHIRE processing");
-
- try {
- pair<bool,bool> shireSSL=sessionProps->getBool("shireSSL");
-
- // Make sure this is SSL, if it should be
- if ((!shireSSL.first || shireSSL.second) && strcmp(ap_http_method(r),"https"))
- throw ShibTargetException(SHIBRPC_OK, "blocked non-SSL access to session creation service");
-
- // If this is a GET, we manufacture an AuthnRequest.
- if (!strcasecmp(r->method,"GET")) {
- const char* areq=r->args ? shire.getLazyAuthnRequest(r->args) : NULL;
- if (!areq)
- throw ShibTargetException(SHIBRPC_OK, "malformed arguments to request a new session");
- ap_table_setn(r->headers_out, "Location", ap_pstrdup(r->pool,areq));
- return REDIRECT;
- }
- else if (strcasecmp(r->method,"POST")) {
- throw ShibTargetException(SHIBRPC_OK, "blocked non-POST to SHIRE POST processor");
- }
-
- // Sure sure this POST is an appropriate content type
- const char *ct = ap_table_get(r->headers_in, "Content-type");
- if (!ct || strcasecmp(ct, "application/x-www-form-urlencoded"))
- throw ShibTargetException(SHIBRPC_OK,
- ap_psprintf(r->pool, "blocked bad content-type to SHIRE POST processor: %s", (ct ? ct : "")));
-
- // Read the posted data
- if (ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))
- throw ShibTargetException(SHIBRPC_OK, "CGI setup_client_block failed");
- if (!ap_should_client_block(r))
- throw ShibTargetException(SHIBRPC_OK, "CGI should_client_block failed");
- if (r->remaining > 1024*1024)
- throw ShibTargetException (SHIBRPC_OK, "CGI length too long...");
-
- string cgistr;
- char buff[HUGE_STRING_LEN];
- ap_hard_timeout("[mod_shib] CGI Parser", r);
- memset(buff, 0, sizeof(buff));
- while (ap_get_client_block(r, buff, sizeof(buff)-1) > 0) {
- ap_reset_timeout(r);
- cgistr += buff;
- memset(buff, 0, sizeof(buff));
- }
- ap_kill_timeout(r);
-
- // Parse the submission.
- pair<const char*,const char*> elements=shire.getFormSubmission(cgistr.c_str(),cgistr.length());
-
- // Make sure the SAML Response parameter exists
- if (!elements.first || !*elements.first)
- throw ShibTargetException(SHIBRPC_OK, "SHIRE POST failed to find SAMLResponse form element");
-
- // Make sure the target parameter exists
- if (!elements.second || !*elements.second)
- throw ShibTargetException(SHIBRPC_OK, "SHIRE POST failed to find TARGET form element");
-
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),
- "shib_handler() Processing POST for target: %s", elements.second);
-
- // process the post
- string cookie;
- RPCError* status = shire.sessionCreate(elements.first, r->connection->remote_ip, cookie);
-
- if (status->isError()) {
- ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,SH_AP_R(r),
- "shib_handler() POST process failed (%d): %s", status->getCode(), status->getText());
-
- if (status->isRetryable()) {
- delete status;
- ap_log_rerror(APLOG_MARK,APLOG_INFO|APLOG_NOERRNO,SH_AP_R(r),
- "shib_handler() retryable error, generating new AuthnRequest");
- ap_table_setn(r->headers_out,"Location",ap_pstrdup(r->pool,shire.getAuthnRequest(elements.second)));
- return REDIRECT;
- }
-
- // return this error to the user.
- markupProcessor.insert(*status);
- delete status;
- return shib_error_page(r, application, "shire", markupProcessor);
- }
- delete status;
-
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),
- "shib_handler() POST process succeeded. New session: %s", cookie.c_str());
-
- // We've got a good session, set the cookie...
- char* val = ap_psprintf(r->pool,"%s=%s%s",shib_cookie.first,cookie.c_str(),shib_cookie.second);
- ap_table_setn(r->err_headers_out, "Set-Cookie", val);
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r), "shib_handler() setting cookie: %s", val);
-
- // ... and redirect to the target
- ap_table_setn(r->headers_out, "Location", ap_pstrdup(r->pool,elements.second));
- return REDIRECT;
- }
- catch (ShibTargetException &e) {
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r), "shib_handler() caught exception: %s", e.what());
- markupProcessor.insert("errorType", "Session Creation Service Error");
- markupProcessor.insert("errorText", e.what());
- markupProcessor.insert("errorDesc", "An error occurred while processing your request.");
- return shib_error_page(r, application, "shire", markupProcessor);
- }
-#ifndef _DEBUG
- catch (...) {
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),"shib_handler(): unexpected exception");
- markupProcessor.insert("errorType", "Session Creation Service Error");
- markupProcessor.insert("errorText", "Unknown Exception");
- markupProcessor.insert("errorDesc", "An error occurred while processing your request.");
- return shib_error_page(r, application, "shire", markupProcessor);
+ SH_AP_POOL* sp;
+#ifdef SHIB_APACHE_13
+ sp=ap_make_sub_pool(r->pool);
+#else
+ if (apr_pool_create(&sp,r->pool) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r,
+ "groups_for_user() could not create a subpool");
+ return NULL;
}
#endif
- ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,SH_AP_R(r),"shib_handler() server error");
- return SERVER_ERROR;
-}
+ while (!(ap_cfg_getline(l,MAX_STRING_LEN,f))) {
+ if ((*l=='#') || (!*l))
+ continue;
+ ll = l;
+ ap_clear_pool(sp);
-static int shib_error_page(request_rec* r, const IApplication* app, const char* page, ShibMLP& mlp)
-{
- const IPropertySet* props=app->getPropertySet("Errors");
- if (props) {
- pair<bool,const char*> p=props->getString(page);
- if (p.first) {
- ifstream infile(p.second);
- if (!infile.fail()) {
- const char* res = mlp.run(infile,props);
- if (res) {
- r->content_type = ap_psprintf(r->pool, "text/html");
- ap_send_http_header(r);
- ap_rprintf(r, res);
- return DONE;
- }
+ group_name=ap_getword(sp,&ll,':');
+
+ while (*ll) {
+ w=ap_getword_conf(sp,&ll);
+ if (!strcmp(w,user)) {
+ ap_table_setn(grps,ap_pstrdup(r->pool,group_name),"in");
+ break;
}
}
}
-
- ap_log_rerror(APLOG_MARK,APLOG_ERR,SH_AP_R(r),
- "shib_error_page() could not process shire error template for application %s",app->getId());
- return SERVER_ERROR;
+ ap_cfg_closefile(f);
+ ap_destroy_pool(sp);
+ return grps;
}
-/*
- * shib_auth_checker() -- a simple resource manager to
- * process the .htaccess settings and copy attributes
- * into the HTTP headers.
- */
-extern "C" int shib_auth_checker(request_rec* r)
+bool htAccessControl::authorized(
+ ShibTarget* st,
+ const char* providerId,
+ const saml::SAMLAuthenticationStatement* authn,
+ const saml::SAMLResponse* attrs
+) const
{
- shib_dir_config* dc=
- (shib_dir_config*)ap_get_module_config(r->per_dir_config,&mod_shib);
-
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),"shib_auth_checker() executing");
-
- // Regular access to arbitrary resource...check AuthType
- const char* auth_type=ap_auth_type(r);
- if (!auth_type || strcasecmp(auth_type,"shibboleth"))
- return DECLINED;
-
- ostringstream threadid;
- threadid << "[" << getpid() << "] shibrm" << '\0';
- saml::NDC ndc(threadid.str().c_str());
-
- // We lock the configuration system for the duration.
- IConfig* conf=g_Config->getINI();
- Locker locker(conf);
-
- const char* application_id=ap_table_get(r->headers_in,"Shib-Application-ID");
- const IApplication* application=NULL;
- if (application_id)
- application = conf->getApplication(application_id);
+ // Make sure the object is our type.
+ ShibTargetApache* sta=dynamic_cast<ShibTargetApache*>(st);
+ if (!sta)
+ throw ConfigurationException("Request wrapper object was not of correct type.");
// mod_auth clone
- int m=r->method_number;
+ int m=sta->m_req->method_number;
bool method_restricted=false;
const char *t, *w;
- const array_header* reqs_arr=ap_requires(r);
+ const array_header* reqs_arr=ap_requires(sta->m_req);
if (!reqs_arr)
- return OK;
+ return true;
require_line* reqs=(require_line*)reqs_arr->elts;
-
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),"REQUIRE nelts: %d", reqs_arr->nelts);
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),"REQUIRE all: %d", dc->bRequireAll);
+
+ ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(sta->m_req),"REQUIRE nelts: %d", reqs_arr->nelts);
+ ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(sta->m_req),"REQUIRE all: %d", sta->m_dc->bRequireAll);
vector<bool> auth_OK(reqs_arr->nelts,false);
-#define SHIB_AP_CHECK_IS_OK { \
- if (dc->bRequireAll < 1) \
- return OK; \
- auth_OK[x] = true; \
- continue; \
+#define SHIB_AP_CHECK_IS_OK { \
+ if (sta->m_dc->bRequireAll < 1) \
+ return true; \
+ auth_OK[x] = true; \
+ continue; \
}
for (int x=0; x<reqs_arr->nelts; x++) {
if (!(reqs[x].method_mask & (1 << m)))
continue;
method_restricted=true;
+ string remote_user = st->getRemoteUser();
t = reqs[x].requirement;
- w = ap_getword_white(r->pool, &t);
+ w = ap_getword_white(sta->m_req->pool, &t);
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.
SHIB_AP_CHECK_IS_OK;
}
- else if (!strcmp(w,"valid-user") && application_id) {
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),"shib_auth_checker() accepting valid-user");
+ else if (!strcmp(w,"valid-user")) {
+ st->log(ShibTarget::LogLevelDebug,"htAccessControl plugin accepting valid-user");
SHIB_AP_CHECK_IS_OK;
}
- else if (!strcmp(w,"user") && SH_AP_USER(r)) {
+ else if (!strcmp(w,"user") && !remote_user.empty()) {
bool regexp=false;
while (*t) {
- w=ap_getword_conf(r->pool,&t);
+ w=ap_getword_conf(sta->m_req->pool,&t);
if (*w=='~') {
regexp=true;
continue;
// 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(SH_AP_USER(r)));
+ auto_ptr<XMLCh> trans2(fromUTF8(remote_user.c_str()));
if (re.matches(trans2.get())) {
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),"shib_auth_checker() accepting user: %s",w);
+ st->log(ShibTarget::LogLevelDebug, string("htAccessControl plugin accepting user (") + w + ")");
SHIB_AP_CHECK_IS_OK;
}
}
catch (XMLException& ex) {
auto_ptr_char tmp(ex.getMessage());
- ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,SH_AP_R(r),
- "shib_auth_checker caught exception while parsing regular expression (%s): %s",w,tmp.get());
+ st->log(ShibTarget::LogLevelError,
+ string("htAccessControl plugin caught exception while parsing regular expression (") + w + "): " + tmp.get());
}
}
- else if (!strcmp(SH_AP_USER(r),w)) {
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),"shib_auth_checker() accepting user: %s",w);
+ else if (remote_user==w) {
+ st->log(ShibTarget::LogLevelDebug, string("htAccessControl plugin accepting user (") + w + ")");
SHIB_AP_CHECK_IS_OK;
}
}
}
else if (!strcmp(w,"group")) {
SH_AP_TABLE* grpstatus=NULL;
- if (dc->szAuthGrpFile && SH_AP_USER(r)) {
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),"shib_auth_checker() using groups file: %s\n",dc->szAuthGrpFile);
- grpstatus=groups_for_user(r,SH_AP_USER(r),dc->szAuthGrpFile);
+ if (sta->m_dc->szAuthGrpFile && !remote_user.empty()) {
+ st->log(ShibTarget::LogLevelDebug,string("htAccessControl plugin using groups file: ") + sta->m_dc->szAuthGrpFile);
+ grpstatus=groups_for_user(sta->m_req,remote_user.c_str(),sta->m_dc->szAuthGrpFile);
}
if (!grpstatus)
- return DECLINED;
+ return false;
while (*t) {
- w=ap_getword_conf(r->pool,&t);
+ w=ap_getword_conf(sta->m_req->pool,&t);
if (ap_table_get(grpstatus,w)) {
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),"shib_auth_checker() accepting group: %s",w);
+ st->log(ShibTarget::LogLevelDebug, string("htAccessControl plugin accepting group (") + w + ")");
SHIB_AP_CHECK_IS_OK;
}
}
}
else {
- Iterator<IAAP*> provs=application ? application->getAAPProviders() : EMPTY(IAAP*);
+ Iterator<IAAP*> provs=st->getApplication()->getAAPProviders();
AAP wrapper(provs,w);
if (wrapper.fail()) {
- ap_log_rerror(APLOG_MARK,APLOG_WARNING|APLOG_NOERRNO,SH_AP_R(r),
- "shib_auth_checker() didn't recognize require rule: %s\n",w);
+ st->log(ShibTarget::LogLevelWarn, string("htAccessControl plugin didn't recognize require rule: ") + w);
continue;
}
bool regexp=false;
- const char* vals=ap_table_get(r->headers_in,wrapper->getHeader());
+ const char* vals=ap_table_get(sta->m_req->headers_in,wrapper->getHeader());
while (*t && vals) {
- w=ap_getword_conf(r->pool,&t);
+ w=ap_getword_conf(sta->m_req->pool,&t);
if (*w=='~') {
regexp=true;
continue;
for (int i = 0; i < vals_str.length(); i++) {
if (vals_str.at(i) == ';') {
if (i == 0) {
- ap_log_rerror(APLOG_MARK,APLOG_WARNING|APLOG_NOERRNO,SH_AP_R(r),
- "shib_auth_checker() invalid header encoding %s: starts with semicolon", vals);
- return SERVER_ERROR;
+ st->log(ShibTarget::LogLevelError, string("htAccessControl plugin found invalid header encoding (") +
+ vals + "): starts with a semicolon");
+ throw SAMLException("Invalid information supplied to authorization plugin.");
}
if (vals_str.at(i-1) == '\\') {
if (regexp) {
auto_ptr<XMLCh> trans(fromUTF8(val.c_str()));
if (re->matches(trans.get())) {
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),
- "shib_auth_checker() expecting %s, got %s: authorization granted", w, val.c_str());
+ st->log(ShibTarget::LogLevelDebug, string("htAccessControl plugin expecting ") + w +
+ ", got " + val + ": authorization granted");
SHIB_AP_CHECK_IS_OK;
}
}
else if ((wrapper->getCaseSensitive() && val==w) || (!wrapper->getCaseSensitive() && !strcasecmp(val.c_str(),w))) {
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),
- "shib_auth_checker() expecting %s, got %s: authorization granted", w, val.c_str());
+ st->log(ShibTarget::LogLevelDebug, string("htAccessControl plugin expecting ") + w +
+ ", got " + val + ": authorization granted.");
SHIB_AP_CHECK_IS_OK;
}
else {
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),
- "shib_auth_checker() expecting %s, got %s: authorization not granted", w, val.c_str());
+ st->log(ShibTarget::LogLevelDebug, string("htAccessControl plugin expecting ") + w +
+ ", got " + val + ": authoritzation not granted.");
}
}
}
if (regexp) {
auto_ptr<XMLCh> trans(fromUTF8(val.c_str()));
if (re->matches(trans.get())) {
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),
- "shib_auth_checker() expecting %s, got %s: authorization granted", w, val.c_str());
+ st->log(ShibTarget::LogLevelDebug, string("htAccessControl plugin expecting ") + w +
+ ", got " + val + ": authorization granted.");
SHIB_AP_CHECK_IS_OK;
}
}
else if ((wrapper->getCaseSensitive() && val==w) || (!wrapper->getCaseSensitive() && !strcasecmp(val.c_str(),w))) {
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),
- "shib_auth_checker() expecting %s, got %s: authorization granted", w, val.c_str());
+ st->log(ShibTarget::LogLevelDebug, string("htAccessControl plugin expecting ") + w +
+ ", got " + val + ": authorization granted");
SHIB_AP_CHECK_IS_OK;
}
else {
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),
- "shib_auth_checker() expecting %s, got %s: authorization not granted", w, val.c_str());
+ st->log(ShibTarget::LogLevelDebug, string("htAccessControl plugin expecting ") + w +
+ ", got " + val + ": authorization not granted");
}
}
catch (XMLException& ex) {
auto_ptr_char tmp(ex.getMessage());
- ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,SH_AP_R(r),
- "shib_auth_checker caught exception while parsing regular expression (%s): %s",w,tmp.get());
+ st->log(ShibTarget::LogLevelError, string("htAccessControl plugin caught exception while parsing regular expression (")
+ + w + "): " + tmp.get());
}
}
}
for (int i= 0; i<reqs_arr->nelts; i++) {
auth_all_OK &= auth_OK[i];
}
- if (auth_all_OK)
- return OK;
-
- if (!method_restricted)
- return OK;
-
- if (!application_id) {
- ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,SH_AP_R(r),
- "shib_auth_checker: Shib-Application-ID header not found in request");
- return HTTP_FORBIDDEN;
- }
- else if (!application) {
- ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,SH_AP_R(r),
- "shib_auth_checker: unable to map request to application settings, check configuration");
- return HTTP_FORBIDDEN;
- }
+ if (auth_all_OK || !method_restricted)
+ return true;
- ShibMLP markupProcessor;
- markupProcessor.insert("requestURL", ap_construct_url(r->pool,r->unparsed_uri,r));
- return shib_error_page(r, application, "access", markupProcessor);
+ return false;
}
-#endif /* 0 */
#ifndef SHIB_APACHE_13
/*
ShibTargetConfig::LocalExtensions |
ShibTargetConfig::Logging
);
- if (!g_Config->init(g_szSchemaDir) || !g_Config->load(g_szSHIBConfig)) {
- ap_log_error(APLOG_MARK,APLOG_CRIT|APLOG_NOERRNO,SH_AP_R(s),"shib_child_init() failed to initialize SHIB Target");
+ if (!g_Config->init(g_szSchemaDir)) {
+ ap_log_error(APLOG_MARK,APLOG_CRIT|APLOG_NOERRNO,SH_AP_R(s),"shib_child_init() failed to initialize libraries");
+ exit(1);
+ }
+ SAMLConfig::getConfig().getPlugMgr().regFactory(shibtarget::XML::htAccessControlType,&htAccessFactory);
+ SAMLConfig::getConfig().getPlugMgr().regFactory(shibtarget::XML::ApacheRequestMapType,&ApacheRequestMapFactory);
+
+ // We hijack the legacy type so that 1.2 config files will load this plugin instead of the basic plugin.
+ SAMLConfig::getConfig().getPlugMgr().regFactory(shibtarget::XML::LegacyRequestMapType,&ApacheRequestMapFactory);
+
+ if (!g_Config->load(g_szSHIBConfig)) {
+ ap_log_error(APLOG_MARK,APLOG_CRIT|APLOG_NOERRNO,SH_AP_R(s),"shib_child_init() failed to load configuration");
exit(1);
}
}
catch (...) {
- ap_log_error(APLOG_MARK,APLOG_CRIT|APLOG_NOERRNO,SH_AP_R(s),"shib_child_init() failed to initialize SHIB Target");
- exit (1);
+ ap_log_error(APLOG_MARK,APLOG_CRIT|APLOG_NOERRNO,SH_AP_R(s),"shib_child_init() failed to initialize system");
+ exit(1);
}
// Set the cleanup handler
m_acsDefault=hprops;
}
}
- else if (saml::XML::isElementNamed(handler,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(SessionInitiator))) {
+ else if (saml::XML::isElementNamed(handler,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(SessionInitiator))) {
pair<bool,const char*> si_id=hprops->getString("id");
if (si_id.first && si_id.second)
m_sessionInitMap[si_id.second]=hprops;
m_audiences.push_back(getXMLString("providerId").second);
if (conf.isEnabled(ShibTargetConfig::AAP)) {
- nlist=e->getElementsByTagNameNS(ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(AAPProvider));
+ nlist=e->getElementsByTagNameNS(shibtarget::XML::SHIBTARGET_NS,SHIBT_L(AAPProvider));
for (i=0; nlist && i<nlist->getLength(); i++) {
auto_ptr_char type(static_cast<DOMElement*>(nlist->item(i))->getAttributeNS(NULL,SHIBT_L(type)));
log.info("building AAP provider of type %s...",type.get());
}
if (conf.isEnabled(ShibTargetConfig::Metadata)) {
- nlist=e->getElementsByTagNameNS(ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(MetadataProvider));
+ nlist=e->getElementsByTagNameNS(shibtarget::XML::SHIBTARGET_NS,SHIBT_L(MetadataProvider));
for (i=0; nlist && i<nlist->getLength(); i++) {
auto_ptr_char type(static_cast<DOMElement*>(nlist->item(i))->getAttributeNS(NULL,SHIBT_L(type)));
log.info("building metadata provider of type %s...",type.get());
throw UnsupportedExtensionException("plugin was not a metadata provider");
}
}
- nlist=e->getElementsByTagNameNS(ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(FederationProvider));
+ nlist=e->getElementsByTagNameNS(shibtarget::XML::SHIBTARGET_NS,SHIBT_L(FederationProvider));
for (i=0; nlist && i<nlist->getLength(); i++) {
auto_ptr_char type(static_cast<DOMElement*>(nlist->item(i))->getAttributeNS(NULL,SHIBT_L(type)));
log.info("building metadata provider of type %s...",type.get());
}
if (conf.isEnabled(ShibTargetConfig::Trust)) {
- nlist=e->getElementsByTagNameNS(ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(TrustProvider));
+ nlist=e->getElementsByTagNameNS(shibtarget::XML::SHIBTARGET_NS,SHIBT_L(TrustProvider));
for (i=0; nlist && i<nlist->getLength(); i++) {
auto_ptr_char type(static_cast<DOMElement*>(nlist->item(i))->getAttributeNS(NULL,SHIBT_L(type)));
log.info("building trust provider of type %s...",type.get());
}
// Finally, load credential mappings.
- const DOMElement* cu=saml::XML::getFirstChildElement(e,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(CredentialUse));
+ const DOMElement* cu=saml::XML::getFirstChildElement(e,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(CredentialUse));
if (cu) {
m_credDefault=new XMLPropertySet();
m_credDefault->load(cu,log,this);
- cu=saml::XML::getFirstChildElement(cu,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(RelyingParty));
+ cu=saml::XML::getFirstChildElement(cu,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(RelyingParty));
while (cu) {
XMLPropertySet* rp=new XMLPropertySet();
rp->load(cu,log,this);
m_credMap[cu->getAttributeNS(NULL,SHIBT_L(Name))]=rp;
- cu=saml::XML::getNextSiblingElement(cu,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(RelyingParty));
+ cu=saml::XML::getNextSiblingElement(cu,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(RelyingParty));
}
}
short XMLConfigImpl::acceptNode(const DOMNode* node) const
{
- if (XMLString::compareString(node->getNamespaceURI(),ShibTargetConfig::SHIBTARGET_NS))
+ if (XMLString::compareString(node->getNamespaceURI(),shibtarget::XML::SHIBTARGET_NS))
return FILTER_ACCEPT;
const XMLCh* name=node->getLocalName();
if (!XMLString::compareString(name,SHIBT_L(Applications)) ||
#ifdef _DEBUG
saml::NDC ndc("init");
#endif
- Category& log=Category::getInstance("shibtarget.XMLConfig");
+ Category& log=Category::getInstance("shibtarget.Config");
try {
- if (!saml::XML::isElementNamed(ReloadableXMLFileImpl::m_root,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(ShibbolethTargetConfig)) &&
- !saml::XML::isElementNamed(ReloadableXMLFileImpl::m_root,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(SPConfig))) {
+ if (!saml::XML::isElementNamed(ReloadableXMLFileImpl::m_root,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(ShibbolethTargetConfig)) &&
+ !saml::XML::isElementNamed(ReloadableXMLFileImpl::m_root,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(SPConfig))) {
log.error("Construction requires a valid configuration file: (conf:SPConfig as root element)");
throw ConfigurationException("Construction requires a valid configuration file: (conf:SPConfig as root element)");
}
SAMLConfig& shibConf=SAMLConfig::getConfig();
ShibTargetConfig& conf=ShibTargetConfig::getConfig();
- const DOMElement* SHAR=saml::XML::getFirstChildElement(ReloadableXMLFileImpl::m_root,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(SHAR));
+ const DOMElement* SHAR=saml::XML::getFirstChildElement(ReloadableXMLFileImpl::m_root,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(SHAR));
if (!SHAR)
- SHAR=saml::XML::getFirstChildElement(ReloadableXMLFileImpl::m_root,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(Global));
- const DOMElement* SHIRE=saml::XML::getFirstChildElement(ReloadableXMLFileImpl::m_root,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(SHIRE));
+ SHAR=saml::XML::getFirstChildElement(ReloadableXMLFileImpl::m_root,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(Global));
+ const DOMElement* SHIRE=saml::XML::getFirstChildElement(ReloadableXMLFileImpl::m_root,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(SHIRE));
if (!SHIRE)
- SHIRE=saml::XML::getFirstChildElement(ReloadableXMLFileImpl::m_root,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(Local));
+ SHIRE=saml::XML::getFirstChildElement(ReloadableXMLFileImpl::m_root,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(Local));
// Initialize log4cpp manually in order to redirect log messages as soon as possible.
if (conf.isEnabled(ShibTargetConfig::Logging)) {
if (first) {
// Now load any extensions to insure any needed plugins are registered.
DOMElement* exts=
- saml::XML::getFirstChildElement(ReloadableXMLFileImpl::m_root,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(Extensions));
+ saml::XML::getFirstChildElement(ReloadableXMLFileImpl::m_root,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(Extensions));
if (exts) {
- exts=saml::XML::getFirstChildElement(exts,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(Library));
+ exts=saml::XML::getFirstChildElement(exts,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(Library));
while (exts) {
auto_ptr_char path(exts->getAttributeNS(NULL,SHIBT_L(path)));
try {
else
log.crit("unable to load optional global extension library %s: %s", path.get(), e.what());
}
- exts=saml::XML::getNextSiblingElement(exts,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(Library));
+ exts=saml::XML::getNextSiblingElement(exts,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(Library));
}
}
if (conf.isEnabled(ShibTargetConfig::GlobalExtensions)) {
- exts=saml::XML::getFirstChildElement(SHAR,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(Extensions));
+ exts=saml::XML::getFirstChildElement(SHAR,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(Extensions));
if (exts) {
- exts=saml::XML::getFirstChildElement(exts,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(Library));
+ exts=saml::XML::getFirstChildElement(exts,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(Library));
while (exts) {
auto_ptr_char path(exts->getAttributeNS(NULL,SHIBT_L(path)));
try {
else
log.crit("unable to load optional Global extension library %s: %s", path.get(), e.what());
}
- exts=saml::XML::getNextSiblingElement(exts,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(Library));
+ exts=saml::XML::getNextSiblingElement(exts,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(Library));
}
}
}
if (conf.isEnabled(ShibTargetConfig::LocalExtensions)) {
- exts=saml::XML::getFirstChildElement(SHIRE,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(Extensions));
+ exts=saml::XML::getFirstChildElement(SHIRE,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(Extensions));
if (exts) {
- exts=saml::XML::getFirstChildElement(exts,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(Library));
+ exts=saml::XML::getFirstChildElement(exts,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(Library));
while (exts) {
auto_ptr_char path(exts->getAttributeNS(NULL,SHIBT_L(path)));
try {
else
log.crit("unable to load optional Local extension library %s: %s", path.get(), e.what());
}
- exts=saml::XML::getNextSiblingElement(exts,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(Library));
+ exts=saml::XML::getNextSiblingElement(exts,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(Library));
}
}
}
// Instantiate the Listener and SessionCache objects.
if (conf.isEnabled(ShibTargetConfig::Listener)) {
IPlugIn* plugin=NULL;
- exts=saml::XML::getFirstChildElement(SHAR,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(UnixListener));
+ exts=saml::XML::getFirstChildElement(SHAR,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(UnixListener));
if (exts) {
log.info("building Listener of type %s...",shibtarget::XML::UnixListenerType);
plugin=shibConf.getPlugMgr().newPlugin(shibtarget::XML::UnixListenerType,exts);
}
else {
- exts=saml::XML::getFirstChildElement(SHAR,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(TCPListener));
+ exts=saml::XML::getFirstChildElement(SHAR,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(TCPListener));
if (exts) {
log.info("building Listener of type %s...",shibtarget::XML::TCPListenerType);
plugin=shibConf.getPlugMgr().newPlugin(shibtarget::XML::TCPListenerType,exts);
}
else {
- exts=saml::XML::getFirstChildElement(SHAR,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(Listener));
+ exts=saml::XML::getFirstChildElement(SHAR,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(Listener));
if (exts) {
auto_ptr_char type(exts->getAttributeNS(NULL,SHIBT_L(type)));
log.info("building Listener of type %s...",type.get());
if (conf.isEnabled(ShibTargetConfig::Caching)) {
IPlugIn* plugin=NULL;
- exts=saml::XML::getFirstChildElement(SHAR,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(MemorySessionCache));
+ exts=saml::XML::getFirstChildElement(SHAR,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(MemorySessionCache));
if (exts) {
log.info("building Session Cache of type %s...",shibtarget::XML::MemorySessionCacheType);
plugin=shibConf.getPlugMgr().newPlugin(shibtarget::XML::MemorySessionCacheType,exts);
}
else {
- exts=saml::XML::getFirstChildElement(SHAR,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(MySQLSessionCache));
+ exts=saml::XML::getFirstChildElement(SHAR,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(MySQLSessionCache));
if (exts) {
log.info("building Session Cache of type %s...",shibtarget::XML::MySQLSessionCacheType);
plugin=shibConf.getPlugMgr().newPlugin(shibtarget::XML::MySQLSessionCacheType,exts);
}
else {
- exts=saml::XML::getFirstChildElement(SHAR,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(SessionCache));
+ exts=saml::XML::getFirstChildElement(SHAR,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(SessionCache));
if (exts) {
auto_ptr_char type(exts->getAttributeNS(NULL,SHIBT_L(type)));
log.info("building Session Cache of type %s...",type.get());
}
// Replay cache.
- exts=saml::XML::getFirstChildElement(SHAR,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(MySQLReplayCache));
+ exts=saml::XML::getFirstChildElement(SHAR,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(MySQLReplayCache));
if (exts) {
log.info("building Replay Cache of type %s...",shibtarget::XML::MySQLReplayCacheType);
m_outer->m_replayCache=IReplayCache::getInstance(shibtarget::XML::MySQLSessionCacheType,exts);
}
else {
- exts=saml::XML::getFirstChildElement(SHAR,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(ReplayCache));
+ exts=saml::XML::getFirstChildElement(SHAR,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(ReplayCache));
if (exts) {
auto_ptr_char type(exts->getAttributeNS(NULL,SHIBT_L(type)));
log.info("building Replay Cache of type %s...",type.get());
// Back to the fully dynamic stuff...next up is the Request Mapper.
if (conf.isEnabled(ShibTargetConfig::RequestMapper)) {
- const DOMElement* child=saml::XML::getFirstChildElement(SHIRE,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(RequestMapProvider));
+ const DOMElement* child=saml::XML::getFirstChildElement(SHIRE,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(RequestMapProvider));
if (child) {
auto_ptr_char type(child->getAttributeNS(NULL,SHIBT_L(type)));
log.info("building Request Mapper of type %s...",type.get());
// Now we load any credentials providers.
DOMNodeList* nlist;
if (conf.isEnabled(ShibTargetConfig::Credentials)) {
- nlist=ReloadableXMLFileImpl::m_root->getElementsByTagNameNS(
- ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(CredentialsProvider)
- );
+ nlist=ReloadableXMLFileImpl::m_root->getElementsByTagNameNS(shibtarget::XML::SHIBTARGET_NS,SHIBT_L(CredentialsProvider));
for (int i=0; nlist && i<nlist->getLength(); i++) {
auto_ptr_char type(static_cast<DOMElement*>(nlist->item(i))->getAttributeNS(NULL,SHIBT_L(type)));
log.info("building Credentials provider of type %s...",type.get());
// Load the default application. This actually has a fixed ID of "default". ;-)
const DOMElement* app=saml::XML::getFirstChildElement(
- ReloadableXMLFileImpl::m_root,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(Applications)
+ ReloadableXMLFileImpl::m_root,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(Applications)
);
if (!app) {
log.fatal("can't build default Application object, missing conf:Applications element?");
m_appmap[defapp->getId()]=defapp;
// Load any overrides.
- nlist=app->getElementsByTagNameNS(ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(Application));
+ nlist=app->getElementsByTagNameNS(shibtarget::XML::SHIBTARGET_NS,SHIBT_L(Application));
for (int i=0; nlist && i<nlist->getLength(); i++) {
XMLApplication* iapp=new XMLApplication(m_outer,m_creds,static_cast<DOMElement*>(nlist->item(i)),defapp);
if (m_appmap.find(iapp->getId())!=m_appmap.end()) {
// The web server modules implement a subclass and then call into
// these methods once they instantiate their request object.
-pair<bool,void*> ShibTarget::doCheckAuthN(bool requireSessionFlag, bool handler)
+pair<bool,void*> ShibTarget::doCheckAuthN(bool handler)
{
#ifdef _DEBUG
saml::NDC ndc("doCheckAuthN");
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<string,const char*> shib_cookie = m_priv->getCookieNameProps("_shibsession_");
const char* session_id = m_priv->getCookie(this,shib_cookie.first);
if (!session_id || !*session_id) {
// No session. Maybe that's acceptable?
- if (!requireSession.second)
+ if (!requireSession.first || !requireSession.second)
return pair<bool,void*>(true,returnOK());
// No cookie, but we require a session. Initiate a new session using the default method.
log(LogLevelError, string("session processing failed: ") + e.what());
// If no session is required, bail now.
- if (!requireSession.second)
+ if (!requireSession.first || !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
procState = "Session Creation Error";
return m_priv->doAssertionConsumer(this,handler);
}
- else if (saml::XML::isElementNamed(handler->getElement(),ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(SessionInitiator))) {
+ else if (saml::XML::isElementNamed(handler->getElement(),shibtarget::XML::SHIBTARGET_NS,SHIBT_L(SessionInitiator))) {
procState = "Session Initiator Error";
return m_priv->doSessionInitiator(this,handler);
}
if (!m_priv->m_app)
throw ConfigurationException("System uninitialized, application did not supply request information.");
+ string auth_type = getAuthType();
+ if (strcasecmp(auth_type.c_str(),"shibboleth"))
+ return make_pair(true,returnDecline());
+
// 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_provider_id.c_str(), m_priv->m_sso_statement, m_priv->m_post_response, this)) {
- log(LogLevelWarn, "doCheckAuthZ() access control provider denied access");
+ if (m_priv->m_settings.second->authorized(this,m_priv->m_provider_id.c_str(), m_priv->m_sso_statement, m_priv->m_post_response)) {
+ // Let the caller decide how to proceed.
+ log(LogLevelDebug, "doCheckAuthZ: access control provider granted access");
+ return pair<bool,void*>(false,NULL);
+ }
+ else {
+ log(LogLevelWarn, "doCheckAuthZ: access control provider denied access");
if (targetURL)
mlp.insert("requestURL", targetURL);
return make_pair(true,m_priv->sendError(this, "access", mlp));
}
}
-
- // Perform HTAccess Checks
- auto_ptr<HTAccessInfo> ht(getAccessInfo());
-
- // No Info means OK. Just return
- if (!ht.get())
- 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) { \
- return pair<bool,void*>(false, NULL); \
- } \
- auth_OK[x] = true; \
- 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")) {
- auto_ptr<HTGroupTable> grpstatus(getGroupTable(remote_user));
- if (!grpstatus.get()) {
- 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;
- }
- }
- }
- 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;
- }
-
- 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];
- }
-
- if (auth_all_OK || !method_restricted)
- return pair<bool,void*>(false, NULL);
-
- // If we get here there's an access error, so just fall through
+ else
+ return make_pair(true,returnDecline());
}
catch (SAMLException& e) {
mlp.insert(e);
return make_pair(true,m_priv->sendError(this, "access", mlp));
}
-pair<bool,void*> ShibTarget::doExportAssertions(bool exportAssertion)
+pair<bool,void*> ShibTarget::doExportAssertions()
{
#ifdef _DEBUG
saml::NDC ndc("doExportAssertions");
// 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) {
+ if (exp.first && exp.second && m_priv->m_pre_response) {
ostringstream os;
os << *(m_priv->m_pre_response);
unsigned int outlen;
m_mapper->lock();
// Obtain the application settings from the parsed URL
- m_settings = m_mapper->getSettingsFromParsedURL(protocol.c_str(),hostname.c_str(),port,uri.c_str(),st);
+ m_settings = m_mapper->getSettings(st);
// Now find the application from the URL settings
pair<bool,const char*> application_id=m_settings.first->getString("applicationId");
- const IApplication* application=m_conf->getApplication(application_id.second);
- if (!application) {
+ m_app=m_conf->getApplication(application_id.second);
+ if (!m_app) {
m_mapper->unlock();
m_mapper = NULL;
m_conf->unlock();
m_conf = NULL;
- throw SAMLException("Unable to map request to application settings, check configuration.");
+ throw ConfigurationException("Unable to map request to application settings, check configuration.");
}
- // Store the application for later use
- m_app = application;
-
- // Compute the target URL
+ // Compute the full target URL
st->m_url = protocol + "://" + hostname;
if ((protocol == "http" && port != 80) || (protocol == "https" && port != 443))
st->m_url += ":" + port;
return ret;
}
// Subclasses may not need to override these particular virtual methods.
+const IApplication* ShibTarget::getApplication() const
+{
+ return m_priv->m_app;
+}
string ShibTarget::getAuthType(void)
{
- return string("shibboleth");
+ return string("shibboleth");
}
void* ShibTarget::returnDecline(void)
{
- return NULL;
+ return NULL;
}
void* ShibTarget::returnOK(void)
{
- return NULL;
-}
-HTAccessInfo* ShibTarget::getAccessInfo(void)
-{
- return NULL;
-}
-HTGroupTable* ShibTarget::getGroupTable(string &user)
-{
- return NULL;
+ return NULL;
}
// CDC implementation