From 81378d116795fa8a7a56dc8e00c3b2666126682d Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Sat, 18 Sep 2010 00:19:52 +0200 Subject: [PATCH] New attribute provider SPI --- Makefile.am | 4 +- delete_name_attribute.c | 13 +- duplicate_name.c | 10 +- eap_mech.c | 5 +- get_name_attribute.c | 28 +- gssapiP_eap.h | 9 +- inquire_name.c | 84 +--- map_name_to_any.c | 6 +- release_any_name_mapping.c | 5 +- set_name_attribute.c | 13 +- util.h | 32 +- util_attr.cpp | 635 +++++++++++++++++++++++++++++ util_attr.h | 286 ++++++++++++++ util_name.c | 199 +--------- util_radius.c | 109 ----- util_radius.cpp | 131 ++++++ util_radius.h | 84 ++-- util_saml.cpp | 965 +++++++++++---------------------------------- util_saml.h | 197 ++++----- util_shib.cpp | 338 ++++++++++++++++ util_shib.h | 87 ++++ 21 files changed, 1904 insertions(+), 1336 deletions(-) create mode 100644 util_attr.cpp create mode 100644 util_attr.h delete mode 100644 util_radius.c create mode 100644 util_radius.cpp create mode 100644 util_shib.cpp create mode 100644 util_shib.h diff --git a/Makefile.am b/Makefile.am index eb3a837..38face2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -60,6 +60,7 @@ libmech_eap_la_SOURCES = \ store_cred.c \ unwrap.c \ unwrap_iov.c \ + util_attr.cpp \ util_buffer.c \ util_context.c \ util_cksum.c \ @@ -70,8 +71,9 @@ libmech_eap_la_SOURCES = \ util_name.c \ util_oid.c \ util_ordering.c \ - util_radius.c \ + util_radius.cpp \ util_saml.cpp \ + util_shib.cpp \ util_token.c \ verify_mic.c \ wrap.c \ diff --git a/delete_name_attribute.c b/delete_name_attribute.c index 49717ff..a57272c 100644 --- a/delete_name_attribute.c +++ b/delete_name_attribute.c @@ -39,7 +39,6 @@ gss_delete_name_attribute(OM_uint32 *minor, { OM_uint32 major; gss_buffer_desc prefix, suffix; - enum gss_eap_attribute_type type; if (name == GSS_C_NO_NAME) { *minor = EINVAL; @@ -48,18 +47,8 @@ gss_delete_name_attribute(OM_uint32 *minor, GSSEAP_MUTEX_LOCK(&name->mutex); - major = decomposeAttributeName(minor, attr, &prefix, &suffix); - if (GSS_ERROR(major)) - goto cleanup; + major = gssEapDeleteNameAttribute(minor, name, attr); - type = gssEapAttributePrefixToType(&prefix); - if (type == ATTR_TYPE_NONE) { - major = samlDeleteAttribute(minor, name, attr); - } else { - major = GSS_S_UNAVAILABLE; - } - -cleanup: GSSEAP_MUTEX_UNLOCK(&name->mutex); return major; diff --git a/duplicate_name.c b/duplicate_name.c index b936655..fc54f7d 100644 --- a/duplicate_name.c +++ b/duplicate_name.c @@ -63,14 +63,8 @@ gss_duplicate_name(OM_uint32 *minor, goto cleanup; } - if (input_name->flags & NAME_FLAG_RADIUS_ATTRIBUTES) { - major = radiusDuplicateAttrContext(minor, input_name, name); - if (GSS_ERROR(major)) - goto cleanup; - } - - if (input_name->flags & NAME_FLAG_SAML_ATTRIBUTES) { - major = samlDuplicateAttrContext(minor, input_name, name); + if (input_name->attrCtx != NULL) { + major = gssEapDuplicateAttrContext(minor, input_name, name); if (GSS_ERROR(major)) goto cleanup; } diff --git a/eap_mech.c b/eap_mech.c index c06714e..fb149e0 100644 --- a/eap_mech.c +++ b/eap_mech.c @@ -270,8 +270,7 @@ gssEapInit(void) gssEapInitLibEap(&minor); gssEapInitLibRadSec(&minor); eapServerRegisterMethods(&minor); - - samlInit(&minor); + gssEapAttrProvidersInit(&minor); } static void @@ -283,6 +282,6 @@ gssEapFinalize(void) #if 1 eap_server_unregister_methods(); #endif - samlFinalize(&minor); + gssEapAttrProvidersFinalize(&minor); } diff --git a/get_name_attribute.c b/get_name_attribute.c index 3b22dc5..c5e5d24 100644 --- a/get_name_attribute.c +++ b/get_name_attribute.c @@ -42,9 +42,8 @@ gss_get_name_attribute(OM_uint32 *minor, gss_buffer_t display_value, int *more) { - OM_uint32 major, tmpMinor; + OM_uint32 major; gss_buffer_desc prefix, suffix; - enum gss_eap_attribute_type type; if (name == GSS_C_NO_NAME) { *minor = EINVAL; @@ -61,33 +60,10 @@ gss_get_name_attribute(OM_uint32 *minor, GSSEAP_MUTEX_LOCK(&name->mutex); - major = decomposeAttributeName(minor, attr, &prefix, &suffix); - if (GSS_ERROR(major)) - goto cleanup; - - type = gssEapAttributePrefixToType(&prefix); - switch (type) { - case ATTR_TYPE_NONE: - case ATTR_TYPE_SAML_ATTR: - major = samlGetAttribute(minor, type, name, - (type == ATTR_TYPE_NONE) ? attr : &suffix, - authenticated, complete, - value, display_value, more); - break; - case ATTR_TYPE_SAML_AAA_ASSERTION: - major = samlGetAssertion(minor, name, value); - break; - case ATTR_TYPE_RADIUS_AVP: - major = radiusGetAttribute(minor, name, &suffix, + major = gssEapGetNameAttribute(minor, name, attr, authenticated, complete, value, display_value, more); - break; - default: - major = GSS_S_UNAVAILABLE; - break; - } -cleanup: GSSEAP_MUTEX_UNLOCK(&name->mutex); return major; diff --git a/gssapiP_eap.h b/gssapiP_eap.h index 35cc154..1d97e73 100644 --- a/gssapiP_eap.h +++ b/gssapiP_eap.h @@ -65,18 +65,16 @@ #define NAME_FLAG_RADIUS_ATTRIBUTES 0x00000004 #define NAME_FLAG_SAML_ATTRIBUTES 0x00000008 -#define NAME_HAS_ATTRIBUTES(name) \ - (((name)->flags & (NAME_FLAG_RADIUS_ATTRIBUTES | \ - NAME_FLAG_SAML_ATTRIBUTES)) != 0) +#define NAME_HAS_ATTRIBUTES(name) ((name)->attrCtx != NULL) struct gss_eap_saml_attr_ctx; +struct gss_eap_attr_ctx; struct gss_name_struct { GSSEAP_MUTEX mutex; /* mutex protecting attributes */ OM_uint32 flags; krb5_principal krbPrincipal; /* this is immutable */ - struct gss_eap_radius_attr_ctx *radiusCtx; - struct gss_eap_saml_attr_ctx *samlCtx; + struct gss_eap_attr_ctx *attrCtx; }; #define CRED_FLAG_INITIATE 0x00000001 @@ -119,6 +117,7 @@ enum gss_eap_state { #define CTX_FLAG_EAP_PORT_ENABLED 0x00400000 #define CTX_FLAG_EAP_ALT_ACCEPT 0x00800000 #define CTX_FLAG_EAP_ALT_REJECT 0x01000000 +#define CTX_FLAG_EAP_MASK 0xFFFF0000 struct gss_eap_initiator_ctx { unsigned int idleWhile; diff --git a/inquire_name.c b/inquire_name.c index 6c640f3..e01cc61 100644 --- a/inquire_name.c +++ b/inquire_name.c @@ -32,46 +32,6 @@ #include "gssapiP_eap.h" -struct gss_eap_attribute_args { - enum gss_eap_attribute_type type; - gss_buffer_set_t attrs; -}; - -/* - * The purpose of this callback interface is to not expose the attribute - * prefixes to the attribute providers themselves. - */ -static OM_uint32 -addAttribute(OM_uint32 *minor, - gss_name_t name, - gss_buffer_t attribute, - void *data) -{ - struct gss_eap_attribute_args *args = (struct gss_eap_attribute_args *)data; - OM_uint32 major, tmpMinor; - gss_buffer_desc qualifiedAttr; - gss_buffer_t prefix; - - if (args->type != ATTR_TYPE_NONE) - prefix = gssEapAttributeTypeToPrefix(args->type); - else - prefix = GSS_C_NO_BUFFER; - - if (prefix != GSS_C_NO_BUFFER && attribute != GSS_C_NO_BUFFER) { - major = composeAttributeName(minor, prefix, attribute, &qualifiedAttr); - if (GSS_ERROR(major)) - return major; - major = gss_add_buffer_set_member(minor, &qualifiedAttr, &args->attrs); - - gss_release_buffer(&tmpMinor, &qualifiedAttr); - } else { - assert(prefix != GSS_C_NO_BUFFER); - major = gss_add_buffer_set_member(minor, prefix, &args->attrs); - } - - return major; -} - OM_uint32 gss_inquire_name(OM_uint32 *minor, gss_name_t name, int *name_is_MN, @@ -79,8 +39,6 @@ OM_uint32 gss_inquire_name(OM_uint32 *minor, gss_buffer_set_t *attrs) { OM_uint32 major, tmpMinor; - krb5_context krbContext; - struct gss_eap_attribute_args args; *name_is_MN = 1; *MN_mech = GSS_EAP_MECHANISM; @@ -91,50 +49,10 @@ OM_uint32 gss_inquire_name(OM_uint32 *minor, return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME; } - GSSEAP_KRB_INIT(&krbContext); GSSEAP_MUTEX_LOCK(&name->mutex); - major = gss_create_empty_buffer_set(minor, attrs); - if (GSS_ERROR(major)) - goto cleanup; - - args.attrs = *attrs; - - if (name->flags & NAME_FLAG_SAML_ATTRIBUTES) { - /* The assertion itself */ - args.type = ATTR_TYPE_SAML_AAA_ASSERTION; - - major = addAttribute(minor, name, GSS_C_NO_BUFFER, &args); - if (GSS_ERROR(major)) - goto cleanup; - - /* Raw SAML attributes */ -#if 0 - args.type = ATTR_TYPE_SAML_ATTR; - major = samlGetAttributeTypes(minor, args.type, - name, addAttribute, &args); - if (GSS_ERROR(major)) - goto cleanup; -#endif - - /* Cooked local attributes */ - args.type = ATTR_TYPE_NONE; - major = samlGetAttributeTypes(minor, name, args.type, - addAttribute, &args); - if (GSS_ERROR(major)) - goto cleanup; - } - - if (name->flags & NAME_FLAG_RADIUS_ATTRIBUTES) { - /* Raw RADIUS attributes */ - args.type = ATTR_TYPE_RADIUS_AVP; - major = radiusGetAttributeTypes(minor, name, - addAttribute, &args); - if (GSS_ERROR(major)) - goto cleanup; - } + major = gssEapInquireName(minor, name, name_is_MN, MN_mech, attrs); -cleanup: GSSEAP_MUTEX_UNLOCK(&name->mutex); if (GSS_ERROR(major)) diff --git a/map_name_to_any.c b/map_name_to_any.c index 164b26a..9bba387 100644 --- a/map_name_to_any.c +++ b/map_name_to_any.c @@ -50,11 +50,7 @@ gss_map_name_to_any(OM_uint32 *minor, GSSEAP_MUTEX_LOCK(&name->mutex); - if (name->flags & NAME_FLAG_SAML_ATTRIBUTES) - major = samlMapNameToAny(minor, name, authenticated, - type_id, output); - else - major = GSS_S_UNAVAILABLE; + major = gssEapMapNameToAny(minor, name, authenticated, type_id, output); GSSEAP_MUTEX_UNLOCK(&name->mutex); diff --git a/release_any_name_mapping.c b/release_any_name_mapping.c index a52642c..791c85b 100644 --- a/release_any_name_mapping.c +++ b/release_any_name_mapping.c @@ -47,10 +47,7 @@ gss_release_any_name_mapping(OM_uint32 *minor, GSSEAP_MUTEX_LOCK(&name->mutex); - if (name->flags & NAME_FLAG_SAML_ATTRIBUTES) - major = samlReleaseAnyNameMapping(minor, name, type_id, input); - else - major = GSS_S_UNAVAILABLE; + major = gssEapReleaseAnyNameMapping(minor, name, type_id, input); GSSEAP_MUTEX_UNLOCK(&name->mutex); diff --git a/set_name_attribute.c b/set_name_attribute.c index 9807557..fa95836 100644 --- a/set_name_attribute.c +++ b/set_name_attribute.c @@ -41,7 +41,6 @@ gss_set_name_attribute(OM_uint32 *minor, { OM_uint32 major; gss_buffer_desc prefix, suffix; - enum gss_eap_attribute_type type; if (name == GSS_C_NO_NAME) { *minor = EINVAL; @@ -50,18 +49,8 @@ gss_set_name_attribute(OM_uint32 *minor, GSSEAP_MUTEX_LOCK(&name->mutex); - major = decomposeAttributeName(minor, attr, &prefix, &suffix); - if (GSS_ERROR(major)) - goto cleanup; + major = gssEapSetNameAttribute(minor, name, complete, attr, value); - type = gssEapAttributePrefixToType(&prefix); - if (type == ATTR_TYPE_NONE) { - major = samlSetAttribute(minor, name, complete, attr, value); - } else { - major = GSS_S_UNAVAILABLE; - } - -cleanup: GSSEAP_MUTEX_UNLOCK(&name->mutex); return major; diff --git a/util.h b/util.h index 936ccea..dd0cb73 100644 --- a/util.h +++ b/util.h @@ -281,18 +281,6 @@ gssEapValidateMechs(OM_uint32 *minor, const gss_OID_set mechs); /* util_name.c */ -enum gss_eap_attribute_type { - ATTR_TYPE_NONE = 0, - ATTR_TYPE_SAML_AAA_ASSERTION = 1, - ATTR_TYPE_SAML_ATTR = 2, - ATTR_TYPE_RADIUS_AVP = 3 -}; - -typedef OM_uint32 (*gss_eap_add_attr_cb)(OM_uint32 *minor, - gss_name_t name, - gss_buffer_t attribute, - void *data); - OM_uint32 gssEapAllocName(OM_uint32 *minor, gss_name_t *pName); OM_uint32 gssEapReleaseName(OM_uint32 *minor, gss_name_t *pName); OM_uint32 gssEapExportName(OM_uint32 *minor, @@ -304,21 +292,6 @@ OM_uint32 gssEapImportName(OM_uint32 *minor, gss_OID input_name_type, gss_name_t *output_name); -enum gss_eap_attribute_type -gssEapAttributePrefixToType(const gss_buffer_t prefix); -gss_buffer_t -gssEapAttributeTypeToPrefix(enum gss_eap_attribute_type type); -OM_uint32 -decomposeAttributeName(OM_uint32 *minor, - const gss_buffer_t attribute, - gss_buffer_t prefix, - gss_buffer_t suffix); -OM_uint32 -composeAttributeName(OM_uint32 *minor, - const gss_buffer_t prefix, - const gss_buffer_t suffix, - gss_buffer_t attribute); - /* util_oid.c */ OM_uint32 composeOid(OM_uint32 *minor_status, @@ -431,9 +404,6 @@ verifyTokenHeader(OM_uint32 *minor, #define GSSEAP_ONCE(o, i) pthread_once((o), (i)) #define GSSEAP_ONCE_INITIALIZER PTHREAD_ONCE_INIT -#include "util_radius.h" -#include "util_saml.h" - /* Helper functions */ static inline void store_uint16_be(uint16_t val, void *vp) @@ -549,4 +519,6 @@ store_oid(gss_OID oid, void *vp) } #endif +#include "util_attr.h" + #endif /* _UTIL_H_ */ diff --git a/util_attr.cpp b/util_attr.cpp new file mode 100644 index 0000000..2686f24 --- /dev/null +++ b/util_attr.cpp @@ -0,0 +1,635 @@ +/* + * Copyright (c) 2010, JANET(UK) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of JANET(UK) nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gssapiP_eap.h" + +#include +#include +#include + +static gss_eap_attr_create_cb +gss_eap_attr_factories[ATTR_TYPE_MAX] = { + gss_eap_radius_attr_provider::createAttrContext, + gss_eap_saml_assertion_provider::createAttrContext, + gss_eap_saml_attr_provider::createAttrContext, + gss_eap_shib_attr_provider::createAttrContext +}; + +gss_eap_attr_ctx * +gss_eap_attr_ctx::createAttrContext(gss_cred_id_t gssCred, + gss_ctx_id_t gssCtx) +{ + gss_eap_attr_ctx *ctx; + + ctx = new gss_eap_attr_ctx(NULL, gssCred, gssCtx); + + for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++) { + gss_eap_attr_provider *provider; + + provider = (gss_eap_attr_factories[i])(ctx, gssCred, gssCtx); + if (provider != NULL) + ctx->m_providers[i] = provider; + } + + return ctx; +} + +gss_eap_attr_ctx::~gss_eap_attr_ctx(void) +{ + for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++) + delete m_providers[i]; +} + +bool +gss_eap_attr_ctx::init(void) +{ + return gss_eap_radius_attr_provider::init() && + gss_eap_saml_assertion_provider::init() && + gss_eap_saml_attr_provider::init() && + gss_eap_shib_attr_provider::init(); +} + +void +gss_eap_attr_ctx::finalize(void) +{ + gss_eap_shib_attr_provider::finalize(); + gss_eap_saml_attr_provider::finalize(); + gss_eap_saml_assertion_provider::finalize(); + gss_eap_radius_attr_provider::finalize(); +} + +gss_eap_attr_provider * +gss_eap_attr_ctx::getProvider(unsigned int type) const +{ + return m_providers[type]; +} + +gss_eap_attr_provider * +gss_eap_attr_ctx::getProvider(const gss_buffer_t prefix) const +{ + unsigned int type; + + type = attributePrefixToType(prefix); + + return m_providers[type]; +} + +gss_eap_attr_ctx::gss_eap_attr_ctx(const gss_eap_attr_ctx &ctx) + : gss_eap_attr_provider(ctx) +{ + for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++) { + if (ctx.m_providers[i] != NULL) { + m_providers[i] = (gss_eap_attr_factories[i])(&ctx, GSS_C_NO_CREDENTIAL, + GSS_C_NO_CONTEXT); + } + } +} + +void +gss_eap_attr_ctx::setAttribute(int complete, + const gss_buffer_t attr, + const gss_buffer_t value) +{ + gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER; + unsigned int type; + gss_eap_attr_provider *provider; + + decomposeAttributeName(attr, &type, &suffix); + + provider = m_providers[type]; + if (provider != NULL) { + provider->setAttribute(complete, + (type == ATTR_TYPE_LOCAL) ? attr : &suffix, + value); + + } +} + +void +gss_eap_attr_ctx::deleteAttribute(const gss_buffer_t attr) +{ + gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER; + unsigned int type; + gss_eap_attr_provider *provider; + + decomposeAttributeName(attr, &type, &suffix); + + provider = m_providers[type]; + if (provider != NULL) { + provider->deleteAttribute(type == ATTR_TYPE_LOCAL ? attr : &suffix); + } +} + +bool +gss_eap_attr_ctx::getAttributeTypes(gss_eap_attr_enumeration_cb cb, void *data) const +{ + bool ret = false; + size_t i; + + for (i = 0; i < ATTR_TYPE_MAX; i++) { + gss_eap_attr_provider *provider; + + provider = m_providers[i]; + if (provider == NULL) + continue; + + ret = provider->getAttributeTypes(cb, data); + if (ret == false) + break; + } + + return ret; +} + +struct eap_gss_get_attr_types_args { + unsigned int type; + gss_buffer_set_t attrs; +}; + +static bool +addAttribute(const gss_eap_attr_provider *provider, + const gss_buffer_t attribute, + void *data) +{ + eap_gss_get_attr_types_args *args = (eap_gss_get_attr_types_args *)data; + gss_buffer_t prefix = GSS_C_NO_BUFFER; + gss_buffer_desc qualified; + OM_uint32 major, minor; + + if (args->type != ATTR_TYPE_LOCAL) { + gss_eap_attr_ctx::composeAttributeName(args->type, attribute, &qualified); + major = gss_add_buffer_set_member(&minor, &qualified, &args->attrs); + gss_release_buffer(&minor, &qualified); + } else { + major = gss_add_buffer_set_member(&minor, prefix, &args->attrs); + } + + return GSS_ERROR(major) ? false : true; +} + +bool +gss_eap_attr_ctx::getAttributeTypes(gss_buffer_set_t *attrs) +{ + eap_gss_get_attr_types_args args; + OM_uint32 major, minor; + bool ret = false; + unsigned int i; + + major = gss_create_empty_buffer_set(&minor, attrs); + if (GSS_ERROR(major)) { + throw new std::bad_alloc; + return false; + } + + args.attrs = *attrs; + + for (i = 0; i < ATTR_TYPE_MAX; i++) { + gss_eap_attr_provider *provider; + + args.type = i; + + provider = m_providers[i]; + if (provider == NULL) + continue; + + ret = provider->getAttributeTypes(addAttribute, (void *)&args); + if (ret == false) + break; + } + + if (ret == false) { + gss_release_buffer_set(&minor, attrs); + } + + return ret; +} + +bool +gss_eap_attr_ctx::getAttribute(const gss_buffer_t attr, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) const +{ + gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER; + unsigned int type; + gss_eap_attr_provider *provider; + bool ret; + + decomposeAttributeName(attr, &type, &suffix); + + provider = m_providers[type]; + if (provider == NULL) { + *more = 0; + return false; + } + + ret = provider->getAttribute(type == ATTR_TYPE_LOCAL ? attr : &suffix, + authenticated, complete, + value, display_value, more); + + return ret; +} + +gss_any_t +gss_eap_attr_ctx::mapToAny(int authenticated, + gss_buffer_t type_id) const +{ + return NULL; +} + +void +gss_eap_attr_ctx::releaseAnyNameMapping(gss_buffer_t type_id, + gss_any_t input) const +{ +} + +void +gss_eap_attr_ctx::marshall(gss_buffer_t buffer) const +{ +} + +/* + * C wrappers + */ + +static OM_uint32 +mapException(OM_uint32 *minor, std::exception &e) +{ + *minor = 0; + return GSS_S_FAILURE; +} + +static gss_buffer_desc attributePrefixes[] = { + { + /* ATTR_TYPE_RADIUS_AVP */ + sizeof("urn:ietf:params:gss-eap:radius-avp"), + (void *)"urn:ietf:params:gss-eap:radius-avp", + }, + { + /* ATTR_TYPE_SAML_AAA_ASSERTION */ + sizeof("urn:ietf:params:gss-eap:saml-aaa-assertion"), + (void *)"urn:ietf:params:gss-eap:saml-aaa-assertion" + }, + { + /* ATTR_TYPE_SAML_ATTR */ + sizeof("urn:ietf:params:gss-eap:saml-attr"), + (void *)"urn:ietf:params:gss-eap:saml-attr" + }, +}; + +unsigned int +gss_eap_attr_ctx::attributePrefixToType(const gss_buffer_t prefix) +{ + unsigned int i; + + for (i = ATTR_TYPE_MIN; + i < sizeof(attributePrefixes) / sizeof(attributePrefixes[0]); + i++) + { + if (bufferEqual(&attributePrefixes[i], prefix)) + return i; + } + + return ATTR_TYPE_LOCAL; +} + +gss_buffer_t +gss_eap_attr_ctx::attributeTypeToPrefix(unsigned int type) +{ + if (type < ATTR_TYPE_MIN || type >= ATTR_TYPE_LOCAL) + return GSS_C_NO_BUFFER; + + return &attributePrefixes[type]; +} + +void +gss_eap_attr_ctx::decomposeAttributeName(const gss_buffer_t attribute, + gss_buffer_t prefix, + gss_buffer_t suffix) +{ + char *p = NULL; + size_t i; + + for (i = 0; i < attribute->length; i++) { + if (((char *)attribute->value)[i] == ' ') { + p = (char *)attribute->value + i + 1; + break; + } + } + + prefix->value = attribute->value; + prefix->length = i; + + if (p != NULL && *p != '\0') { + suffix->length = attribute->length - 1 - prefix->length; + suffix->value = p; + } else { + suffix->length = 0; + suffix->value = NULL; + } +} + +void +gss_eap_attr_ctx::composeAttributeName(const gss_buffer_t prefix, + const gss_buffer_t suffix, + gss_buffer_t attribute) +{ + size_t len = 0; + char *p; + + attribute->length = 0; + attribute->value = NULL; + + if (prefix == GSS_C_NO_BUFFER || prefix->length == 0) + return; + + len = prefix->length; + if (suffix != GSS_C_NO_BUFFER) { + len += 1 + suffix->length; + } + + attribute->value = GSSEAP_MALLOC(len + 1); + if (attribute->value == NULL) { + throw new std::bad_alloc; + } + attribute->length = len; + + p = (char *)attribute->value; + memcpy(p, prefix->value, prefix->length); + if (suffix != NULL) { + p[prefix->length] = ' '; + memcpy(p + prefix->length + 1, suffix->value, suffix->length); + } + + p[attribute->length] = '\0'; +} + +void +gss_eap_attr_ctx::decomposeAttributeName(const gss_buffer_t attribute, + unsigned int*type, + gss_buffer_t suffix) +{ + gss_buffer_desc prefix = GSS_C_EMPTY_BUFFER; + + decomposeAttributeName(attribute, &prefix, suffix); + *type = attributePrefixToType(&prefix); +} + +void +gss_eap_attr_ctx::composeAttributeName(unsigned int type, + const gss_buffer_t suffix, + gss_buffer_t attribute) +{ + gss_buffer_t prefix = attributeTypeToPrefix(type); + + composeAttributeName(prefix, suffix, attribute); +} + +OM_uint32 +gssEapInquireName(OM_uint32 *minor, + gss_name_t name, + int *name_is_MN, + gss_OID *MN_mech, + gss_buffer_set_t *attrs) +{ + *minor = 0; + *name_is_MN = false; + *MN_mech = GSS_EAP_MECHANISM; + *attrs = GSS_C_NO_BUFFER_SET; + + if (name->attrCtx == NULL) + return GSS_S_UNAVAILABLE; + + try { + if (!name->attrCtx->getAttributeTypes(attrs)) + return GSS_S_UNAVAILABLE; + } catch (std::exception &e) { + return mapException(minor, e); + } + + return GSS_S_COMPLETE; +} + +OM_uint32 +gssEapGetNameAttribute(OM_uint32 *minor, + gss_name_t name, + gss_buffer_t attr, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) +{ + *authenticated = 0; + *complete = 0; + + value->length = 0; + value->value = NULL; + + if (display_value != NULL) { + display_value->length = 0; + display_value->value = NULL; + } + + *more = -1; + + if (name->attrCtx == NULL) + return GSS_S_UNAVAILABLE; + + try { + if (!name->attrCtx->getAttribute(attr, authenticated, complete, + value, display_value, more)) + return GSS_S_UNAVAILABLE; + } catch (std::exception &e) { + return mapException(minor, e); + } + + return GSS_S_COMPLETE; +} + +OM_uint32 +gssEapDeleteNameAttribute(OM_uint32 *minor, + gss_name_t name, + gss_buffer_t attr) +{ + if (name->attrCtx == NULL) + return GSS_S_UNAVAILABLE; + + try { + name->attrCtx->deleteAttribute(attr); + } catch (std::exception &ex) { + return mapException(minor, ex); + } + + return GSS_S_COMPLETE; +} + +OM_uint32 +gssEapSetNameAttribute(OM_uint32 *minor, + gss_name_t name, + int complete, + gss_buffer_t attr, + gss_buffer_t value) +{ + if (name->attrCtx == NULL) + return GSS_S_UNAVAILABLE; + + try { + name->attrCtx->setAttribute(complete, attr, value); + } catch (std::exception &ex) { + return mapException(minor, ex); + } + + return GSS_S_COMPLETE; +} + +OM_uint32 +gssEapExportAttrContext(OM_uint32 *minor, + gss_name_t name, + gss_buffer_t buffer) +{ + if (name->attrCtx == NULL) + return GSS_S_UNAVAILABLE; + + try { + name->attrCtx->marshall(buffer); + } catch (std::exception &e) { + return mapException(minor, e); + } + + return GSS_S_COMPLETE; +} + +OM_uint32 +gssEapImportAttrContext(OM_uint32 *minor, + gss_buffer_t buffer, + gss_name_t name) +{ + GSSEAP_NOT_IMPLEMENTED; +} + +OM_uint32 +gssEapDuplicateAttrContext(OM_uint32 *minor, + gss_name_t in, + gss_name_t out) +{ + try { + if (in->attrCtx != NULL) + out->attrCtx = new gss_eap_attr_ctx(*(in->attrCtx)); + else + out->attrCtx = NULL; + } catch (std::exception &e) { + return mapException(minor, e); + } + + return GSS_S_COMPLETE; +} + +OM_uint32 +gssEapMapNameToAny(OM_uint32 *minor, + gss_name_t name, + int authenticated, + gss_buffer_t type_id, + gss_any_t *output) +{ + try { + *output = name->attrCtx->mapToAny(authenticated, type_id); + } catch (std::exception &e) { + return mapException(minor, e); + } + + return GSS_S_COMPLETE; +} + +OM_uint32 +gssEapReleaseAnyNameMapping(OM_uint32 *minor, + gss_name_t name, + gss_buffer_t type_id, + gss_any_t *input) +{ + if (name->attrCtx == NULL) + return GSS_S_UNAVAILABLE; + + try { + if (*input != NULL) + name->attrCtx->releaseAnyNameMapping(type_id, *input); + *input = NULL; + } catch (std::exception &e) { + return mapException(minor, e); + } + + return GSS_S_COMPLETE; +} + +OM_uint32 +gssEapReleaseAttrContext(OM_uint32 *minor, + gss_name_t name) +{ + if (name->attrCtx != NULL) + delete name->attrCtx; + + return GSS_S_COMPLETE; +} + +OM_uint32 +gssEapAttrProvidersInit(OM_uint32 *minor) +{ + try { + gss_eap_attr_ctx::init(); + } catch (std::exception &e) { + return mapException(minor, e); + } + + return GSS_S_COMPLETE; +} + +OM_uint32 +gssEapAttrProvidersFinalize(OM_uint32 *minor) +{ + try { + gss_eap_attr_ctx::finalize(); + } catch (std::exception &e) { + return mapException(minor, e); + } + + return GSS_S_COMPLETE; +} + +struct gss_eap_attr_ctx * +gssEapCreateAttrContext(gss_cred_id_t cred, + gss_ctx_id_t ctx) +{ + assert(ctx != GSS_C_NO_CONTEXT); + return gss_eap_attr_ctx::createAttrContext(cred, ctx); +} diff --git a/util_attr.h b/util_attr.h new file mode 100644 index 0000000..abdcb99 --- /dev/null +++ b/util_attr.h @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2010, JANET(UK) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of JANET(UK) nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _UTIL_ATTR_H_ +#define _UTIL_ATTR_H_ 1 + +#define ATTR_TYPE_RADIUS 0U +#define ATTR_TYPE_SAML_ASSERTION 1U +#define ATTR_TYPE_SAML 2U +#define ATTR_TYPE_LOCAL 3U +#define ATTR_TYPE_MIN ATTR_TYPE_RADIUS +#define ATTR_TYPE_MAX (ATTR_TYPE_LOCAL + 1U) + +#ifdef __cplusplus +struct gss_eap_attr_ctx; + +struct gss_eap_attr_provider +{ +public: + gss_eap_attr_provider(const gss_eap_attr_ctx *ctx, + gss_cred_id_t acceptorCred = GSS_C_NO_CREDENTIAL, + gss_ctx_id_t acceptorCtx = GSS_C_NO_CONTEXT) + { + m_source = ctx; + } + + gss_eap_attr_provider(const gss_eap_attr_provider &ctx) {} + virtual ~gss_eap_attr_provider(void) {} + + typedef bool + gss_eap_attr_enumeration_cb(const gss_eap_attr_provider *provider, + const gss_buffer_t attribute, + void *data); + + virtual bool getAttributeTypes(gss_eap_attr_enumeration_cb, void *data) const + { + return false; + } + + virtual void setAttribute(int complete, + const gss_buffer_t attr, + const gss_buffer_t value) {} + virtual void deleteAttribute(const gss_buffer_t value) {} + virtual bool getAttribute(const gss_buffer_t attr, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) const { return false; } + + virtual gss_any_t mapToAny(int authenticated, + gss_buffer_t type_id) const { return NULL; } + virtual void releaseAnyNameMapping(gss_buffer_t type_id, + gss_any_t input) const {} + + virtual void marshall(gss_buffer_t buffer) const {} + static gss_eap_attr_provider *unmarshall(const gss_eap_attr_ctx *ctx, + const gss_buffer_t buffer) + { return NULL; } + + static bool init() { return true; } + static void finalize() {} + + static gss_eap_attr_provider * + createAttrContext(const gss_eap_attr_ctx *ctx, + gss_cred_id_t acceptorCred, + gss_ctx_id_t acceptorCtx) { return NULL; } + +protected: + const gss_eap_attr_ctx *m_source; +}; + +typedef gss_eap_attr_provider * (*gss_eap_attr_create_cb)( + const gss_eap_attr_ctx *ctx, + gss_cred_id_t acceptorCred, + gss_ctx_id_t acceptorCtx); + +struct gss_eap_attr_ctx : gss_eap_attr_provider +{ +public: + gss_eap_attr_ctx(const gss_eap_attr_ctx *ctx, + gss_cred_id_t acceptorCred, + gss_ctx_id_t acceptorCtx) : + gss_eap_attr_provider(ctx, acceptorCred, acceptorCtx) {} + + gss_eap_attr_ctx(const gss_eap_attr_ctx &ctx); + + ~gss_eap_attr_ctx(void); + + static gss_eap_attr_ctx *createAttrContext(gss_cred_id_t acceptorCred, + gss_ctx_id_t acceptorCtx); + + bool getAttributeTypes(gss_eap_attr_enumeration_cb, void *data) const; + bool getAttributeTypes(gss_buffer_set_t *attrs); + + void setAttribute(int complete, + const gss_buffer_t attr, + const gss_buffer_t value); + void deleteAttribute(const gss_buffer_t value); + bool getAttribute(const gss_buffer_t attr, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) const; + gss_any_t mapToAny(int authenticated, + gss_buffer_t type_id) const; + void releaseAnyNameMapping(gss_buffer_t type_id, + gss_any_t input) const; + + void marshall(gss_buffer_t buffer) const; + gss_eap_attr_provider *unmarshall(const gss_eap_attr_ctx *ctx, + const gss_buffer_t buffer); + static bool init(); + static void finalize(); + + static unsigned int + attributePrefixToType(const gss_buffer_t prefix); + + static gss_buffer_t + attributeTypeToPrefix(unsigned int type); + + static void + decomposeAttributeName(const gss_buffer_t attribute, + gss_buffer_t prefix, + gss_buffer_t suffix); + static void + composeAttributeName(const gss_buffer_t prefix, + const gss_buffer_t suffix, + gss_buffer_t attribute); + static void + decomposeAttributeName(const gss_buffer_t attribute, + unsigned int *type, + gss_buffer_t suffix); + static void + composeAttributeName(unsigned int type, + const gss_buffer_t suffix, + gss_buffer_t attribute); + + gss_eap_attr_provider *getProvider(unsigned int type) const; + gss_eap_attr_provider *getProvider(const gss_buffer_t prefix) const; + +private: + gss_eap_attr_provider *m_providers[ATTR_TYPE_MAX]; +}; + +#include "util_radius.h" +#include "util_saml.h" +#include "util_shib.h" + +#include +#include + +static inline void +duplicateBuffer(gss_buffer_desc &src, gss_buffer_t dst) +{ + OM_uint32 minor; + + if (GSS_ERROR(duplicateBuffer(&minor, &src, dst))) + throw new std::bad_alloc(); +} + +static inline void +duplicateBuffer(std::string &str, gss_buffer_t buffer) +{ + gss_buffer_desc tmp; + + tmp.length = str.length(); + tmp.value = (char *)str.c_str(); + + duplicateBuffer(tmp, buffer); +} + +#else +struct gss_eap_attr_ctx; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +struct gss_eap_attr_ctx * +gssEapCreateAttrContext(gss_cred_id_t acceptorCred, + gss_ctx_id_t acceptorCtx); + +OM_uint32 +gssEapInquireName(OM_uint32 *minor, + gss_name_t name, + int *name_is_MN, + gss_OID *MN_mech, + gss_buffer_set_t *attrs); + +OM_uint32 +gssEapGetNameAttribute(OM_uint32 *minor, + gss_name_t name, + gss_buffer_t attr, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more); + +OM_uint32 +gssEapDeleteNameAttribute(OM_uint32 *minor, + gss_name_t name, + gss_buffer_t attr); + +OM_uint32 +gssEapSetNameAttribute(OM_uint32 *minor, + gss_name_t name, + int complete, + gss_buffer_t attr, + gss_buffer_t value); + +OM_uint32 +gssEapExportAttrContext(OM_uint32 *minor, + gss_name_t name, + gss_buffer_t buffer); + +OM_uint32 +gssEapImportAttrContext(OM_uint32 *minor, + gss_buffer_t buffer, + gss_name_t name); + +OM_uint32 +gssEapDuplicateAttrContext(OM_uint32 *minor, + gss_name_t in, + gss_name_t out); + +OM_uint32 +gssEapMapNameToAny(OM_uint32 *minor, + gss_name_t name, + int authenticated, + gss_buffer_t type_id, + gss_any_t *output); + +OM_uint32 +gssEapReleaseAnyNameMapping(OM_uint32 *minor, + gss_name_t name, + gss_buffer_t type_id, + gss_any_t *input); + +OM_uint32 +gssEapReleaseAttrContext(OM_uint32 *minor, + gss_name_t name); + +OM_uint32 +gssEapAttrProvidersInit(OM_uint32 *minor); + +OM_uint32 +gssEapAttrProvidersFinalize(OM_uint32 *minor); + +#ifdef __cplusplus +} +#endif + +#endif /* _UTIL_ATTR_H_ */ diff --git a/util_name.c b/util_name.c index be7f4cb..29b0839 100644 --- a/util_name.c +++ b/util_name.c @@ -106,8 +106,7 @@ gssEapReleaseName(OM_uint32 *minor, gss_name_t *pName) GSSEAP_KRB_INIT(&krbContext); krb5_free_principal(krbContext, name->krbPrincipal); - samlReleaseAttrContext(&tmpMinor, name); - radiusReleaseAttrContext(&tmpMinor, name); + gssEapReleaseAttrContext(&tmpMinor, name); GSSEAP_MUTEX_DESTROY(&name->mutex); GSSEAP_FREE(name); @@ -291,33 +290,17 @@ importExportedName(OM_uint32 *minor, name->flags = load_uint32_be(p); UPDATE_REMAIN(4); - if (name->flags & NAME_FLAG_RADIUS_ATTRIBUTES) { - CHECK_REMAIN(4); - buf.length = load_uint32_be(p); - UPDATE_REMAIN(4); - - CHECK_REMAIN(buf.length); - buf.value = p; - UPDATE_REMAIN(buf.length); - - major = radiusImportAttrContext(minor, &buf, name); - if (GSS_ERROR(major)) - goto cleanup; - } - - if (name->flags & NAME_FLAG_SAML_ATTRIBUTES) { - CHECK_REMAIN(4); - buf.length = load_uint32_be(p); - UPDATE_REMAIN(4); - - CHECK_REMAIN(buf.length); - buf.value = p; - UPDATE_REMAIN(buf.length); - - major = samlImportAttrContext(minor, &buf, name); - if (GSS_ERROR(major)) - goto cleanup; - } + CHECK_REMAIN(4); + buf.length = load_uint32_be(p); + UPDATE_REMAIN(4); + + CHECK_REMAIN(buf.length); + buf.value = p; + UPDATE_REMAIN(buf.length); + + major = gssEapImportAttrContext(minor, &buf, name); + if (GSS_ERROR(major)) + goto cleanup; } major = GSS_S_COMPLETE; @@ -370,13 +353,7 @@ gssEapExportName(OM_uint32 *minor, char *krbName = NULL; size_t krbNameLen; unsigned char *p; - gss_buffer_desc radius, saml; - - radius.length = 0; - radius.value = NULL; - - saml.length = 0; - saml.value = NULL; + gss_buffer_desc attrs = GSS_C_EMPTY_BUFFER; exportedName->length = 0; exportedName->value = NULL; @@ -395,18 +372,10 @@ gssEapExportName(OM_uint32 *minor, if (composite) { exportedName->length += 4; - if (name->flags & NAME_FLAG_RADIUS_ATTRIBUTES) { - major = radiusExportAttrContext(minor, name, &radius); - if (GSS_ERROR(major)) - goto cleanup; - exportedName->length += 4 + radius.length; - } - if (name->flags & NAME_FLAG_SAML_ATTRIBUTES) { - major = samlExportAttrContext(minor, name, &saml); - if (GSS_ERROR(major)) - goto cleanup; - exportedName->length += 4 + saml.length; - } + major = gssEapExportAttrContext(minor, name, &attrs); + if (GSS_ERROR(major)) + goto cleanup; + exportedName->length += 4 + attrs.length; } exportedName->value = GSSEAP_MALLOC(exportedName->length); @@ -444,16 +413,9 @@ gssEapExportName(OM_uint32 *minor, store_uint32_be(name->flags, p); p += 4; - if (name->flags & NAME_FLAG_RADIUS_ATTRIBUTES) { - store_uint32_be(radius.length, p); - memcpy(&p[4], radius.value, radius.length); - p += 4 + radius.length; - } - if (name->flags & NAME_FLAG_SAML_ATTRIBUTES) { - store_uint32_be(saml.length, p); - memcpy(&p[4], saml.value, saml.length); - p += 4 + saml.length; - } + store_uint32_be(attrs.length, p); + memcpy(&p[4], attrs.value, attrs.length); + p += 4 + attrs.length; } *minor = 0; @@ -461,8 +423,7 @@ gssEapExportName(OM_uint32 *minor, cleanup: GSSEAP_MUTEX_UNLOCK(&name->mutex); - gss_release_buffer(&tmpMinor, &saml); - gss_release_buffer(&tmpMinor, &radius); + gss_release_buffer(&tmpMinor, &attrs); if (GSS_ERROR(major)) gss_release_buffer(&tmpMinor, exportedName); krb5_free_unparsed_name(krbContext, krbName); @@ -470,121 +431,3 @@ cleanup: return major; } -static gss_buffer_desc attributePrefixes[] = { - { - /* ATTR_TYPE_NONE */ - 0, - NULL, - }, - { - /* ATTR_TYPE_SAML_AAA_ASSERTION */ - sizeof("urn:ietf:params:gss-eap:saml-aaa-assertion"), - "urn:ietf:params:gss-eap:saml-aaa-assertion" - }, - { - /* ATTR_TYPE_SAML_ATTR */ - sizeof("urn:ietf:params:gss-eap:saml-attr"), - "urn:ietf:params:gss-eap:saml-attr" - }, - { - /* ATTR_TYPE_RADIUS_AVP */ - sizeof("urn:ietf:params:gss-eap:radius-avp"), - "urn:ietf:params:gss-eap:radius-avp", - } -}; - -enum gss_eap_attribute_type -gssEapAttributePrefixToType(const gss_buffer_t prefix) -{ - enum gss_eap_attribute_type i; - - for (i = ATTR_TYPE_SAML_AAA_ASSERTION; - i < sizeof(attributePrefixes) / sizeof(attributePrefixes[0]); - i++) - { - if (bufferEqual(&attributePrefixes[i], prefix)) - return i; - } - - return ATTR_TYPE_NONE; -} - -gss_buffer_t -gssEapAttributeTypeToPrefix(enum gss_eap_attribute_type type) -{ - if (type <= ATTR_TYPE_NONE || - type > ATTR_TYPE_RADIUS_AVP) - return GSS_C_NO_BUFFER; - - return &attributePrefixes[type]; -} - -OM_uint32 -decomposeAttributeName(OM_uint32 *minor, - const gss_buffer_t attribute, - gss_buffer_t prefix, - gss_buffer_t suffix) -{ - char *p = NULL; - int i; - - for (i = 0; i < attribute->length; i++) { - if (((char *)attribute->value)[i] == ' ') { - p = (char *)attribute->value + i + 1; - break; - } - } - - prefix->value = attribute->value; - prefix->length = i; - - if (p != NULL && *p != '\0') { - suffix->length = attribute->length - 1 - prefix->length; - suffix->value = p; - } else { - suffix->length = 0; - suffix->value = NULL; - } - - *minor = 0; - return GSS_S_COMPLETE; -} - -OM_uint32 -composeAttributeName(OM_uint32 *minor, - const gss_buffer_t prefix, - const gss_buffer_t suffix, - gss_buffer_t attribute) -{ - size_t len = 0; - char *p; - - attribute->length = 0; - attribute->value = NULL; - - if (prefix == GSS_C_NO_BUFFER || prefix->length == 0) - return GSS_S_COMPLETE; - - len = prefix->length; - if (suffix != NULL) { - len += 1 + suffix->length; - } - - p = attribute->value = GSSEAP_MALLOC(len + 1); - if (attribute->value == NULL) { - *minor = ENOMEM; - return GSS_S_FAILURE; - } - attribute->length = len; - - memcpy(p, prefix->value, prefix->length); - if (suffix != NULL) { - p[prefix->length] = ' '; - memcpy(p + prefix->length + 1, suffix->value, suffix->length); - } - - p[attribute->length] = '\0'; - - *minor = 0; - return GSS_S_COMPLETE; -} diff --git a/util_radius.c b/util_radius.c deleted file mode 100644 index 2174752..0000000 --- a/util_radius.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2010, JANET(UK) - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of JANET(UK) nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "gssapiP_eap.h" - -struct gss_eap_radius_attr_ctx { -}; - -OM_uint32 -radiusDuplicateAttrContext(OM_uint32 *minor, - const gss_name_t in, - gss_name_t out) -{ - GSSEAP_NOT_IMPLEMENTED; -} - -OM_uint32 -radiusReleaseAttrContext(OM_uint32 *minor, - gss_name_t in) -{ - GSSEAP_NOT_IMPLEMENTED; -} - -OM_uint32 -radiusGetAttributeTypes(OM_uint32 *minor, - gss_name_t name, - gss_eap_add_attr_cb addAttribute, - void *data) -{ - GSSEAP_NOT_IMPLEMENTED; -} - -OM_uint32 -radiusGetAttribute(OM_uint32 *minor, - gss_name_t name, - gss_buffer_t attr, - int *authenticated, - int *complete, - gss_buffer_t value, - gss_buffer_t display_value, - int *more) -{ - GSSEAP_NOT_IMPLEMENTED; -} - -#if 0 -OM_uint32 -radiusSetAttribute(OM_uint32 *minor, - gss_name_t name, - int complete, - gss_buffer_t attr, - gss_buffer_t value) -{ - GSSEAP_NOT_IMPLEMENTED; -} - -OM_uint32 -radiusDeleteAttribute(OM_uint32 *minor, - gss_name_t name, - gss_buffer_t attr) -{ - GSSEAP_NOT_IMPLEMENTED; -} -#endif - -OM_uint32 -radiusExportAttrContext(OM_uint32 *minor, - gss_name_t name, - gss_buffer_t buffer) -{ - GSSEAP_NOT_IMPLEMENTED; -} - -OM_uint32 -radiusImportAttrContext(OM_uint32 *minor, - gss_buffer_t buffer, - gss_name_t name) -{ - GSSEAP_NOT_IMPLEMENTED; -} diff --git a/util_radius.cpp b/util_radius.cpp new file mode 100644 index 0000000..6cc0dd2 --- /dev/null +++ b/util_radius.cpp @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2010, JANET(UK) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of JANET(UK) nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gssapiP_eap.h" + +gss_eap_radius_attr_provider::gss_eap_radius_attr_provider(const gss_eap_attr_ctx *ctx, + gss_cred_id_t gssCred, + gss_ctx_id_t gssCtx) + : gss_eap_attr_provider(ctx, gssCred, gssCtx) +{ +} + +gss_eap_radius_attr_provider::gss_eap_radius_attr_provider( + const gss_eap_radius_attr_provider &src) + : gss_eap_attr_provider(src) +{ +} + +gss_eap_radius_attr_provider::~gss_eap_radius_attr_provider(void) +{ +} + +bool +gss_eap_radius_attr_provider::getAttributeTypes(gss_eap_attr_enumeration_cb addAttribute, void *data) const +{ + return true; +} + +void +gss_eap_radius_attr_provider::setAttribute(int complete, + const gss_buffer_t attr, + const gss_buffer_t value) +{ +} + +void +gss_eap_radius_attr_provider::deleteAttribute(const gss_buffer_t value) +{ +} + +bool +gss_eap_radius_attr_provider::getAttribute(const gss_buffer_t attr, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) const +{ + return false; +} + +bool +gss_eap_radius_attr_provider::getAttribute(unsigned int attr, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) const +{ + return false; +} + +gss_any_t +gss_eap_radius_attr_provider::mapToAny(int authenticated, + gss_buffer_t type_id) const +{ +} + +void +gss_eap_radius_attr_provider::releaseAnyNameMapping(gss_buffer_t type_id, + gss_any_t input) const +{ +} + +void +gss_eap_radius_attr_provider::marshall(gss_buffer_t buffer) const +{ +} + +gss_eap_attr_provider * +gss_eap_radius_attr_provider::unmarshall(const gss_eap_attr_ctx *ctx, + const gss_buffer_t buffer) +{ +} + +bool +gss_eap_radius_attr_provider::init(void) +{ +} + +void +gss_eap_radius_attr_provider::finalize(void) +{ +} + +gss_eap_attr_provider * +gss_eap_radius_attr_provider::createAttrContext(const gss_eap_attr_ctx *ctx, + gss_cred_id_t gssCred, + gss_ctx_id_t gssCtx) +{ + return new gss_eap_radius_attr_provider(ctx, gssCred, gssCtx); +} diff --git a/util_radius.h b/util_radius.h index dd9650b..33c6c89 100644 --- a/util_radius.h +++ b/util_radius.h @@ -33,55 +33,49 @@ #ifndef _UTIL_RADIUS_H_ #define _UTIL_RADIUS_H_ 1 -struct gss_eap_radius_attr_ctx; +struct gss_eap_radius_attr_provider : gss_eap_attr_provider { +public: + gss_eap_radius_attr_provider(const gss_eap_attr_ctx *ctx, + gss_cred_id_t acceptorCred, + gss_ctx_id_t acceptorCtx); + gss_eap_radius_attr_provider(const gss_eap_radius_attr_provider &ctx); + ~gss_eap_radius_attr_provider(void); -OM_uint32 -radiusDuplicateAttrContext(OM_uint32 *minor, - const gss_name_t in, - gss_name_t out); + bool getAttributeTypes(gss_eap_attr_enumeration_cb, void *data) const; + void setAttribute(int complete, + const gss_buffer_t attr, + const gss_buffer_t value); + void deleteAttribute(const gss_buffer_t value); + bool getAttribute(const gss_buffer_t attr, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) const; + gss_any_t mapToAny(int authenticated, + gss_buffer_t type_id) const; + void releaseAnyNameMapping(gss_buffer_t type_id, + gss_any_t input) const; -OM_uint32 -radiusReleaseAttrContext(OM_uint32 *minor, - gss_name_t name); + void marshall(gss_buffer_t buffer) const; + static gss_eap_attr_provider *unmarshall(const gss_eap_attr_ctx *ctx, + const gss_buffer_t buffer); -OM_uint32 -radiusGetAttributeTypes(OM_uint32 *minor, - gss_name_t name, - gss_eap_add_attr_cb cb, - void *data); + bool getAttribute(unsigned int attribute, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) const; -OM_uint32 -radiusGetAttribute(OM_uint32 *minor, - gss_name_t name, - gss_buffer_t attr, - int *authenticated, - int *complete, - gss_buffer_t value, - gss_buffer_t display_value, - int *more); + static bool init(); + static void finalize(); -#if 0 -OM_uint32 -radiusSetAttribute(OM_uint32 *minor, - gss_name_t name, - int complete, - gss_buffer_t attr, - gss_buffer_t value); - -OM_uint32 -radiusDeleteAttribute(OM_uint32 *minor, - gss_name_t name, - gss_buffer_t attr); -#endif - -OM_uint32 -radiusExportAttrContext(OM_uint32 *minor, - gss_name_t name, - gss_buffer_t buffer); - -OM_uint32 -radiusImportAttrContext(OM_uint32 *minor, - gss_buffer_t buffer, - gss_name_t name); + static gss_eap_attr_provider * + createAttrContext(const gss_eap_attr_ctx *ctx, + gss_cred_id_t acceptorCred, + gss_ctx_id_t acceptorCtx); +private: +}; #endif /* _UTIL_RADIUS_H_ */ diff --git a/util_saml.cpp b/util_saml.cpp index 050e5bd..b859d9b 100644 --- a/util_saml.cpp +++ b/util_saml.cpp @@ -29,154 +29,96 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -/* - * Copyright 2001-2009 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ #include "gssapiP_eap.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include +#include + #include -#include +#include #include -#include "resolver.h" +#include +#include +#include -using namespace shibsp; -using namespace shibresolver; +using namespace xmltooling; using namespace opensaml::saml2md; using namespace opensaml; -using namespace xmltooling::logging; -using namespace xmltooling; using namespace xercesc; using namespace std; -static vector -duplicateAttributes(const vector src); +class auto_ptr_gss_buffer { + MAKE_NONCOPYABLE(auto_ptr_gss_buffer); + public: + auto_ptr_gss_buffer() : m_buf(NULL) { + } + auto_ptr_gss_buffer(const gss_buffer_t src) { + m_buf = new XMLCh[src->length + 1]; + XMLString::transcode((const char *)src->value, m_buf, src->length); + } + ~auto_ptr_gss_buffer() { + xercesc::XMLString::release(&m_buf); + } + const XMLCh* get() const { + return m_buf; + } + XMLCh* release() { + XMLCh *temp = m_buf; m_buf = NULL; return temp; + } + private: + XMLCh *m_buf; +}; /* - * Class representing the SAML compoments of a EAP GSS name. + * gss_eap_saml_assertion_provider is for retrieving the underlying + * assertion. */ -struct gss_eap_saml_attr_ctx -{ -public: - gss_eap_saml_attr_ctx(void) {} - - gss_eap_saml_attr_ctx(const vector& attributes, - const saml2::Assertion *assertion = NULL) { - if (assertion != NULL) - setAssertion(assertion); - if (attributes.size()) - setAttributes(duplicateAttributes(attributes)); - } - - gss_eap_saml_attr_ctx(const gss_eap_saml_attr_ctx &ctx) { - gss_eap_saml_attr_ctx(ctx.m_attributes, ctx.m_assertion); - } - - ~gss_eap_saml_attr_ctx() { - for_each(m_attributes.begin(), - m_attributes.end(), - xmltooling::cleanup()) - ; - delete m_assertion; - } - - const vector getAttributes(void) const { - return m_attributes; - } - - void addAttribute(Attribute *attr, bool copy = true); - void setAttributes(const vector attributes); - - void setAttribute(int complete, - const gss_buffer_t attr, - const gss_buffer_t value); - void deleteAttribute(const gss_buffer_t attr); - - int getAttributeIndex(const gss_buffer_t attr) const; - const Attribute *getAttribute(const gss_buffer_t attr) const; - - bool getAttribute(const gss_buffer_t attr, - int *authenticated, - int *complete, - gss_buffer_t value, - gss_buffer_t display_value, - int *more); - - const saml2::Assertion *getAssertion(void) const { - return m_assertion; - } - - void setAssertion(const saml2::Assertion *assertion) { - delete m_assertion; - if (assertion != NULL) - m_assertion = dynamic_cast(assertion->clone()); - else - m_assertion = NULL; - } - - void setAssertion(const gss_buffer_t buffer) { - delete m_assertion; - m_assertion = parseAssertion(buffer); +gss_eap_saml_assertion_provider::gss_eap_saml_assertion_provider(const gss_eap_attr_ctx *ctx, + gss_cred_id_t gssCred, + gss_ctx_id_t gssCtx) + : gss_eap_attr_provider(ctx, gssCred, gssCtx) +{ + if (gssCtx == GSS_C_NO_CONTEXT) { + /* Then we are creating from an existing attribute context */ + gss_eap_saml_assertion_provider *saml; + + saml = dynamic_cast + (ctx->getProvider(ATTR_TYPE_SAML_ASSERTION)); + if (saml != NULL) + setAssertion(saml->getAssertion()); + } else { + gss_eap_radius_attr_provider *radius; + gss_buffer_desc value = GSS_C_EMPTY_BUFFER; + int authenticated, complete, more = -1; + OM_uint32 minor; + + radius = dynamic_cast + (ctx->getProvider(ATTR_TYPE_RADIUS)); + if (radius != NULL && + radius->getAttribute(512, &authenticated, &complete, + &value, NULL, &more)) { + m_assertion = parseAssertion(&value); + gss_release_buffer(&minor, &value); + } } +} - bool getAssertion(gss_buffer_t buffer); - - DDF marshall() const; - static gss_eap_saml_attr_ctx *unmarshall(DDF &in); - - void marshall(gss_buffer_t buffer); - static gss_eap_saml_attr_ctx *unmarshall(const gss_buffer_t buffer); - -private: - mutable vector m_attributes; - mutable saml2::Assertion *m_assertion; - - static saml2::Assertion *parseAssertion(const gss_buffer_t buffer); -}; +gss_eap_saml_assertion_provider::~gss_eap_saml_assertion_provider(void) +{ + delete m_assertion; +} -/* - * Map an exception to a GSS major/mechanism status code. - * TODO - */ -static OM_uint32 -mapException(OM_uint32 *minor, exception &e) +void +gss_eap_saml_assertion_provider::setAssertion(const saml2::Assertion *assertion) { - *minor = 0; - return GSS_S_FAILURE; + + delete m_assertion; + m_assertion = dynamic_cast(assertion->clone()); } -/* - * Parse a GSS buffer into a SAML v2 assertion. - */ saml2::Assertion * -gss_eap_saml_attr_ctx::parseAssertion(const gss_buffer_t buffer) +gss_eap_saml_assertion_provider::parseAssertion(const gss_buffer_t buffer) { string str((char *)buffer->value, buffer->length); istringstream istream(str); @@ -184,724 +126,297 @@ gss_eap_saml_attr_ctx::parseAssertion(const gss_buffer_t buffer) const XMLObjectBuilder *b; doc = XMLToolingConfig::getConfig().getParser().parse(istream); - b =XMLObjectBuilder::getBuilder(doc->getDocumentElement()); + b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); return dynamic_cast(b->buildFromDocument(doc)); } -static inline void -duplicateBuffer(gss_buffer_desc &src, gss_buffer_t dst) -{ - OM_uint32 minor; - - if (GSS_ERROR(duplicateBuffer(&minor, &src, dst))) - throw new bad_alloc(); -} - -static inline void -duplicateBuffer(string &str, gss_buffer_t buffer) -{ - gss_buffer_desc tmp; - - tmp.length = str.length(); - tmp.value = (char *)str.c_str(); - - duplicateBuffer(tmp, buffer); -} - -/* - * Marshall SAML attribute context into a form suitable for - * exported names. - */ -DDF -gss_eap_saml_attr_ctx::marshall() const -{ - DDF obj(NULL); - DDF attrs; - DDF assertion; - - obj.addmember("version").integer(1); - - 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); - } - - ostringstream sink; - sink << *m_assertion; - assertion = obj.addmember("assertion").string(sink.str().c_str()); - - return obj; -} - -/* - * Unmarshall SAML attribute context from a form suitable for - * exported names. - */ -gss_eap_saml_attr_ctx * -gss_eap_saml_attr_ctx::unmarshall(DDF &obj) +bool +gss_eap_saml_assertion_provider::getAttributeTypes(gss_eap_attr_enumeration_cb addAttribute, void *data) const { - gss_eap_saml_attr_ctx *ctx = new gss_eap_saml_attr_ctx(); - - DDF version = obj["version"]; - if (version.integer() != 1) - return NULL; - - DDF assertion = obj["assertion"]; - gss_buffer_desc buffer; - - if (!assertion.isnull()) { - buffer.length = assertion.strlen(); - buffer.value = (void *)assertion.string(); - } else { - buffer.length = 0; - } - - if (buffer.length != 0) - ctx->parseAssertion(&buffer); - - DDF attrs = obj["attributes"]; - DDF attr = attrs.first(); - while (!attr.isnull()) { - Attribute *attribute = Attribute::unmarshall(attr); - ctx->addAttribute(attribute, false); - attr = attrs.next(); - } - - return ctx; + addAttribute(this, GSS_C_NO_BUFFER, data); } void -gss_eap_saml_attr_ctx::marshall(gss_buffer_t buffer) +gss_eap_saml_assertion_provider::setAttribute(int complete, + const gss_buffer_t attr, + const gss_buffer_t value) { - DDF obj = marshall(); - ostringstream sink; - sink << obj; - string str = sink.str(); - - duplicateBuffer(str, buffer); + saml2::Assertion *assertion = parseAssertion(value); - obj.destroy(); + m_assertion = assertion; } -gss_eap_saml_attr_ctx * -gss_eap_saml_attr_ctx::unmarshall(const gss_buffer_t buffer) +void +gss_eap_saml_assertion_provider::deleteAttribute(const gss_buffer_t value) { - gss_eap_saml_attr_ctx *ctx; - - string str((const char *)buffer->value, buffer->length); - istringstream source(str); - DDF obj(NULL); - source >> obj; - - ctx = unmarshall(obj); - - obj.destroy(); - - return ctx; + delete m_assertion; + m_assertion = NULL; } -/* - * Return the serialised assertion. - */ bool -gss_eap_saml_attr_ctx::getAssertion(gss_buffer_t buffer) +gss_eap_saml_assertion_provider::getAttribute(const gss_buffer_t attr, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) const { string str; - if (m_assertion == NULL) + if (attr->length != 0 || m_assertion == NULL) return false; - buffer->value = NULL; - buffer->length = 0; - - XMLHelper::serialize(m_assertion->marshall((DOMDocument *)NULL), str); - - duplicateBuffer(str, buffer); + if (*more == -1) + *more = 0; - return true; -} + if (*more == 0) { + *authenticated = true; + *complete = false; -static Attribute * -duplicateAttribute(const Attribute *src) -{ - Attribute *attribute; + XMLHelper::serialize(m_assertion->marshall((DOMDocument *)NULL), str); - DDF obj = src->marshall(); - attribute = Attribute::unmarshall(obj); - obj.destroy(); + duplicateBuffer(str, value); + } - return attribute; + return true; } -static vector -duplicateAttributes(const vector src) +gss_any_t +gss_eap_saml_assertion_provider::mapToAny(int authenticated, + gss_buffer_t type_id) const { - vector dst; - - for (vector::const_iterator a = src.begin(); - a != src.end(); - ++a) - dst.push_back(duplicateAttribute(*a)); - - return dst; + return (gss_any_t)m_assertion; } void -gss_eap_saml_attr_ctx::addAttribute(Attribute *attribute, bool copy) +gss_eap_saml_assertion_provider::releaseAnyNameMapping(gss_buffer_t type_id, + gss_any_t input) const { - Attribute *a; - - a = copy ? duplicateAttribute(attribute) : attribute; - - m_attributes.push_back(a); + delete ((saml2::Assertion *)input); } void -gss_eap_saml_attr_ctx::setAttributes(const vector attributes) +gss_eap_saml_assertion_provider::marshall(gss_buffer_t buffer) const { - for_each(m_attributes.begin(), m_attributes.end(), xmltooling::cleanup()); - m_attributes = attributes; -} - -int -gss_eap_saml_attr_ctx::getAttributeIndex(const gss_buffer_t attr) const -{ - int i = 0; - - for (vector::const_iterator a = getAttributes().begin(); - a != getAttributes().end(); - ++a) - { - for (vector::const_iterator s = (*a)->getAliases().begin(); - s != (*a)->getAliases().end(); - ++s) { - if (attr->length == (*s).length() && - memcmp((*s).c_str(), attr->value, attr->length) == 0) { - return i; - } - } - } - - return -1; -} - -const Attribute * -gss_eap_saml_attr_ctx::getAttribute(const gss_buffer_t attr) const -{ - const Attribute *ret = NULL; - - for (vector::const_iterator a = getAttributes().begin(); - a != getAttributes().end(); - ++a) - { - for (vector::const_iterator s = (*a)->getAliases().begin(); - s != (*a)->getAliases().end(); - ++s) { - if (attr->length == (*s).length() && - memcmp((*s).c_str(), attr->value, attr->length) == 0) { - ret = *a; - break; - } - } - if (ret != NULL) - break; - } - - return ret; -} - -bool -gss_eap_saml_attr_ctx::getAttribute(const gss_buffer_t attr, - int *authenticated, - int *complete, - gss_buffer_t value, - gss_buffer_t display_value, - int *more) -{ - const Attribute *shibAttr = NULL; - gss_buffer_desc buf; - - shibAttr = getAttribute(attr); - if (shibAttr == NULL) - return false; + ostringstream sink; + string str; - if (*more == -1) { - *more = 0; - } else if (*more >= (int)shibAttr->valueCount()) { - *more = 0; - return true; - } + buffer->length = 0; + buffer->value = NULL; - buf.value = (void *)shibAttr->getString(*more); - buf.length = strlen((char *)buf.value); + if (m_assertion == NULL) + return; - duplicateBuffer(buf, value); - - *authenticated = TRUE; - *complete = FALSE; + sink << *m_assertion; + str = sink.str(); - return true; + duplicateBuffer(str, buffer); } -static Attribute * -samlAttributeFromGssBuffers(const gss_buffer_t attr, - const gss_buffer_t value) +gss_eap_attr_provider * +gss_eap_saml_assertion_provider::unmarshall(const gss_eap_attr_ctx *ctx, + const gss_buffer_t buffer) { - string attrStr((char *)attr->value, attr->length); - vector ids(1); - SimpleAttribute *a; - - ids.push_back(attrStr); - - a = new SimpleAttribute(ids); - - if (value->length != 0) { - string valStr((char *)value->value, value->length); - - a->getValues().push_back(valStr); - } - - return a; + return new gss_eap_saml_assertion_provider(ctx, buffer); } -void -gss_eap_saml_attr_ctx::setAttribute(int complete, - const gss_buffer_t attr, - const gss_buffer_t value) +bool +gss_eap_saml_assertion_provider::init(void) { - Attribute *a = samlAttributeFromGssBuffers(attr, value); - - addAttribute(a, false); } void -gss_eap_saml_attr_ctx::deleteAttribute(const gss_buffer_t attr) +gss_eap_saml_assertion_provider::finalize(void) { - int i; - - i = getAttributeIndex(attr); - if (i >= 0) - m_attributes.erase(m_attributes.begin() + i); } -OM_uint32 -samlReleaseAttrContext(OM_uint32 *minor, gss_name_t name) +gss_eap_attr_provider * +gss_eap_saml_assertion_provider::createAttrContext(const gss_eap_attr_ctx *ctx, + gss_cred_id_t gssCred, + gss_ctx_id_t gssCtx) { - try { - delete name->samlCtx; - name->samlCtx = NULL; - } catch (exception &e) { - return mapException(minor, e); - } - - return GSS_S_COMPLETE; + return new gss_eap_saml_assertion_provider(ctx, gssCred, gssCtx); } -static gss_buffer_desc -gssEapRadiusAssertionAttr = { 3, (void *)"128" }; /* TODO */ - -class gss_eap_saml_attr_args { -public: - vector attrs; - ShibbolethResolver *resolver; -}; - /* - * Callback to add a RADIUS attribute as input to the resolver. + * gss_eap_saml_attr_provider is for retrieving the underlying attributes. */ -static OM_uint32 -samlAddRadiusAttribute(OM_uint32 *minor, - gss_name_t name, - gss_buffer_t attr, - void *data) +const saml2::Assertion * +gss_eap_saml_attr_provider::getAssertion(void) const { - OM_uint32 major; - gss_eap_saml_attr_args *args = (gss_eap_saml_attr_args *)data; - Attribute *a; - int authenticated, complete, more = -1; - gss_buffer_desc value; - - /* Put attributes to skip here (or in a table somewhere) */ - if (bufferEqual(attr, &gssEapRadiusAssertionAttr)) { - return GSS_S_COMPLETE; - } - - major = radiusGetAttribute(minor, name, attr, - &authenticated, &complete, - &value, GSS_C_NO_BUFFER, &more); - if (major == GSS_S_COMPLETE) { - /* XXX TODO prefix */ - a = samlAttributeFromGssBuffers(attr, &value); - args->attrs.push_back(a); - args->resolver->addAttribute(a); - } + gss_eap_saml_assertion_provider *saml; + + saml = dynamic_cast(m_source->getProvider(ATTR_TYPE_SAML_ASSERTION)); + assert(saml != NULL); - return GSS_S_COMPLETE; + return saml->getAssertion(); } -/* - * Add attributes retrieved via RADIUS. - */ -static OM_uint32 -samlAddRadiusAttributes(OM_uint32 *minor, - gss_name_t name, - gss_eap_saml_attr_args *args) +gss_eap_saml_attr_provider::gss_eap_saml_attr_provider(const gss_eap_attr_ctx *ctx, + gss_cred_id_t gssCred, + gss_ctx_id_t gssCtx) + : gss_eap_attr_provider(ctx, gssCred, gssCtx) { - return radiusGetAttributeTypes(minor, - name, - samlAddRadiusAttribute, - (void *)args); + /* Nothing to do, we're just a wrapper around the assertion provider. */ } -/* - * Add assertion retrieved via RADIUS. - */ -static OM_uint32 -samlAddRadiusAssertion(OM_uint32 *minor, - gss_name_t name, - gss_eap_saml_attr_ctx *ctx) +gss_eap_saml_attr_provider::~gss_eap_saml_attr_provider(void) { - OM_uint32 major; - int authenticated, complete, more = -1; - gss_buffer_desc value; - - value.value = NULL; - value.length = 0; - - major = radiusGetAttribute(minor, name, &gssEapRadiusAssertionAttr, - &authenticated, &complete, - &value, GSS_C_NO_BUFFER, &more); - if (GSS_ERROR(major) && major != GSS_S_UNAVAILABLE) - return major; - - ctx->setAssertion(&value); - - gss_release_buffer(minor, &value); - - return GSS_S_COMPLETE; + /* Nothing to do, we're just a wrapper around the assertion provider. */ } -/* - * Initialise SAML attribute context in initiator name. RADIUS context - * must have been previously initialised. - */ -OM_uint32 -samlCreateAttrContext(OM_uint32 *minor, - gss_cred_id_t acceptorCred, - gss_name_t initiatorName, - time_t *pExpiryTime) -{ - OM_uint32 major, tmpMinor; - gss_buffer_desc nameBuf; - gss_eap_saml_attr_ctx *ctx = NULL; - ShibbolethResolver *resolver = NULL; - gss_eap_saml_attr_args args; - - assert(initiatorName != GSS_C_NO_NAME); - - if (initiatorName->radiusCtx == NULL) - return GSS_S_UNAVAILABLE; - - nameBuf.length = 0; - nameBuf.value = NULL; - - resolver = ShibbolethResolver::create(); - if (resolver == NULL) - return GSS_S_FAILURE; - - args.resolver = resolver; - - if (acceptorCred != GSS_C_NO_CREDENTIAL) { - major = gss_display_name(minor, acceptorCred->name, &nameBuf, NULL); - if (GSS_ERROR(major)) - goto cleanup; - } - - try { - const saml2::Assertion *assertion; - vector attrs; - - ctx = new gss_eap_saml_attr_ctx(); - - major = samlAddRadiusAssertion(minor, initiatorName, ctx); - if (GSS_ERROR(major)) - goto cleanup; - - assertion = ctx->getAssertion(); - - if (assertion != NULL) { - if (assertion->getConditions()) { - *pExpiryTime = - assertion->getConditions()->getNotOnOrAfter()->getEpoch(); - } - - resolver->addToken(assertion); - } - - resolver->setApplicationID((const char *)nameBuf.value); - if (initiatorName->radiusCtx != NULL) - samlAddRadiusAttributes(minor, initiatorName, &args); - resolver->resolveAttributes(attrs); - ctx->setAttributes(attrs); - } catch (exception &ex) { - major = mapException(minor, ex); - goto cleanup; - } - - *minor = 0; - major = GSS_S_COMPLETE; - - initiatorName->samlCtx = ctx; - -cleanup: - for_each(args.attrs.begin(), args.attrs.end(), xmltooling::cleanup()); - gss_release_buffer(&tmpMinor, &nameBuf); - if (GSS_ERROR(major)) - delete ctx; - delete resolver; - - return major; -} - -OM_uint32 -samlGetAttributeTypes(OM_uint32 *minor, - gss_name_t name, - enum gss_eap_attribute_type type, - gss_eap_add_attr_cb addAttribute, - void *data) +bool +gss_eap_saml_attr_provider::getAttributeTypes(gss_eap_attr_enumeration_cb addAttribute, + void *data) const { - OM_uint32 major = GSS_S_COMPLETE; - gss_eap_saml_attr_ctx *ctx = name->samlCtx; - - if (ctx == NULL) - return GSS_S_COMPLETE; + const saml2::Assertion *assertion = getAssertion(); - if (type != ATTR_TYPE_NONE) - return GSS_S_UNAVAILABLE; + if (assertion == NULL) + return true; - for (vector::const_iterator a = ctx->getAttributes().begin(); - a != ctx->getAttributes().end(); + const vector& attrs2 = + const_cast(assertion->getAttributeStatements().front())->getAttributes(); + for (vector::const_iterator a = attrs2.begin(); + a != attrs2.end(); ++a) { gss_buffer_desc attribute; - attribute.value = (void *)((*a)->getId()); + attribute.value = (void *)toUTF8((*a)->getName(), true); attribute.length = strlen((char *)attribute.value); - major = addAttribute(minor, name, &attribute, data); - if (GSS_ERROR(major)) - break; + if (!addAttribute(this, &attribute, data)) + return false; + + delete (char *)attribute.value; } - return major; + return true; } -/* - * SAML implementation of gss_get_name_attribute - */ -OM_uint32 -samlGetAttribute(OM_uint32 *minor, - enum gss_eap_attribute_type type, - gss_name_t name, - gss_buffer_t attr, - int *authenticated, - int *complete, - gss_buffer_t value, - gss_buffer_t display_value, - int *more) +void +gss_eap_saml_attr_provider::setAttribute(int complete, + const gss_buffer_t attr, + const gss_buffer_t value) { - struct gss_eap_saml_attr_ctx *ctx = name->samlCtx; - bool ret; - - if (ctx == NULL) - return GSS_S_UNAVAILABLE; - - switch (type) { - case ATTR_TYPE_NONE: - ret = ctx->getAttribute(attr, authenticated, complete, - value, display_value, more); - break; - default: - ret = false; - break; - } +} - return ret ? GSS_S_COMPLETE : GSS_S_UNAVAILABLE; +void +gss_eap_saml_attr_provider::deleteAttribute(const gss_buffer_t value) +{ } -OM_uint32 -samlSetAttribute(OM_uint32 *minor, - gss_name_t name, - int complete, - gss_buffer_t attr, - gss_buffer_t value) +const saml2::Attribute * +gss_eap_saml_attr_provider::getAttribute(const gss_buffer_t attr) const { - struct gss_eap_saml_attr_ctx *ctx = name->samlCtx; + const saml2::Assertion *assertion = getAssertion(); + saml2::AttributeStatement *statement; - if (ctx == NULL) - return GSS_S_UNAVAILABLE; + if (assertion == NULL) + return NULL; - try { - ctx->setAttribute(complete, attr, value); - } catch (exception &e) { - return mapException(minor, e); - } + if (assertion->getAttributeStatements().size() == 0) + return NULL; - return GSS_S_COMPLETE; -} + statement = assertion->getAttributeStatements().front(); -OM_uint32 -samlDeleteAttribute(OM_uint32 *minor, - gss_name_t name, - gss_buffer_t attr) -{ - struct gss_eap_saml_attr_ctx *ctx = name->samlCtx; + auto_ptr_gss_buffer attrname(attr); - if (ctx == NULL) - return GSS_S_UNAVAILABLE; + const vector& attrs2 = + const_cast(statement)->getAttributes(); - try { - ctx->deleteAttribute(attr); - } catch (exception &e) { - return mapException(minor, e); + for (vector::const_iterator a = attrs2.begin(); + a != attrs2.end(); + ++a) { + if (XMLString::equals((*a)->getName(), attrname.get())) + return *a; } - return GSS_S_COMPLETE; + return NULL; } -/* - * In order to implement gss_export_name and gss_export_sec_context, - * we need to serialise a resolved attribute context to a buffer. - */ -OM_uint32 -samlExportAttrContext(OM_uint32 *minor, - gss_name_t name, - gss_buffer_t buffer) +bool +gss_eap_saml_attr_provider::getAttribute(const gss_buffer_t attr, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) const { - struct gss_eap_saml_attr_ctx *ctx = name->samlCtx; + const saml2::Attribute *a; + const saml2::AttributeValue *av; + int nvalues, i = *more; - try { - ctx->marshall(buffer); - } catch (exception &e) { - return mapException(minor, e); - } + *more = 0; - return GSS_S_COMPLETE; -} + a = getAttribute(attr); + if (a == NULL) + return false; -/* - * In order to implement gss_import_name and gss_import_sec_context, - * we need to deserialise a resolved attribute context from a buffer. - */ -OM_uint32 -samlImportAttrContext(OM_uint32 *minor, - gss_buffer_t buffer, - gss_name_t name) -{ - try { - assert(name->samlCtx == NULL); - name->samlCtx = gss_eap_saml_attr_ctx::unmarshall(buffer); - } catch (exception &e) { - return mapException(minor, e); - } + nvalues = a->getAttributeValues().size(); - return GSS_S_COMPLETE; -} + if (i == -1) + i = 0; + else if (i >= nvalues) + return false; + av = dynamic_cast(a->getAttributeValues().at(i) +); + if (av == NULL) + return false; -OM_uint32 -samlGetAssertion(OM_uint32 *minor, - gss_name_t name, - gss_buffer_t assertion) -{ - struct gss_eap_saml_attr_ctx *ctx = name->samlCtx; + *authenticated = TRUE; + *complete = FALSE; - if (ctx == NULL) - return GSS_S_UNAVAILABLE; + value->value = toUTF8(av->getTextContent(), true); + value->length = strlen((char *)value->value); - try { - ctx->getAssertion(assertion); - } catch (exception &e) { - return mapException(minor, e); - } + if (nvalues > ++i) + *more = i; - return GSS_S_COMPLETE; + return true; } -OM_uint32 -samlDuplicateAttrContext(OM_uint32 *minor, - gss_name_t in, - gss_name_t out) +gss_any_t +gss_eap_saml_attr_provider::mapToAny(int authenticated, + gss_buffer_t type_id) const { - try { - if (in->samlCtx != NULL) - out->samlCtx = new gss_eap_saml_attr_ctx(*(in->samlCtx)); - else - out->samlCtx = NULL; - } catch (exception &e) { - return mapException(minor, e); - } - - return GSS_S_COMPLETE; + return (gss_any_t)0; } -OM_uint32 -samlMapNameToAny(OM_uint32 *minor, - gss_name_t name, - int authenticated, - gss_buffer_t type_id, - gss_any_t *output) +void +gss_eap_saml_attr_provider::releaseAnyNameMapping(gss_buffer_t type_id, + gss_any_t input) const { - struct gss_eap_saml_attr_ctx *ctx = name->samlCtx; - - if (bufferEqualString(type_id, "shibsp::Attribute")) { - vector v = duplicateAttributes(ctx->getAttributes()); - - *output = (gss_any_t)new vector (v); - } else if (bufferEqualString(type_id, "opensaml::Assertion")) { - *output = (gss_any_t)ctx->getAssertion()->clone(); - } else { - *output = (gss_any_t)NULL; - return GSS_S_UNAVAILABLE; - } - - return GSS_S_COMPLETE; } -OM_uint32 -samlReleaseAnyNameMapping(OM_uint32 *minor, - gss_name_t name, - gss_buffer_t type_id, - gss_any_t *input) +void +gss_eap_saml_attr_provider::marshall(gss_buffer_t buffer) const { - if (bufferEqualString(type_id, "vector")) { - vector *v = ((vector *)*input); - delete v; - } else if (bufferEqualString(type_id, "opensaml::Assertion")) { - delete (Assertion *)*input; - } else { - return GSS_S_UNAVAILABLE; - } - - *input = (gss_any_t)NULL; - return GSS_S_COMPLETE; } -OM_uint32 -samlInit(OM_uint32 *minor) +gss_eap_attr_provider * +gss_eap_saml_attr_provider::unmarshall(const gss_eap_attr_ctx *ctx, + const gss_buffer_t buffer) { - *minor = 0; + return new gss_eap_saml_attr_provider(ctx); +} - return ShibbolethResolver::init() ? GSS_S_COMPLETE : GSS_S_FAILURE; +bool +gss_eap_saml_attr_provider::init(void) +{ + return true; } -OM_uint32 -samlFinalize(OM_uint32 *minor) +void +gss_eap_saml_attr_provider::finalize(void) { - *minor = 0; +} - ShibbolethResolver::term(); - return GSS_S_COMPLETE; +gss_eap_attr_provider * +gss_eap_saml_attr_provider::createAttrContext(const gss_eap_attr_ctx *ctx, + gss_cred_id_t gssCred, + gss_ctx_id_t gssCtx) +{ + return new gss_eap_saml_attr_provider(ctx, gssCred, gssCtx); } diff --git a/util_saml.h b/util_saml.h index 8d90de9..7065326 100644 --- a/util_saml.h +++ b/util_saml.h @@ -33,95 +33,112 @@ #ifndef _UTIL_SAML_H_ #define _UTIL_SAML_H_ 1 -#ifdef __cplusplus -extern "C" { -#endif - -struct gss_eap_saml_attr_ctx; - -OM_uint32 -samlDuplicateAttrContext(OM_uint32 *minor, - gss_name_t in, - gss_name_t out); - -OM_uint32 -samlCreateAttrContext(OM_uint32 *minor, - gss_cred_id_t acceptorCred, - gss_name_t initiatorName, - time_t *pExpiryTime); - -OM_uint32 -samlReleaseAttrContext(OM_uint32 *minor, - gss_name_t name); - -OM_uint32 -samlGetAttributeTypes(OM_uint32 *minor, - gss_name_t name, - enum gss_eap_attribute_type type, - gss_eap_add_attr_cb cb, - void *data); - -OM_uint32 -samlGetAttribute(OM_uint32 *minor, - enum gss_eap_attribute_type type, - gss_name_t name, - gss_buffer_t attr, - int *authenticated, - int *complete, - gss_buffer_t value, - gss_buffer_t display_value, - int *more); - -OM_uint32 -samlSetAttribute(OM_uint32 *minor, - gss_name_t name, - int complete, - gss_buffer_t attr, - gss_buffer_t value); - -OM_uint32 -samlDeleteAttribute(OM_uint32 *minor, - gss_name_t name, - gss_buffer_t attr); - -OM_uint32 -samlExportAttrContext(OM_uint32 *minor, - gss_name_t name, - gss_buffer_t buffer); - -OM_uint32 -samlImportAttrContext(OM_uint32 *minor, - gss_buffer_t buffer, - gss_name_t name); - -OM_uint32 -samlGetAssertion(OM_uint32 *minor, - gss_name_t name, - gss_buffer_t assertion); - - -OM_uint32 -samlMapNameToAny(OM_uint32 *minor, - gss_name_t name, - int authenticated, - gss_buffer_t type_id, - gss_any_t *output); - -OM_uint32 -samlReleaseAnyNameMapping(OM_uint32 *minor, - gss_name_t name, - gss_buffer_t type_id, - gss_any_t *input); - -OM_uint32 -samlInit(OM_uint32 *minor); - -OM_uint32 -samlFinalize(OM_uint32 *minor); - - -#ifdef __cplusplus -} -#endif +namespace opensaml { + namespace saml2 { + class Attribute; + class Assertion; + class NameID; + }; +}; + +struct gss_eap_saml_assertion_provider : gss_eap_attr_provider { +public: + gss_eap_saml_assertion_provider(const gss_eap_attr_ctx *ctx, + const gss_buffer_t buffer) + : gss_eap_attr_provider(ctx) + { + m_assertion = parseAssertion(buffer); + } + + gss_eap_saml_assertion_provider(const gss_eap_attr_ctx *ctx, + gss_cred_id_t acceptorCred, + gss_ctx_id_t acceptorCtx); + + ~gss_eap_saml_assertion_provider(void); + + bool getAttributeTypes(gss_eap_attr_enumeration_cb, void *data) const; + void setAttribute(int complete, + const gss_buffer_t attr, + const gss_buffer_t value); + void deleteAttribute(const gss_buffer_t value); + bool getAttribute(const gss_buffer_t attr, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) const; + gss_any_t mapToAny(int authenticated, + gss_buffer_t type_id) const; + void releaseAnyNameMapping(gss_buffer_t type_id, + gss_any_t input) const; + + void marshall(gss_buffer_t buffer) const; + static gss_eap_attr_provider *unmarshall(const gss_eap_attr_ctx *ctx, + const gss_buffer_t buffer); + + void setAssertion(const opensaml::saml2::Assertion *assertion); + + const opensaml::saml2::Assertion *getAssertion(void) const { + return m_assertion; + } + + static bool init(); + static void finalize(); + + static gss_eap_attr_provider * + createAttrContext(const gss_eap_attr_ctx *ctx, + gss_cred_id_t acceptorCred, + gss_ctx_id_t acceptorCtx); +private: + static opensaml::saml2::Assertion * + parseAssertion(const gss_buffer_t buffer); + + opensaml::saml2::Assertion *m_assertion; +}; + +struct gss_eap_saml_attr_provider : gss_eap_attr_provider { +public: + gss_eap_saml_attr_provider(const gss_eap_attr_ctx *ctx) + : gss_eap_attr_provider(ctx) {} + + gss_eap_saml_attr_provider(const gss_eap_attr_ctx *ctx, + gss_cred_id_t acceptorCred, + gss_ctx_id_t acceptorCtx); + + ~gss_eap_saml_attr_provider(void); + + bool getAttributeTypes(gss_eap_attr_enumeration_cb, void *data) const; + void setAttribute(int complete, + const gss_buffer_t attr, + const gss_buffer_t value); + void deleteAttribute(const gss_buffer_t value); + bool getAttribute(const gss_buffer_t attr, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) const; + gss_any_t mapToAny(int authenticated, + gss_buffer_t type_id) const; + void releaseAnyNameMapping(gss_buffer_t type_id, + gss_any_t input) const; + + void marshall(gss_buffer_t buffer) const; + static gss_eap_attr_provider *unmarshall(const gss_eap_attr_ctx *ctx, + const gss_buffer_t buffer); + + const opensaml::saml2::Attribute * + getAttribute(const gss_buffer_t attr) const; + + const opensaml::saml2::Assertion *getAssertion(void) const; + + static bool init(); + static void finalize(); + + static gss_eap_attr_provider * + createAttrContext(const gss_eap_attr_ctx *ctx, + gss_cred_id_t acceptorCred, + gss_ctx_id_t acceptorCtx); +}; #endif /* _UTIL_SAML_H_ */ diff --git a/util_shib.cpp b/util_shib.cpp new file mode 100644 index 0000000..7d34577 --- /dev/null +++ b/util_shib.cpp @@ -0,0 +1,338 @@ +/* + * Copyright (c) 2010, JANET(UK) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of JANET(UK) nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * Copyright 2001-2009 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "gssapiP_eap.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "resolver.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; + +static vector +duplicateAttributes(const vector src); + +gss_eap_shib_attr_provider::gss_eap_shib_attr_provider(const gss_eap_attr_ctx *ctx, + gss_cred_id_t gssCred, + gss_ctx_id_t gssCtx) + : gss_eap_attr_provider(ctx, gssCred, gssCtx) +{ + if (gssCtx == GSS_C_NO_CONTEXT) { + gss_eap_shib_attr_provider *shib; + + shib = dynamic_cast + (ctx->getProvider(ATTR_TYPE_LOCAL)); + if (shib != NULL) + m_attributes = duplicateAttributes(shib->m_attributes); + } else { + gss_eap_saml_assertion_provider *saml; + gss_eap_radius_attr_provider *radius; + gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER; + ShibbolethResolver *resolver = NULL; + OM_uint32 minor; + + saml = dynamic_cast + (ctx->getProvider(ATTR_TYPE_SAML_ASSERTION)); + radius = dynamic_cast + (ctx->getProvider(ATTR_TYPE_RADIUS)); + + if (radius == NULL) + return; + + if (gssCred != GSS_C_NO_CREDENTIAL && + gss_display_name(&minor, gssCred->name, &nameBuf, NULL) == GSS_S_COMPLETE) + resolver->setApplicationID((const char *)nameBuf.value); + + if (saml != NULL && saml->getAssertion() != NULL) + resolver->addToken(saml->getAssertion()); + + /* TODO inject RADIUS attribute types */ + + resolver->resolveAttributes(m_attributes); + + gss_release_buffer(&minor, &nameBuf); + + delete resolver; + } +} + +gss_eap_shib_attr_provider::~gss_eap_shib_attr_provider(void) +{ + for_each(m_attributes.begin(), m_attributes.end(), xmltooling::cleanup()); +} + +int +gss_eap_shib_attr_provider::getAttributeIndex(const gss_buffer_t attr) const +{ + int i = 0; + + for (vector::const_iterator a = m_attributes.begin(); + a != m_attributes.end(); + ++a) + { + for (vector::const_iterator s = (*a)->getAliases().begin(); + s != (*a)->getAliases().end(); + ++s) { + if (attr->length == (*s).length() && + memcmp((*s).c_str(), attr->value, attr->length) == 0) { + return i; + } + } + } + + return -1; +} + +void +gss_eap_shib_attr_provider::setAttribute(int complete, + const gss_buffer_t attr, + const gss_buffer_t value) +{ + string attrStr((char *)attr->value, attr->length); + vector ids(1); + + ids.push_back(attrStr); + + SimpleAttribute *a = new SimpleAttribute(ids); + + if (value->length != 0) { + string valStr((char *)value->value, value->length); + + a->getValues().push_back(valStr); + } + + m_attributes.push_back(a); +} + +void +gss_eap_shib_attr_provider::deleteAttribute(const gss_buffer_t attr) +{ + int i; + + i = getAttributeIndex(attr); + if (i >= 0) + m_attributes.erase(m_attributes.begin() + i); +} + +bool +gss_eap_shib_attr_provider::getAttributeTypes(gss_eap_attr_enumeration_cb addAttribute, + void *data) const +{ + for (vector::const_iterator a = m_attributes.begin(); + a != m_attributes.end(); + ++a) + { + gss_buffer_desc attribute; + + attribute.value = (void *)((*a)->getId()); + attribute.length = strlen((char *)attribute.value); + + if (!addAttribute(this, &attribute, data)) + return false; + } + + return true; +} + +const Attribute * +gss_eap_shib_attr_provider::getAttribute(const gss_buffer_t attr) const +{ + const Attribute *ret = NULL; + + for (vector::const_iterator a = m_attributes.begin(); + a != m_attributes.end(); + ++a) + { + for (vector::const_iterator s = (*a)->getAliases().begin(); + s != (*a)->getAliases().end(); + ++s) { + if (attr->length == (*s).length() && + memcmp((*s).c_str(), attr->value, attr->length) == 0) { + ret = *a; + break; + } + } + if (ret != NULL) + break; + } + + return ret; +} + +bool +gss_eap_shib_attr_provider::getAttribute(const gss_buffer_t attr, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) const +{ + const Attribute *shibAttr = NULL; + gss_buffer_desc buf; + + shibAttr = getAttribute(attr); + if (shibAttr == NULL) + return false; + + if (*more == -1) { + *more = 0; + } else if (*more >= (int)shibAttr->valueCount()) { + *more = 0; + return true; + } + + buf.value = (void *)shibAttr->getString(*more); + buf.length = strlen((char *)buf.value); + + duplicateBuffer(buf, value); + + *authenticated = TRUE; + *complete = FALSE; + + return true; +} + +gss_any_t +gss_eap_shib_attr_provider::mapToAny(int authenticated, + gss_buffer_t type_id) const +{ + gss_any_t output; + + vector v = duplicateAttributes(m_attributes); + + output = (gss_any_t)new vector (v); + + return output; +} + +void +gss_eap_shib_attr_provider::releaseAnyNameMapping(gss_buffer_t type_id, + gss_any_t input) const +{ + vector *v = ((vector *)input); + delete v; +} + +void +gss_eap_shib_attr_provider::marshall(gss_buffer_t buffer) const +{ +} + +gss_eap_attr_provider * +gss_eap_shib_attr_provider::unmarshall(const gss_eap_attr_ctx *ctx, + const gss_buffer_t buffer) +{ + return NULL; +} + +bool +gss_eap_shib_attr_provider::init(void) +{ + return ShibbolethResolver::init(); +} + +void +gss_eap_shib_attr_provider::finalize(void) +{ + ShibbolethResolver::term(); +} + +gss_eap_attr_provider * +gss_eap_shib_attr_provider::createAttrContext(const gss_eap_attr_ctx *ctx, + gss_cred_id_t gssCred, + gss_ctx_id_t gssCtx) +{ + return new gss_eap_shib_attr_provider(ctx, gssCred, gssCtx); +} + +static Attribute * +duplicateAttribute(const Attribute *src) +{ + Attribute *attribute; + + DDF obj = src->marshall(); + attribute = Attribute::unmarshall(obj); + obj.destroy(); + + return attribute; +} + +static vector +duplicateAttributes(const vector src) +{ + vector dst; + + for (vector::const_iterator a = src.begin(); + a != src.end(); + ++a) + dst.push_back(duplicateAttribute(*a)); + + return dst; +} diff --git a/util_shib.h b/util_shib.h new file mode 100644 index 0000000..1d2e60c --- /dev/null +++ b/util_shib.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2010, JANET(UK) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of JANET(UK) nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _UTIL_SHIB_H_ +#define _UTIL_SHIB_H_ 1 + +#include + +namespace shibsp { + class Attribute; +}; + +struct gss_eap_shib_attr_provider : gss_eap_attr_provider { +public: + gss_eap_shib_attr_provider(const gss_eap_attr_ctx *ctx, + gss_cred_id_t acceptorCred, + gss_ctx_id_t acceptorCtx); + ~gss_eap_shib_attr_provider(void); + + void setAttribute(int complete, + const gss_buffer_t attr, + const gss_buffer_t value); + void deleteAttribute(const gss_buffer_t value); + bool getAttributeTypes(gss_eap_attr_enumeration_cb, void *data) const; + bool getAttribute(const gss_buffer_t attr, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) const; + gss_any_t mapToAny(int authenticated, + gss_buffer_t type_id) const; + void releaseAnyNameMapping(gss_buffer_t type_id, + gss_any_t input) const; + + void marshall(gss_buffer_t buffer) const; + static gss_eap_attr_provider *unmarshall(const gss_eap_attr_ctx *ctx, + const gss_buffer_t buffer); + + static bool init(); + static void finalize(); + + static gss_eap_attr_provider * + createAttrContext(const gss_eap_attr_ctx *ctx, + gss_cred_id_t acceptorCred, + gss_ctx_id_t acceptorCtx); +private: + int getAttributeIndex(const gss_buffer_t attr) const; + const shibsp::Attribute *getAttribute(const gss_buffer_t attr) const; + + const std::vector getAttributes(void) const { + return m_attributes; + } + + std::vector m_attributes; +}; + +#endif /* _UTIL_SHIB_H_ */ -- 2.1.4