X-Git-Url: http://www.project-moonshot.org/gitweb/?p=shibboleth%2Fcpp-opensaml.git;a=blobdiff_plain;f=saml%2Fbinding%2Fimpl%2FClientCertAuthRule.cpp;h=4f3a8841d84cf3267b702627c234c3d6e373d2f7;hp=63a6bb127bfab94df9e2ddce1b6642013c317b50;hb=1462057b3b9ae7e165d34d988e30b14c213672ca;hpb=b951e528ad7d0764ddc4ced037a8bd53bd3c9890 diff --git a/saml/binding/impl/ClientCertAuthRule.cpp b/saml/binding/impl/ClientCertAuthRule.cpp index 63a6bb1..4f3a884 100644 --- a/saml/binding/impl/ClientCertAuthRule.cpp +++ b/saml/binding/impl/ClientCertAuthRule.cpp @@ -1,117 +1,113 @@ -/* - * Copyright 2001-2006 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 +/** + * Licensed to the University Corporation for Advanced Internet + * Development, Inc. (UCAID) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. * - * http://www.apache.org/licenses/LICENSE-2.0 + * UCAID licenses this file to you 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 * - * 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. + * 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. */ /** * ClientCertAuthRule.cpp * - * XML Signature checking SecurityPolicyRule + * TLS client authentication SecurityPolicyRule. */ #include "internal.h" #include "exceptions.h" -#include "binding/ClientCertAuthRule.h" +#include "binding/SecurityPolicy.h" +#include "binding/SecurityPolicyRule.h" #include "saml2/metadata/Metadata.h" +#include "saml2/metadata/MetadataCredentialCriteria.h" #include "saml2/metadata/MetadataProvider.h" -#include "security/X509TrustEngine.h" -#include +#include +#include +#include +#include #include -#include using namespace opensaml::saml2md; using namespace opensaml; +using namespace xmltooling::logging; using namespace xmltooling; -using namespace log4cpp; using namespace std; namespace opensaml { + class SAML_DLLLOCAL ClientCertAuthRule : public SecurityPolicyRule + { + public: + ClientCertAuthRule(const DOMElement* e); + virtual ~ClientCertAuthRule() {} + + const char* getType() const { + return CLIENTCERTAUTH_POLICY_RULE; + } + bool evaluate(const XMLObject& message, const GenericRequest* request, SecurityPolicy& policy) const; + + private: + bool m_errorFatal; + }; + SecurityPolicyRule* SAML_DLLLOCAL ClientCertAuthRuleFactory(const DOMElement* const & e) { return new ClientCertAuthRule(e); } + + static const XMLCh errorFatal[] = UNICODE_LITERAL_10(e,r,r,o,r,F,a,t,a,l); }; -pair ClientCertAuthRule::evaluate( - const GenericRequest& request, - const XMLObject& message, - const MetadataProvider* metadataProvider, - const QName* role, - const opensaml::TrustEngine* trustEngine, - const MessageExtractor& extractor - ) const +ClientCertAuthRule::ClientCertAuthRule(const DOMElement* e) : m_errorFatal(XMLHelper::getAttrBool(e, false, errorFatal)) { - Category& log=Category::getInstance(SAML_LOGCAT".SecurityPolicyRule.ClientCertAuth"); - log.debug("evaluating client certificate authentication policy"); +} + +bool ClientCertAuthRule::evaluate(const XMLObject& message, const GenericRequest* request, SecurityPolicy& policy) const +{ + Category& log=Category::getInstance(SAML_LOGCAT ".SecurityPolicyRule.ClientCertAuth"); - pair ret = pair(NULL,NULL); + if (!request) + return false; - const opensaml::X509TrustEngine* x509trust; - if (!metadataProvider || !role || !(x509trust=dynamic_cast(trustEngine))) { - log.debug("ignoring message, no metadata or X509TrustEngine supplied"); - return ret; + if (!policy.getIssuerMetadata()) { + log.debug("ignoring message, no issuer metadata supplied"); + return false; } - - const std::vector& chain = request.getClientCertificates(); - if (chain.empty()) { - log.debug("ignoring message, no client certificates in request"); - return ret; + + const X509TrustEngine* x509trust; + if (!(x509trust=dynamic_cast(policy.getTrustEngine()))) { + log.debug("ignoring message, no X509TrustEngine supplied"); + return false; } - try { - log.debug("extracting issuer from message"); - pair issuerInfo = extractor.getIssuerAndProtocol(message); - - auto_ptr issuer(issuerInfo.first); - if (!issuerInfo.first || !issuerInfo.second || - (issuer->getFormat() && !XMLString::equals(issuer->getFormat(), saml2::NameIDType::ENTITY))) { - log.warn("issuer identity not estabished, or was not an entityID"); - return ret; - } - - log.debug("searching metadata for message issuer..."); - const EntityDescriptor* entity = metadataProvider->getEntityDescriptor(issuer->getName()); - if (!entity) { - auto_ptr_char temp(issuer->getName()); - log.warn("no metadata found, can't establish identity of issuer (%s)", temp.get()); - return ret; - } - - log.debug("matched message issuer against metadata, searching for applicable role..."); - const RoleDescriptor* roledesc=entity->getRoleDescriptor(*role, issuerInfo.second); - if (!roledesc) { - log.warn("unable to find compatible role (%s) in metadata", role->toString().c_str()); - return ret; - } - - if (!x509trust->validate(chain.front(), chain, *roledesc, true, metadataProvider->getKeyResolver())) { - log.error("unable to verify certificate chain with supplied trust engine"); - return ret; - } + const vector& chain = request->getClientCertificates(); + if (chain.empty()) + return false; + + // Set up criteria object, including peer name to enforce cert name checking. + MetadataCredentialCriteria cc(*(policy.getIssuerMetadata())); + auto_ptr_char pn(policy.getIssuer()->getName()); + cc.setPeerName(pn.get()); + cc.setUsage(Credential::TLS_CREDENTIAL); - if (log.isDebugEnabled()) { - auto_ptr_char iname(entity->getEntityID()); - log.debug("message from (%s), signature verified", iname.get()); - } - - ret.first = issuer.release(); - ret.second = roledesc; - } - catch (bad_cast&) { - // Just trap it. - log.warn("caught a bad_cast while extracting issuer"); + if (!x509trust->validate(chain.front(), chain, *(policy.getMetadataProvider()), &cc)) { + if (m_errorFatal) + throw SecurityPolicyException("Client certificate supplied, but could not be verified."); + log.error("unable to verify certificate chain with supplied trust engine"); + return false; } - return ret; + + log.debug("client certificate verified against message issuer"); + policy.setAuthenticated(true); + return true; }