From c581903743f5bf281548368f49bc5d37d338a4ea Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Mon, 13 Sep 2010 12:10:48 +0200 Subject: [PATCH] more work on SAML ification --- Makefile.am | 2 +- delete_name_attribute.c | 66 ++++++ duplicate_name.c | 7 - get_name_attribute.c | 17 +- gssapiP_eap.h | 7 +- inquire_name.c | 8 - set_name_attribute.c | 16 +- util.h | 1 - util_name.c | 40 +++- util_saml.cpp | 528 ++++++++++++++++++++++++++++++++++++------------ util_saml.h | 12 +- 11 files changed, 513 insertions(+), 191 deletions(-) create mode 100644 delete_name_attribute.c diff --git a/Makefile.am b/Makefile.am index 1a5b5d0..e010d6f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -23,6 +23,7 @@ libmech_eap_la_SOURCES = \ canonicalize_name.c \ compare_name.c \ context_time.c \ + delete_name_attribute.c \ delete_sec_context.c \ display_name.c \ display_name_ext.c \ @@ -68,7 +69,6 @@ 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/delete_name_attribute.c b/delete_name_attribute.c new file mode 100644 index 0000000..657d7a6 --- /dev/null +++ b/delete_name_attribute.c @@ -0,0 +1,66 @@ +/* + * 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" + +OM_uint32 +gss_delete_name_attribute(OM_uint32 *minor, + gss_name_t name, + gss_buffer_t attr) +{ + OM_uint32 major; + gss_buffer_desc prefix, suffix; + enum gss_eap_attribute_type type; + + if (name == GSS_C_NO_NAME) { + *minor = EINVAL; + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME; + } + + GSSEAP_MUTEX_LOCK(&name->mutex); + + major = decomposeAttributeName(minor, attr, &prefix, &suffix); + if (GSS_ERROR(major)) + goto cleanup; + + type = gssEapAttributePrefixToType(&prefix); + if (type != ATTR_TYPE_SAML_AAA_ASSERTION) { + major = samlDeleteAttribute(minor, name->samlCtx, 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 3f52acb..ad45a28 100644 --- a/duplicate_name.c +++ b/duplicate_name.c @@ -63,13 +63,6 @@ gss_duplicate_name(OM_uint32 *minor, goto cleanup; } - if (input_name->radiusCtx != NULL) { - major = radiusDuplicateAttrContext(minor, input_name->radiusCtx, - &name->radiusCtx); - if (GSS_ERROR(major)) - goto cleanup; - } - if (input_name->samlCtx != NULL) { major = samlDuplicateAttrContext(minor, input_name->samlCtx, &name->samlCtx); diff --git a/get_name_attribute.c b/get_name_attribute.c index 8eaf412..525137f 100644 --- a/get_name_attribute.c +++ b/get_name_attribute.c @@ -66,23 +66,12 @@ gss_get_name_attribute(OM_uint32 *minor, goto cleanup; type = gssEapAttributePrefixToType(&prefix); - switch (type) { - case ATTR_TYPE_SAML_ATTR: + if (type == ATTR_TYPE_SAML_AAA_ASSERTION) { + major = samlGetAssertion(minor, name->samlCtx, value); + } else { major = samlGetAttribute(minor, name->samlCtx, &suffix, authenticated, complete, value, display_value, more); - break; - case ATTR_TYPE_SAML_AAA_ASSERTION: - break; - case ATTR_TYPE_RADIUS_AVP: - major = radiusGetAttribute(minor, name->radiusCtx, &suffix, - authenticated, complete, - value, display_value, more); - break; - default: - *minor = ENOENT; - major = GSS_S_UNAVAILABLE; - break; } cleanup: diff --git a/gssapiP_eap.h b/gssapiP_eap.h index db39ccf..e02927c 100644 --- a/gssapiP_eap.h +++ b/gssapiP_eap.h @@ -58,21 +58,16 @@ #define NAME_FLAG_NAI 0x00000001 #define NAME_FLAG_SERVICE 0x00000002 -#define NAME_FLAG_SAML 0x00000010 -#define NAME_FLAG_RADIUS 0x00000020 -#define NAME_HAS_ATTRIBUTES(name) ((name)->flags & \ - (NAME_FLAG_SAML | NAME_FLAG_RADIUS)) +#define NAME_HAS_ATTRIBUTES(name) ((name)->samlCtx != NULL) struct eap_gss_saml_attr_ctx; -struct eap_gss_radius_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 eap_gss_radius_attr_ctx *radiusCtx; }; #define CRED_FLAG_INITIATE 0x00000001 diff --git a/inquire_name.c b/inquire_name.c index 6407cba..c41d246 100644 --- a/inquire_name.c +++ b/inquire_name.c @@ -107,14 +107,6 @@ OM_uint32 gss_inquire_name(OM_uint32 *minor, goto cleanup; } - if (name->radiusCtx != NULL) { - args.prefix = gssEapAttributeTypeToPrefix(ATTR_TYPE_RADIUS_AVP); - major = radiusGetAttributeTypes(minor, name->radiusCtx, - &args, addAttribute); - if (GSS_ERROR(major)) - goto cleanup; - } - cleanup: GSSEAP_MUTEX_UNLOCK(&name->mutex); diff --git a/set_name_attribute.c b/set_name_attribute.c index a8a4a56..1c50037 100644 --- a/set_name_attribute.c +++ b/set_name_attribute.c @@ -55,19 +55,11 @@ gss_set_name_attribute(OM_uint32 *minor, goto cleanup; type = gssEapAttributePrefixToType(&prefix); - switch (type) { - case ATTR_TYPE_SAML_ATTR: - major = samlSetAttribute(minor, name->samlCtx, - complete, &suffix, value); - break; - case ATTR_TYPE_RADIUS_AVP: - major = radiusSetAttribute(minor, name->radiusCtx, - complete, &suffix, value); - break; - default: - *minor = ENOENT; + if (type != ATTR_TYPE_SAML_AAA_ASSERTION) { + major = samlSetAttribute(minor, name->samlCtx, complete, + attr, value); + } else { major = GSS_S_UNAVAILABLE; - break; } cleanup: diff --git a/util.h b/util.h index bc88681..087dc1c 100644 --- a/util.h +++ b/util.h @@ -67,7 +67,6 @@ extern "C" { #endif #include "util_saml.h" -#include "util_radius.h" #define KRB_KEY_TYPE(key) ((key)->enctype) #define KRB_KEY_DATA(key) ((key)->contents) diff --git a/util_name.c b/util_name.c index 8f25002..8265d22 100644 --- a/util_name.c +++ b/util_name.c @@ -106,7 +106,6 @@ gssEapReleaseName(OM_uint32 *minor, gss_name_t *pName) GSSEAP_KRB_INIT(&krbContext); krb5_free_principal(krbContext, name->krbPrincipal); - radiusReleaseAttrContext(&tmpMinor, &name->radiusCtx); samlReleaseAttrContext(&tmpMinor, &name->samlCtx); GSSEAP_MUTEX_DESTROY(&name->mutex); @@ -222,7 +221,6 @@ importExportedName(OM_uint32 *minor, OM_uint32 major, tmpMinor; krb5_context krbContext; unsigned char *p; - int composite = 0; size_t len, remain; gss_buffer_desc buf; enum gss_eap_token_type tok_type; @@ -275,14 +273,25 @@ importExportedName(OM_uint32 *minor, p += len; remain -= len; - if (composite == 0 && remain != 0) + if (remain != 0) return GSS_S_BAD_NAME; major = importUserName(minor, &buf, pName); if (GSS_ERROR(major)) return major; - /* XXX TODO composite handling */ + if (tok_type == TOK_TYPE_EXPORT_NAME_COMPOSITE) { + gss_buffer_desc saml; + + saml.length = remain; + saml.value = p; + + major = samlImportAttrContext(minor, &saml, &(*pName)->samlCtx); + if (GSS_ERROR(major)) { + gssEapReleaseName(&tmpMinor, pName); + return major; + } + } return GSS_S_COMPLETE; } @@ -326,6 +335,10 @@ gssEapExportName(OM_uint32 *minor, char *krbName = NULL; size_t krbNameLen; unsigned char *p; + gss_buffer_desc saml; + + saml.length = 0; + saml.value = NULL; exportedName->length = 0; exportedName->value = NULL; @@ -340,18 +353,24 @@ gssEapExportName(OM_uint32 *minor, composite = 0; *minor = krb5_unparse_name(krbContext, name->krbPrincipal, &krbName); - if (*minor != 0) + if (*minor != 0) { + major = GSS_S_FAILURE; goto cleanup; + } krbNameLen = strlen(krbName); exportedName->length = 6 + GSS_EAP_MECHANISM->length + 4 + krbNameLen; if (composite) { - /* TODO: export SAML/AVP, this is pending specification */ - + major = samlExportAttrContext(minor, name->samlCtx, &saml); + if (GSS_ERROR(major)) + goto cleanup; + + exportedName->length += 4 + saml.length; } exportedName->value = GSSEAP_MALLOC(exportedName->length); if (exportedName->value == NULL) { + major = GSS_S_FAILURE; *minor = ENOMEM; goto cleanup; } @@ -380,11 +399,18 @@ gssEapExportName(OM_uint32 *minor, memcpy(p, krbName, krbNameLen); p += krbNameLen; + store_uint32_be(saml.length, p); + p += 4; + + memcpy(p, saml.value, saml.length); + p += saml.length; + *minor = 0; major = GSS_S_COMPLETE; cleanup: GSSEAP_MUTEX_UNLOCK(&name->mutex); + gss_release_buffer(&tmpMinor, &saml); if (GSS_ERROR(major)) gss_release_buffer(&tmpMinor, exportedName); krb5_free_unparsed_name(krbContext, krbName); diff --git a/util_saml.cpp b/util_saml.cpp index 68bc3be..3bef5ff 100644 --- a/util_saml.cpp +++ b/util_saml.cpp @@ -54,6 +54,7 @@ #include #include #include +#include #include #include #include @@ -111,113 +112,354 @@ private: } }; -class SHIBSP_DLLLOCAL DummyContext : public ResolutionContext -{ +struct eap_gss_saml_attr_ctx { public: - DummyContext(const vector& attributes) : m_attributes(attributes) { - } + eap_gss_saml_attr_ctx(); + eap_gss_saml_attr_ctx(const gss_buffer_t buffer); + eap_gss_saml_attr_ctx(const Assertion *assertion); + + eap_gss_saml_attr_ctx(const vector& attributes, + const Assertion *assertion); - virtual ~DummyContext() { - for_each(m_attributes.begin(), m_attributes.end(), xmltooling::cleanup()); + eap_gss_saml_attr_ctx(const eap_gss_saml_attr_ctx &ctx) { + eap_gss_saml_attr_ctx(ctx.m_attributes, ctx.m_assertion); } - vector& getResolvedAttributes() { + ~eap_gss_saml_attr_ctx(); + + const vector getAttributes(void) const { return m_attributes; } - vector& getResolvedAssertions() { - return m_tokens; + + 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 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); + + bool marshall(gss_buffer_t buffer); + static eap_gss_saml_attr_ctx *unmarshall(const gss_buffer_t buffer); + private: - vector m_attributes; - static vector m_tokens; // never any tokens, so just share an empty vector -}; + mutable vector m_attributes; + mutable Assertion *m_assertion; -struct eap_gss_saml_attr_ctx { - ResolutionContext *resCtx; + bool parseAssertion(const gss_buffer_t buffer); }; -static OM_uint32 -samlAllocAttrContext(OM_uint32 *minor, - struct eap_gss_saml_attr_ctx **pCtx) +eap_gss_saml_attr_ctx::eap_gss_saml_attr_ctx(const vector& attributes, + const Assertion *assertion) { - struct eap_gss_saml_attr_ctx *ctx; + m_assertion = dynamic_cast(assertion->clone()); + setAttributes(attributes); +} - ctx = (struct eap_gss_saml_attr_ctx *)GSSEAP_CALLOC(1, sizeof(*ctx)); - if (ctx == NULL) { - *minor = ENOMEM; - return GSS_S_FAILURE; +eap_gss_saml_attr_ctx::~eap_gss_saml_attr_ctx() +{ + for_each(m_attributes.begin(), m_attributes.end(), xmltooling::cleanup()); + delete m_assertion; +} + +eap_gss_saml_attr_ctx::eap_gss_saml_attr_ctx(const gss_buffer_t buffer) +{ + parseAssertion(buffer); +} + +bool +eap_gss_saml_attr_ctx::parseAssertion(const gss_buffer_t buffer) +{ + DOMDocument *doc; + const XMLObjectBuilder *b; + DOMElement *elem; + XMLObject *xobj; + string str((char *)buffer->value, buffer->length); + istringstream istream(str); + + doc = XMLToolingConfig::getConfig().getParser().parse(istream); + b = XMLObjectBuilder::getDefaultBuilder(); + elem = doc->getDocumentElement(); + xobj = b->buildOneFromElement(elem, true); + + m_assertion = dynamic_cast(xobj); + + return (m_assertion != NULL); +} + +static inline bool +duplicateBuffer(string &str, gss_buffer_t buffer) +{ + gss_buffer_desc tmp; + OM_uint32 minor; + + tmp.length = str.length(); + tmp.value = (char *)str.c_str(); + + if (GSS_ERROR(duplicateBuffer(&minor, &tmp, buffer))) + return false; + + return true; +} + +DDF +eap_gss_saml_attr_ctx::marshall() const +{ + DDF obj; + 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); } - *pCtx = ctx; - *minor = 0; - return GSS_S_COMPLETE; + ostringstream sink; + sink << *m_assertion; + assertion = obj.addmember("assertion").string(sink.str().c_str()); + + return obj; } -static OM_uint32 -samlImportAssertion(OM_uint32 *minor, - gss_buffer_t buffer, - saml2::Assertion **pAssertion) +eap_gss_saml_attr_ctx * +eap_gss_saml_attr_ctx::unmarshall(DDF &obj) { - *pAssertion = NULL; + eap_gss_saml_attr_ctx *ctx = new eap_gss_saml_attr_ctx(); - try { - DOMDocument *doc; - const XMLObjectBuilder *b; - DOMElement *elem; - XMLObject *xobj; - string samlBuf((char *)buffer->value, buffer->length); - istringstream samlIn(samlBuf); - - doc = XMLToolingConfig::getConfig().getParser().parse(samlIn); - b = XMLObjectBuilder::getDefaultBuilder(); - elem = doc->getDocumentElement(); - xobj = b->buildOneFromElement(elem, true); - - *pAssertion = dynamic_cast(xobj); - if (*pAssertion == NULL) { - /* TODO minor_status */ - return GSS_S_BAD_NAME; + 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; +} + +bool +eap_gss_saml_attr_ctx::marshall(gss_buffer_t buffer) +{ + DDF obj; + ostringstream sink; + string str; + + obj = marshall(); + sink << obj; + str = sink.str(); + + return duplicateBuffer(str, buffer); +} + +eap_gss_saml_attr_ctx * +eap_gss_saml_attr_ctx::unmarshall(const gss_buffer_t buffer) +{ + DDF obj; + string str((const char *)buffer->value, buffer->length); + istringstream source(str); + source >> obj; + + return unmarshall(obj); +} + +bool +eap_gss_saml_attr_ctx::getAssertion(gss_buffer_t buffer) +{ + string str; + + buffer->value = NULL; + buffer->length = 0; + + XMLHelper::serialize(m_assertion->marshall((DOMDocument *)NULL), str); + + return duplicateBuffer(str, buffer); +} + +void +eap_gss_saml_attr_ctx::addAttribute(Attribute *attribute, bool copy) +{ + Attribute *a; + if (copy) { + DDF obj = attribute->marshall(); + a = Attribute::unmarshall(obj); + } else { + a = attribute; + } + m_attributes.push_back(a); +} + +void +eap_gss_saml_attr_ctx::setAttributes(const vector attributes) +{ + for (vector::const_iterator a = attributes.begin(); + a != attributes.end(); + ++a) + addAttribute(*a); +} + +int +eap_gss_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; + } } - } catch (exception &e){ - /* TODO minor_status */ - return GSS_S_BAD_NAME; } - *minor = 0; - return GSS_S_COMPLETE; + return -1; } -OM_uint32 -samlDuplicateAttrContext(OM_uint32 *minor, - const struct eap_gss_saml_attr_ctx *in, - struct eap_gss_saml_attr_ctx **out) +const Attribute * +eap_gss_saml_attr_ctx::getAttribute(const gss_buffer_t attr) const { - OM_uint32 major, tmpMinor; - struct eap_gss_saml_attr_ctx *ctx; + const Attribute *ret = NULL; - major = samlAllocAttrContext(minor, &ctx); - if (GSS_ERROR(major)) - goto cleanup; + 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; + } - ctx->resCtx = new DummyContext(in->resCtx->getResolvedAttributes()); + return ret; +} -cleanup: +bool +eap_gss_saml_attr_ctx::getAttribute(const gss_buffer_t attr, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) +{ + OM_uint32 major, minor; + 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); + + major = duplicateBuffer(&minor, &buf, value); if (GSS_ERROR(major)) - samlReleaseAttrContext(&tmpMinor, &ctx); + return false; + + *authenticated = TRUE; + *complete = FALSE; - return major; + return true; +} + +void +eap_gss_saml_attr_ctx::setAttribute(int complete, + const gss_buffer_t attr, + const gss_buffer_t value) +{ + 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); + } + + m_attributes.push_back(a); +} + +void +eap_gss_saml_attr_ctx::deleteAttribute(const gss_buffer_t attr) +{ + int i; + + i = getAttributeIndex(attr); + if (i >= 0) + m_attributes.erase(m_attributes.begin() + i); } OM_uint32 samlReleaseAttrContext(OM_uint32 *minor, struct eap_gss_saml_attr_ctx **pCtx) { - struct eap_gss_saml_attr_ctx *ctx = *pCtx; + eap_gss_saml_attr_ctx *ctx = *pCtx; if (ctx != NULL) { - delete ctx->resCtx; - GSSEAP_FREE(ctx); + delete ctx; *pCtx = NULL; } @@ -232,7 +474,7 @@ samlCreateAttrContext(OM_uint32 *minor, struct eap_gss_saml_attr_ctx **pCtx) { OM_uint32 major, tmpMinor; - struct eap_gss_saml_attr_ctx *ctx; + eap_gss_saml_attr_ctx *ctx = NULL; SPConfig &conf = SPConfig::getConfig(); ServiceProvider *sp; const Application *app; @@ -241,6 +483,7 @@ samlCreateAttrContext(OM_uint32 *minor, const XMLCh *issuer = NULL; saml2::NameID *subjectName = NULL; saml2::Assertion *assertion; + ResolutionContext *resolverContext; nameBuf.length = 0; nameBuf.value = NULL; @@ -268,20 +511,14 @@ samlCreateAttrContext(OM_uint32 *minor, goto cleanup; } - major = samlAllocAttrContext(minor, &ctx); - if (GSS_ERROR(major)) - goto cleanup; - - major = samlImportAssertion(minor, buffer, &assertion); - 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->getIssuer() != NULL) + issuer = assertion->getIssuer()->getName(); + if (assertion->getSubject() != NULL) + subjectName = assertion->getSubject()->getNameID(); - try { m = app->getMetadataProvider(); xmltooling::Locker mlocker(m); MetadataProviderCriteria mc(*app, issuer, @@ -296,10 +533,11 @@ samlCreateAttrContext(OM_uint32 *minor, } vector tokens(1, assertion); GSSEAPResolver gssResolver(NULL, (const char *)nameBuf.value); - ctx->resCtx = gssResolver.resolveAttributes(*app, site.second, - samlconstants::SAML20P_NS, - NULL, subjectName, NULL, - NULL, &tokens); + resolverContext = gssResolver.resolveAttributes(*app, site.second, + samlconstants::SAML20P_NS, + NULL, subjectName, NULL, + NULL, &tokens); + ctx->setAttributes(resolverContext->getResolvedAttributes()); } catch (exception &ex) { major = GSS_S_BAD_NAME; goto cleanup; @@ -313,7 +551,7 @@ cleanup: conf.term(); if (GSS_ERROR(major)) - samlReleaseAttrContext(&tmpMinor, &ctx); + delete ctx; gss_release_buffer(&tmpMinor, &nameBuf); return major; @@ -330,8 +568,8 @@ samlGetAttributeTypes(OM_uint32 *minor, if (ctx == NULL) return GSS_S_COMPLETE; - for (vector::const_iterator a = ctx->resCtx->getResolvedAttributes().begin(); - a != ctx->resCtx->getResolvedAttributes().end(); + for (vector::const_iterator a = ctx->getAttributes().begin(); + a != ctx->getAttributes().end(); ++a) { gss_buffer_desc attribute; @@ -352,7 +590,7 @@ samlGetAttributeTypes(OM_uint32 *minor, */ OM_uint32 samlGetAttribute(OM_uint32 *minor, - const struct eap_gss_saml_attr_ctx *ctx, + struct eap_gss_saml_attr_ctx *ctx, gss_buffer_t attr, int *authenticated, int *complete, @@ -360,55 +598,16 @@ samlGetAttribute(OM_uint32 *minor, gss_buffer_t display_value, int *more) { - OM_uint32 major; - Attribute *shibAttr = NULL; - gss_buffer_desc buf; - if (ctx == NULL) return GSS_S_UNAVAILABLE; - for (vector::const_iterator a = ctx->resCtx->getResolvedAttributes().begin(); - a != ctx->resCtx->getResolvedAttributes().end(); - ++a) { - for (vector::const_iterator s = (*a)->getAliases().begin(); - s != (*a)->getAliases().end(); - ++s) { - if (attr->length == strlen((*s).c_str()) && - memcmp((*s).c_str(), attr->value, attr->length) == 0) { - shibAttr = *a; - break; - } - } - if (shibAttr != NULL) - break; - } - - if (shibAttr == NULL) + if (!ctx->getAttribute(attr, authenticated, complete, + value, display_value, more)) return GSS_S_UNAVAILABLE; - if (*more == -1) { - *more = 0; - } else if (*more >= (int)shibAttr->valueCount()) { - *more = 0; - return GSS_S_COMPLETE; - } - - buf.value = (void *)shibAttr->getString(*more); - buf.length = strlen((char *)buf.value); - - major = duplicateBuffer(minor, &buf, value); - if (GSS_ERROR(major)) - return major; - - *authenticated = TRUE; - *complete = FALSE; - return GSS_S_COMPLETE; } -/* - * No plans to support gss_set_name_attribute at this time. - */ OM_uint32 samlSetAttribute(OM_uint32 *minor, struct eap_gss_saml_attr_ctx *ctx, @@ -416,7 +615,27 @@ samlSetAttribute(OM_uint32 *minor, gss_buffer_t attr, gss_buffer_t value) { - return GSS_S_UNAVAILABLE; + try { + ctx->setAttribute(complete, attr, value); + } catch (exception &e) { + return GSS_S_FAILURE; + } + + return GSS_S_COMPLETE; +} + +OM_uint32 +samlDeleteAttribute(OM_uint32 *minor, + struct eap_gss_saml_attr_ctx *ctx, + gss_buffer_t attr) +{ + try { + ctx->deleteAttribute(attr); + } catch (exception &e) { + return GSS_S_FAILURE; + } + + return GSS_S_COMPLETE; } /* @@ -428,7 +647,14 @@ samlExportAttrContext(OM_uint32 *minor, struct eap_gss_saml_attr_ctx *ctx, gss_buffer_t buffer) { - GSSEAP_NOT_IMPLEMENTED; + try { + if (!ctx->marshall(buffer)) + return GSS_S_FAILURE; + } catch (exception &e) { + return GSS_S_FAILURE; + } + + return GSS_S_COMPLETE; } /* @@ -438,7 +664,41 @@ samlExportAttrContext(OM_uint32 *minor, OM_uint32 samlImportAttrContext(OM_uint32 *minor, gss_buffer_t buffer, - struct eap_gss_saml_attr_ctx **ppCtx) + struct eap_gss_saml_attr_ctx **pCtx) { - GSSEAP_NOT_IMPLEMENTED; + try { + *pCtx = eap_gss_saml_attr_ctx::unmarshall(buffer); + } catch (exception &e) { + return GSS_S_FAILURE; + } + + return GSS_S_COMPLETE; +} + +OM_uint32 +samlGetAssertion(OM_uint32 *minor, + struct eap_gss_saml_attr_ctx *ctx, + gss_buffer_t assertion) +{ + try { + ctx->getAssertion(assertion); + } catch (exception &e) { + return GSS_S_FAILURE; + } + + return GSS_S_COMPLETE; +} + +OM_uint32 +samlDuplicateAttrContext(OM_uint32 *minor, + const struct eap_gss_saml_attr_ctx *in, + struct eap_gss_saml_attr_ctx **out) +{ + try { + *out = new eap_gss_saml_attr_ctx(*in); + } catch (exception &e) { + return GSS_S_FAILURE; + } + + return GSS_S_COMPLETE; } diff --git a/util_saml.h b/util_saml.h index 744618f..5cd0d9d 100644 --- a/util_saml.h +++ b/util_saml.h @@ -63,7 +63,7 @@ samlGetAttributeTypes(OM_uint32 *minor, OM_uint32 samlGetAttribute(OM_uint32 *minor, - const struct eap_gss_saml_attr_ctx *ctx, + struct eap_gss_saml_attr_ctx *ctx, gss_buffer_t attr, int *authenticated, int *complete, @@ -79,6 +79,11 @@ samlSetAttribute(OM_uint32 *minor, gss_buffer_t value); OM_uint32 +samlDeleteAttribute(OM_uint32 *minor, + struct eap_gss_saml_attr_ctx *ctx, + gss_buffer_t attr); + +OM_uint32 samlExportAttrContext(OM_uint32 *minor, struct eap_gss_saml_attr_ctx *ctx, gss_buffer_t buffer); @@ -88,6 +93,11 @@ samlImportAttrContext(OM_uint32 *minor, gss_buffer_t buffer, struct eap_gss_saml_attr_ctx **pCtx); +OM_uint32 +samlGetAssertion(OM_uint32 *minor, + struct eap_gss_saml_attr_ctx *ctx, + gss_buffer_t assertion); + #ifdef __cplusplus } #endif -- 2.1.4