PKIFPathValidator2.cpp

Go to the documentation of this file.
00001 
00010 #include "PKIFPathValidator2.h"
00011 
00012 #include "ToolkitUtils.h"
00013 #include "IPKIFCryptoRawOperations.h"
00014 #include "IPKIFCryptoMisc.h"
00015 #include "PKIFFuncStorage.h"
00016 #include "PKIFRevocationStatusInterfaces.h"
00017 #include "PKIFMediators.h"
00018 #include "PKIFX509Extensions2.h"
00019 
00020 #include "PKIFErrors.h"
00021 #include "PKIFPathException.h"
00022 #include "PKIFCertificatePath.h"
00023 #include "PKIFPathSettings.h"
00024 #include "BasicChecksUtils.h"
00025 #include "CRLEntry.h"
00026 
00027 #include "PKIFTrustRoot.h"
00028 #include "Certificate.h"
00029 #include "PKIFCertStatus.h"
00030 #include "PathResults.h"
00031 #include "PKIFCertificateNodeEntry.h"
00032 #include "PKIFPathBasicChecks2.h"
00033 #include "NameConstraints.h"
00034 #include "InhibitAnyPolicy.h"
00035 #include "PolicyConstraints.h"
00036 #include "BasicConstraints.h"
00037 #include "GeneralSubtree.h"
00038 #include "PolicyInformationSet.h"
00039 #include "PolicyInformation.h"
00040 
00041 using boost::dynamic_pointer_cast;
00042 
00044 struct CPKIFPathValidator2Impl
00045 {
00046     CPKIFFuncStoragePtr m_funcs;
00047     bool m_deleteFunctor;
00048     bool m_bEnforceTrustAnchorConstraints;
00049 };
00051 
00058 CPKIFPathValidator2::CPKIFPathValidator2():m_impl (new CPKIFPathValidator2Impl)
00059 {
00060     m_impl->m_deleteFunctor = false;
00061     m_impl->m_bEnforceTrustAnchorConstraints = false;
00062 }
00076 void CPKIFPathValidator2::SetAdditionalCertificateChecks(
00079     CPKIFFuncStoragePtr& funcs) 
00080 { 
00081     LOG_STRING_DEBUG("CPKIFPathValidator2", TOOLKIT_PATH_VALIDATOR, 0, this);
00082 
00083     //XXX-DEFER Should develop a means of accumulating functors or otherwise manipulating the list.
00084     //          Possibly the interim addition of a "this call only" functor parameter to the validate call will suffice.
00085     m_impl->m_funcs = funcs; 
00086 }
00087 
00095 CPKIFPathValidator2::~CPKIFPathValidator2(void)
00096 {
00097     LOG_STRING_DEBUG("CPKIFPathValidator2", TOOLKIT_PATH_VALIDATOR, 0, this);
00098     delete m_impl;
00099     m_impl = 0;
00100 }
00101 
00111 void CPKIFPathValidator2::Initialize() 
00112 {
00113     LOG_STRING_DEBUG("CPKIFPathValidator2", TOOLKIT_PATH_VALIDATOR, 0, this);
00114 }
00115 
00146 bool CPKIFPathValidator2::ValidatePath(
00148     CPKIFCertificatePath& path, 
00150     CPKIFPathValidationResults& results,
00152     CPKIFFuncStoragePtr& thisCallOnlyFuncs)
00153 {
00154     LOG_STRING_DEBUG("CPKIFPathValidator2", TOOLKIT_PATH_VALIDATOR, 0, this);
00155 
00156     IPKIFCryptoRawOperations* crypto = GetMediatorFromParent<IPKIFCryptoRawOperations>();
00157     IPKIFCryptoMisc* cryptoMisc = GetMediatorFromParent<IPKIFCryptoMisc>();
00158     if(NULL == crypto || NULL == cryptoMisc)
00159         throw CPKIFPathException(thisComponent,COMMON_MEDIATOR_MISSING,"One or both of the IPKIFCryptoRawOperations and IPKIFCryptoMisc interfaces was not available.");
00160 
00161     bool pathGood = false;
00162 
00163     IPKIFTrustAnchorPtr root;
00164     //IPKIFNameAndKey* targetCertNK = NULL, *rootCertNK = NULL;
00165     IPKIFNameAndKeyPtr targetCertNK, rootCertNK;
00166     CPKIFCertificatePtr targetCert;
00167     path.GetTarget(targetCert);
00168     path.GetTrustRoot(root);
00169     if(root == (CPKIFTrustRoot*)NULL)
00170         throw CPKIFPathException(thisComponent,COMMON_INVALID_INPUT,"The path has no trust root.");
00171 
00172     rootCertNK = boost::dynamic_pointer_cast<IPKIFNameAndKey, IPKIFTrustAnchor>(root);
00173     //rootCertNK = dynamic_cast<IPKIFNameAndKey*>(&(*(root)));
00174     targetCertNK = boost::dynamic_pointer_cast<IPKIFNameAndKey, CPKIFCertificate>(targetCert);
00175     //targetCertNK = dynamic_cast<IPKIFNameAndKey*>(&(*(targetCert)));
00176 
00177     CPKIFCertificateNodeList certs;
00178     path.GetPath(certs);
00179 
00180     //MOVED THIS UP HERE FROM DOWN BELOW - 04/04/2003 (to handle non-self-signed trust anchors)
00181     //if the target is a trust root then return true now
00182     if(*rootCertNK == *targetCertNK && 1 == certs.size())
00183     {
00184         CPKIFCertStatusPtr newStatus(new CPKIFCertStatus);
00185         newStatus->SetIsTrustAnchor(true);
00186         results.SetCertStatus(newStatus);
00187         results.SetTargetIsTrustAnchor(true);
00188         results.SetRevocationStatusMostSevere(NOT_REVOKED);
00189         results.SetTrustAnchor(root);
00190 
00191         //need to include the status on the target cert in the path too (4/16/2003 - CRW)
00192         certs[0]->SetStatus(newStatus);
00193 
00194         return true;
00195     }
00196 
00197     //-----------------------------------------------------------------
00198     //from section 3.1
00199     //enforceTrustAnchorConstraints: indicates if trust anchor
00200     //constraints should be enforced
00201     //-----------------------------------------------------------------
00202     if(m_impl->m_bEnforceTrustAnchorConstraints)
00203     {
00204         //-----------------------------------------------------------------
00205         //from section 3.2
00206         //If no subject distinguished name is associated with the trust
00207         //anchor, path validation fails.  The name may appear in the subject
00208         //field of a Certificate or TBSCertificate structure or in the
00209         //taName field of CertPathControls in a TrustAnchorInfo structure.
00210         //-----------------------------------------------------------------
00211 
00212         //Nothing to do relative to the subject name requirement.  Path discovery will not return a TA that has no name.
00213 
00214         //declare variables to receive configuration information from TA
00215         CPKIFPolicyInformationSetPtr pis;
00216         CPKIFNameConstraintsPtr nc;
00217         CPKIFInhibitAnyPolicyPtr iap;
00218         CPKIFPolicyConstraintsPtr pc;
00219         CPKIFBasicConstraintsPtr bc;
00220 
00221         //harvest the data from the TA
00222         IPKIFTrustAnchorPtr ta;
00223         path.GetTrustRoot(ta);
00224 
00225         IPKIFHasExtensionsPtr hep = dynamic_pointer_cast<IPKIFHasExtensions, IPKIFTrustAnchor>(ta);
00226         if(hep)
00227         {
00228             pis = hep->GetExtension<CPKIFPolicyInformationSet>();
00229             nc = hep->GetExtension<CPKIFNameConstraints>();
00230             iap = hep->GetExtension<CPKIFInhibitAnyPolicy>();
00231             pc = hep->GetExtension<CPKIFPolicyConstraints>();
00232             bc = hep->GetExtension<CPKIFBasicConstraints>();
00233         }
00234 
00235         std::vector<CPKIFX509ExtensionPtr> exts;
00236         CPKIFX509ExtensionMediator2 * mediator = CPKIFX509ExtensionMediator2::GetInstance();
00237         hep->GetExtensions(mediator, exts);
00238 
00239         std::vector<CPKIFX509ExtensionPtr>::iterator pos;
00240         std::vector<CPKIFX509ExtensionPtr>::iterator end = exts.end();
00241         for(pos = exts.begin(); pos != end; ++pos)
00242         {
00243             //the only extensions we process are those listed above and CCC (which is initialized/processed elsewhere)
00244             if(dynamic_pointer_cast<CPKIFPolicyInformationSet, CPKIFX509Extension>(*pos))
00245                 continue;
00246             else if(dynamic_pointer_cast<CPKIFNameConstraints, CPKIFX509Extension>(*pos))
00247                 continue;
00248             else if(dynamic_pointer_cast<CPKIFInhibitAnyPolicy, CPKIFX509Extension>(*pos))
00249                 continue;
00250             else if(dynamic_pointer_cast<CPKIFPolicyConstraints, CPKIFX509Extension>(*pos))
00251                 continue;
00252             else if(dynamic_pointer_cast<CPKIFBasicConstraints, CPKIFX509Extension>(*pos))
00253                 continue;
00254             else
00255             {
00256                 //only other possibility we support is CCC - check it by OID
00257                 CPKIFOIDPtr cccOid(new CPKIFOID(CPKIFStringPtr(new std::string("1.3.6.1.5.5.7.1.18"))));
00258                 CPKIFOIDPtr posOid = (*pos)->oid();
00259                 if(*cccOid == *posOid)
00260                     continue;
00261                 else if((*pos)->isCritical())
00262                 {
00263                     CPKIFCertificateNodeList certNodeList;
00264                     path.GetPath(certNodeList);
00265 
00266                     CPKIFCertificateNodeEntryPtr node = certNodeList.front();
00267 
00268                     CPKIFCertStatusPtr status(new CPKIFCertStatus); 
00269                     status->SetDiagnosticCode(PATH_UNPROCESSED_CRITICAL_EXTENSION); 
00270                     node->SetStatus(status);    
00271                     results.SetCertificate(node); 
00272                     return false;                   
00273                 }
00274             }
00275         }
00276 
00277         //get the current user supplied settings
00278         CPKIFPathSettingsPtr ps;
00279         path.GetPathSettings(ps);
00280 
00281         if(pis)
00282         {
00283             //-----------------------------------------------------------------
00284             //from section 3.2
00285             //If certificate policies are associated with the trust anchor, set
00286             //the user-initial-policy-set variable equal to the intersection of
00287             //the certificate policies associated with the trust anchor and the
00288             //user provided user-initial-policy-set.  If one of these two inputs
00289             //is not provided, the user-initial-policy-set variable is set to
00290             //the value that is available.  If neither is provided, the user-
00291             //initial-policy-set variable is set to any-policy.
00292             //-----------------------------------------------------------------
00293             CPKIFPolicyInformationListPtr pilFromTa = pis->GetPolicySet();
00294             CPKIFPolicyInformationListPtr pilFromUser;
00295             ps->GetInitialPolicySet(pilFromUser);
00296             if(pilFromTa && pilFromUser)
00297             {
00298                 if(!pilFromUser->empty() && *g_anyPolicy == *pilFromUser->front())
00299                 {
00300                     ps->SetInitialPolicySet(pilFromTa);
00301                 }
00302                 else
00303                 {
00304                     CPKIFPolicyInformationListPtr newPil(new CPKIFPolicyInformationList);
00305                     IntersectSets(pilFromTa, pilFromUser, newPil);
00306                     ps->SetInitialPolicySet(newPil);
00307                 }
00308             }
00309             else if(pilFromTa)
00310             {
00311                 ps->SetInitialPolicySet(pilFromTa);
00312             }
00313         }
00314 
00315         if(nc)
00316         {
00317             //-----------------------------------------------------------------
00318             //from section 3.2
00319             //If name constraints are associated with the trust anchor, set the
00320             //initial-permitted-subtrees variable equal to the intersection of
00321             //the permitted subtrees from the trust anchor and the user provided
00322             //initial-permitted-subtrees.  If one of these two inputs is not
00323             //provided, the initial-permitted-subtrees variable is set to the
00324             //value that is available.  If neither is provided, the initial-
00325             //permitted-subtrees variable is set to an infinite set.
00326             //-----------------------------------------------------------------
00327             CPKIFGeneralSubtreesPtr permFromTa = nc->GetPermitted();
00328             CPKIFGeneralSubtreesPtr permFromUser;
00329             ps->GetInitialPermSubtrees(permFromUser);
00330             if(permFromTa && permFromUser)
00331             {
00332                 CPKIFGeneralSubtreesPtr newPerm(new CPKIFGeneralSubtrees);
00333                 IntersectSubtrees(permFromTa, permFromUser, newPerm);
00334                 ps->SetInitialPermSubtrees(newPerm);
00335             }
00336             else if(permFromTa)
00337             {
00338                 ps->SetInitialPermSubtrees(permFromTa);
00339             }
00340 
00341             //-----------------------------------------------------------------
00342             //from section 3.2
00343             //If name constraints are associated with the trust anchor, set the
00344             //initial-excluded-subtrees variable equal to the union of the
00345             //excluded subtrees from the trust anchor and the user provided
00346             //initial-excluded-subtrees.  If one of these two inputs is not
00347             //provided, the initial-excluded-subtrees variable is set to the
00348             //value that is available.  If neither is provided, the initial-
00349             //excluded-subtrees variable is set to an empty set.
00350             //-----------------------------------------------------------------
00351             CPKIFGeneralSubtreesPtr exclFromTa = nc->GetExcluded();
00352             CPKIFGeneralSubtreesPtr exclFromUser;
00353             ps->GetInitialExclSubtrees(exclFromUser);
00354             if(exclFromTa && exclFromUser)
00355             {
00356                 CPKIFGeneralSubtreesPtr newExcl(new CPKIFGeneralSubtrees);
00357                 IntersectSubtrees(exclFromTa, exclFromUser, newExcl);
00358                 ps->SetInitialExclSubtrees(newExcl);
00359             }
00360             else if(exclFromTa)
00361             {
00362                 ps->SetInitialExclSubtrees(exclFromTa);
00363             }
00364         }
00365 
00366         if(iap)
00367         {
00368             //-----------------------------------------------------------------
00369             //from section 3.2
00370             //If an inhibit any policy value of true is associated with the
00371             //trust anchor (either in a CertPathControls or in an
00372             //InhibitAnyPolicy extension) and the initial-any-policy-inhibit
00373             //value is false, set the initial-any-policy-inhibit to true.
00374             //-----------------------------------------------------------------
00375             ps->SetInitialInhibitAnyPolicyIndicator(true);
00376         }
00377 
00378         if(pc)
00379         {
00380             if(pc->InhibitPolicyMappingPresent())
00381             {
00382                 //-----------------------------------------------------------------
00383                 //from section 3.2
00384                 //If an inhibit policy mapping value of true is associated with the
00385                 //trust anchor (either in a CertPathControls or in a
00386                 //PolicyConstraints extension) and the initial-policy-mapping-
00387                 //inhibit value is false, set the initial-policy-mapping-inhibit to
00388                 //true.
00389                 //-----------------------------------------------------------------
00390                 ps->SetInitialPolicyMappingInhibitIndicator(true);
00391             }
00392             if(pc->RequireExplicitPolicyPresent())
00393             {
00394                 //-----------------------------------------------------------------
00395                 //from section 3.2
00396                 //If a require explicit policy value of true is associated with the
00397                 //trust anchor (either in a CertPathControls or in a
00398                 //PolicyConstraints extension) and the initial-explicit-policy value
00399                 //is false, set the initial-explicit-policy to true.
00400                 //-----------------------------------------------------------------
00401                 ps->SetInitialExplicitPolicyIndicator(true);
00402             }
00403         }
00404 
00405         //-----------------------------------------------------------------
00406         //from section 3.2
00407         //If a basic constraints extension is associated with the trust
00408         //anchor and contains a pathLenConstraint value, set the
00409         //max_path_length state variable equal to the pathLenConstraint
00410         //value from the basic constraints extension.
00411         //-----------------------------------------------------------------
00412         if(bc && bc->pathLengthPresent())
00413         {
00414             //We do no have the ability to specify the max_path_length state variable.  Thus,
00415             //the length check emanating from the TA is implemented in full here.  Length constraints
00416             //included in CA certificates are not checked here, but will be checked as part of routine 
00417             //path validation.
00418             int pathLength = bc->pathLength();
00419 
00420             CPKIFCertificateNodeList certsFromPath;
00421             path.GetPath(certsFromPath);
00422 
00423             CPKIFCertificateNodeList::iterator pos;
00424             CPKIFCertificateNodeList::iterator end = certsFromPath.end();
00425             for(pos = certsFromPath.begin(); pos != end; ++pos)
00426             {
00427                 CPKIFCertificatePtr curCert = (*pos)->GetCert();
00428                 if(curCert && !curCert->IsSelfIssued())
00429                 {
00430                     --pathLength;
00431 
00432                     if(pathLength < 0)
00433                     {
00434                         CPKIFCertStatusPtr status(new CPKIFCertStatus); 
00435                         status->SetDiagnosticCode(PATH_LENGTH_VIOLATION); 
00436                         (*pos)->SetStatus(status);  
00437                         results.SetCertificate(*pos); 
00438                     }
00439                 }
00440             }
00441         }
00442     }//end trust anchor constraint enforcement block
00443 
00444     //First step: perform basic path checks
00445     if(m_impl->m_funcs == (CPKIFFuncStorage*)NULL)//no functions set via SetAdd'l
00446     {
00447         if(thisCallOnlyFuncs == (CPKIFFuncStorage*)NULL)
00448         {
00449             CPKIFFuncStoragePtr empty;
00450             pathGood = CPKIFPathBasicChecks2::DoChecks(path, results, empty);
00451         }
00452         else
00453             pathGood = CPKIFPathBasicChecks2::DoChecks(path, results, thisCallOnlyFuncs);
00454     }
00455     else //there were some passed via SetAdd'l
00456     {
00457         //need to chain the two
00458         if(thisCallOnlyFuncs == NULL)
00459             pathGood = CPKIFPathBasicChecks2::DoChecks(path, results, m_impl->m_funcs);
00460         else
00461         {
00462             CPKIFFuncStoragePtr combo(new CPKIFFuncStorage(NULL));
00463             combo->addFuncs(*m_impl->m_funcs);
00464             combo->addFuncs(*thisCallOnlyFuncs);
00465 
00466             pathGood = CPKIFPathBasicChecks2::DoChecks(path, results, combo);
00467         }
00468     }
00469 
00470     //if we failed a basic check - return failure
00471     if(!pathGood)
00472     {
00473         //added next line 7/28/2004 to make cert status setting consistent
00474         FindErrorAndSetOnResults(path, results);
00475         return false;
00476     }
00477 
00478     //otherwise, check signatures on all certs in the path 
00479     if(!PathSigChecker(path, crypto, cryptoMisc, results))
00480     {
00481         //added next line 7/28/2004 to make cert status setting consistent
00482         FindErrorAndSetOnResults(path, results);
00483         return false;
00484     }
00485 
00486     //added settings check 2/20/2003 - CRW
00487     CPKIFPathSettingsPtr settings;
00488     path.GetPathSettings(settings);
00489 
00490     bool bCheckRevStatus = true;
00491     if(settings != (CPKIFPathSettings*)NULL)
00492         bCheckRevStatus = settings->GetCheckRevocationStatus();
00493 
00494     //finally, check the revocation status of all certs in the path
00495     IPKIFRevocationStatus* revStatus = GetMediatorFromParent<IPKIFRevocationStatus>();
00496     if(NULL != revStatus && bCheckRevStatus)//added check rev status condition 2/20/2003 - CRW
00497     {
00498         //if we have no status checking interface then we may be in an offline mode
00499         //of operation.  don't fail but don't advance the status to indicate revocation
00500         //status is good.
00501 
00502         RevocationStatus rStatus;
00503         CPKIFCRLEntryPtr crlEntry;
00504         bool statusDetermined = revStatus->CheckStatusPath(path, rStatus);
00505         if(NOT_REVOKED != rStatus)
00506         {
00507             //walk the path, find the cert that caused the error and set it
00508             //on the validation results object
00509             FindErrorAndSetOnResults(path, results);
00510             //results.SetCRLEntry(crlEntry);
00511 
00512             return false;
00513         }
00514 
00515         //the path has earned still another check mark
00516         results.SetRevocationStatusMostSevere(rStatus);
00517     }
00518 
00519     //if we get here then all basic checks succeeded, all signature verified and revocation status is non-revoked
00520 
00521     //added following code 7/28/2004 to make cert status setting consistent
00522     CPKIFCertificateNodeList nodes;
00523     path.GetPath(nodes);
00524     if(!nodes.empty())
00525     {
00526         CPKIFCertificateNodeEntryPtr target = nodes.back();
00527         if(target != NULL) {
00528             CPKIFCertStatusPtr tmpStatus = target->GetStatus();
00529             results.SetCertStatus(tmpStatus);
00530         }
00531     }
00532 
00533     return true;
00534 }
00535 
00542 bool CPKIFPathValidator2::GetEnforceTrustAnchorConstraints() const
00543 {
00544     return m_impl->m_bEnforceTrustAnchorConstraints;
00545 }
00553 void CPKIFPathValidator2::SetEnforceTrustAnchorConstraints(bool b)
00554 {
00555     m_impl->m_bEnforceTrustAnchorConstraints = b;
00556 }

Generated on Mon Nov 15 11:15:55 2010 for PublicKeyInfrastructureFramework(PKIF) by  doxygen 1.5.6