X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=util_shib.cpp;h=14757d1d417c491249b011e294e6c06144a232c5;hb=e063ba4e45d12dbc1a397653f9e77228835e4a2b;hp=3d028b8e56be7bc299ff78a42ef18bd450efc5ce;hpb=80930e33ba06427e25527dd8ab0fc8b905335aac;p=mech_eap.git diff --git a/util_shib.cpp b/util_shib.cpp index 3d028b8..14757d1 100644 --- a/util_shib.cpp +++ b/util_shib.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, JANET(UK) + * Copyright (c) 2011, JANET(UK) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -45,21 +45,27 @@ * limitations under the License. */ -#include "gssapiP_eap.h" +/* + * Local attribute provider implementation. + */ + +#include + +#include #include #include -#include - #include +#include + +#include "gssapiP_eap.h" + using namespace shibsp; using namespace shibresolver; using namespace opensaml::saml2md; using namespace opensaml; -using namespace xmltooling::logging; using namespace xmltooling; -using namespace xercesc; using namespace std; gss_eap_shib_attr_provider::gss_eap_shib_attr_provider(void) @@ -97,12 +103,13 @@ gss_eap_shib_attr_provider::initFromExistingContext(const gss_eap_attr_ctx *mana } bool -addRadiusAttribute(const gss_eap_attr_provider *provider, +addRadiusAttribute(const gss_eap_attr_ctx *manager, + const gss_eap_attr_provider *provider, const gss_buffer_t attribute, void *data) { - const gss_eap_shib_attr_provider *shib; const gss_eap_radius_attr_provider *radius; + const gss_eap_shib_attr_provider *shib; int authenticated, complete, more = -1; vector attributeIds(1); SimpleAttribute *a; @@ -113,7 +120,7 @@ addRadiusAttribute(const gss_eap_attr_provider *provider, assert(radius != NULL && shib != NULL); string attributeName = - gss_eap_attr_ctx::composeAttributeName(ATTR_TYPE_RADIUS, attribute); + manager->composeAttributeName(ATTR_TYPE_RADIUS, attribute); attributeIds.push_back(attributeName); a = new SimpleAttribute(attributeIds); @@ -150,23 +157,33 @@ gss_eap_shib_attr_provider::initFromGssContext(const gss_eap_attr_ctx *manager, { const gss_eap_saml_assertion_provider *saml; const gss_eap_radius_attr_provider *radius; +#if 0 gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER; - ShibbolethResolver *resolver; OM_uint32 minor; - +#endif if (!gss_eap_attr_provider::initFromGssContext(manager, gssCred, gssCtx)) return false; saml = static_cast - (manager->getProvider(ATTR_TYPE_SAML_ASSERTION)); + (m_manager->getProvider(ATTR_TYPE_SAML_ASSERTION)); radius = static_cast - (manager->getProvider(ATTR_TYPE_RADIUS)); + (m_manager->getProvider(ATTR_TYPE_RADIUS)); - resolver = ShibbolethResolver::create(); + auto_ptr resolver(ShibbolethResolver::create()); + /* + * For now, leave ApplicationID defaulted. + * Later on, we could allow this via config option to the mechanism + * or rely on an SPRequest interface to pass in a URI identifying the + * acceptor. + */ +#if 0 if (gssCred != GSS_C_NO_CREDENTIAL && - gss_display_name(&minor, gssCred->name, &nameBuf, NULL) == GSS_S_COMPLETE) + gssEapDisplayName(&minor, gssCred->name, &nameBuf, NULL) == GSS_S_COMPLETE) { resolver->setApplicationID((const char *)nameBuf.value); + gss_release_buffer(&minor, &nameBuf); + } +#endif m_authenticated = false; @@ -181,27 +198,20 @@ gss_eap_shib_attr_provider::initFromGssContext(const gss_eap_attr_ctx *manager, m_authenticated = saml->authenticated(); } - resolver->resolve(); - - m_attributes = resolver->getResolvedAttributes(); - resolver->getResolvedAttributes().clear(); - - gss_release_buffer(&minor, &nameBuf); - - delete resolver; - -#ifdef GSSEAP_DEBUG - gss_buffer_desc testattr = { - sizeof("urn:greet:greeting") - 1, (void *)"urn:greet:greeting" }; - gss_buffer_desc testval = - { sizeof("Hello, GSS EAP.") - 1, (void *)"Hello, GSS EAP." }; - setAttribute(true, &testattr, &testval); -#endif /* GSSEAP_DEBUG */ + try { + resolver->resolve(); + m_attributes = resolver->getResolvedAttributes(); + resolver->getResolvedAttributes().clear(); + } catch (exception &e) { +#if 0 + fprintf(stderr, "%s", e.what()); +#endif + } return true; } -int +ssize_t gss_eap_shib_attr_provider::getAttributeIndex(const gss_buffer_t attr) const { int i = 0; @@ -223,8 +233,8 @@ gss_eap_shib_attr_provider::getAttributeIndex(const gss_buffer_t attr) const return -1; } -void -gss_eap_shib_attr_provider::setAttribute(int complete, +bool +gss_eap_shib_attr_provider::setAttribute(int complete GSSEAP_UNUSED, const gss_buffer_t attr, const gss_buffer_t value) { @@ -240,9 +250,11 @@ gss_eap_shib_attr_provider::setAttribute(int complete, m_attributes.push_back(a); m_authenticated = false; + + return true; } -void +bool gss_eap_shib_attr_provider::deleteAttribute(const gss_buffer_t attr) { int i; @@ -252,6 +264,8 @@ gss_eap_shib_attr_provider::deleteAttribute(const gss_buffer_t attr) m_attributes.erase(m_attributes.begin() + i); m_authenticated = false; + + return true; } bool @@ -267,7 +281,7 @@ gss_eap_shib_attr_provider::getAttributeTypes(gss_eap_attr_enumeration_cb addAtt attribute.value = (void *)((*a)->getId()); attribute.length = strlen((char *)attribute.value); - if (!addAttribute(this, &attribute, data)) + if (!addAttribute(m_manager, this, &attribute, data)) return false; } @@ -324,7 +338,7 @@ gss_eap_shib_attr_provider::getAttribute(const gss_buffer_t attr, else if (i >= nvalues) return false; - buf.value = (void *)shibAttr->getString(*more); + buf.value = (void *)shibAttr->getSerializedValues()[*more].c_str(); buf.length = strlen((char *)buf.value); if (buf.length != 0) { @@ -348,10 +362,13 @@ gss_eap_shib_attr_provider::getAttribute(const gss_buffer_t attr, gss_any_t gss_eap_shib_attr_provider::mapToAny(int authenticated, - gss_buffer_t type_id) const + gss_buffer_t type_id GSSEAP_UNUSED) const { gss_any_t output; + if (authenticated && !m_authenticated) + return (gss_any_t)NULL; + vector v = duplicateAttributes(m_attributes); output = (gss_any_t)new vector (v); @@ -360,104 +377,189 @@ gss_eap_shib_attr_provider::mapToAny(int authenticated, } void -gss_eap_shib_attr_provider::releaseAnyNameMapping(gss_buffer_t type_id, +gss_eap_shib_attr_provider::releaseAnyNameMapping(gss_buffer_t type_id GSSEAP_UNUSED, gss_any_t input) const { vector *v = ((vector *)input); delete v; } -void -gss_eap_shib_attr_provider::exportToBuffer(gss_buffer_t buffer) const +const char * +gss_eap_shib_attr_provider::prefix(void) const { - DDF obj(NULL); - DDF attrs(NULL); + return NULL; +} - buffer->length = 0; - buffer->value = NULL; +const char * +gss_eap_shib_attr_provider::name(void) const +{ + return "local"; +} + +static json_t * +ddfToJson(DDF &ddf) +{ + json_t *json; + + if (ddf.isstruct()) { + DDF elem = ddf.first(); + json = json_array(); + if (json == NULL) + throw new std::bad_alloc; + + while (!elem.isnull()) { + if (json_array_append_new(json, ddfToJson(elem)) != 0) { + json_decref(json); + throw new std::bad_alloc; + } - obj.addmember("version").integer(1); - obj.addmember("authenticated").integer(m_authenticated); + elem = ddf.next(); + } + } else if (ddf.islist()) { + DDF elem = ddf.first(); + json = json_object(); + if (json == NULL) + throw new std::bad_alloc; + + while (!elem.isnull()) { + if (json_object_set(json, elem.name(), ddfToJson(elem)) != 0) { + json_decref(json); + throw new std::bad_alloc; + } + + elem = ddf.next(); + } + } else if (ddf.isstring()) { + json = json_string(ddf.string()); + } else if (ddf.isint()) { + json = json_integer(ddf.integer()); + } else if (ddf.isfloat()) { + json = json_real(ddf.floating()); + } else if (ddf.isempty() || ddf.ispointer()) { + json = json_object(); + } else if (ddf.isnull()) { + json = json_null(); + } else { + assert(0 && "Invalid DDF object"); + } + + if (json == NULL) + throw new std::bad_alloc; + + return json; +} + +static DDF +jsonToDdf(json_t *json) +{ + DDF ddf(NULL); + + switch (json_typeof(json)) { + case JSON_OBJECT: { + void *iter = json_object_iter(json); + + while (iter != NULL) { + const char *key = json_object_iter_key(iter); + json_t *value = json_object_iter_value(iter); + ddf.add(jsonToDdf(value).name(key)); + iter = json_object_iter_next(json, iter); + } + break; + } + case JSON_ARRAY: { + size_t i; + + for (i = 0; i < json_array_size(json); i++) { + DDF value = jsonToDdf(json_array_get(json, i)); + ddf.add(value); + } + break; + } + case JSON_STRING: + ddf.string(json_string_value(json)); + break; + case JSON_INTEGER: + ddf.integer(json_integer_value(json)); + break; + case JSON_REAL: + ddf.floating(json_real_value(json)); + break; + case JSON_TRUE: + ddf.integer(1L); + break; + case JSON_FALSE: + ddf.integer(0L); + break; + case JSON_NULL: + break; + } + + return ddf; +} + +json_t * +gss_eap_shib_attr_provider::jsonRepresentation(void) const +{ + json_t *obj, *attrs; + + obj = json_object(); + if (obj == NULL) + throw new std::bad_alloc; + + /* FIXME check json_object_set_new return value */ + json_object_set_new(obj, "authenticated", json_integer(m_authenticated)); + + attrs = json_array(); + if (attrs == NULL) { + json_decref(obj); + throw new std::bad_alloc; + } - attrs = obj.addmember("attributes").list(); for (vector::const_iterator a = m_attributes.begin(); a != m_attributes.end(); ++a) { DDF attr = (*a)->marshall(); - attrs.add(attr); + /* FIXME check json_array_append_new return value */ + json_array_append_new(attrs, ddfToJson(attr)); } - ostringstream sink; - sink << attrs; - string str = sink.str(); - - duplicateBuffer(str, buffer); + json_object_set_new(obj, "attributes", attrs); - attrs.destroy(); + return obj; } bool -gss_eap_shib_attr_provider::initFromBuffer(const gss_eap_attr_ctx *ctx, - const gss_buffer_t buffer) +gss_eap_shib_attr_provider::initWithJsonObject(const gss_eap_attr_ctx *ctx, + json_t *obj) { - if (!gss_eap_attr_provider::initFromBuffer(ctx, buffer)) - return false; + size_t i; + json_t *attrs; - if (buffer->length == 0) - return true; + if (!gss_eap_attr_provider::initWithJsonObject(ctx, obj)) + return false; assert(m_authenticated == false); assert(m_attributes.size() == 0); - DDF obj(NULL); - string str((const char *)buffer->value, buffer->length); - istringstream source(str); + m_authenticated = json_integer_value(json_object_get(obj, "authenticated")); - source >> obj; + attrs = json_object_get(obj, "attributes"); - if (obj["version"].integer() != 1) - return false; - - m_authenticated = (obj["authenticated"].integer() != 0); - - DDF attrs = obj["attributes"]; - DDF attr = attrs.first(); - while (!attr.isnull()) { + for (i = 0; i < json_array_size(attrs); i++) { + DDF attr = jsonToDdf(json_array_get(attrs, i)); Attribute *attribute = Attribute::unmarshall(attr); m_attributes.push_back(attribute); - attr = attrs.next(); } - attrs.destroy(); - return true; } bool gss_eap_shib_attr_provider::init(void) { -#if 1 - SPConfig& conf=SPConfig::getConfig(); - conf.setFeatures( - SPConfig::Metadata | - SPConfig::Trust | - SPConfig::AttributeResolution | - SPConfig::Credentials | - SPConfig::OutOfProcess - ); - if (!conf.init()) - return false; - if (!conf.instantiate()) { - conf.term(); - return false; - } -#else if (!ShibbolethResolver::init()) return false; -#endif - gss_eap_attr_ctx::registerProvider(ATTR_TYPE_LOCAL, - NULL, - gss_eap_shib_attr_provider::createAttrContext); + gss_eap_attr_ctx::registerProvider(ATTR_TYPE_LOCAL, createAttrContext); return true; } @@ -466,7 +568,29 @@ void gss_eap_shib_attr_provider::finalize(void) { gss_eap_attr_ctx::unregisterProvider(ATTR_TYPE_LOCAL); -// ShibbolethResolver::term(); + ShibbolethResolver::term(); +} + +OM_uint32 +gss_eap_shib_attr_provider::mapException(OM_uint32 *minor, + std::exception &e) const +{ + if (typeid(e) == typeid(AttributeException)) + *minor = GSSEAP_SHIB_ATTR_FAILURE; + else if (typeid(e) == typeid(AttributeExtractionException)) + *minor = GSSEAP_SHIB_ATTR_EXTRACT_FAILURE; + else if (typeid(e) == typeid(AttributeFilteringException)) + *minor = GSSEAP_SHIB_ATTR_FILTER_FAILURE; + else if (typeid(e) == typeid(AttributeResolutionException)) + *minor = GSSEAP_SHIB_ATTR_RESOLVE_FAILURE; + else if (typeid(e) == typeid(ConfigurationException)) + *minor = GSSEAP_SHIB_CONFIG_FAILURE; + else if (typeid(e) == typeid(ListenerException)) + *minor = GSSEAP_SHIB_LISTENER_FAILURE; + else + return GSS_S_CONTINUE_NEEDED; + + return GSS_S_FAILURE; } gss_eap_attr_provider * @@ -501,13 +625,18 @@ gss_eap_shib_attr_provider::duplicateAttributes(const vector src) OM_uint32 gssEapLocalAttrProviderInit(OM_uint32 *minor) { - return gss_eap_shib_attr_provider::init() - ? GSS_S_COMPLETE : GSS_S_FAILURE; + if (!gss_eap_shib_attr_provider::init()) { + *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; }