From 1f273eda615c04331df6849cfbf3cfad069ea8b0 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Wed, 15 Sep 2010 17:21:56 +0200 Subject: [PATCH] More work on SAML code --- Makefile.am | 1 + accept_sec_context.c | 4 +- delete_name_attribute.c | 4 +- duplicate_name.c | 11 +- eap_mech.c | 45 ++--- get_name_attribute.c | 21 ++- gssapiP_eap.h | 29 ++-- init_sec_context.c | 4 +- inquire_name.c | 59 +++++-- map_name_to_any.c | 8 +- release_any_name_mapping.c | 7 +- resolver.h | 160 ++++++++++++++++++ set_name_attribute.c | 5 +- util.h | 10 +- util_context.c | 4 +- util_name.c | 130 ++++++++++---- util_radius.c | 50 ++++-- util_radius.h | 35 +++- util_saml.cpp | 410 +++++++++++++++++++++++++++------------------ util_saml.h | 41 +++-- 20 files changed, 722 insertions(+), 316 deletions(-) create mode 100644 resolver.h diff --git a/Makefile.am b/Makefile.am index 082c740..eb3a837 100644 --- a/Makefile.am +++ b/Makefile.am @@ -70,6 +70,7 @@ libmech_eap_la_SOURCES = \ util_name.c \ util_oid.c \ util_ordering.c \ + util_radius.c \ util_saml.cpp \ util_token.c \ verify_mic.c \ diff --git a/accept_sec_context.c b/accept_sec_context.c index 4d68918..cefb5a9 100644 --- a/accept_sec_context.c +++ b/accept_sec_context.c @@ -397,7 +397,7 @@ eapGssSmAcceptEstablished(OM_uint32 *minor, return GSS_S_BAD_STATUS; } -static struct eap_gss_acceptor_sm { +static struct gss_eap_acceptor_sm { enum gss_eap_token_type inputTokenType; enum gss_eap_token_type outputTokenType; OM_uint32 (*processToken)(OM_uint32 *, @@ -432,7 +432,7 @@ gss_accept_sec_context(OM_uint32 *minor, OM_uint32 major; OM_uint32 tmpMajor, tmpMinor; gss_ctx_id_t ctx = *context_handle; - struct eap_gss_acceptor_sm *sm = NULL; + struct gss_eap_acceptor_sm *sm = NULL; gss_buffer_desc innerInputToken, innerOutputToken; *minor = 0; diff --git a/delete_name_attribute.c b/delete_name_attribute.c index 657d7a6..49717ff 100644 --- a/delete_name_attribute.c +++ b/delete_name_attribute.c @@ -53,8 +53,8 @@ gss_delete_name_attribute(OM_uint32 *minor, goto cleanup; type = gssEapAttributePrefixToType(&prefix); - if (type != ATTR_TYPE_SAML_AAA_ASSERTION) { - major = samlDeleteAttribute(minor, name->samlCtx, attr); + if (type == ATTR_TYPE_NONE) { + major = samlDeleteAttribute(minor, name, attr); } else { major = GSS_S_UNAVAILABLE; } diff --git a/duplicate_name.c b/duplicate_name.c index ad45a28..b936655 100644 --- a/duplicate_name.c +++ b/duplicate_name.c @@ -63,9 +63,14 @@ gss_duplicate_name(OM_uint32 *minor, goto cleanup; } - if (input_name->samlCtx != NULL) { - major = samlDuplicateAttrContext(minor, input_name->samlCtx, - &name->samlCtx); + 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 (GSS_ERROR(major)) goto cleanup; } diff --git a/eap_mech.c b/eap_mech.c index 5f977b6..c06714e 100644 --- a/eap_mech.c +++ b/eap_mech.c @@ -32,10 +32,10 @@ #include "gssapiP_eap.h" -static int -eapPeerRegisterMethods(void) +static OM_uint32 +eapPeerRegisterMethods(OM_uint32 *minor) { - int ret = 0; + OM_uint32 ret = 0; #ifdef EAP_MD5 if (ret == 0) @@ -137,13 +137,13 @@ eapPeerRegisterMethods(void) ret = eap_peer_tnc_register(); #endif /* EAP_TNC */ - return ret; + return ret ? GSS_S_FAILURE : GSS_S_COMPLETE; } -static int -eapServerRegisterMethods(void) +static OM_uint32 +eapServerRegisterMethods(OM_uint32 *minor) { - int ret = 0; + OM_uint32 ret = 0; #ifdef EAP_SERVER_IDENTITY if (ret == 0) @@ -244,19 +244,19 @@ eapServerRegisterMethods(void) ret = eap_server_tnc_register(); #endif /* EAP_SERVER_TNC */ - return ret; + return ret ? GSS_S_FAILURE : GSS_S_COMPLETE; } -static int -gssEapInitLibEap(void) +static OM_uint32 +gssEapInitLibEap(OM_uint32 *minor) { - return eapPeerRegisterMethods(); + return eapPeerRegisterMethods(minor); } -static int -gssEapInitLibRadSec(void) +static OM_uint32 +gssEapInitLibRadSec(OM_uint32 *minor) { - return 0; + return GSS_S_COMPLETE; } static void gssEapInit(void) __attribute__((constructor)); @@ -265,23 +265,24 @@ static void gssEapFinalize(void) __attribute__((destructor)); static void gssEapInit(void) { - int ret; + OM_uint32 major, minor; - ret = gssEapInitLibEap(); - if (ret == 0) -#if 0 - ret = gssEapInitLibRadSec(); -#else - ret = eapServerRegisterMethods(); -#endif + gssEapInitLibEap(&minor); + gssEapInitLibRadSec(&minor); + eapServerRegisterMethods(&minor); + + samlInit(&minor); } static void gssEapFinalize(void) { + OM_uint32 major, minor; + eap_peer_unregister_methods(); #if 1 eap_server_unregister_methods(); #endif + samlFinalize(&minor); } diff --git a/get_name_attribute.c b/get_name_attribute.c index 525137f..3b22dc5 100644 --- a/get_name_attribute.c +++ b/get_name_attribute.c @@ -66,12 +66,25 @@ gss_get_name_attribute(OM_uint32 *minor, goto cleanup; type = gssEapAttributePrefixToType(&prefix); - if (type == ATTR_TYPE_SAML_AAA_ASSERTION) { - major = samlGetAssertion(minor, name->samlCtx, value); - } else { - major = samlGetAttribute(minor, name->samlCtx, &suffix, + 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, + authenticated, complete, + value, display_value, more); + break; + default: + major = GSS_S_UNAVAILABLE; + break; } cleanup: diff --git a/gssapiP_eap.h b/gssapiP_eap.h index 3c6968d..35cc154 100644 --- a/gssapiP_eap.h +++ b/gssapiP_eap.h @@ -52,24 +52,31 @@ #include /* EAP includes */ +#ifndef __cplusplus #include #include #include #include /* XXX testing implementation only */ #include +#endif #define NAME_FLAG_NAI 0x00000001 #define NAME_FLAG_SERVICE 0x00000002 +#define NAME_FLAG_RADIUS_ATTRIBUTES 0x00000004 +#define NAME_FLAG_SAML_ATTRIBUTES 0x00000008 -#define NAME_HAS_ATTRIBUTES(name) ((name)->samlCtx != NULL) +#define NAME_HAS_ATTRIBUTES(name) \ + (((name)->flags & (NAME_FLAG_RADIUS_ATTRIBUTES | \ + NAME_FLAG_SAML_ATTRIBUTES)) != 0) -struct eap_gss_saml_attr_ctx; +struct gss_eap_saml_attr_ctx; struct gss_name_struct { GSSEAP_MUTEX mutex; /* mutex protecting attributes */ OM_uint32 flags; krb5_principal krbPrincipal; /* this is immutable */ - struct eap_gss_saml_attr_ctx *samlCtx; + struct gss_eap_radius_attr_ctx *radiusCtx; + struct gss_eap_saml_attr_ctx *samlCtx; }; #define CRED_FLAG_INITIATE 0x00000001 @@ -90,7 +97,7 @@ struct gss_cred_id_struct { #define CTX_IS_INITIATOR(ctx) (((ctx)->flags & CTX_FLAG_INITIATOR) != 0) -enum eap_gss_state { +enum gss_eap_state { EAP_STATE_AUTHENTICATE = 0, #if 0 EAP_STATE_KEY_TRANSPORT, @@ -113,15 +120,17 @@ enum eap_gss_state { #define CTX_FLAG_EAP_ALT_ACCEPT 0x00800000 #define CTX_FLAG_EAP_ALT_REJECT 0x01000000 -struct eap_gss_initiator_ctx { +struct gss_eap_initiator_ctx { unsigned int idleWhile; +#ifndef __cplusplus struct eap_peer_config eapPeerConfig; struct eap_sm *eap; struct wpabuf reqData; +#endif }; -struct eap_gss_acceptor_ctx { -#ifdef BUILTIN_EAP +struct gss_eap_acceptor_ctx { +#if defined(BUILTIN_EAP) && !defined(__cplusplus) struct eap_eapol_interface *eapPolInterface; void *tlsContext; struct eap_sm *eap; @@ -130,7 +139,7 @@ struct eap_gss_acceptor_ctx { struct gss_ctx_id_struct { GSSEAP_MUTEX mutex; - enum eap_gss_state state; + enum gss_eap_state state; OM_uint32 flags; OM_uint32 gssFlags; gss_OID mechanismUsed; @@ -143,9 +152,9 @@ struct gss_ctx_id_struct { uint64_t sendSeq, recvSeq; void *seqState; union { - struct eap_gss_initiator_ctx initiator; + struct gss_eap_initiator_ctx initiator; #define initiatorCtx ctxU.initiator - struct eap_gss_acceptor_ctx acceptor; + struct gss_eap_acceptor_ctx acceptor; #define acceptorCtx ctxU.acceptor } ctxU; }; diff --git a/init_sec_context.c b/init_sec_context.c index 330d0ae..252c468 100644 --- a/init_sec_context.c +++ b/init_sec_context.c @@ -503,7 +503,7 @@ eapGssSmInitEstablished(OM_uint32 *minor, return GSS_S_BAD_STATUS; } -static struct eap_gss_initiator_sm { +static struct gss_eap_initiator_sm { enum gss_eap_token_type inputTokenType; enum gss_eap_token_type outputTokenType; OM_uint32 (*processToken)(OM_uint32 *, @@ -544,7 +544,7 @@ gss_init_sec_context(OM_uint32 *minor, OM_uint32 major; OM_uint32 tmpMajor, tmpMinor; gss_ctx_id_t ctx = *context_handle; - struct eap_gss_initiator_sm *sm = NULL; + struct gss_eap_initiator_sm *sm = NULL; gss_buffer_desc innerInputToken, innerOutputToken; *minor = 0; diff --git a/inquire_name.c b/inquire_name.c index c41d246..6c640f3 100644 --- a/inquire_name.c +++ b/inquire_name.c @@ -32,8 +32,8 @@ #include "gssapiP_eap.h" -struct eap_gss_attribute_args { - gss_buffer_t prefix; +struct gss_eap_attribute_args { + enum gss_eap_attribute_type type; gss_buffer_set_t attrs; }; @@ -43,23 +43,30 @@ struct eap_gss_attribute_args { */ static OM_uint32 addAttribute(OM_uint32 *minor, - void *data, - gss_buffer_t attribute) + gss_name_t name, + gss_buffer_t attribute, + void *data) { - struct eap_gss_attribute_args *args = (struct eap_gss_attribute_args *)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 (attribute != GSS_C_NO_BUFFER) { - major = composeAttributeName(minor, args->prefix, attribute, &qualifiedAttr); + 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 { - major = gss_add_buffer_set_member(minor, args->prefix, &args->attrs); + assert(prefix != GSS_C_NO_BUFFER); + major = gss_add_buffer_set_member(minor, prefix, &args->attrs); } return major; @@ -73,7 +80,7 @@ OM_uint32 gss_inquire_name(OM_uint32 *minor, { OM_uint32 major, tmpMinor; krb5_context krbContext; - struct eap_gss_attribute_args args; + struct gss_eap_attribute_args args; *name_is_MN = 1; *MN_mech = GSS_EAP_MECHANISM; @@ -93,16 +100,36 @@ OM_uint32 gss_inquire_name(OM_uint32 *minor, args.attrs = *attrs; - if (name->samlCtx != NULL) { - args.prefix = gssEapAttributeTypeToPrefix(ATTR_TYPE_SAML_AAA_ASSERTION); + if (name->flags & NAME_FLAG_SAML_ATTRIBUTES) { + /* The assertion itself */ + args.type = ATTR_TYPE_SAML_AAA_ASSERTION; - major = addAttribute(minor, &args, GSS_C_NO_BUFFER); + major = addAttribute(minor, name, GSS_C_NO_BUFFER, &args); if (GSS_ERROR(major)) goto cleanup; - args.prefix = gssEapAttributeTypeToPrefix(ATTR_TYPE_SAML_ATTR); - major = samlGetAttributeTypes(minor, name->samlCtx, - &args, addAttribute); + /* 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; } diff --git a/map_name_to_any.c b/map_name_to_any.c index f6a5684..164b26a 100644 --- a/map_name_to_any.c +++ b/map_name_to_any.c @@ -50,11 +50,11 @@ gss_map_name_to_any(OM_uint32 *minor, GSSEAP_MUTEX_LOCK(&name->mutex); - if (name->samlCtx == NULL) - major = GSS_S_UNAVAILABLE; - else - major = samlMapNameToAny(minor, name->samlCtx, authenticated, + if (name->flags & NAME_FLAG_SAML_ATTRIBUTES) + major = samlMapNameToAny(minor, name, authenticated, type_id, output); + else + major = GSS_S_UNAVAILABLE; GSSEAP_MUTEX_UNLOCK(&name->mutex); diff --git a/release_any_name_mapping.c b/release_any_name_mapping.c index 8504b75..a52642c 100644 --- a/release_any_name_mapping.c +++ b/release_any_name_mapping.c @@ -47,11 +47,10 @@ gss_release_any_name_mapping(OM_uint32 *minor, GSSEAP_MUTEX_LOCK(&name->mutex); - if (name->samlCtx == NULL) - major = GSS_S_UNAVAILABLE; + if (name->flags & NAME_FLAG_SAML_ATTRIBUTES) + major = samlReleaseAnyNameMapping(minor, name, type_id, input); else - major = samlReleaseAnyNameMapping(minor, name->samlCtx, - type_id, input); + major = GSS_S_UNAVAILABLE; GSSEAP_MUTEX_UNLOCK(&name->mutex); diff --git a/resolver.h b/resolver.h new file mode 100644 index 0000000..6f8ff46 --- /dev/null +++ b/resolver.h @@ -0,0 +1,160 @@ +/* + * Copyright 2010 Project Moonshot + * + * 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. + */ + +/** + * @file shibresolver/resolver.h + * + * An embeddable component interface to Shibboleth SP attribute processing. + */ + +#ifndef __shibresolver_h__ +#define __shibresolver_h__ + +#if 0 +#include +#else +#define SHIBRESOLVER_API SHIBSP_API +#endif + +#include +#include + +namespace xmltooling { + class XMLTOOL_API XMLObject; +}; + +namespace opensaml { + namespace saml2 { + class SAML_API Assertion; + class SAML_API NameID; + }; +}; + +namespace shibsp { + class SHIBSP_API Attribute; +}; + +namespace shibresolver { + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4250 4251 ) +#endif + + /** + * An embeddable component interface to Shibboleth SP attribute processing. + */ + class SHIBRESOLVER_API ShibbolethResolver + { + MAKE_NONCOPYABLE(ShibbolethResolver); + protected: + ShibbolethResolver() {} + public: + ~ShibbolethResolver() {} + + /** + * Sets the application ID to use for resolution. + * + * @param appID identifies an application in the SP configuration + */ + void setApplicationID(const char* appID) {} + + /** + * Sets the identity issuer to use for resolution. + * + * @param issuer entityID of the identity "source", if known + */ + void setIssuer(const char* issuer) {} + + /** + * Adds a SAML token as input to the resolver. + *

The caller retains ownership of the object. + * + * @param token an input token to evaluate + */ + void addToken( +#ifdef SHIBSP_LITE + const xmltooling::XMLObject* token +#else + const opensaml::saml2::Assertion* token +#endif + ) {} + + /** + * Adds an Attribute as input to the resolver. + *

The caller retains ownership of the object, but it MAY be modified + * during the resolution process. + * + * @param attr an input attribute + */ + void addAttribute(shibsp::Attribute* attr) {} + + /** + * Resolves attributes and returns them in the supplied array. + *

The caller is responsible for freeing them. + * + * @param attrs array to populate + */ + void resolveAttributes(std::vector& attrs) {} + + /** + * Initializes SP runtime objects based on an XML configuration string or a configuration pathname. + *

Each process using the library MUST call this function exactly once before using any library classes. + * + * @param config a snippet of XML to parse (it MUST contain a type attribute) or a pathname + * @param rethrow true iff caught exceptions should be rethrown instead of just returning the status + * @return true iff initialization was successful + */ + static bool init(const char* config=NULL, bool rethrow=false) { return true; } + + /** + * Shuts down runtime. + * + * Each process using the library SHOULD call this function exactly once before terminating itself. + */ + static void term() {} + + /** + * Returns a ShibbolethResolver instance. + * + * @return a ShibbolethResolver instance, must be freed by the caller. + */ + static ShibbolethResolver* create() { return new ShibbolethResolver(); } + + protected: + /** Application ID. */ + std::string m_appID; + + /** Source of identity, if known. */ + std::string m_issuer; + + /** Input tokens. */ +#ifdef SHIBSP_LITE + std::vector m_tokens; +#else + std::vector m_tokens; +#endif + /** Input attributes. */ + std::vector m_attributes; + }; + +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + +}; + +#endif /* __shibresolver_h__ */ diff --git a/set_name_attribute.c b/set_name_attribute.c index 1c50037..9807557 100644 --- a/set_name_attribute.c +++ b/set_name_attribute.c @@ -55,9 +55,8 @@ gss_set_name_attribute(OM_uint32 *minor, goto cleanup; type = gssEapAttributePrefixToType(&prefix); - if (type != ATTR_TYPE_SAML_AAA_ASSERTION) { - major = samlSetAttribute(minor, name->samlCtx, complete, - attr, value); + if (type == ATTR_TYPE_NONE) { + major = samlSetAttribute(minor, name, complete, attr, value); } else { major = GSS_S_UNAVAILABLE; } diff --git a/util.h b/util.h index c95dc37..936ccea 100644 --- a/util.h +++ b/util.h @@ -66,8 +66,6 @@ extern "C" { #endif -#include "util_saml.h" - #ifndef MIN /* Usually found in . */ #define MIN(_a,_b) ((_a)<(_b)?(_a):(_b)) #endif @@ -290,6 +288,11 @@ enum gss_eap_attribute_type { 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, @@ -428,6 +431,9 @@ 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) diff --git a/util_context.c b/util_context.c index ea5d80d..13372ea 100644 --- a/util_context.c +++ b/util_context.c @@ -74,13 +74,13 @@ gssEapAllocContext(OM_uint32 *minor, } static void -releaseInitiatorContext(struct eap_gss_initiator_ctx *ctx) +releaseInitiatorContext(struct gss_eap_initiator_ctx *ctx) { eap_peer_sm_deinit(ctx->eap); } static void -releaseAcceptorContext(struct eap_gss_acceptor_ctx *ctx) +releaseAcceptorContext(struct gss_eap_acceptor_ctx *ctx) { #ifdef BUILTIN_EAP eap_server_sm_deinit(ctx->eap); diff --git a/util_name.c b/util_name.c index fc5a73f..58919e1 100644 --- a/util_name.c +++ b/util_name.c @@ -106,7 +106,8 @@ gssEapReleaseName(OM_uint32 *minor, gss_name_t *pName) GSSEAP_KRB_INIT(&krbContext); krb5_free_principal(krbContext, name->krbPrincipal); - samlReleaseAttrContext(&tmpMinor, &name->samlCtx); + samlReleaseAttrContext(&tmpMinor, name); + radiusReleaseAttrContext(&tmpMinor, name); GSSEAP_MUTEX_DESTROY(&name->mutex); GSSEAP_FREE(name); @@ -224,6 +225,7 @@ importExportedName(OM_uint32 *minor, size_t len, remain; gss_buffer_desc buf; enum gss_eap_token_type tok_type; + gss_name_t name = GSS_C_NO_NAME; GSSEAP_KRB_INIT(&krbContext); @@ -233,20 +235,23 @@ importExportedName(OM_uint32 *minor, if (remain < 6 + GSS_EAP_MECHANISM->length + 4) return GSS_S_BAD_NAME; +#define UPDATE_REMAIN(n) do { \ + p += (n); \ + remain -= (n); \ + } while (0) + /* TOK_ID */ tok_type = load_uint16_be(p); if (tok_type != TOK_TYPE_EXPORT_NAME && tok_type != TOK_TYPE_EXPORT_NAME_COMPOSITE) return GSS_S_BAD_NAME; - p += 2; - remain -= 2; + UPDATE_REMAIN(2); /* MECH_OID_LEN */ len = load_uint16_be(p); if (len != 2 + GSS_EAP_MECHANISM->length) return GSS_S_BAD_NAME; - p += 2; - remain -= 2; + UPDATE_REMAIN(2); /* MECH_OID */ if (p[0] != 0x06) @@ -255,45 +260,75 @@ importExportedName(OM_uint32 *minor, return GSS_S_BAD_MECH; if (memcmp(&p[2], GSS_EAP_MECHANISM->elements, GSS_EAP_MECHANISM->length)) return GSS_S_BAD_MECH; - p += 2 + GSS_EAP_MECHANISM->length; - remain -= 2 + GSS_EAP_MECHANISM->length; + UPDATE_REMAIN(2 + GSS_EAP_MECHANISM->length); /* NAME_LEN */ len = load_uint32_be(p); - p += 4; - remain -= 4; + UPDATE_REMAIN(4); - if (remain < len) - return GSS_S_BAD_NAME; +#define CHECK_REMAIN(n) do { \ + if (remain < (n)) { \ + *minor = ERANGE; \ + major = GSS_S_BAD_NAME; \ + goto cleanup; \ + } \ + } while (0) /* NAME */ + CHECK_REMAIN(len); buf.length = len; buf.value = p; + UPDATE_REMAIN(len); - p += len; - remain -= len; - - if (remain != 0) - return GSS_S_BAD_NAME; - - major = importUserName(minor, &buf, pName); + major = importUserName(minor, &buf, &name); if (GSS_ERROR(major)) - return major; + goto cleanup; if (tok_type == TOK_TYPE_EXPORT_NAME_COMPOSITE) { - gss_buffer_desc saml; + gss_buffer_desc buf; + + CHECK_REMAIN(4); + 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); - saml.length = remain; - saml.value = p; + 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); - major = samlImportAttrContext(minor, &saml, &(*pName)->samlCtx); - if (GSS_ERROR(major)) { - gssEapReleaseName(&tmpMinor, pName); - return major; + CHECK_REMAIN(buf.length); + buf.value = p; + UPDATE_REMAIN(buf.length); + + major = samlImportAttrContext(minor, &buf, name); + if (GSS_ERROR(major)) + goto cleanup; } } - return GSS_S_COMPLETE; + major = GSS_S_COMPLETE; + +cleanup: + if (GSS_ERROR(major)) + gssEapReleaseName(&tmpMinor, &name); + else + *pName = name; + + return major; } OM_uint32 @@ -335,7 +370,10 @@ gssEapExportName(OM_uint32 *minor, char *krbName = NULL; size_t krbNameLen; unsigned char *p; - gss_buffer_desc saml; + gss_buffer_desc radius, saml; + + radius.length = 0; + radius.value = NULL; saml.length = 0; saml.value = NULL; @@ -361,11 +399,20 @@ gssEapExportName(OM_uint32 *minor, exportedName->length = 6 + GSS_EAP_MECHANISM->length + 4 + krbNameLen; if (composite) { - major = samlExportAttrContext(minor, name->samlCtx, &saml); - if (GSS_ERROR(major)) - goto cleanup; + exportedName->length += 4; - exportedName->length += 4 + saml.length; + 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; + } } exportedName->value = GSSEAP_MALLOC(exportedName->length); @@ -399,11 +446,21 @@ gssEapExportName(OM_uint32 *minor, memcpy(p, krbName, krbNameLen); p += krbNameLen; - store_uint32_be(saml.length, p); - p += 4; + if (composite) { + store_uint32_be(name->flags, p); + p += 4; - memcpy(p, saml.value, saml.length); - p += saml.length; + 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; + } + } *minor = 0; major = GSS_S_COMPLETE; @@ -411,6 +468,7 @@ gssEapExportName(OM_uint32 *minor, cleanup: GSSEAP_MUTEX_UNLOCK(&name->mutex); gss_release_buffer(&tmpMinor, &saml); + gss_release_buffer(&tmpMinor, &radius); if (GSS_ERROR(major)) gss_release_buffer(&tmpMinor, exportedName); krb5_free_unparsed_name(krbContext, krbName); diff --git a/util_radius.c b/util_radius.c index 992350b..2174752 100644 --- a/util_radius.c +++ b/util_radius.c @@ -32,40 +32,36 @@ #include "gssapiP_eap.h" -struct eap_gss_radius_attr_ctx { +struct gss_eap_radius_attr_ctx { }; OM_uint32 radiusDuplicateAttrContext(OM_uint32 *minor, - const struct eap_gss_radius_attr_ctx *in, - struct eap_gss_radius_attr_ctx **out) + const gss_name_t in, + gss_name_t out) { GSSEAP_NOT_IMPLEMENTED; } OM_uint32 radiusReleaseAttrContext(OM_uint32 *minor, - struct eap_gss_radius_attr_ctx **pCtx) + gss_name_t in) { - if (*pCtx != NULL) { - GSSEAP_NOT_IMPLEMENTED; - *pCtx = NULL; - } + GSSEAP_NOT_IMPLEMENTED; } OM_uint32 radiusGetAttributeTypes(OM_uint32 *minor, - const struct eap_gss_radius_attr_ctx *ctx, - void *data, - OM_uint32 (*addAttribute)(OM_uint32 *, - void *, gss_buffer_t)) + gss_name_t name, + gss_eap_add_attr_cb addAttribute, + void *data) { GSSEAP_NOT_IMPLEMENTED; } OM_uint32 radiusGetAttribute(OM_uint32 *minor, - const struct eap_gss_radius_attr_ctx *ctx, + gss_name_t name, gss_buffer_t attr, int *authenticated, int *complete, @@ -76,12 +72,38 @@ radiusGetAttribute(OM_uint32 *minor, GSSEAP_NOT_IMPLEMENTED; } +#if 0 OM_uint32 radiusSetAttribute(OM_uint32 *minor, - struct eap_gss_radius_attr_ctx *ctx, + 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.h b/util_radius.h index f789830..dd9650b 100644 --- a/util_radius.h +++ b/util_radius.h @@ -33,26 +33,26 @@ #ifndef _UTIL_RADIUS_H_ #define _UTIL_RADIUS_H_ 1 -struct eap_gss_radius_attr_ctx; +struct gss_eap_radius_attr_ctx; OM_uint32 radiusDuplicateAttrContext(OM_uint32 *minor, - const struct eap_gss_radius_attr_ctx *in, - struct eap_gss_radius_attr_ctx **out); + const gss_name_t in, + gss_name_t out); OM_uint32 radiusReleaseAttrContext(OM_uint32 *minor, - struct eap_gss_radius_attr_ctx **ctx); + gss_name_t name); OM_uint32 radiusGetAttributeTypes(OM_uint32 *minor, - const struct eap_gss_radius_attr_ctx *ctx, - void *data, - OM_uint32 (*addAttribute)(OM_uint32 *, void *, gss_buffer_t)); + gss_name_t name, + gss_eap_add_attr_cb cb, + void *data); OM_uint32 radiusGetAttribute(OM_uint32 *minor, - const struct eap_gss_radius_attr_ctx *ctx, + gss_name_t name, gss_buffer_t attr, int *authenticated, int *complete, @@ -60,11 +60,28 @@ radiusGetAttribute(OM_uint32 *minor, gss_buffer_t display_value, int *more); +#if 0 OM_uint32 radiusSetAttribute(OM_uint32 *minor, - struct eap_gss_radius_attr_ctx *ctx, + 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); + #endif /* _UTIL_RADIUS_H_ */ diff --git a/util_saml.cpp b/util_saml.cpp index 4d07af1..7d5ae01 100644 --- a/util_saml.cpp +++ b/util_saml.cpp @@ -45,9 +45,7 @@ * limitations under the License. */ -#include -#include -#include "util.h" +#include "gssapiP_eap.h" #include #include @@ -67,7 +65,10 @@ #include #include +#include "resolver.h" + using namespace shibsp; +using namespace shibresolver; using namespace opensaml::saml2md; using namespace opensaml; using namespace xmltooling::logging; @@ -75,63 +76,30 @@ using namespace xmltooling; using namespace xercesc; using namespace std; -class GSSEAPResolver : public shibsp::AssertionConsumerService -{ -public: - GSSEAPResolver(const DOMElement *e, const char *appId) - : shibsp::AssertionConsumerService(e, appId, Category::getInstance(SHIBSP_LOGCAT".GSSEAPResolver")) { - } - virtual ~GSSEAPResolver() {} - - ResolutionContext* resolveAttributes ( - const Application& application, - const RoleDescriptor* issuer, - const XMLCh* protocol, - const saml1::NameIdentifier* v1nameid, - const saml2::NameID* nameid, - const XMLCh* authncontext_class, - const XMLCh* authncontext_decl, - const vector* tokens - ) const { - return shibsp::AssertionConsumerService::resolveAttributes( - application, issuer, protocol, v1nameid, - nameid, authncontext_class, authncontext_decl, tokens - ); - } - -private: - void implementProtocol( - const Application& application, - const HTTPRequest& httpRequest, - HTTPResponse& httpResponse, - SecurityPolicy& policy, - const PropertySet* settings, - const XMLObject& xmlObject - ) const { - throw FatalProfileException("Should never be called."); - } -}; +static vector +duplicateAttributes(const vector src); -struct eap_gss_saml_attr_ctx { +struct gss_eap_saml_attr_ctx +{ public: - eap_gss_saml_attr_ctx(const gss_buffer_t buffer) { - parseAssertion(buffer); + gss_eap_saml_attr_ctx(const gss_buffer_t buffer = GSS_C_NO_BUFFER) { + if (buffer != GSS_C_NO_BUFFER && buffer->length != 0) + parseAssertion(buffer); } - eap_gss_saml_attr_ctx(const vector& attributes, - const Assertion *assertion = NULL) { + gss_eap_saml_attr_ctx(const vector& attributes, + const saml2::Assertion *assertion = NULL) { if (assertion != NULL) - m_assertion = dynamic_cast(assertion->clone()); + m_assertion = dynamic_cast(assertion->clone()); if (attributes.size()) - setAttributes(attributes); + setAttributes(duplicateAttributes(attributes)); } - eap_gss_saml_attr_ctx(const eap_gss_saml_attr_ctx &ctx) { - eap_gss_saml_attr_ctx(ctx.m_attributes, ctx.m_assertion); + gss_eap_saml_attr_ctx(const gss_eap_saml_attr_ctx &ctx) { + gss_eap_saml_attr_ctx(ctx.m_attributes, ctx.m_assertion); } - eap_gss_saml_attr_ctx() {} - ~eap_gss_saml_attr_ctx() { + ~gss_eap_saml_attr_ctx() { for_each(m_attributes.begin(), m_attributes.end(), xmltooling::cleanup()) @@ -161,21 +129,21 @@ public: gss_buffer_t display_value, int *more); - const Assertion *getAssertion(void) const { + const saml2::Assertion *getAssertion(void) const { return m_assertion; } bool getAssertion(gss_buffer_t buffer); DDF marshall() const; - static eap_gss_saml_attr_ctx *unmarshall(DDF &in); + static gss_eap_saml_attr_ctx *unmarshall(DDF &in); void marshall(gss_buffer_t buffer); - static eap_gss_saml_attr_ctx *unmarshall(const gss_buffer_t buffer); + static gss_eap_saml_attr_ctx *unmarshall(const gss_buffer_t buffer); private: mutable vector m_attributes; - mutable Assertion *m_assertion; + mutable saml2::Assertion *m_assertion; bool parseAssertion(const gss_buffer_t buffer); }; @@ -188,7 +156,7 @@ mapException(OM_uint32 *minor, exception &e) } bool -eap_gss_saml_attr_ctx::parseAssertion(const gss_buffer_t buffer) +gss_eap_saml_attr_ctx::parseAssertion(const gss_buffer_t buffer) { DOMDocument *doc; const XMLObjectBuilder *b; @@ -202,7 +170,7 @@ eap_gss_saml_attr_ctx::parseAssertion(const gss_buffer_t buffer) elem = doc->getDocumentElement(); xobj = b->buildOneFromElement(elem, true); - m_assertion = dynamic_cast(xobj); + m_assertion = dynamic_cast(xobj); return (m_assertion != NULL); } @@ -228,7 +196,7 @@ duplicateBuffer(string &str, gss_buffer_t buffer) } DDF -eap_gss_saml_attr_ctx::marshall() const +gss_eap_saml_attr_ctx::marshall() const { DDF obj(NULL); DDF attrs; @@ -250,10 +218,10 @@ eap_gss_saml_attr_ctx::marshall() const return obj; } -eap_gss_saml_attr_ctx * -eap_gss_saml_attr_ctx::unmarshall(DDF &obj) +gss_eap_saml_attr_ctx * +gss_eap_saml_attr_ctx::unmarshall(DDF &obj) { - eap_gss_saml_attr_ctx *ctx = new eap_gss_saml_attr_ctx(); + gss_eap_saml_attr_ctx *ctx = new gss_eap_saml_attr_ctx(); DDF version = obj["version"]; if (version.integer() != 1) @@ -284,7 +252,7 @@ eap_gss_saml_attr_ctx::unmarshall(DDF &obj) } void -eap_gss_saml_attr_ctx::marshall(gss_buffer_t buffer) +gss_eap_saml_attr_ctx::marshall(gss_buffer_t buffer) { DDF obj = marshall(); ostringstream sink; @@ -296,10 +264,10 @@ eap_gss_saml_attr_ctx::marshall(gss_buffer_t buffer) obj.destroy(); } -eap_gss_saml_attr_ctx * -eap_gss_saml_attr_ctx::unmarshall(const gss_buffer_t buffer) +gss_eap_saml_attr_ctx * +gss_eap_saml_attr_ctx::unmarshall(const gss_buffer_t buffer) { - eap_gss_saml_attr_ctx *ctx; + gss_eap_saml_attr_ctx *ctx; string str((const char *)buffer->value, buffer->length); istringstream source(str); @@ -314,7 +282,7 @@ eap_gss_saml_attr_ctx::unmarshall(const gss_buffer_t buffer) } bool -eap_gss_saml_attr_ctx::getAssertion(gss_buffer_t buffer) +gss_eap_saml_attr_ctx::getAssertion(gss_buffer_t buffer) { string str; @@ -357,7 +325,7 @@ duplicateAttributes(const vector src) } void -eap_gss_saml_attr_ctx::addAttribute(Attribute *attribute, bool copy) +gss_eap_saml_attr_ctx::addAttribute(Attribute *attribute, bool copy) { Attribute *a; @@ -367,14 +335,14 @@ eap_gss_saml_attr_ctx::addAttribute(Attribute *attribute, bool copy) } void -eap_gss_saml_attr_ctx::setAttributes(const vector attributes) +gss_eap_saml_attr_ctx::setAttributes(const vector attributes) { for_each(m_attributes.begin(), m_attributes.end(), xmltooling::cleanup()); - m_attributes = duplicateAttributes(attributes); + m_attributes = attributes; } int -eap_gss_saml_attr_ctx::getAttributeIndex(const gss_buffer_t attr) const +gss_eap_saml_attr_ctx::getAttributeIndex(const gss_buffer_t attr) const { int i = 0; @@ -396,7 +364,7 @@ eap_gss_saml_attr_ctx::getAttributeIndex(const gss_buffer_t attr) const } const Attribute * -eap_gss_saml_attr_ctx::getAttribute(const gss_buffer_t attr) const +gss_eap_saml_attr_ctx::getAttribute(const gss_buffer_t attr) const { const Attribute *ret = NULL; @@ -421,7 +389,7 @@ eap_gss_saml_attr_ctx::getAttribute(const gss_buffer_t attr) const } bool -eap_gss_saml_attr_ctx::getAttribute(const gss_buffer_t attr, +gss_eap_saml_attr_ctx::getAttribute(const gss_buffer_t attr, int *authenticated, int *complete, gss_buffer_t value, @@ -453,10 +421,9 @@ eap_gss_saml_attr_ctx::getAttribute(const gss_buffer_t attr, return true; } -void -eap_gss_saml_attr_ctx::setAttribute(int complete, - const gss_buffer_t attr, - const gss_buffer_t value) +static Attribute * +samlAttributeFromGssBuffers(const gss_buffer_t attr, + const gss_buffer_t value) { string attrStr((char *)attr->value, attr->length); vector ids(1); @@ -472,11 +439,21 @@ eap_gss_saml_attr_ctx::setAttribute(int complete, a->getValues().push_back(valStr); } - m_attributes.push_back(a); + return a; } void -eap_gss_saml_attr_ctx::deleteAttribute(const gss_buffer_t attr) +gss_eap_saml_attr_ctx::setAttribute(int complete, + const gss_buffer_t attr, + const gss_buffer_t value) +{ + Attribute *a = samlAttributeFromGssBuffers(attr, value); + + addAttribute(a, false); +} + +void +gss_eap_saml_attr_ctx::deleteAttribute(const gss_buffer_t attr) { int i; @@ -486,12 +463,11 @@ eap_gss_saml_attr_ctx::deleteAttribute(const gss_buffer_t attr) } OM_uint32 -samlReleaseAttrContext(OM_uint32 *minor, - struct eap_gss_saml_attr_ctx **pCtx) +samlReleaseAttrContext(OM_uint32 *minor, gss_name_t name) { try { - delete *pCtx; - *pCtx = NULL; + delete name->samlCtx; + name->samlCtx = NULL; } catch (exception &e) { return mapException(minor, e); } @@ -499,110 +475,166 @@ samlReleaseAttrContext(OM_uint32 *minor, return GSS_S_COMPLETE; } +static gss_buffer_desc +gssEapRadiusAssertionAttr = { 3, (void *)"128" }; + +static OM_uint32 +samlAddRadiusAttribute(OM_uint32 *minor, + gss_name_t name, + gss_buffer_t attr, + void *data) +{ + OM_uint32 major; + ShibbolethResolver *resolver = (ShibbolethResolver *)resolver; + Attribute *a; + int authenticated, complete, more = -1; + gss_buffer_desc value; + + 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) { + /* Do some prefixing? */ + a = samlAttributeFromGssBuffers(attr, &value); + /* XXX leaky */ + resolver->addAttribute(a); + } + + return GSS_S_COMPLETE; +} + +static OM_uint32 +samlAddRadiusAttributes(OM_uint32 *minor, + gss_name_t name, + ShibbolethResolver *resolver) +{ + return radiusGetAttributeTypes(minor, + name, + samlAddRadiusAttribute, + (void *)resolver); +} + +static OM_uint32 +samlInitAttrContextFromRadius(OM_uint32 *minor, + gss_name_t name, + gss_eap_saml_attr_ctx **pSamlCtx) +{ + 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 (major == GSS_S_UNAVAILABLE) { + /* No assertion provided via RADIUS. */ + value.length = 0; + value.value = NULL; + } else if (GSS_ERROR(major)) { + /* Some other error */ + return major; + } + + *pSamlCtx = new gss_eap_saml_attr_ctx(&value); + + gss_release_buffer(minor, &value); + + return GSS_S_COMPLETE; +} + OM_uint32 samlCreateAttrContext(OM_uint32 *minor, - gss_buffer_t buffer, - gss_name_t acceptorName, - struct eap_gss_saml_attr_ctx **pCtx, + gss_cred_id_t acceptorCred, + gss_name_t initiatorName, time_t *pExpiryTime) { OM_uint32 major, tmpMinor; - eap_gss_saml_attr_ctx *ctx = NULL; - SPConfig &conf = SPConfig::getConfig(); - ServiceProvider *sp; - const Application *app; - MetadataProvider *m; gss_buffer_desc nameBuf; - const XMLCh *issuer = NULL; - saml2::NameID *subjectName = NULL; - saml2::Assertion *assertion; - ResolutionContext *resolverContext; + gss_eap_saml_attr_ctx *ctx = NULL; + ShibbolethResolver *resolver = NULL; + + assert(initiatorName != GSS_C_NO_NAME); nameBuf.length = 0; nameBuf.value = NULL; - conf.setFeatures(SPConfig::Metadata | - SPConfig::Trust | - SPConfig::AttributeResolution | - SPConfig::Credentials | - SPConfig::OutOfProcess); - if (!conf.init()) - return GSS_S_FAILURE; - if (!conf.instantiate()) + resolver = ShibbolethResolver::create(); + if (resolver == NULL) return GSS_S_FAILURE; - sp = conf.getServiceProvider(); - sp->lock(); - - major = gss_display_name(minor, acceptorName, &nameBuf, NULL); - if (GSS_ERROR(major)) - goto cleanup; - - app = sp->getApplication((const char *)nameBuf.value); - if (app == NULL) { - major = GSS_S_FAILURE; - goto cleanup; + if (acceptorCred != GSS_C_NO_CREDENTIAL) { + major = gss_display_name(minor, acceptorCred->name, &nameBuf, NULL); + if (GSS_ERROR(major)) + goto cleanup; } try { - ctx = new eap_gss_saml_attr_ctx(buffer); - - if (assertion->getIssuer() != NULL) - issuer = assertion->getIssuer()->getName(); - if (assertion->getSubject() != NULL) - subjectName = assertion->getSubject()->getNameID(); - if (assertion->getConditions()) - *pExpiryTime = assertion->getConditions()->getNotOnOrAfter()->getEpoch(); - - m = app->getMetadataProvider(); - xmltooling::Locker mlocker(m); - MetadataProviderCriteria mc(*app, issuer, - &IDPSSODescriptor::ELEMENT_QNAME, - samlconstants::SAML20P_NS); - pair site = - m->getEntityDescriptor(mc); - if (!site.first) { - auto_ptr_char temp(issuer); - throw MetadataException("Unable to locate metadata for IdP ($1).", - params(1,temp.get())); + const saml2::Assertion *assertion; + vector attrs; + + major = samlInitAttrContextFromRadius(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); + } + + if (initiatorName->radiusCtx != NULL) { + samlAddRadiusAttributes(minor, initiatorName, resolver); } - vector tokens(1, assertion); - GSSEAPResolver gssResolver(NULL, (const char *)nameBuf.value); - resolverContext = gssResolver.resolveAttributes(*app, site.second, - samlconstants::SAML20P_NS, - NULL, subjectName, NULL, - NULL, &tokens); - ctx->setAttributes(resolverContext->getResolvedAttributes()); + + resolver->resolveAttributes(attrs); + ctx->setAttributes(attrs); } catch (exception &ex) { major = mapException(minor, ex); goto cleanup; } + *minor = 0; major = GSS_S_COMPLETE; - *pCtx = ctx; -cleanup: - sp->unlock(); - conf.term(); + initiatorName->samlCtx = ctx; +cleanup: + gss_release_buffer(&tmpMinor, &nameBuf); if (GSS_ERROR(major)) delete ctx; - gss_release_buffer(&tmpMinor, &nameBuf); + delete resolver; return major; } OM_uint32 samlGetAttributeTypes(OM_uint32 *minor, - const struct eap_gss_saml_attr_ctx *ctx, - void *data, - OM_uint32 (*addAttribute)(OM_uint32 *, void *, gss_buffer_t)) + gss_name_t name, + enum gss_eap_attribute_type type, + gss_eap_add_attr_cb addAttribute, + void *data) { OM_uint32 major = GSS_S_COMPLETE; + gss_eap_saml_attr_ctx *ctx = name->samlCtx; if (ctx == NULL) return GSS_S_COMPLETE; + if (type != ATTR_TYPE_NONE) + return GSS_S_UNAVAILABLE; + for (vector::const_iterator a = ctx->getAttributes().begin(); a != ctx->getAttributes().end(); ++a) @@ -612,7 +644,7 @@ samlGetAttributeTypes(OM_uint32 *minor, attribute.value = (void *)((*a)->getId()); attribute.length = strlen((char *)attribute.value); - major = addAttribute(minor, data, &attribute); + major = addAttribute(minor, name, &attribute, data); if (GSS_ERROR(major)) break; } @@ -625,7 +657,8 @@ samlGetAttributeTypes(OM_uint32 *minor, */ OM_uint32 samlGetAttribute(OM_uint32 *minor, - struct eap_gss_saml_attr_ctx *ctx, + enum gss_eap_attribute_type type, + gss_name_t name, gss_buffer_t attr, int *authenticated, int *complete, @@ -633,23 +666,37 @@ samlGetAttribute(OM_uint32 *minor, gss_buffer_t display_value, int *more) { + struct gss_eap_saml_attr_ctx *ctx = name->samlCtx; + bool ret; + if (ctx == NULL) return GSS_S_UNAVAILABLE; - if (!ctx->getAttribute(attr, authenticated, complete, - value, display_value, more)) - 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 GSS_S_COMPLETE; + return ret ? GSS_S_COMPLETE : GSS_S_UNAVAILABLE; } OM_uint32 samlSetAttribute(OM_uint32 *minor, - struct eap_gss_saml_attr_ctx *ctx, + gss_name_t name, int complete, gss_buffer_t attr, gss_buffer_t value) { + struct gss_eap_saml_attr_ctx *ctx = name->samlCtx; + + if (ctx == NULL) + return GSS_S_UNAVAILABLE; + try { ctx->setAttribute(complete, attr, value); } catch (exception &e) { @@ -661,9 +708,14 @@ samlSetAttribute(OM_uint32 *minor, OM_uint32 samlDeleteAttribute(OM_uint32 *minor, - struct eap_gss_saml_attr_ctx *ctx, + gss_name_t name, gss_buffer_t attr) { + struct gss_eap_saml_attr_ctx *ctx = name->samlCtx; + + if (ctx == NULL) + return GSS_S_UNAVAILABLE; + try { ctx->deleteAttribute(attr); } catch (exception &e) { @@ -679,9 +731,11 @@ samlDeleteAttribute(OM_uint32 *minor, */ OM_uint32 samlExportAttrContext(OM_uint32 *minor, - struct eap_gss_saml_attr_ctx *ctx, + gss_name_t name, gss_buffer_t buffer) { + struct gss_eap_saml_attr_ctx *ctx = name->samlCtx; + try { ctx->marshall(buffer); } catch (exception &e) { @@ -698,10 +752,11 @@ samlExportAttrContext(OM_uint32 *minor, OM_uint32 samlImportAttrContext(OM_uint32 *minor, gss_buffer_t buffer, - struct eap_gss_saml_attr_ctx **pCtx) + gss_name_t name) { try { - *pCtx = eap_gss_saml_attr_ctx::unmarshall(buffer); + assert(name->samlCtx == NULL); + name->samlCtx = gss_eap_saml_attr_ctx::unmarshall(buffer); } catch (exception &e) { return mapException(minor, e); } @@ -711,9 +766,14 @@ samlImportAttrContext(OM_uint32 *minor, OM_uint32 samlGetAssertion(OM_uint32 *minor, - struct eap_gss_saml_attr_ctx *ctx, + gss_name_t name, gss_buffer_t assertion) { + struct gss_eap_saml_attr_ctx *ctx = name->samlCtx; + + if (ctx == NULL) + return GSS_S_UNAVAILABLE; + try { ctx->getAssertion(assertion); } catch (exception &e) { @@ -725,11 +785,14 @@ samlGetAssertion(OM_uint32 *minor, OM_uint32 samlDuplicateAttrContext(OM_uint32 *minor, - const struct eap_gss_saml_attr_ctx *in, - struct eap_gss_saml_attr_ctx **out) + gss_name_t in, + gss_name_t out) { try { - *out = new eap_gss_saml_attr_ctx(*in); + 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); } @@ -739,11 +802,13 @@ samlDuplicateAttrContext(OM_uint32 *minor, OM_uint32 samlMapNameToAny(OM_uint32 *minor, - const struct eap_gss_saml_attr_ctx *ctx, + gss_name_t name, int authenticated, gss_buffer_t type_id, gss_any_t *output) { + struct gss_eap_saml_attr_ctx *ctx = name->samlCtx; + if (bufferEqualString(type_id, "shibsp::Attribute")) { vector v = duplicateAttributes(ctx->getAttributes()); @@ -760,7 +825,7 @@ samlMapNameToAny(OM_uint32 *minor, OM_uint32 samlReleaseAnyNameMapping(OM_uint32 *minor, - const struct eap_gss_saml_attr_ctx *ctx, + gss_name_t name, gss_buffer_t type_id, gss_any_t *input) { @@ -776,3 +841,20 @@ samlReleaseAnyNameMapping(OM_uint32 *minor, *input = (gss_any_t)NULL; return GSS_S_COMPLETE; } + +OM_uint32 +samlInit(OM_uint32 *minor) +{ + *minor = 0; + + return ShibbolethResolver::init() ? GSS_S_COMPLETE : GSS_S_FAILURE; +} + +OM_uint32 +samlFinalize(OM_uint32 *minor) +{ + *minor = 0; + + ShibbolethResolver::term(); + return GSS_S_COMPLETE; +} diff --git a/util_saml.h b/util_saml.h index c3b0525..8d90de9 100644 --- a/util_saml.h +++ b/util_saml.h @@ -37,34 +37,34 @@ extern "C" { #endif -struct eap_gss_saml_attr_ctx; +struct gss_eap_saml_attr_ctx; OM_uint32 samlDuplicateAttrContext(OM_uint32 *minor, - const struct eap_gss_saml_attr_ctx *in, - struct eap_gss_saml_attr_ctx **out); + gss_name_t in, + gss_name_t out); OM_uint32 samlCreateAttrContext(OM_uint32 *minor, gss_cred_id_t acceptorCred, gss_name_t initiatorName, - gss_buffer_t buffer, - struct eap_gss_saml_attr_ctx **pCtx, time_t *pExpiryTime); OM_uint32 samlReleaseAttrContext(OM_uint32 *minor, - struct eap_gss_saml_attr_ctx **ctx); + gss_name_t name); OM_uint32 samlGetAttributeTypes(OM_uint32 *minor, - const struct eap_gss_saml_attr_ctx *ctx, - void *data, - OM_uint32 (*addAttribute)(OM_uint32 *, void *, gss_buffer_t)); + gss_name_t name, + enum gss_eap_attribute_type type, + gss_eap_add_attr_cb cb, + void *data); OM_uint32 samlGetAttribute(OM_uint32 *minor, - struct eap_gss_saml_attr_ctx *ctx, + enum gss_eap_attribute_type type, + gss_name_t name, gss_buffer_t attr, int *authenticated, int *complete, @@ -74,45 +74,52 @@ samlGetAttribute(OM_uint32 *minor, OM_uint32 samlSetAttribute(OM_uint32 *minor, - struct eap_gss_saml_attr_ctx *ctx, + gss_name_t name, int complete, gss_buffer_t attr, gss_buffer_t value); OM_uint32 samlDeleteAttribute(OM_uint32 *minor, - struct eap_gss_saml_attr_ctx *ctx, + gss_name_t name, gss_buffer_t attr); OM_uint32 samlExportAttrContext(OM_uint32 *minor, - struct eap_gss_saml_attr_ctx *ctx, + gss_name_t name, gss_buffer_t buffer); OM_uint32 samlImportAttrContext(OM_uint32 *minor, gss_buffer_t buffer, - struct eap_gss_saml_attr_ctx **pCtx); + gss_name_t name); OM_uint32 samlGetAssertion(OM_uint32 *minor, - struct eap_gss_saml_attr_ctx *ctx, + gss_name_t name, gss_buffer_t assertion); OM_uint32 samlMapNameToAny(OM_uint32 *minor, - const struct eap_gss_saml_attr_ctx *ctx, + gss_name_t name, int authenticated, gss_buffer_t type_id, gss_any_t *output); OM_uint32 samlReleaseAnyNameMapping(OM_uint32 *minor, - const struct eap_gss_saml_attr_ctx *ctx, + 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 -- 2.1.4