+void RemotedResolver::resolve(
+ const Application& app,
+ const char* issuer,
+ const vector<const XMLObject*>& tokens,
+ const vector<Attribute*>& inputAttrs,
+ vector <Attribute*>& resolvedAttrs
+ ) const
+{
+#ifndef SHIBSP_LITE
+ Category& log = Category::getInstance(SHIBRESOLVER_LOGCAT);
+ pair<const EntityDescriptor*,const RoleDescriptor*> entity = pair<const EntityDescriptor*,const RoleDescriptor*>(nullptr,nullptr);
+ MetadataProvider* m = app.getMetadataProvider();
+ Locker locker(m);
+ if (issuer) {
+ // Use metadata to locate the IdP's SSO service.
+ MetadataProviderCriteria mc(app, issuer, &IDPSSODescriptor::ELEMENT_QNAME, samlconstants::SAML20P_NS);
+ entity=m->getEntityDescriptor(mc);
+ if (!entity.first) {
+ log.warn("unable to locate metadata for provider (%s)", issuer);
+ throw MetadataException("Unable to locate metadata for identity provider ($entityID)", namedparams(1, "entityID", issuer));
+ }
+ else if (!entity.second) {
+ log.warn("unable to locate SAML 2.0 identity provider role for provider (%s)", issuer);
+ throw MetadataException("Unable to locate SAML 2.0 identity provider role for provider ($entityID)", namedparams(1, "entityID", issuer));
+ }
+ }
+
+ vector<const Assertion*> assertions;
+
+ AttributeExtractor* extractor = app.getAttributeExtractor();
+ if (extractor) {
+ Locker extlocker(extractor);
+ if (issuer) {
+ pair<bool,const char*> mprefix = app.getString("metadataAttributePrefix");
+ if (mprefix.first) {
+ log.debug("extracting metadata-derived attributes...");
+ try {
+ // We pass nullptr for "issuer" because the IdP isn't the one asserting metadata-based attributes.
+ extractor->extractAttributes(app, nullptr, *entity.second, resolvedAttrs);
+ for (vector<Attribute*>::iterator a = resolvedAttrs.begin(); a != resolvedAttrs.end(); ++a) {
+ vector<string>& ids = (*a)->getAliases();
+ for (vector<string>::iterator id = ids.begin(); id != ids.end(); ++id)
+ *id = mprefix.second + *id;
+ }
+ }
+ catch (exception& ex) {
+ log.error("caught exception extracting attributes: %s", ex.what());
+ }
+ }
+ }
+ log.debug("extracting pushed attributes...");
+ for (vector<const XMLObject*>::const_iterator t = tokens.begin(); t!=tokens.end(); ++t) {
+ try {
+ // Save off any assertions for later use by resolver.
+ const Assertion* assertion = dynamic_cast<const Assertion*>(*t);
+ if (assertion)
+ assertions.push_back(assertion);
+ extractor->extractAttributes(app, entity.second, *(*t), resolvedAttrs);
+ }
+ catch (exception& ex) {
+ log.error("caught exception extracting attributes: %s", ex.what());
+ }
+ }
+
+ AttributeFilter* filter = app.getAttributeFilter();
+ if (filter && !resolvedAttrs.empty()) {
+ BasicFilteringContext fc(app, resolvedAttrs, entity.second);
+ Locker filtlocker(filter);
+ try {
+ filter->filterAttributes(fc, resolvedAttrs);
+ }
+ catch (exception& ex) {
+ log.error("caught exception filtering attributes: %s", ex.what());
+ log.error("dumping extracted attributes due to filtering exception");
+ for_each(resolvedAttrs.begin(), resolvedAttrs.end(), xmltooling::cleanup<shibsp::Attribute>());
+ resolvedAttrs.clear();
+ }
+ }
+ }
+ else {
+ log.warn("no AttributeExtractor plugin installed, check log during startup");
+ }
+
+ try {
+ AttributeResolver* resolver = app.getAttributeResolver();
+ if (resolver) {
+ log.debug("resolving attributes...");
+
+ vector<Attribute*> inputs = inputAttrs;
+ inputs.insert(inputs.end(), resolvedAttrs.begin(), resolvedAttrs.end());
+
+ Locker locker(resolver);
+ auto_ptr<ResolutionContext> ctx(
+ resolver->createResolutionContext(
+ app,
+ entity.first,
+ samlconstants::SAML20P_NS,
+ nullptr,
+ nullptr,
+ nullptr,
+ &assertions,
+ &inputs
+ )
+ );
+ resolver->resolveAttributes(*ctx.get());
+ if (!ctx->getResolvedAttributes().empty())
+ resolvedAttrs.insert(resolvedAttrs.end(), ctx->getResolvedAttributes().begin(), ctx->getResolvedAttributes().end());
+ }
+ }
+ catch (exception& ex) {
+ log.error("attribute resolution failed: %s", ex.what());
+ }
+#else
+ throw ConfigurationException("Cannot process request using lite version of shibsp library.");
+#endif
+}
+
+bool ShibbolethResolver::init(unsigned long features, const char* config, bool rethrow)
+{
+ if (features && SPConfig::OutOfProcess) {
+#ifndef SHIBSP_LITE
+ features = features | SPConfig::AttributeResolution | SPConfig::Metadata | SPConfig::Trust | SPConfig::Credentials;
+#endif
+ if (!(features && SPConfig::InProcess))
+ features |= SPConfig::Listener;
+ }
+ else if (features && SPConfig::InProcess) {
+ features |= SPConfig::Listener;
+ }
+ SPConfig::getConfig().setFeatures(features);
+ if (!SPConfig::getConfig().init())
+ return false;
+ if (!SPConfig::getConfig().instantiate(config, rethrow))
+ return false;
+ return true;
+}
+
+/**
+ * Shuts down runtime.
+ *
+ * Each process using the library SHOULD call this function exactly once before terminating itself.
+ */
+void ShibbolethResolver::term()
+{
+ SPConfig::getConfig().term();
+}
+
+