X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=util_saml.cpp;h=b859d9b91f8479c6c07bf817e281790fb5bc5adc;hb=81378d116795fa8a7a56dc8e00c3b2666126682d;hp=dcd7ae315ee9d9d400af406aeed2c6a62da9d2b6;hpb=5897d9020b79c771072b3fd397f2e274aacf9537;p=mech_eap.git diff --git a/util_saml.cpp b/util_saml.cpp index dcd7ae3..b859d9b 100644 --- a/util_saml.cpp +++ b/util_saml.cpp @@ -29,403 +29,394 @@ * 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 "gssapiP_eap.h" + +#include + #include -#include +#include #include -using namespace shibsp; +#include +#include +#include + +using namespace xmltooling; 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 +class auto_ptr_gss_buffer { + MAKE_NONCOPYABLE(auto_ptr_gss_buffer); + public: + auto_ptr_gss_buffer() : m_buf(NULL) { + } + auto_ptr_gss_buffer(const gss_buffer_t src) { + m_buf = new XMLCh[src->length + 1]; + XMLString::transcode((const char *)src->value, m_buf, src->length); + } + ~auto_ptr_gss_buffer() { + xercesc::XMLString::release(&m_buf); + } + const XMLCh* get() const { + return m_buf; + } + XMLCh* release() { + XMLCh *temp = m_buf; m_buf = NULL; return temp; + } + private: + XMLCh *m_buf; +}; + +/* + * gss_eap_saml_assertion_provider is for retrieving the underlying + * assertion. + */ +gss_eap_saml_assertion_provider::gss_eap_saml_assertion_provider(const gss_eap_attr_ctx *ctx, + gss_cred_id_t gssCred, + gss_ctx_id_t gssCtx) + : gss_eap_attr_provider(ctx, gssCred, gssCtx) { -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 - ); + if (gssCtx == GSS_C_NO_CONTEXT) { + /* Then we are creating from an existing attribute context */ + gss_eap_saml_assertion_provider *saml; + + saml = dynamic_cast + (ctx->getProvider(ATTR_TYPE_SAML_ASSERTION)); + if (saml != NULL) + setAssertion(saml->getAssertion()); + } else { + gss_eap_radius_attr_provider *radius; + gss_buffer_desc value = GSS_C_EMPTY_BUFFER; + int authenticated, complete, more = -1; + OM_uint32 minor; + + radius = dynamic_cast + (ctx->getProvider(ATTR_TYPE_RADIUS)); + if (radius != NULL && + radius->getAttribute(512, &authenticated, &complete, + &value, NULL, &more)) { + m_assertion = parseAssertion(&value); + gss_release_buffer(&minor, &value); + } } +} -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."); - } -}; +gss_eap_saml_assertion_provider::~gss_eap_saml_assertion_provider(void) +{ + delete m_assertion; +} -class SHIBSP_DLLLOCAL DummyContext : public ResolutionContext +void +gss_eap_saml_assertion_provider::setAssertion(const saml2::Assertion *assertion) { -public: - DummyContext(const vector& attributes) : m_attributes(attributes) { - } - virtual ~DummyContext() { - for_each(m_attributes.begin(), m_attributes.end(), xmltooling::cleanup()); - } + delete m_assertion; + m_assertion = dynamic_cast(assertion->clone()); +} - vector& getResolvedAttributes() { - return m_attributes; - } - vector& getResolvedAssertions() { - return m_tokens; - } +saml2::Assertion * +gss_eap_saml_assertion_provider::parseAssertion(const gss_buffer_t buffer) +{ + string str((char *)buffer->value, buffer->length); + istringstream istream(str); + DOMDocument *doc; + const XMLObjectBuilder *b; -private: - vector m_attributes; - static vector m_tokens; // never any tokens, so just share an empty vector -}; + doc = XMLToolingConfig::getConfig().getParser().parse(istream); + b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); -struct eap_gss_saml_attr_ctx { - ResolutionContext *resCtx; - gss_buffer_desc assertion; -}; + return dynamic_cast(b->buildFromDocument(doc)); +} -static OM_uint32 -samlAllocAttrContext(OM_uint32 *minor, - struct eap_gss_saml_attr_ctx **pCtx) +bool +gss_eap_saml_assertion_provider::getAttributeTypes(gss_eap_attr_enumeration_cb addAttribute, void *data) const { - struct eap_gss_saml_attr_ctx *ctx; + addAttribute(this, GSS_C_NO_BUFFER, data); +} - ctx = (struct eap_gss_saml_attr_ctx *)GSSEAP_CALLOC(1, sizeof(*ctx)); - if (ctx == NULL) { - *minor = ENOMEM; - return GSS_S_FAILURE; - } +void +gss_eap_saml_assertion_provider::setAttribute(int complete, + const gss_buffer_t attr, + const gss_buffer_t value) +{ + saml2::Assertion *assertion = parseAssertion(value); - *pCtx = ctx; - *minor = 0; - return GSS_S_COMPLETE; + m_assertion = assertion; } -static OM_uint32 -samlImportAssertion(OM_uint32 *minor, - gss_buffer_t buffer, - saml2::Assertion **pAssertion) +void +gss_eap_saml_assertion_provider::deleteAttribute(const gss_buffer_t value) { - *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; + delete m_assertion; + m_assertion = NULL; +} + +bool +gss_eap_saml_assertion_provider::getAttribute(const gss_buffer_t attr, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) const +{ + string str; + + if (attr->length != 0 || m_assertion == NULL) + return false; + + if (*more == -1) + *more = 0; + + if (*more == 0) { + *authenticated = true; + *complete = false; + + XMLHelper::serialize(m_assertion->marshall((DOMDocument *)NULL), str); + + duplicateBuffer(str, value); } - *minor = 0; - return GSS_S_COMPLETE; + return true; +} + +gss_any_t +gss_eap_saml_assertion_provider::mapToAny(int authenticated, + gss_buffer_t type_id) const +{ + return (gss_any_t)m_assertion; +} + +void +gss_eap_saml_assertion_provider::releaseAnyNameMapping(gss_buffer_t type_id, + gss_any_t input) const +{ + delete ((saml2::Assertion *)input); } -OM_uint32 -samlDuplicateAttrContext(OM_uint32 *minor, - const struct eap_gss_saml_attr_ctx *in, - struct eap_gss_saml_attr_ctx **out) +void +gss_eap_saml_assertion_provider::marshall(gss_buffer_t buffer) const { - OM_uint32 major, tmpMinor; - struct eap_gss_saml_attr_ctx *ctx; + ostringstream sink; + string str; - major = samlAllocAttrContext(minor, &ctx); - if (GSS_ERROR(major)) - goto cleanup; + buffer->length = 0; + buffer->value = NULL; - ctx->resCtx = new DummyContext(in->resCtx->getResolvedAttributes()); + if (m_assertion == NULL) + return; -cleanup: - if (GSS_ERROR(major)) - samlReleaseAttrContext(&tmpMinor, &ctx); + sink << *m_assertion; + str = sink.str(); - return major; + duplicateBuffer(str, buffer); } -OM_uint32 -samlReleaseAttrContext(OM_uint32 *minor, - struct eap_gss_saml_attr_ctx **pCtx) +gss_eap_attr_provider * +gss_eap_saml_assertion_provider::unmarshall(const gss_eap_attr_ctx *ctx, + const gss_buffer_t buffer) { - struct eap_gss_saml_attr_ctx *ctx = *pCtx; - - if (ctx != NULL) { - delete ctx->resCtx; - GSSEAP_FREE(ctx); - *pCtx = NULL; - } + return new gss_eap_saml_assertion_provider(ctx, buffer); +} - *minor = 0; - return GSS_S_COMPLETE; +bool +gss_eap_saml_assertion_provider::init(void) +{ } -OM_uint32 -samlCreateAttrContext(OM_uint32 *minor, - gss_buffer_t buffer, - gss_name_t acceptorName, - struct eap_gss_saml_attr_ctx **pCtx) +void +gss_eap_saml_assertion_provider::finalize(void) { - 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 = samlImportAssertion(minor, buffer, &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; - } +gss_eap_attr_provider * +gss_eap_saml_assertion_provider::createAttrContext(const gss_eap_attr_ctx *ctx, + gss_cred_id_t gssCred, + gss_ctx_id_t gssCtx) +{ + return new gss_eap_saml_assertion_provider(ctx, gssCred, gssCtx); +} - major = GSS_S_COMPLETE; - *pCtx = ctx; +/* + * gss_eap_saml_attr_provider is for retrieving the underlying attributes. + */ +const saml2::Assertion * +gss_eap_saml_attr_provider::getAssertion(void) const +{ + gss_eap_saml_assertion_provider *saml; + + saml = dynamic_cast(m_source->getProvider(ATTR_TYPE_SAML_ASSERTION)); + assert(saml != NULL); -cleanup: - sp->unlock(); - conf.term(); + return saml->getAssertion(); +} - if (GSS_ERROR(major)) - samlReleaseAttrContext(&tmpMinor, &ctx); - gss_release_buffer(&tmpMinor, &nameBuf); +gss_eap_saml_attr_provider::gss_eap_saml_attr_provider(const gss_eap_attr_ctx *ctx, + gss_cred_id_t gssCred, + gss_ctx_id_t gssCtx) + : gss_eap_attr_provider(ctx, gssCred, gssCtx) +{ + /* Nothing to do, we're just a wrapper around the assertion provider. */ +} - return major; +gss_eap_saml_attr_provider::~gss_eap_saml_attr_provider(void) +{ + /* Nothing to do, we're just a wrapper around the assertion provider. */ } -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)) +bool +gss_eap_saml_attr_provider::getAttributeTypes(gss_eap_attr_enumeration_cb addAttribute, + void *data) const { - OM_uint32 major = GSS_S_COMPLETE; + const saml2::Assertion *assertion = getAssertion(); - if (ctx == NULL) - return GSS_S_COMPLETE; + if (assertion == NULL) + return true; - for (vector::const_iterator a = ctx->resCtx->getResolvedAttributes().begin(); - a != ctx->resCtx->getResolvedAttributes().end(); + const vector& attrs2 = + const_cast(assertion->getAttributeStatements().front())->getAttributes(); + for (vector::const_iterator a = attrs2.begin(); + a != attrs2.end(); ++a) { gss_buffer_desc attribute; - attribute.value = (void *)((*a)->getId()); + attribute.value = (void *)toUTF8((*a)->getName(), true); attribute.length = strlen((char *)attribute.value); - major = addAttribute(minor, data, &attribute); - if (GSS_ERROR(major)) - break; + if (!addAttribute(this, &attribute, data)) + return false; + + delete (char *)attribute.value; } - return major; + return true; } -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) +void +gss_eap_saml_attr_provider::setAttribute(int complete, + const gss_buffer_t attr, + const gss_buffer_t value) { - 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; +void +gss_eap_saml_attr_provider::deleteAttribute(const gss_buffer_t value) +{ +} - if (*more == -1) { - *more = 0; - } else if (*more >= (int)shibAttr->valueCount()) { - *more = 0; - return GSS_S_COMPLETE; +const saml2::Attribute * +gss_eap_saml_attr_provider::getAttribute(const gss_buffer_t attr) const +{ + const saml2::Assertion *assertion = getAssertion(); + saml2::AttributeStatement *statement; + + if (assertion == NULL) + return NULL; + + if (assertion->getAttributeStatements().size() == 0) + return NULL; + + statement = assertion->getAttributeStatements().front(); + + auto_ptr_gss_buffer attrname(attr); + + const vector& attrs2 = + const_cast(statement)->getAttributes(); + + for (vector::const_iterator a = attrs2.begin(); + a != attrs2.end(); + ++a) { + if (XMLString::equals((*a)->getName(), attrname.get())) + return *a; } - buf.value = (void *)shibAttr->getString(*more); - buf.length = strlen((char *)buf.value); + return NULL; +} + +bool +gss_eap_saml_attr_provider::getAttribute(const gss_buffer_t attr, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) const +{ + const saml2::Attribute *a; + const saml2::AttributeValue *av; + int nvalues, i = *more; + + *more = 0; + + a = getAttribute(attr); + if (a == NULL) + return false; + + nvalues = a->getAttributeValues().size(); + + if (i == -1) + i = 0; + else if (i >= nvalues) + return false; + av = dynamic_cast(a->getAttributeValues().at(i) +); + if (av == NULL) + return false; - major = duplicateBuffer(minor, &buf, value); - if (GSS_ERROR(major)) - return major; - *authenticated = TRUE; *complete = FALSE; - return GSS_S_COMPLETE; + value->value = toUTF8(av->getTextContent(), true); + value->length = strlen((char *)value->value); + + if (nvalues > ++i) + *more = i; + + return true; +} + +gss_any_t +gss_eap_saml_attr_provider::mapToAny(int authenticated, + gss_buffer_t type_id) const +{ + return (gss_any_t)0; +} + +void +gss_eap_saml_attr_provider::releaseAnyNameMapping(gss_buffer_t type_id, + gss_any_t input) const +{ +} + +void +gss_eap_saml_attr_provider::marshall(gss_buffer_t buffer) const +{ +} + +gss_eap_attr_provider * +gss_eap_saml_attr_provider::unmarshall(const gss_eap_attr_ctx *ctx, + const gss_buffer_t buffer) +{ + return new gss_eap_saml_attr_provider(ctx); } -OM_uint32 -samlSetAttribute(OM_uint32 *minor, - struct eap_gss_saml_attr_ctx *ctx, - int complete, - gss_buffer_t attr, - gss_buffer_t value) +bool +gss_eap_saml_attr_provider::init(void) { - return GSS_S_UNAVAILABLE; + return true; } -OM_uint32 -samlExportAttrContext(OM_uint32 *minor, - struct eap_gss_saml_attr_ctx *ctx, - gss_buffer_t buffer) +void +gss_eap_saml_attr_provider::finalize(void) { - GSSEAP_NOT_IMPLEMENTED; } -OM_uint32 -samlImportAttrContext(OM_uint32 *minor, - gss_buffer_t buffer, - struct eap_gss_saml_attr_ctx **ppCtx) +gss_eap_attr_provider * +gss_eap_saml_attr_provider::createAttrContext(const gss_eap_attr_ctx *ctx, + gss_cred_id_t gssCred, + gss_ctx_id_t gssCtx) { - GSSEAP_NOT_IMPLEMENTED; + return new gss_eap_saml_attr_provider(ctx, gssCred, gssCtx); }