From: Luke Howard Date: Sun, 12 Sep 2010 13:45:47 +0000 (+0200) Subject: Some work on SAML X-Git-Tag: vm/20110310~336 X-Git-Url: http://www.project-moonshot.org/gitweb/?p=mech_eap.git;a=commitdiff_plain;h=70b02ff081eff826695916c70e166b128769f4ca Some work on SAML --- diff --git a/Makefile.am b/Makefile.am index 7cbe203..e7886e8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,11 +4,15 @@ gssdir = $(libdir)/gss gss_LTLIBRARIES = libmech_eap.la -libmech_eap_la_CFLAGS = -DBUILD_GSSEAP_LIB -g -Wall -fno-strict-aliasing \ - @EAP_CFLAGS@ @KRB5_CFLAGS@ @TARGET_CFLAGS@ -libmech_eap_la_LDFLAGS = -export-symbols mech_eap.exports -version-info 0:0:0 \ - @EAP_LDFLAGS@ @KRB5_LDFLAGS@ @TARGET_LDFLAGS@ -libmech_eap_la_LIBADD = @EAP_LIBS@ @KRB5_LIBS@ +libmech_eap_la_CPPFLAGS = -DBUILD_GSSEAP_LIB +libmech_eap_la_CFLAGS = -g -Wall -fno-strict-aliasing \ + @EAP_CFLAGS@ @KRB5_CFLAGS@ @TARGET_CFLAGS@ +libmech_eap_la_CXXFLAGS = -g -Wall \ + @EAP_CFLAGS@ @KRB5_CFLAGS@ @SHIBSP_CXXFLAGS@ \ + @TARGET_CFLAGS@ +libmech_eap_la_LDFLAGS = -export-symbols mech_eap.exports -version-info 0:0:0 \ + @EAP_LDFLAGS@ @KRB5_LDFLAGS@ @TARGET_LDFLAGS@ +libmech_eap_la_LIBADD = @EAP_LIBS@ @KRB5_LIBS@ libmech_eap_la_SOURCES = \ accept_sec_context.c \ @@ -65,7 +69,7 @@ libmech_eap_la_SOURCES = \ util_oid.c \ util_ordering.c \ util_radius.c \ - util_saml.c \ + util_saml.cpp \ util_token.c \ verify_mic.c \ wrap.c \ diff --git a/acinclude.m4 b/acinclude.m4 index f91ab0d..7de99cc 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -102,3 +102,41 @@ else AC_SUBST(EAP_LIBS) fi ])dnl + +AC_DEFUN([AX_CHECK_SHIBSP], +[AC_MSG_CHECKING(for Shibboleth implementation) +SHIBSP_DIR= +found_shibsp="no" +AC_ARG_WITH(shibsp, + AC_HELP_STRING([--with-shibsp], + [Use shibspboleth (in specified installation directory)]), + [check_shibsp_dir="$withval"], + [check_shibsp_dir=]) +for dir in $check_shibsp_dir /usr /usr/local ; do + shibspdir="$dir" + if test -f "$dir/include/shibsp/SPConfig.h"; then + found_shibsp="yes"; + SHIBSP_DIR="${shibspdir}" + SHIBSP_CXXFLAGS="-I$shibspdir/include"; + break; + fi +done +AC_MSG_RESULT($found_shibsp) +if test x_$found_shibsp != x_yes; then + AC_MSG_ERROR([ +---------------------------------------------------------------------- + Cannot find Shibboleth/OpenSAML libraries. + + Please install Shibboleth or specify installation directory with + --with-shibsp=(dir). +---------------------------------------------------------------------- +]) +else + printf "Shibboleth found in $shibspdir\n"; + SHIBSP_LIBS="-lshibspsp -lsaml -lxml-security-c -lxmltooling -lxerces-c"; + SHIBSP_LDFLAGS="-L$shibspdir/lib"; + AC_SUBST(SHIBSP_CXXFLAGS) + AC_SUBST(SHIBSP_LDFLAGS) + AC_SUBST(SHIBSP_LIBS) +fi +])dnl diff --git a/configure.ac b/configure.ac index ee0ae6b..82bc27a 100644 --- a/configure.ac +++ b/configure.ac @@ -6,6 +6,7 @@ LT_PREREQ([2.2]) LT_INIT([dlopen disable-static]) AC_PROG_CC +AC_PROG_CXX dnl Check if we're on Solaris and set CFLAGS accordingly dnl AC_CANONICAL_TARGET @@ -28,5 +29,6 @@ AC_SUBST(TARGET_CFLAGS) AC_SUBST(TARGET_LDFLAGS) AX_CHECK_KRB5 AX_CHECK_EAP +AX_CHECK_SHIBSP AC_CONFIG_FILES([Makefile]) AC_OUTPUT diff --git a/duplicate_name.c b/duplicate_name.c index 6ad33a0..3f52acb 100644 --- a/duplicate_name.c +++ b/duplicate_name.c @@ -63,15 +63,16 @@ gss_duplicate_name(OM_uint32 *minor, goto cleanup; } - if (input_name->avps != NULL) { - major = radiusDuplicateAVPs(minor, input_name->avps, &name->avps); + if (input_name->radiusCtx != NULL) { + major = radiusDuplicateAttrContext(minor, input_name->radiusCtx, + &name->radiusCtx); if (GSS_ERROR(major)) goto cleanup; } - if (input_name->assertion != NULL) { - major = samlDuplicateAssertion(minor, input_name->assertion, - &name->assertion); + if (input_name->samlCtx != NULL) { + major = samlDuplicateAttrContext(minor, input_name->samlCtx, + &name->samlCtx); if (GSS_ERROR(major)) goto cleanup; } diff --git a/get_name_attribute.c b/get_name_attribute.c index 0987f15..e12dffb 100644 --- a/get_name_attribute.c +++ b/get_name_attribute.c @@ -68,17 +68,17 @@ gss_get_name_attribute(OM_uint32 *minor, type = gssEapAttributePrefixToType(&prefix); switch (type) { case ATTR_TYPE_SAML_AAA_ASSERTION: - major = samlExportAssertion(minor, name->assertion, value); + major = samlGetAssertion(minor, name->samlCtx, value); break; case ATTR_TYPE_SAML_ATTR: - major = samlGetAttribute(minor, name->assertion, &suffix, + major = samlGetAttribute(minor, name->samlCtx, &suffix, authenticated, complete, value, display_value, more); break; case ATTR_TYPE_RADIUS_AVP: - major = radiusGetAVP(minor, name->avps, &suffix, - authenticated, complete, - value, display_value, more); + major = radiusGetAttribute(minor, name->radiusCtx, &suffix, + authenticated, complete, + value, display_value, more); break; default: *minor = ENOENT; diff --git a/gssapiP_eap.h b/gssapiP_eap.h index 3a2dd80..db39ccf 100644 --- a/gssapiP_eap.h +++ b/gssapiP_eap.h @@ -46,6 +46,9 @@ #include "gssapi_eap.h" #include "util.h" +/* Kerberos includes */ +#include + /* EAP includes */ #include #include @@ -53,9 +56,6 @@ #include /* XXX testing implementation only */ #include -/* Kerberos includes */ -#include - #define NAME_FLAG_NAI 0x00000001 #define NAME_FLAG_SERVICE 0x00000002 #define NAME_FLAG_SAML 0x00000010 @@ -64,15 +64,15 @@ #define NAME_HAS_ATTRIBUTES(name) ((name)->flags & \ (NAME_FLAG_SAML | NAME_FLAG_RADIUS)) -struct eap_gss_saml_assertion; -struct eap_gss_avp_list; +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_assertion *assertion; - struct eap_gss_avp_list *avps; + 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 47f694b..6407cba 100644 --- a/inquire_name.c +++ b/inquire_name.c @@ -93,7 +93,7 @@ OM_uint32 gss_inquire_name(OM_uint32 *minor, args.attrs = *attrs; - if (name->assertion != NULL) { + if (name->samlCtx != NULL) { args.prefix = gssEapAttributeTypeToPrefix(ATTR_TYPE_SAML_AAA_ASSERTION); major = addAttribute(minor, &args, GSS_C_NO_BUFFER); @@ -101,14 +101,16 @@ OM_uint32 gss_inquire_name(OM_uint32 *minor, goto cleanup; args.prefix = gssEapAttributeTypeToPrefix(ATTR_TYPE_SAML_ATTR); - major = samlGetAttributeTypes(minor, name->assertion, &args, addAttribute); + major = samlGetAttributeTypes(minor, name->samlCtx, + &args, addAttribute); if (GSS_ERROR(major)) goto cleanup; } - if (name->avps != NULL) { + if (name->radiusCtx != NULL) { args.prefix = gssEapAttributeTypeToPrefix(ATTR_TYPE_RADIUS_AVP); - major = radiusGetAttributeTypes(minor, name->avps, &args, addAttribute); + major = radiusGetAttributeTypes(minor, name->radiusCtx, + &args, addAttribute); if (GSS_ERROR(major)) goto cleanup; } diff --git a/set_name_attribute.c b/set_name_attribute.c index c2b13c3..a8a4a56 100644 --- a/set_name_attribute.c +++ b/set_name_attribute.c @@ -57,12 +57,12 @@ gss_set_name_attribute(OM_uint32 *minor, type = gssEapAttributePrefixToType(&prefix); switch (type) { case ATTR_TYPE_SAML_ATTR: - major = samlSetAttribute(minor, name->assertion, + major = samlSetAttribute(minor, name->samlCtx, complete, &suffix, value); break; case ATTR_TYPE_RADIUS_AVP: - major = radiusSetAVP(minor, name->avps, - complete, &suffix, value); + major = radiusSetAttribute(minor, name->radiusCtx, + complete, &suffix, value); break; default: *minor = ENOENT; diff --git a/util.h b/util.h index ea0d820..bc88681 100644 --- a/util.h +++ b/util.h @@ -57,8 +57,15 @@ #ifndef _UTIL_H_ #define _UTIL_H_ 1 +#include +#include + #include +#ifdef __cplusplus +extern "C" { +#endif + #include "util_saml.h" #include "util_radius.h" @@ -504,4 +511,9 @@ store_oid(gss_OID oid, void *vp) return store_buffer(&buf, vp, FALSE); } + +#ifdef __cplusplus +} +#endif + #endif /* _UTIL_H_ */ diff --git a/util_name.c b/util_name.c index eef8ff5..8f25002 100644 --- a/util_name.c +++ b/util_name.c @@ -106,8 +106,8 @@ gssEapReleaseName(OM_uint32 *minor, gss_name_t *pName) GSSEAP_KRB_INIT(&krbContext); krb5_free_principal(krbContext, name->krbPrincipal); - radiusReleaseAVPs(&tmpMinor, &name->avps); - samlReleaseAssertion(&tmpMinor, &name->assertion); + radiusReleaseAttrContext(&tmpMinor, &name->radiusCtx); + samlReleaseAttrContext(&tmpMinor, &name->samlCtx); GSSEAP_MUTEX_DESTROY(&name->mutex); GSSEAP_FREE(name); diff --git a/util_radius.c b/util_radius.c index cb1934c..992350b 100644 --- a/util_radius.c +++ b/util_radius.c @@ -32,30 +32,30 @@ #include "gssapiP_eap.h" -struct eap_gss_avp_list { +struct eap_gss_radius_attr_ctx { }; OM_uint32 -radiusDuplicateAVPs(OM_uint32 *minor, - const struct eap_gss_avp_list *in, - struct eap_gss_avp_list **out) +radiusDuplicateAttrContext(OM_uint32 *minor, + const struct eap_gss_radius_attr_ctx *in, + struct eap_gss_radius_attr_ctx **out) { GSSEAP_NOT_IMPLEMENTED; } OM_uint32 -radiusReleaseAVPs(OM_uint32 *minor, - struct eap_gss_avp_list **avps) +radiusReleaseAttrContext(OM_uint32 *minor, + struct eap_gss_radius_attr_ctx **pCtx) { - if (*avps != NULL) { + if (*pCtx != NULL) { GSSEAP_NOT_IMPLEMENTED; - *avps = NULL; + *pCtx = NULL; } } OM_uint32 radiusGetAttributeTypes(OM_uint32 *minor, - const struct eap_gss_avp_list *avps, + const struct eap_gss_radius_attr_ctx *ctx, void *data, OM_uint32 (*addAttribute)(OM_uint32 *, void *, gss_buffer_t)) @@ -64,24 +64,24 @@ radiusGetAttributeTypes(OM_uint32 *minor, } OM_uint32 -radiusGetAVP(OM_uint32 *minor, - const struct eap_gss_avp_list *avps, - gss_buffer_t attr, - int *authenticated, - int *complete, - gss_buffer_t value, - gss_buffer_t display_value, - int *more) +radiusGetAttribute(OM_uint32 *minor, + const struct eap_gss_radius_attr_ctx *ctx, + gss_buffer_t attr, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) { GSSEAP_NOT_IMPLEMENTED; } OM_uint32 -radiusSetAVP(OM_uint32 *minor, - struct eap_gss_avp_list *avps, - int complete, - gss_buffer_t attr, - gss_buffer_t value) +radiusSetAttribute(OM_uint32 *minor, + struct eap_gss_radius_attr_ctx *ctx, + int complete, + gss_buffer_t attr, + gss_buffer_t value) { GSSEAP_NOT_IMPLEMENTED; } diff --git a/util_radius.h b/util_radius.h index 4f9a841..f789830 100644 --- a/util_radius.h +++ b/util_radius.h @@ -30,43 +30,41 @@ * SUCH DAMAGE. */ -#include "gssapiP_eap.h" - #ifndef _UTIL_RADIUS_H_ #define _UTIL_RADIUS_H_ 1 -struct eap_gss_avp_list; +struct eap_gss_radius_attr_ctx; OM_uint32 -radiusDuplicateAVPs(OM_uint32 *minor, - const struct eap_gss_avp_list *in, - struct eap_gss_avp_list **out); +radiusDuplicateAttrContext(OM_uint32 *minor, + const struct eap_gss_radius_attr_ctx *in, + struct eap_gss_radius_attr_ctx **out); OM_uint32 -radiusReleaseAVPs(OM_uint32 *minor, - struct eap_gss_avp_list **avps); +radiusReleaseAttrContext(OM_uint32 *minor, + struct eap_gss_radius_attr_ctx **ctx); OM_uint32 radiusGetAttributeTypes(OM_uint32 *minor, - const struct eap_gss_avp_list *assertion, + const struct eap_gss_radius_attr_ctx *ctx, void *data, OM_uint32 (*addAttribute)(OM_uint32 *, void *, gss_buffer_t)); OM_uint32 -radiusGetAVP(OM_uint32 *minor, - const struct eap_gss_avp_list *avps, - gss_buffer_t attr, - int *authenticated, - int *complete, - gss_buffer_t value, - gss_buffer_t display_value, - int *more); +radiusGetAttribute(OM_uint32 *minor, + const struct eap_gss_radius_attr_ctx *ctx, + gss_buffer_t attr, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more); OM_uint32 -radiusSetAVP(OM_uint32 *minor, - struct eap_gss_avp_list *avps, - int complete, - gss_buffer_t attr, - gss_buffer_t value); +radiusSetAttribute(OM_uint32 *minor, + struct eap_gss_radius_attr_ctx *ctx, + int complete, + gss_buffer_t attr, + gss_buffer_t value); #endif /* _UTIL_RADIUS_H_ */ diff --git a/util_saml.c b/util_saml.c deleted file mode 100644 index e86b232..0000000 --- a/util_saml.c +++ /dev/null @@ -1,99 +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" - -OM_uint32 -samlDuplicateAssertion(OM_uint32 *minor, - const struct eap_gss_saml_assertion *in, - struct eap_gss_saml_assertion **out) -{ - GSSEAP_NOT_IMPLEMENTED; -} - -OM_uint32 -samlReleaseAssertion(OM_uint32 *minor, - struct eap_gss_saml_assertion **assertion) -{ - if (*assertion != NULL) { - GSSEAP_NOT_IMPLEMENTED; - *assertion = NULL; - } -} - -OM_uint32 -samlImportAssertion(OM_uint32 *minor, - gss_buffer_t buffer, - struct eap_gss_saml_assertion *pAssertion) -{ - GSSEAP_NOT_IMPLEMENTED; -} - -OM_uint32 -samlExportAssertion(OM_uint32 *minor, - struct eap_gss_saml_assertion *assertion, - gss_buffer_t buffer) -{ - GSSEAP_NOT_IMPLEMENTED; -} - -OM_uint32 -samlGetAttributeTypes(OM_uint32 *minor, - const struct eap_gss_saml_assertion *assertion, - void *data, - OM_uint32 (*addAttribute)(OM_uint32 *, void *, gss_buffer_t)) -{ - GSSEAP_NOT_IMPLEMENTED; -} - -OM_uint32 -samlGetAttribute(OM_uint32 *minor, - const struct eap_gss_saml_assertion *assertion, - gss_buffer_t attr, - int *authenticated, - int *complete, - gss_buffer_t value, - gss_buffer_t display_value, - int *more) -{ - GSSEAP_NOT_IMPLEMENTED; -} - -OM_uint32 -samlSetAttribute(OM_uint32 *minor, - struct eap_gss_saml_assertion *assertion, - int complete, - gss_buffer_t attr, - gss_buffer_t value) -{ - GSSEAP_NOT_IMPLEMENTED; -} diff --git a/util_saml.cpp b/util_saml.cpp new file mode 100644 index 0000000..6256579 --- /dev/null +++ b/util_saml.cpp @@ -0,0 +1,451 @@ +/* + * 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 +#include +#include "util.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace shibsp; +using namespace opensaml::saml2md; +using namespace opensaml; +using namespace xmltooling::logging; +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."); + } +}; + +class SHIBSP_DLLLOCAL DummyContext : public ResolutionContext +{ +public: + DummyContext(const vector& attributes) : m_attributes(attributes) { + } + + virtual ~DummyContext() { + for_each(m_attributes.begin(), m_attributes.end(), xmltooling::cleanup()); + } + + vector& getResolvedAttributes() { + return m_attributes; + } + vector& getResolvedAssertions() { + return m_tokens; + } + +private: + vector m_attributes; + static vector m_tokens; // never any tokens, so just share an empty vector +}; + +struct eap_gss_saml_attr_ctx { + ResolutionContext *resCtx; + gss_buffer_desc assertion; +}; + +static OM_uint32 +samlAllocAttrContext(OM_uint32 *minor, + struct eap_gss_saml_attr_ctx **pCtx) +{ + struct eap_gss_saml_attr_ctx *ctx; + + ctx = (struct eap_gss_saml_attr_ctx *)GSSEAP_CALLOC(1, sizeof(*ctx)); + if (ctx == NULL) { + *minor = ENOMEM; + return GSS_S_FAILURE; + } + + *pCtx = ctx; + *minor = 0; + return GSS_S_COMPLETE; +} + +static OM_uint32 +samlImportAssertion(OM_uint32 *minor, + gss_buffer_t buffer, + saml2::Assertion **pAssertion) +{ + *pAssertion = NULL; + + 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; + } + } catch (exception &e){ + /* TODO minor_status */ + return GSS_S_BAD_NAME; + } + + *minor = 0; + 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) +{ + OM_uint32 major, tmpMinor; + struct eap_gss_saml_attr_ctx *ctx; + + major = samlAllocAttrContext(minor, &ctx); + if (GSS_ERROR(major)) + goto cleanup; + + major = duplicateBuffer(minor, (gss_buffer_t)&in->assertion, &ctx->assertion); + if (GSS_ERROR(major)) + goto cleanup; + + ctx->resCtx = new DummyContext(in->resCtx->getResolvedAttributes()); + +cleanup: + if (GSS_ERROR(major)) + samlReleaseAttrContext(&tmpMinor, &ctx); + + return major; +} + +OM_uint32 +samlReleaseAttrContext(OM_uint32 *minor, + struct eap_gss_saml_attr_ctx **pCtx) +{ + struct eap_gss_saml_attr_ctx *ctx = *pCtx; + + if (ctx != NULL) { + delete ctx->resCtx; + gss_release_buffer(minor, &ctx->assertion); + GSSEAP_FREE(ctx); + *pCtx = NULL; + } + + *minor = 0; + 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) +{ + OM_uint32 major, tmpMinor; + struct eap_gss_saml_attr_ctx *ctx; + 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; + + 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()) + 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; + } + + major = samlAllocAttrContext(minor, &ctx); + if (GSS_ERROR(major)) + goto cleanup; + + major = duplicateBuffer(minor, buffer, &ctx->assertion); + if (GSS_ERROR(major)) + goto cleanup; + + major = samlImportAssertion(minor, &ctx->assertion, &assertion); + if (GSS_ERROR(major)) + goto cleanup; + + 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, + &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())); + } + 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); + } catch (exception &ex) { + major = GSS_S_BAD_NAME; + goto cleanup; + } + + major = GSS_S_COMPLETE; + *pCtx = ctx; + +cleanup: + sp->unlock(); + conf.term(); + + if (GSS_ERROR(major)) + samlReleaseAttrContext(&tmpMinor, &ctx); + gss_release_buffer(&tmpMinor, &nameBuf); + + 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)) +{ + OM_uint32 major = GSS_S_COMPLETE; + + if (ctx == NULL) + return GSS_S_COMPLETE; + + for (vector::const_iterator a = ctx->resCtx->getResolvedAttributes().begin(); + a != ctx->resCtx->getResolvedAttributes().end(); + ++a) + { + gss_buffer_desc attribute; + + attribute.value = (void *)((*a)->getId()); + attribute.length = strlen((char *)attribute.value); + + major = addAttribute(minor, data, &attribute); + if (GSS_ERROR(major)) + break; + } + + return major; +} + +OM_uint32 +samlGetAttribute(OM_uint32 *minor, + const struct eap_gss_saml_attr_ctx *ctx, + gss_buffer_t attr, + int *authenticated, + int *complete, + gss_buffer_t value, + 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) + 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; +} + +OM_uint32 +samlSetAttribute(OM_uint32 *minor, + struct eap_gss_saml_attr_ctx *ctx, + int complete, + gss_buffer_t attr, + gss_buffer_t value) +{ + return GSS_S_UNAVAILABLE; +} + +OM_uint32 +samlGetAssertion(OM_uint32 *minor, + struct eap_gss_saml_attr_ctx *ctx, + gss_buffer_t buffer) +{ + if (ctx == NULL) + return GSS_S_UNAVAILABLE; + + return duplicateBuffer(minor, &ctx->assertion, buffer); +} + +OM_uint32 +samlExportAttrContext(OM_uint32 *minor, + struct eap_gss_saml_attr_ctx *ctx, + gss_buffer_t buffer) +{ + GSSEAP_NOT_IMPLEMENTED; +} + +OM_uint32 +samlImportAttrContext(OM_uint32 *minor, + gss_buffer_t buffer, + struct eap_gss_saml_attr_ctx **ppCtx) +{ + GSSEAP_NOT_IMPLEMENTED; +} diff --git a/util_saml.h b/util_saml.h index 300f822..1115eb5 100644 --- a/util_saml.h +++ b/util_saml.h @@ -30,41 +30,40 @@ * SUCH DAMAGE. */ -#include "gssapiP_eap.h" - #ifndef _UTIL_SAML_H_ #define _UTIL_SAML_H_ 1 -struct eap_gss_saml_assertion; +#ifdef __cplusplus +extern "C" { +#endif -OM_uint32 -samlDuplicateAssertion(OM_uint32 *minor, - const struct eap_gss_saml_assertion *in, - struct eap_gss_saml_assertion **out); +struct eap_gss_saml_attr_ctx; OM_uint32 -samlImportAssertion(OM_uint32 *minor, - gss_buffer_t buffer, - struct eap_gss_saml_assertion *pAssertion); +samlDuplicateAttrContext(OM_uint32 *minor, + const struct eap_gss_saml_attr_ctx *in, + struct eap_gss_saml_attr_ctx **out); OM_uint32 -samlExportAssertion(OM_uint32 *minor, - struct eap_gss_saml_assertion *assertion, - gss_buffer_t buffer); +samlCreateAttrContext(OM_uint32 *minor, + gss_cred_id_t acceptorCred, + gss_name_t initiatorName, + gss_buffer_t buffer, + struct eap_gss_saml_attr_ctx **pCtx); OM_uint32 -samlReleaseAssertion(OM_uint32 *minor, - struct eap_gss_saml_assertion **assertion); +samlReleaseAttrContext(OM_uint32 *minor, + struct eap_gss_saml_attr_ctx **ctx); OM_uint32 samlGetAttributeTypes(OM_uint32 *minor, - const struct eap_gss_saml_assertion *assertion, + const struct eap_gss_saml_attr_ctx *ctx, void *data, OM_uint32 (*addAttribute)(OM_uint32 *, void *, gss_buffer_t)); OM_uint32 samlGetAttribute(OM_uint32 *minor, - const struct eap_gss_saml_assertion *assertion, + const struct eap_gss_saml_attr_ctx *ctx, gss_buffer_t attr, int *authenticated, int *complete, @@ -74,9 +73,28 @@ samlGetAttribute(OM_uint32 *minor, OM_uint32 samlSetAttribute(OM_uint32 *minor, - struct eap_gss_saml_assertion *assertion, + struct eap_gss_saml_attr_ctx *ctx, int complete, gss_buffer_t attr, gss_buffer_t value); +OM_uint32 +samlGetAssertion(OM_uint32 *minor, + struct eap_gss_saml_attr_ctx *ctx, + gss_buffer_t buffer); + +OM_uint32 +samlExportAttrContext(OM_uint32 *minor, + struct eap_gss_saml_attr_ctx *ctx, + gss_buffer_t buffer); + +OM_uint32 +samlImportAttrContext(OM_uint32 *minor, + gss_buffer_t buffer, + struct eap_gss_saml_attr_ctx **pCtx); + +#ifdef __cplusplus +} +#endif + #endif /* _UTIL_SAML_H_ */