-/*
- * Copyright 2001-2010 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.
+ *
+ * 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
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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.
+ * 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.
*/
/**
X509* EE,
STACK_OF(X509)* untrusted,
AbstractPKIXTrustEngine::PKIXValidationInfoIterator* pkixInfo,
- bool useCRL,
+ bool useCRL,
bool fullCRLChain,
- const vector<XSECCryptoX509CRL*>* inlineCRLs=nullptr
+ const vector<XSECCryptoX509CRL*>* inlineCRLs=nullptr,
+ bool policyMappingInhibit=false,
+ bool anyPolicyInhibit=false,
+ const set<string>* policyOIDs=nullptr
)
{
Category& log=Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine");
log_openssl();
return false;
}
+
+ // PKIX policy checking (cf. RFCs 3280/5280 section 6)
+ if (policyMappingInhibit || anyPolicyInhibit || (policyOIDs && !policyOIDs->empty())) {
+#if (OPENSSL_VERSION_NUMBER < 0x00908000L)
+ log.error("PKIX policy checking option is configured, but OpenSSL version is less than 0.9.8");
+ X509_STORE_free(store);
+ return false;
+#else
+ unsigned long pflags = 0;
+ X509_VERIFY_PARAM *vpm = X509_VERIFY_PARAM_new();
+ if (!vpm) {
+ log_openssl();
+ X509_STORE_free(store);
+ return false;
+ }
+
+ // populate the "user-initial-policy-set" input variable
+ if (policyOIDs && !policyOIDs->empty()) {
+ for (set<string>::const_iterator o=policyOIDs->begin(); o!=policyOIDs->end(); o++) {
+ ASN1_OBJECT *oid = OBJ_txt2obj(o->c_str(), 1);
+ if (oid && X509_VERIFY_PARAM_add0_policy(vpm, oid)) {
+ log.debug("OID (%s) added to set of acceptable policies", o->c_str());
+ }
+ else {
+ log_openssl();
+ log.error("unable to parse/configure policy OID value (%s)", o->c_str());
+ if (oid)
+ ASN1_OBJECT_free(oid);
+ X509_VERIFY_PARAM_free(vpm);
+ X509_STORE_free(store);
+ return false;
+ }
+ }
+ // when the user has supplied at least one policy OID, he obviously wants to check
+ // for an explicit policy ("initial-explicit-policy")
+ pflags |= X509_V_FLAG_EXPLICIT_POLICY;
+ }
+
+ // "initial-policy-mapping-inhibit" input variable
+ if (policyMappingInhibit)
+ pflags |= X509_V_FLAG_INHIBIT_MAP;
+ // "initial-any-policy-inhibit" input variable
+ if (anyPolicyInhibit)
+ pflags |= X509_V_FLAG_INHIBIT_ANY;
+
+ if (!X509_VERIFY_PARAM_set_flags(vpm, pflags) || !X509_STORE_set1_param(store, vpm)) {
+ log_openssl();
+ log.error("unable to set PKIX policy checking parameters");
+ X509_VERIFY_PARAM_free(vpm);
+ X509_STORE_free(store);
+ return false;
+ }
+
+ X509_VERIFY_PARAM_free(vpm);
+#endif
+ }
// This contains the state of the validate operation.
int count=0;
const char* cdpuri = (const char*)gen->d.ia5->data;
auto_ptr<XSECCryptoX509CRL> crl(getRemoteCRLs(cdpuri, log));
if (crl.get() && crl->getProviderName()==DSIGConstants::s_unicodeStrPROVOpenSSL &&
- (isFreshCRL(crl.get()) || (ii == sk_DIST_POINT_num(dps) && iii == sk_GENERAL_NAME_num(dp->distpoint->name.fullname)))) {
+ (isFreshCRL(crl.get()) || (ii == sk_DIST_POINT_num(dps)-1 && iii == sk_GENERAL_NAME_num(dp->distpoint->name.fullname)-1))) {
// owned by store
X509_STORE_add_crl(store, X509_CRL_dup(static_cast<OpenSSLCryptoX509CRL*>(crl.get())->getOpenSSLX509CRL()));
log.debug("added CRL issued by (%s)", crlissuer.c_str());
sk_DIST_POINT_free(dps);
}
- if (!crlissuers.empty()) {
- X509_STORE_set_flags(store, fullCRLChain ? (X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL) : (X509_V_FLAG_CRL_CHECK));
- }
- else {
- log.warn("CRL checking is enabled, but none were supplied");
- X509_STORE_CTX_cleanup(&ctx);
- X509_STORE_free(store);
- sk_X509_free(CAstack);
- return false;
- }
-#else
- log.warn("CRL checking is enabled, but OpenSSL version is too old");
- X509_STORE_CTX_cleanup(&ctx);
- X509_STORE_free(store);
- sk_X509_free(CAstack);
- return false;
-#endif
// Do a second pass verify with CRLs in place.
+ X509_STORE_CTX_set_flags(&ctx, fullCRLChain ? (X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL) : (X509_V_FLAG_CRL_CHECK));
ret=X509_verify_cert(&ctx);
+#else
+ log.warn("CRL checking is enabled, but OpenSSL version is too old");
+ ret = 0;
+#endif
}
// Clean up...
return false;
}
- static XMLCh fullCRLChain[] = UNICODE_LITERAL_12(f,u,l,l,C,R,L,C,h,a,i,n);
- static XMLCh checkRevocation[] = UNICODE_LITERAL_15(c,h,e,c,k,R,e,v,o,c,a,t,i,o,n);
+ static XMLCh fullCRLChain[] = UNICODE_LITERAL_12(f,u,l,l,C,R,L,C,h,a,i,n);
+ static XMLCh checkRevocation[] = UNICODE_LITERAL_15(c,h,e,c,k,R,e,v,o,c,a,t,i,o,n);
+ static XMLCh policyMappingInhibit[] = UNICODE_LITERAL_20(p,o,l,i,c,y,M,a,p,p,i,n,g,I,n,h,i,b,i,t);
+ static XMLCh anyPolicyInhibit[] = UNICODE_LITERAL_16(a,n,y,P,o,l,i,c,y,I,n,h,i,b,i,t);
+ static XMLCh PolicyOID[] = UNICODE_LITERAL_9(P,o,l,i,c,y,O,I,D);
+ static XMLCh TrustedName[] = UNICODE_LITERAL_11(T,r,u,s,t,e,d,N,a,m,e);
};
AbstractPKIXTrustEngine::PKIXValidationInfoIterator::PKIXValidationInfoIterator()
AbstractPKIXTrustEngine::AbstractPKIXTrustEngine(const xercesc::DOMElement* e)
: TrustEngine(e),
+ m_checkRevocation(XMLHelper::getAttrString(e, nullptr, checkRevocation)),
m_fullCRLChain(XMLHelper::getAttrBool(e, false, fullCRLChain)),
- m_checkRevocation(XMLHelper::getAttrString(e, nullptr, checkRevocation))
+ m_policyMappingInhibit(XMLHelper::getAttrBool(e, false, policyMappingInhibit)),
+ m_anyPolicyInhibit(XMLHelper::getAttrBool(e, false, anyPolicyInhibit))
{
if (m_fullCRLChain) {
Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine.PKIX").warn(
else if (m_checkRevocation == "fullChain") {
m_fullCRLChain = true; // in case anything's using this
}
+
+ xercesc::DOMElement* c = XMLHelper::getFirstChildElement(e);
+ while (c) {
+ if (c->hasChildNodes()) {
+ auto_ptr_char v(c->getTextContent());
+ if (v.get() && *v.get()) {
+ if (XMLString::equals(c->getLocalName(), PolicyOID))
+ m_policyOIDs.insert(v.get());
+ else if (XMLString::equals(c->getLocalName(), TrustedName))
+ m_trustedNames.insert(v.get());
+ }
+ }
+ c = XMLHelper::getNextSiblingElement(c);
+ }
}
AbstractPKIXTrustEngine::~AbstractPKIXTrustEngine()
credResolver.resolve(creds,&criteria);
// Build a list of acceptable names.
- set<string> trustednames;
- trustednames.insert(criteria.getPeerName());
- for (vector<const Credential*>::const_iterator cred = creds.begin(); cred!=creds.end(); ++cred)
+ set<string> trustednames = m_trustedNames;
+ if (log.isDebugEnabled()) {
+ for (set<string>::const_iterator n=m_trustedNames.begin(); n!=m_trustedNames.end(); n++) {
+ log.debug("adding to list of trusted names (%s)", n->c_str());
+ }
+ }
+ if (criteria.getPeerName()) {
+ trustednames.insert(criteria.getPeerName());
+ log.debug("adding to list of trusted names (%s)", criteria.getPeerName());
+ }
+ for (vector<const Credential*>::const_iterator cred = creds.begin(); cred!=creds.end(); ++cred) {
trustednames.insert((*cred)->getKeyNames().begin(), (*cred)->getKeyNames().end());
+ if (log.isDebugEnabled()) {
+ for (set<string>::const_iterator n=(*cred)->getKeyNames().begin(); n!=(*cred)->getKeyNames().end(); n++) {
+ log.debug("adding to list of trusted names (%s)", n->c_str());
+ }
+ }
+ }
X509_NAME* subject=X509_get_subject_name(certEE);
if (subject) {
if (criteria && criteria->getPeerName() && *(criteria->getPeerName())) {
log.debug("checking that the certificate name is acceptable");
- if (criteria->getUsage()==Credential::UNSPECIFIED_CREDENTIAL)
+ if (criteria && criteria->getUsage()==Credential::UNSPECIFIED_CREDENTIAL)
criteria->setUsage(Credential::SIGNING_CREDENTIAL);
if (!checkEntityNames(certEE,credResolver,*criteria)) {
log.error("certificate name was not acceptable");
return false;
}
}
+ else if (!m_trustedNames.empty()) {
+ log.debug("checking that the certificate name is acceptable");
+ CredentialCriteria cc;
+ cc.setUsage(Credential::SIGNING_CREDENTIAL);
+ if (!checkEntityNames(certEE,credResolver,cc)) {
+ log.error("certificate name was not acceptable");
+ return false;
+ }
+ }
log.debug("performing certificate path validation...");
pkix.get(),
(m_checkRevocation=="entityOnly" || m_checkRevocation=="fullChain"),
(m_checkRevocation=="fullChain"),
- (m_checkRevocation=="entityOnly" || m_checkRevocation=="fullChain") ? inlineCRLs : nullptr
+ (m_checkRevocation=="entityOnly" || m_checkRevocation=="fullChain") ? inlineCRLs : nullptr,
+ m_policyMappingInhibit,
+ m_anyPolicyInhibit,
+ &m_policyOIDs
)) {
return true;
}