* Local attribute provider implementation.
*/
+#include "gssapiP_eap.h"
+
#include <xmltooling/XMLObject.h>
+#ifndef HAVE_OPENSAML
+#include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/util/ParserPool.h>
+#endif
#include <saml/saml2/core/Assertions.h>
#include <shibsp/exceptions.h>
-#include <shibsp/attribute/BinaryAttribute.h>
#include <shibsp/attribute/SimpleAttribute.h>
+#include <shibsp/attribute/BinaryAttribute.h>
+#include <shibsp/attribute/ScopedAttribute.h>
#include <shibresolver/resolver.h>
#include <sstream>
-#include "gssapiP_eap.h"
-
using namespace shibsp;
using namespace shibresolver;
-using namespace opensaml::saml2md;
-using namespace opensaml;
using namespace xmltooling;
using namespace std;
+#ifdef HAVE_OPENSAML
+using namespace opensaml::saml2md;
+using namespace opensaml;
+#else
+using namespace xercesc;
+#endif
+
+
+namespace {
+
+
+ class ShibFinalizer {
+ public:
+
+ static bool isShibInitialized() {return shibInitialized;}
+ static void createSingleton();
+
+ private:
+ ShibFinalizer(): is_extra(false) {
+ if (shibInitialized) {
+ // This should never, ever happen. Initialization is (supposed to be)
+ // funneled through a single thread, so there should be no race
+ // conditions here. And only this class sets this flag, and there's
+ // only a single instance of this class.
+ wpa_printf(MSG_ERROR, "### ShibFinalizer::ShibFinalizer(): Attempt to construct an extraneous instance!");
+ is_extra = true;
+ }
+ else {
+ wpa_printf(MSG_INFO, "### ShibFinalizer::ShibFinalizer(): Constructing");
+ shibInitialized = true;
+ }
+ }
+
+ ~ShibFinalizer() {
+ if (!is_extra) {
+ wpa_printf(MSG_INFO, "### ShibFinalizer::~ShibFinalizer(): Destructing");
+ gss_eap_shib_attr_provider::finalize();
+ shibInitialized = false;
+ }
+ else {
+ wpa_printf(MSG_INFO, "### ShibFinalizer::~ShibFinalizer(): This was an extraneous instance; not destructing anything.");
+ }
+ }
+
+ bool is_extra;
+ static bool shibInitialized;
+ };
+}
+
+
+bool ShibFinalizer::shibInitialized = false;
+
+void ShibFinalizer::createSingleton() {
+ // This object's constructor is invoked on the first call to this method.
+ // At exit, its destructor will terminate Shibboleth.
+ static ShibFinalizer finalizer;
+}
+
gss_eap_shib_attr_provider::gss_eap_shib_attr_provider(void)
{
gss_release_buffer(&minor, &mechName);
}
+#ifdef HAVE_OPENSAML
const gss_eap_saml_assertion_provider *saml;
saml = static_cast<const gss_eap_saml_assertion_provider *>
(m_manager->getProvider(ATTR_TYPE_SAML_ASSERTION));
if (saml != NULL && saml->getAssertion() != NULL) {
resolver->addToken(saml->getAssertion());
}
+#else
+ /* If no OpenSAML, parse the XML assertion explicitly */
+ const gss_eap_radius_attr_provider *radius;
+ int authenticated, complete;
+ gss_buffer_desc value = GSS_C_EMPTY_BUFFER;
+ gss_eap_attrid attrid(VENDORPEC_UKERNA, PW_SAML_AAA_ASSERTION);
+
+ radius = static_cast<const gss_eap_radius_attr_provider *>
+ (m_manager->getProvider(ATTR_TYPE_RADIUS));
+ if (radius != NULL &&
+ radius->getFragmentedAttribute(attrid, &authenticated, &complete, &value)) {
+ string str((char *)value.value, value.length);
+ istringstream istream(str);
+ DOMDocument *doc = XMLToolingConfig::getConfig().getParser().parse(istream);
+ const XMLObjectBuilder *b = XMLObjectBuilder::getBuilder(doc->getDocumentElement());
+ resolver->addToken(b->buildFromDocument(doc));
+ gss_release_buffer(&minor, &value);
+ }
+#endif /* HAVE_OPENSAML */
try {
resolver->resolve();
{
int i = 0;
- assert(m_initialized);
+ GSSEAP_ASSERT(m_initialized);
for (vector<Attribute *>::const_iterator a = m_attributes.begin();
a != m_attributes.end();
vector <string> ids(1, attrStr);
BinaryAttribute *a = new BinaryAttribute(ids);
- assert(m_initialized);
+ GSSEAP_ASSERT(m_initialized);
if (value->length != 0) {
string valueStr((char *)value->value, value->length);
{
int i;
- assert(m_initialized);
+ GSSEAP_ASSERT(m_initialized);
i = getAttributeIndex(attr);
if (i >= 0)
gss_eap_shib_attr_provider::getAttributeTypes(gss_eap_attr_enumeration_cb addAttribute,
void *data) const
{
- assert(m_initialized);
+ GSSEAP_ASSERT(m_initialized);
for (vector<Attribute*>::const_iterator a = m_attributes.begin();
a != m_attributes.end();
{
const Attribute *ret = NULL;
- assert(m_initialized);
+ GSSEAP_ASSERT(m_initialized);
for (vector<Attribute *>::const_iterator a = m_attributes.begin();
a != m_attributes.end();
gss_buffer_desc displayValueBuf = GSS_C_EMPTY_BUFFER;
int nvalues, i = *more;
- assert(m_initialized);
+ GSSEAP_ASSERT(m_initialized);
*more = 0;
valueBuf.value = (void *)str.c_str();
valueBuf.length = str.length();
- displayValueBuf = valueBuf;
+ const SimpleAttribute *simpleAttr =
+ dynamic_cast<const SimpleAttribute *>(shibAttr);
+ const ScopedAttribute *scopedAttr =
+ dynamic_cast<const ScopedAttribute *>(shibAttr);
+ if (simpleAttr != NULL || scopedAttr != NULL)
+ displayValueBuf = valueBuf;
}
if (authenticated != NULL)
{
gss_any_t output;
- assert(m_initialized);
+ GSSEAP_ASSERT(m_initialized);
if (authenticated && !m_authenticated)
return (gss_any_t)NULL;
gss_eap_shib_attr_provider::releaseAnyNameMapping(gss_buffer_t type_id GSSEAP_UNUSED,
gss_any_t input) const
{
- assert(m_initialized);
+ GSSEAP_ASSERT(m_initialized);
vector <Attribute *> *v = ((vector <Attribute *> *)input);
delete v;
if (!gss_eap_attr_provider::initWithJsonObject(ctx, obj))
return false;
- assert(m_authenticated == false);
- assert(m_attributes.size() == 0);
+ GSSEAP_ASSERT(m_authenticated == false);
+ GSSEAP_ASSERT(m_attributes.size() == 0);
JSONObject jattrs = obj["attributes"];
size_t nelems = jattrs.size();
{
bool ret = false;
+ if (ShibFinalizer::isShibInitialized()) {
+ wpa_printf(MSG_INFO, "### gss_eap_shib_attr_provider::init(): ShibResolver library is already initialized; ignoring.");
+ return true;
+ }
+
+ wpa_printf(MSG_INFO, "### gss_eap_shib_attr_provider::init(): Initializing ShibResolver library");
+
try {
- if (SPConfig::getConfig().getFeatures() == 0)
- ret = ShibbolethResolver::init();
+ ret = ShibbolethResolver::init();
} catch (exception &e) {
}
- if (ret)
+ if (ret) {
+ ShibFinalizer::createSingleton();
gss_eap_attr_ctx::registerProvider(ATTR_TYPE_LOCAL, createAttrContext);
+ }
return ret;
}
void
gss_eap_shib_attr_provider::finalize(void)
{
+ wpa_printf(MSG_INFO, "### gss_eap_shib_attr_provider::finalize(): calling ShibbolethResolver::term()");
gss_eap_attr_ctx::unregisterProvider(ATTR_TYPE_LOCAL);
ShibbolethResolver::term();
}
return dst;
}
+
OM_uint32
gssEapLocalAttrProviderInit(OM_uint32 *minor)
{
*minor = GSSEAP_SHIB_INIT_FAILURE;
return GSS_S_FAILURE;
}
- return GSS_S_COMPLETE;
-}
-
-OM_uint32
-gssEapLocalAttrProviderFinalize(OM_uint32 *minor)
-{
- gss_eap_shib_attr_provider::finalize();
- *minor = 0;
return GSS_S_COMPLETE;
}