BasicChecksUtils.cpp

Go to the documentation of this file.
00001 
00009 #include "AlgorithmIdentifier.h"
00010 #include "BasicChecksUtils.h"
00011 #include "Buffer.h"
00012 #include "Certificate.h"
00013 #include "CertificateNodeListWithSourceInfo.h"
00014 #include "GeneralName.h"
00015 #include "GeneralSubtree.h"
00016 #include "GottaMatch.h"
00017 #include "IPKIFCryptoMisc.h"
00018 #include "IPKIFCryptoRawOperations.h"
00019 #include "IPKIFHashContext.h"
00020 #include "Name.h"
00021 #include "OID.h"
00022 #include "PKIFCertStatus.h"
00023 #include "PKIFCertificateNodeEntry.h"
00024 #include "PKIFCertificatePath.h"
00025 #include "PKIFCommonErrors.h"
00026 #include "PKIFKeyMaterial.h"
00027 #include "PKIFNameAndKeyWithScore.h"
00028 #include "PKIFPATHErrors.h"
00029 #include "PKIFPathException.h"
00030 #include "PKIFPathSettings.h"
00031 #include "PKIFTrustRoot.h"
00032 #include "PathResults.h"
00033 #include "PolicyInformation.h"
00034 #include "PolicyInformationSet.h"
00035 #include "PolicyMapping.h"
00036 #include "PolicyMappings.h"
00037 #include "SubjectAltName.h"
00038 #include "SubjectPublicKeyInfo.h"
00039 #include "SubtreeMatch.h"
00040 #include "ToolkitUtils.h"
00041 #include "Name.h"
00042 #include "PKIFCertificatePath.h"
00043 #include "PKIFTrustRoot.h"
00044 #include "PKIFCertificateNodeEntry.h"
00045 #include "PathResults.h"
00046 #include "ooasn1.h"
00047 #include "asn1ber.h"
00048 
00049 #include "boost/numeric/conversion/cast.hpp"
00050 
00051 #include <iterator>
00052 
00053 using boost::numeric_cast;
00054 using boost::bad_numeric_cast;
00055 
00056 using namespace std;
00057 
00058 
00059 using namespace boost;
00060 
00061 #ifdef _DEBUG_PATH_POL
00062 #include <iostream>
00063 
00071 void DumpPolicySet(
00073     const char* message, 
00074     //[in] Vecotr of CPKIFPolicyInformationList objects that will be outputed
00075     const vector<CPKIFPolicyInformationListPtr>& authSet )
00076 {
00077     cout << endl << message << endl;
00078 
00079     vector<CPKIFPolicyInformationListPtr>::const_iterator authSetPos;
00080     vector<CPKIFPolicyInformationListPtr>::const_iterator authSetEnd = authSet.end();
00081     int rowCount = 0;
00082     for(authSetPos = authSet.begin(); authSetPos != authSetEnd; ++authSetPos,++rowCount)
00083     {
00084         cout << "Row: " << rowCount << endl;
00085         CPKIFPolicyInformationList::const_iterator authSetPolPos;
00086         CPKIFPolicyInformationList::const_iterator authSetPolEnd = (*authSetPos)->end();
00087         for(authSetPolPos = (*authSetPos)->begin(); authSetPolPos != authSetPolEnd; ++authSetPolPos)
00088         {
00089             cout << (*authSetPolPos)->PolicyOID()->ToString() << endl;
00090         }
00091     }
00092     if(authSet.empty())
00093         cout << "Empty" << endl;
00094 
00095 }
00096 #endif
00097 
00104 bool RowContainsAnyPolicy(
00106     const CPKIFPolicyInformationListPtr& test)
00107 {
00108     //if test set has any policy then return true
00109     if(*g_anyPolicy == *test->back()) 
00110         return true;
00111     else
00112         return false;
00113 }
00127 void ProcessPolicyMapping(
00129     const CPKIFPolicyMappingsPtr& policyMappings, 
00131     const std::bitset<3>& indicators,
00133     vector<CPKIFPolicyInformationListPtr>& authSet)
00134 {
00135     CPKIFOIDPtr anyPolicyOID(new CPKIFOID(CPKIFStringPtr(new std::string("2.5.29.32.0"))));
00136     if(indicators[CPKIFPathSettings::POLICY_MAPPING])
00137     {
00138         //we are inhibiting mapping
00139         //10.5.2 c) process any policy mappings extension by, for each mapping identified in the extension, 
00140         //locate all rows in the authorities-constrained-policy-set table whose [path-depth] column entry 
00141         //is equal to the issuer domain policy value in the extension and delete the row.
00142 
00143         CPKIFPolicyMappingListPtr policyMappingList = policyMappings->PolicyMappings();
00144         CPKIFPolicyMappingList::iterator pos;
00145         CPKIFPolicyMappingList::iterator end = policyMappingList->end();
00146         CPKIFOIDPtr issuerDomain;
00147         CPKIFPolicyInformationListPtr piList(new CPKIFPolicyInformationList);
00148         for(pos = policyMappingList->begin(); pos != end; ++pos)
00149         {
00150             issuerDomain = (*pos)->IssuerDomain();
00151 
00152             //added anyPolicy check per 3280 - 12/3/2003
00153             //ignore mappings involving anyPolicy
00154             if((*anyPolicyOID == *issuerDomain) || (*anyPolicyOID == *(*pos)->SubjectDomain()))
00155                 throw CPKIFPathException(TOOLKIT_PATH_VALIDATOR,COMMON_INVALID_INPUT,"A certificate includes a policy mapping extension that maps to or from anyPolicy.");
00156             else
00157             {   
00158                 CPKIFPolicyInformationPtr tmpPI(new CPKIFPolicyInformation(issuerDomain));
00159                 piList->push_back(tmpPI);
00160             }
00161         }
00162 
00163         RowDoesContainPolicyInSet funcObj;
00164         funcObj.SetPolicySet(piList);
00165         vector<CPKIFPolicyInformationListPtr>::iterator authSetEnd = remove_if(authSet.begin(), authSet.end(), funcObj);
00166         authSet.erase(authSetEnd, authSet.end());
00167     }
00168     else
00169     {
00170         //we are not inhibiting mapping
00171         //10.5.2. d) process any policy mappings extension by, for each mapping identified in the extension, 
00172         //locate all rows in the authorities-constrained-policy-set table whose [path-depth] column entry is 
00173         //equal to the issuer domain policy value in the extension, and write the subject domain policy value 
00174         //from the extension in the [path-depth+1] column entry of the same row.  If the extension maps an 
00175         //issuer domain policy to more than one subject domain policy, then the affected row is copied and the 
00176         //new entry added to each row.  If the value in authorities-constrained-policy-set[0, path-depth] is 
00177         //any-policy, then write each issuer domain policy identifier from the policy mappings extension in the 
00178         //[path-depth] column, making duplicate rows as necessary and retaining qualifiers if they are present, 
00179         //and write the subject domain policy value from the extension in the [path-depth+1] column entry of 
00180         //the same row.
00181 
00182         //create a list containing all mappings for a given issuer domain
00183         CIssuerDomainMappingList idml;
00184         CPKIFPolicyMappingListPtr policyMappingList = policyMappings->PolicyMappings();
00185         CPKIFPolicyMappingList::iterator pos;
00186         CPKIFPolicyMappingList::iterator end = policyMappingList->end();
00187         for(pos = policyMappingList->begin(); pos != end; ++pos)
00188         {
00189             //added anyPolicy check per 3280 - 12/3/2003
00190             //ignore mappings involving anyPolicy
00191             if((*anyPolicyOID == *(*pos)->IssuerDomain()) || (*anyPolicyOID == *(*pos)->SubjectDomain()))
00192                 throw CPKIFPathException(TOOLKIT_PATH_VALIDATOR,COMMON_INVALID_INPUT,"A certificate includes a policy mapping extension that maps to or from anyPolicy.");
00193             else
00194                 idml.AddMapping(*pos);
00195         }
00196 
00197         bool zerothRowContainsAnyPolicy = false;
00198         CPKIFPolicyInformationPtr anyPolicy(new CPKIFPolicyInformation(anyPolicyOID));
00199         if(!authSet.empty() && !authSet.front()->empty() && *anyPolicy == *authSet.front()->back())
00200             zerothRowContainsAnyPolicy = true;
00201 
00202         struct IssuerDomainMappingList* list = idml.GetList();
00203         while(NULL != list)
00204         {
00205             //10.5.2 d)process any policy mappings extension by, for each mapping identified in the extension, 
00206             //locate all rows in the authorities-constrained-policy-set table whose [path-depth] column entry 
00207             //is equal to the issuer domain policy value in the extension, and write the subject domain policy 
00208             //value from the extension in the [path-depth+1] column entry of the same row.  If the extension 
00209             //maps an issuer domain policy to more than one subject domain policy, then the affected row is 
00210             //copied and the new entry added to each row.  If the value in 
00211             //authorities-constrained-policy-set[0, path-depth] is any-policy, then write each issuer domain 
00212             //policy identifier from the policy mappings extension in the [path-depth] column, making duplicate 
00213             //rows as necessary and retaining qualifiers if they are present, and write the subject domain 
00214             //policy value from the extension in the [path-depth+1] column entry of the same row.           
00215 
00216             //vector<CPKIFPolicyInformationListPtr>::iterator authSetPos;
00217             //vector<CPKIFPolicyInformationListPtr>::iterator authSetEnd = authSet.end();
00218             //for(authSetPos = authSet.begin(); authSetPos != authSetEnd; authSetPos++)
00219             for(unsigned int ii = 0; ii < authSet.size(); ii++)
00220             {
00221                 CPKIFPolicyInformationListPtr curr = authSet[ii];
00222                 if(!curr->empty() && (*(list->m_issuerDomain) == *(curr->back())))
00223                 {
00224                     list->m_bProcessed = true;
00225                     CPKIFPolicyInformationListPtr curRow = curr;
00226                     CPKIFPolicyInformationList::iterator subDomainPos = list->m_subjectDomains.begin();
00227                     CPKIFPolicyInformationList::iterator subDomainEnd = list->m_subjectDomains.end();
00228 
00229                     CPKIFPolicyInformationPtr tmpPol(new CPKIFPolicyInformation((*subDomainPos)->PolicyOID()));
00230                     curr->push_back(tmpPol);
00231                     for(++subDomainPos; subDomainPos != subDomainEnd; ++subDomainPos)
00232                     {
00233                         //for all additional mappings to the same issuer copy the row and add it
00234                         CPKIFPolicyInformationListPtr newRow(new CPKIFPolicyInformationList);
00235                         copy(curRow->begin(),curRow->end(), back_inserter(*newRow));
00236                         CPKIFPolicyInformationPtr pathDepthColumn(*subDomainPos);
00237                         newRow->pop_back();
00238                         newRow->push_back(pathDepthColumn);
00239                         authSet.push_back(newRow);
00240                     }
00241                 }
00242             }
00243 
00244             list = list->m_next;
00245         }
00246 
00247         if(zerothRowContainsAnyPolicy)
00248         {
00249             CPKIFPolicyInformationListPtr zerothRow = authSet.front();
00250             struct IssuerDomainMappingList* list = idml.GetList();
00251             while(NULL != list)
00252             {
00253                 if(!list->m_bProcessed)
00254                 {
00255                     //create a row by copying the zeroth row and placing issuer domain in 
00256                     //the path depth column (i.e. overwriting the last entry)
00257                     CPKIFPolicyInformationListPtr newRow(new CPKIFPolicyInformationList);
00258                     copy(zerothRow->begin(),zerothRow->end(), back_inserter(*newRow));
00259                     CPKIFPolicyInformationPtr pathDepthColumn(list->m_issuerDomain);
00260                     newRow->pop_back();
00261                     newRow->push_back(pathDepthColumn);
00262 
00263                     CPKIFPolicyInformationList::iterator subDomainPos = list->m_subjectDomains.begin();
00264                     CPKIFPolicyInformationList::iterator subDomainEnd = list->m_subjectDomains.end();
00265 
00266                     for(; subDomainPos != subDomainEnd; ++subDomainPos)
00267                     {
00268                         //for each subject domain policy copy the newRow, add the sub domain to
00269                         //the path depth plus one column and push it into the auth set
00270                         CPKIFPolicyInformationListPtr newRowWithSubDomain(new CPKIFPolicyInformationList);
00271                         copy(zerothRow->begin(),zerothRow->end(), back_inserter(*newRowWithSubDomain));
00272                         CPKIFPolicyInformationPtr pathDepthColumn(list->m_issuerDomain);
00273                         newRowWithSubDomain->push_back(pathDepthColumn);
00274                         authSet.push_back(newRowWithSubDomain);
00275                     }
00276                 }
00277 
00278                 list = list->m_next;
00279             }
00280         }
00281     }
00282 #ifdef _DEBUG_PATH_POL
00283     DumpPolicySet("Dumping authority constrained set leaving ProcessPolicyMapping", authSet);
00284 #endif
00285 }
00293 void AddPoliciesToAuthSet(
00295     const CPKIFPolicyInformationSetPtr& certPols,
00297     const std::bitset<3>& indicators,
00299     vector<CPKIFPolicyInformationListPtr>& authSet, 
00301     bool isSelfIssued, 
00303     bool isIntermediate)
00304 {
00305 #ifdef _DEBUG_PATH_POL
00306     DumpPolicySet("Dumping authority constrained set entering AddPoliciesToAuthSet", authSet);
00307 #endif
00308 
00309     CPKIFPolicyInformationListPtr certPolList = certPols->GetPolicySet();
00310 
00311     CPKIFOIDPtr anyPolicyOID(new CPKIFOID(CPKIFStringPtr(new std::string("2.5.29.32.0"))));
00312     CPKIFPolicyInformationPtr anyPolicy(new CPKIFPolicyInformation(anyPolicyOID));
00313 
00314     CPKIFPolicyInformationPtr anyPolicyFromCertPolList;
00315 
00316     CPKIFPolicyInformationList::iterator currentPolicy;
00317     CPKIFPolicyInformationList::iterator end = certPolList->end();
00318     bool foundPolicy = false, foundAnyPolicy = false, zerothRowContainsAnyPolicy = false;
00319     vector<CPKIFPolicyInformationListPtr>::iterator authSetPos, authSetEnd;
00320     for(currentPolicy = certPolList->begin(); currentPolicy != end; ++currentPolicy)
00321     {
00322         zerothRowContainsAnyPolicy = false;
00323         if(!authSet.empty() && *anyPolicy == *authSet.front()->back())
00324             zerothRowContainsAnyPolicy = true;
00325 
00326         //10.5.1.d) If the certificate policies extension is present, then for each policy, P, 
00327         //in the extension other than anyPolicy, attach the policy qualifiers associated with P 
00328         //to each row in the authorities-constrained-policy-set table whose [path-depth] column 
00329         //entry contains the value P. If no row in the authorities-constrained-policy-set table 
00330         //contains P in its [path-depth] column entry but the value in 
00331         //authorities-constrained-policy-set[0, path-depth] is any-policy, then add a new row 
00332         //to the table by duplicating the zeroth row and writing the policy identifier P along 
00333         //with its qualifiers in the [path-depth] column entry of the new row.
00334 
00335         //we don't do any processing of anyPolicy occurances in cert pol extensions
00336         if(*(*currentPolicy) == *anyPolicy)
00337         {
00338             anyPolicyFromCertPolList = *currentPolicy;
00339             foundAnyPolicy = true;
00340             continue;
00341         }
00342 
00343         authSetEnd = authSet.end();
00344         foundPolicy = false;
00345         //iterate over all rows in authSet table looking for current policy
00346         //the "back" element in each row is the "path-depth" column
00347         for(authSetPos = authSet.begin(); authSetPos != authSetEnd; ++authSetPos)
00348         {
00349             if(!(*authSetPos)->empty() && *(*currentPolicy) == *((*authSetPos)->back()))
00350             {
00351                 //we found a row that matches the current policy
00352                 foundPolicy = true;
00353 
00354                 //attach qualifiers
00355                 CPKIFPolicyQualifierListPtr qList = (*currentPolicy)->Qualifiers();
00356                 if(qList != (CPKIFPolicyQualifierList*)NULL && !qList->empty())
00357                 {
00358                     CPKIFPolicyQualifierListPtr existingQualifiers = (*authSetPos)->back()->Qualifiers();
00359                     if(existingQualifiers != (CPKIFPolicyQualifierList*)NULL)
00360                     {
00361                         //if there are qualifiers already in place - attach all of the 
00362                         //new qualifiers to the existing ones (if we get duplicates so be it)
00363                         copy(qList->begin(), qList->end(), back_inserter(*existingQualifiers));
00364                     }
00365                     else
00366                     {
00367                         //added 12/6/2003
00368                         CPKIFPolicyQualifierListPtr newQualifiers(new CPKIFPolicyQualifierList);
00369                         copy(qList->begin(), qList->end(), back_inserter(*newQualifiers));
00370     
00371                         //there were no qualifiers and now there are
00372                         (*authSetPos)->back()->SetQualifiers(newQualifiers);
00373                     }
00374                 }
00375             }
00376         }
00377 
00378         if(!foundPolicy && zerothRowContainsAnyPolicy)
00379         {
00380             //if we didn't find the current policy in the path depth column of any row
00381             //and the zeroth row contains anyPolicy then we duplicate the zeroth row and 
00382             //overwrite the path depth column with the current policy then attach the altered row.
00383             CPKIFPolicyInformationListPtr newRow(new CPKIFPolicyInformationList);
00384             copy(authSet.front()->begin(), authSet.front()->end(), back_inserter(*newRow));
00385             newRow->pop_back();
00386             newRow->push_back(*currentPolicy);
00387             authSet.push_back(newRow);
00388         }
00389     }
00390 
00391     //10.5.1 e)  If the certificate policies extension is present and does not include the value 
00392     //anyPolicy or if the inhibit-any-policy-indicator is set, then delete any row for which the 
00393     //[path-depth] column entry contains the value any-policy along with any row for which the 
00394     //[path-depth] column entry does not contain one of the values in the certificate policies 
00395     //extension.
00396     //mod to align with technical corrigendum 1: 02/13/03 CRW
00397     //technical corrigendum 1 item 5: Replace "or if the inhibit-any-policy-indicator is set, then 
00398     //delete" with "or if the inhibit-any-policy-indicator is set and the certificate is not a 
00399     //self-issued intermediate certificate, then delete". 
00400     if(!foundAnyPolicy || (indicators[CPKIFPathSettings::ANY_POLICY] && !(isSelfIssued && isIntermediate)))
00401     {
00402         //if the current set of policies did not contain any policy or the inhibit any bit is set
00403         //then remove any row in the auth set with any policy in path depth column and any row that
00404         //contains a value not found in certPolList
00405         vector<CPKIFPolicyInformationListPtr>::iterator end = remove_if(authSet.begin(), authSet.end(), RowContainsAnyPolicy);
00406         authSet.erase(end, authSet.end());
00407 
00408         RowDoesNotContainPolicyInSet funcObj;
00409         funcObj.SetPolicySet(certPolList);
00410         end = remove_if(authSet.begin(), authSet.end(), funcObj);
00411         authSet.erase(end, authSet.end());
00412     }
00413     else if(foundAnyPolicy && !indicators[CPKIFPathSettings::ANY_POLICY])
00414     {
00415 
00416         //10.5.1 f) If the certificate policies extension is present and includes the value 
00417         //          anyPolicy and the inhibit-any-policy-indicator is not set, then attach 
00418         //          the policy qualifiers associated with anyPolicy to each row in the 
00419         //          authorities-constrained-policy-set table whose [path-depth] column entry 
00420         //          contains the value any-policy or contains a value that does not appear 
00421         //          in the certificate policies extension.
00422         //add qualifiers from anyPolicyFromCertPolList to any row that 
00423         //contains any policy or a policy not found in the certPolList
00424 
00425         authSetEnd = authSet.end();
00426         for(authSetPos = authSet.begin(); authSetPos != authSetEnd; ++authSetPos)
00427         {
00428             if(!(*authSetPos)->empty())
00429             {
00430                 //see if the current authSet position is any policy or is not present in the certPolList.  in 
00431                 //either case attach the qualifiers from the anyPolicy entry in certPolList to the row.
00432                 GottaMatch<CPKIFPolicyInformationPtr> gm;
00433                 gm.SetRHS((*authSetPos)->back());
00434                 if(*anyPolicy == *(*authSetPos)->back() || certPolList->end() == find_if(certPolList->begin(), certPolList->end(), gm))
00435                 {
00436                     //attach qualifiers
00437                     CPKIFPolicyQualifierListPtr qList = anyPolicyFromCertPolList->Qualifiers();
00438                     if(qList != (CPKIFPolicyQualifierList*)NULL && !qList->empty())
00439                     {
00440                         CPKIFPolicyQualifierListPtr existingQualifiers = (*authSetPos)->back()->Qualifiers();
00441                         if(existingQualifiers != (CPKIFPolicyQualifierList*)NULL)
00442                         {
00443                             //if there are qualifiers already in place - attach all of the 
00444                             //new qualifiers to the existing ones (if we get duplicates so be it)
00445                             copy(qList->begin(), qList->end(), back_inserter(*existingQualifiers));
00446                         }
00447                         else
00448                         {
00449                             //added 12/6/2003
00450                             CPKIFPolicyQualifierListPtr newQualifiers(new CPKIFPolicyQualifierList);
00451                             copy(qList->begin(), qList->end(), back_inserter(*newQualifiers));
00452         
00453                             //there were no qualifiers and now there are
00454                             (*authSetPos)->back()->SetQualifiers(newQualifiers);
00455                         }
00456                     }
00457                 }
00458             }
00459         }
00460     }
00461 
00462 #ifdef _DEBUG_PATH_POL
00463     DumpPolicySet("Dumping authority constrained set leaving AddPoliciesToAuthSet", authSet);
00464 #endif
00465 }
00473 void CAC_API IntersectSets(
00475     CPKIFPolicyInformationListPtr& authSetCondensed,
00477     CPKIFPolicyInformationListPtr& initSet, 
00479     CPKIFPolicyInformationListPtr& userSet)
00480 {
00481     //empty the user set
00482     userSet->clear();
00483 
00484     //set up variables needed when calling find_if
00485     MatchesPolicy mp;
00486     CPKIFPolicyInformationList::iterator authBegin = authSetCondensed->begin();
00487     CPKIFPolicyInformationList::iterator authEnd = authSetCondensed->end();
00488 
00489     //iterate over all policies in the initial policy set and create a list of policies found 
00490     //in both the initial policy set and authority constrainted set in userSet
00491     CPKIFPolicyInformationList::iterator initPos;
00492     CPKIFPolicyInformationList::iterator initEnd = initSet->end();
00493     for(initPos = initSet->begin(); initPos != initEnd; ++initPos)
00494     {
00495         //see if the current policy from the initial policy set is in the auth set
00496         mp.SetPolicyToMatch(*initPos);
00497         if(authEnd != find_if(authBegin, authEnd, mp))
00498         {
00499             //if it is then add it to the user set
00500             userSet->push_back(*initPos);
00501         }
00502     }
00503 }
00511 void CAC_API IntersectSubtrees(
00513     CPKIFGeneralSubtreeListPtr& fromExtension, 
00515     CPKIFGeneralSubtreeListPtr& curTrees, 
00517     CPKIFGeneralSubtreeListPtr& newSet)
00518 {
00519     //empty the user set
00520     newSet->clear();
00521 
00522     if(curTrees->empty())
00523     {
00524         //empty means unbounded - set new set to fromExtensions
00525         newSet = fromExtension;
00526         return;
00527     }
00528 
00529     // GIB: Note: now that we support non-DN nameConstraints, the meaning of this
00530     // match predicate has been inverted. Where before it would return trees
00531     // that intersect, now it returns trees that are disjoint. This is because
00532     // IntersectSubtrees now needs to retain the set of subtrees that intersect
00533     // or are unrelated (i.e. if a DN constraint is imposed by a CA and an
00534     // rfc822Name constraint is imposed by a subordinate, both must
00535     // go into the final set)
00536     // So now we mark known bad subtrees as excluded instead.
00537     SubtreeMatch isImpossible;
00538 
00539     // find_if will iterate over subtrees pulled from the 
00540     // PermittedSubtrees extension
00541     CPKIFGeneralSubtreeList::iterator fromExtBegin = fromExtension->begin();
00542     CPKIFGeneralSubtreeList::iterator fromExtEnd = fromExtension->end();
00543     CPKIFGeneralSubtreeList::iterator fromExtTemp = fromExtension->begin();
00544 
00545     // for each subtree in the permitted set, see if any of the ones from the
00546     // extension are excluded and mark them as such
00547     CPKIFGeneralSubtreeList::iterator curTreesPos;
00548     CPKIFGeneralSubtreeList::iterator curTreesEnd = curTrees->end();
00549     for(curTreesPos = curTrees->begin(); curTreesPos != curTreesEnd; ++curTreesPos)
00550     {
00551         isImpossible.SetRHS(*curTreesPos);
00552         fromExtTemp = find_if(fromExtBegin, fromExtEnd, isImpossible);
00553         if(fromExtTemp != fromExtEnd)
00554         {
00555             // if a subtree that's excluded by the issuer set is found,
00556             // mark it empty and add it to the new set
00557             // with different subtree types, invalid ones need to be marked empty rather
00558             // than simply discarded
00559             CPKIFGeneralSubtreePtr empty((*fromExtTemp)->ShallowCopy());
00560             empty->SetEmpty();
00561             newSet->push_back(empty);
00562         }
00563     }
00564     // if any trees from the extension haven't been marked as empty, add them to
00565     // the new set
00566     for(fromExtTemp = fromExtBegin; fromExtTemp != fromExtEnd; ++fromExtTemp)
00567     {
00568         CPKIFGeneralSubtreeList::iterator newTreesPos;
00569         CPKIFGeneralSubtreeList::iterator newTreesEnd = newSet->end();
00570         bool found = false;
00571         for(newTreesPos = newSet->begin();!found && newTreesPos != newTreesEnd; ++newTreesPos)
00572         {
00573             if(*newTreesPos == *fromExtTemp) {
00574                 found = true;
00575             }
00576         }
00577         if(!found) {
00578             newSet->push_back(*fromExtTemp);
00579         }
00580     }
00581 
00582 }
00590 bool IsInSubtree(
00592     CPKIFGeneralSubtreeListPtr& subtree, 
00594     CPKIFCertificatePtr& curCert,
00595     bool bIsPerm)
00596 {
00597     //This function will return true if either the subject DN is found in a subtree
00598     //or ANY alt name is found in a subtree.  
00599 
00600     CPKIFGeneralSubtreeList::iterator pos;
00601     CPKIFGeneralSubtreeList::iterator end = subtree->end();
00602 
00603     CPKIFGeneralSubtree::MatchState subjectMatch = CPKIFGeneralSubtree::NOT_APPLICABLE;
00604     CPKIFNamePtr subjectName = curCert->Subject();
00605     if(subjectName != (CPKIFName*)NULL && 0 != strcmp(subjectName->ToString(), ""))
00606     {
00607         for(pos = subtree->begin();
00608             subjectMatch != CPKIFGeneralSubtree::MATCH && pos != end;
00609             ++pos)
00610         {
00611             CPKIFGeneralName::GENNAMETYPE stType = (*pos)->GetBase()->GetType();
00612             // only check the subject if the subtree is directoryName or rfc822Name
00613             if(CPKIFGeneralName::DIRECTORYNAME == stType || CPKIFGeneralName::RFC822 == stType)
00614             {
00615                 CPKIFGeneralSubtree::MatchState tmpState = (*pos)->IsInSubtree(subjectName);
00616                 // never move from NO_MATCH to NOT_APPLICABLE
00617                 if(tmpState != CPKIFGeneralSubtree::NOT_APPLICABLE) subjectMatch = tmpState;
00618             }
00619         }
00620     }
00621 
00622     CPKIFGeneralSubtree::MatchState sanMatch = CPKIFGeneralSubtree::NOT_APPLICABLE;
00623     CPKIFSubjectAltNamePtr subAltName = curCert->GetExtension<CPKIFSubjectAltName>();
00624     bool hasSAN = (subAltName != (CPKIFSubjectAltName*) 0);
00625     if( hasSAN )
00626     {
00627         CPKIFGeneralNameList genNames;
00628         subAltName->GeneralNames(genNames);
00629         CPKIFGeneralNameList::iterator gnPos;
00630         CPKIFGeneralNameList::iterator gnEnd = genNames.end();
00631         for(gnPos = genNames.begin();
00632             sanMatch != CPKIFGeneralSubtree::MATCH && gnPos != gnEnd;
00633             ++gnPos)
00634         {
00635             end = subtree->end();
00636             for(pos = subtree->begin();
00637                 sanMatch != CPKIFGeneralSubtree::MATCH && pos != end;
00638                 ++ pos)
00639             {
00640                 try {
00641                     CPKIFGeneralSubtree::MatchState tmpState = (*pos)->IsInSubtree((*gnPos));
00642                     // never move from NO_MATCH to NOT_APPLICABLE
00643                     if(tmpState != CPKIFGeneralSubtree::NOT_APPLICABLE)
00644                         sanMatch = tmpState;
00645                 }catch(CPKIFException &pe){
00646                     // GIB 4/20/2006: The code that was here before set the flag to true
00647                     // if the subjectAltName was unsupported (i.e. behaved as if it wasn't present
00648                     // Given the refactoring of this function, doing nothing now represents
00649                     // the same behavior.
00650                     // We may want to log the fact that an unsupported name type was
00651                     // encountered now
00652                     if(bIsPerm)
00653                         throw pe;
00654                 }
00655             }
00656         }
00657     }
00658     if(sanMatch == CPKIFGeneralSubtree::NO_MATCH || subjectMatch == CPKIFGeneralSubtree::NO_MATCH)
00659         return false;
00660     
00661     return true;
00662 }
00670 bool CheckNameConstraints(
00672     CPKIFCertificatePtr& curCert, 
00674     CPKIFGeneralSubtreeListPtr& permSubtrees, 
00676     CPKIFGeneralSubtreeListPtr& exclSubtrees, 
00678     bool permSubtreesHasBeenSet)
00679 {
00680     //added empty check 12/3/2003
00681     if(exclSubtrees && !exclSubtrees->empty() && IsInSubtree(exclSubtrees, curCert, false))
00682         return false;
00683 
00684     if(!permSubtrees || (permSubtrees->empty() && !permSubtreesHasBeenSet))
00685         return true;
00686     else
00687         return IsInSubtree(permSubtrees, curCert, true);
00688 }
00689 
00690 //removed export declarations 8/18/2004
00698 bool IsEmpty(CPKIFCertificateNodeListWithSourceInfoPtr& node)
00699 {
00700     return node->empty();
00701 }
00709 bool IsEmptyNameAndKey(
00711     CPKIFNameAndKeyWithScoreListPtr& node)
00712 {
00713     return node->empty();
00714 }
00722 bool IsNullCertificateSourceList(CPKIFCertificateSourceListPtr& node)
00723 {
00724     return node == (CPKIFCertificateSourceList*)NULL;
00725 }
00726 
00727 
00738 bool _GetHashOfToBeSignedCert(
00740     const CPKIFCertificate& cert, 
00742     IPKIFCryptoMisc* cryptoMisc, 
00744     PKIFCRYPTO::HASH_ALG hashAlg, 
00746     unsigned char* hashResult, 
00748     int* hashResultLen)                       //output, input/output
00749 {
00750     int stat = ASN_OK;
00751 
00752     if(NULL == cryptoMisc || NULL == hashResult)
00753         throw CPKIFPathException(TOOLKIT_PATH_VALIDATOR,COMMON_INVALID_INPUT,"Invalid input passed to certificate hash calculation function");
00754 
00755     //get a pointer to the encoded CRL and the length of the encoded CRL
00756     CPKIFBufferPtr certBuf = cert.Encoded();
00757     int length = certBuf->GetLength();
00758 
00759     if(0 == length)
00760         throw CPKIFPathException(TOOLKIT_PATH_VALIDATOR,COMMON_INVALID_INPUT,"Empty CRL passed to CRL hash calculation function");
00761 
00762     //prepare an OOCTXT object with the CRL buffer and length
00763     OOCTXT ctxt;
00764     initContext (&ctxt);
00765     setBERDecBufPtr(&ctxt, certBuf->GetBuffer(), length, NULL, NULL);
00766     OOCTXT* pctxt = &ctxt;
00767 
00768     //parse the first sequence (SIGNED macro)
00769     stat = matchTag (pctxt, TM_UNIV|TM_CONS|16, &length, XM_ADVANCE);
00770     if (stat != ASN_OK)
00771     {
00772         freeEncodeBuffer(&ctxt);
00773         memFreeAll(&ctxt);
00774         return false;
00775     }
00776 
00777     //save the offset
00778     size_t byteIndex = ctxt.buffer.byteIndex;
00779 
00780     //parse the next sequence to get the length
00781     stat = matchTag (pctxt, TM_UNIV|TM_CONS|16, &length, XM_ADVANCE);
00782     if (stat != ASN_OK)
00783     {
00784         freeEncodeBuffer(&ctxt);
00785         memFreeAll(&ctxt);
00786         return false;
00787     }
00788 
00789     //set the pointer to the offset collected above and the length to the length
00790     //returned by the second parse operation plus the offset difference.  this is the
00791     //to be signed CRL to pass to the hash function below.
00792     unsigned char* p = (unsigned char*)ctxt.buffer.data + byteIndex; 
00793 
00794     size_t tmpST = ctxt.buffer.byteIndex - byteIndex;
00795     unsigned int tmpUI = 0;
00796 
00797     try {
00798         tmpUI = numeric_cast<unsigned int>(tmpST);
00799     }catch(bad_numeric_cast &) {
00800         throw CPKIFException(TOOLKIT_PATH, COMMON_INVALID_INPUT, "Byte offset difference too large.");
00801     }
00802 
00803     length += (tmpUI);
00804 
00805     IPKIFHashContext* hash = NULL;
00806     try
00807     {
00808         //create a hash object, pass the buffer and length we calculated and obtain the result
00809         hash = cryptoMisc->HashInit(hashAlg);
00810         cryptoMisc->HashUpdate(hash, p, length);
00811         cryptoMisc->HashFinal(hash, (unsigned char*)hashResult, hashResultLen);
00812     }
00813     catch(CPKIFException& e)
00814     {
00815         if(NULL != hash)
00816             delete hash;
00817 
00818         //clean up the context
00819         freeEncodeBuffer(&ctxt);
00820         memFreeAll(&ctxt);
00821 
00822         throw e;
00823     }
00824 
00825     //clean up the hash
00826     delete hash; 
00827 
00828     //clean up the context
00829     freeEncodeBuffer(&ctxt);
00830     memFreeAll(&ctxt);
00831 
00832     return true;
00833 }
00834 
00835 //utility function to walk a path and validate all certs.  assumes the path is constructed
00836 //as follows: trust root -> begin -> next -> ... -> end where each cert is verified using the 
00837 //cert to the left in the diagram.  For clarity, root -> ICA1 (issued by root) -> ICA2 (issued by ICA1) -> EE (issued by ICA2)
00850 bool CAC_API PathSigChecker(
00852     const CPKIFCertificatePath& path, 
00854     IPKIFCryptoRawOperations* crypto, 
00856     IPKIFCryptoMisc* cryptoMisc, 
00858     CPKIFPathValidationResults& results)
00859 {
00860     //check the input - we need two interfaces here
00861     if(NULL == crypto || NULL == cryptoMisc)
00862     {
00863         RAISE_PATH_EXCEPTION("NULL crypto or cryptoMisc parameter.", TOOLKIT_PATH_VALIDATOR, COMMON_INVALID_INPUT, NULL)
00864     }
00865 
00866     //get the list of certs that comprise the path
00867     CPKIFCertificateNodeList certNodeList;
00868     path.GetPath(certNodeList);
00869 
00870     //make sure the list is not NULL and is not empty
00871     if(0 == certNodeList.size())
00872     {
00873         RAISE_PATH_EXCEPTION("Empty certificate path parameter.", TOOLKIT_PATH_VALIDATOR, COMMON_INVALID_INPUT, NULL)
00874     }
00875 
00876     //declare some variables
00877     CPKIFCertificatePtr curCert;
00878     //IPKIFNameAndKeyPtr prevCert = NULL;
00879     IPKIFNameAndKeyPtr prevCert;
00880     IPKIFTrustAnchorPtr trustRoot;
00881 
00882     //get the trust root from the path
00883     path.GetTrustRoot(trustRoot);
00884     if(trustRoot == (IPKIFTrustAnchor*)NULL)
00885     {
00886         RAISE_PATH_EXCEPTION("Path does not specify a trust root.", TOOLKIT_PATH_VALIDATOR, PATH_TRUST_ROOT_NOT_SET, NULL)
00887     }
00888 
00889     //retrieve a cert from the trust root to serve as the first "previous cert" for the loop below
00890     //CPKIFTrustRoot* ta = dynamic_cast<CPKIFTrustRoot*>(&(*(trustRoot)));
00891     //if(ta != NULL)
00892     //{
00893     //  ta->GetCert(prevCert);
00894     //  if(prevCert == (CPKIFCertificate*)NULL)
00895     //  {
00896     //      RAISE_PATH_EXCEPTION("Trust root is not a certificate.", TOOLKIT_PATH_VALIDATOR, PATH_TRUST_ROOT_NO_CERT, NULL)
00897     //  }
00898     //}
00899 
00900     //prevCert = dynamic_cast<IPKIFNameAndKey*>(&(*(trustRoot)));
00901     prevCert = boost::dynamic_pointer_cast<IPKIFNameAndKey, IPKIFTrustAnchor>(trustRoot);
00902 
00903     //working params stuff
00904     CPKIFAlgorithmIdentifierPtr workingParams = prevCert->GetSubjectPublicKeyInfo()->alg();
00905     AlgClass workingAlg = GetAlgClass(workingParams);
00906 
00907     //iterate over all certs in the list verifying each signature using the previous cert
00908     CPKIFCertificateNodeList::iterator pos;
00909     CPKIFCertificateNodeList::iterator end = certNodeList.end();
00910     for(pos = certNodeList.begin(); pos != end; ++pos)
00911     {
00912         curCert = (*pos)->GetCert();
00913         CPKIFCertStatusPtr status = (*pos)->GetStatus();
00914 
00915         //set up some variables for use in calculating hash of CRL (alg will be set up below)
00916         char hashResult[MAXHASH];
00917         int nResultLen = MAXHASH;
00918         PKIFCRYPTO::HASH_ALG hashAlg = PKIFCRYPTO::SHA1;
00919 
00920         CPKIFAlgorithmIdentifierPtr prevCertSigAlg = prevCert->GetSubjectPublicKeyInfo()->alg();
00921         CPKIFAlgorithmIdentifierPtr curCertSigAlg = curCert->SignatureAlgorithm();
00922         AlgClass prevAC = GetAlgClass(prevCertSigAlg);
00923         AlgClass curAC = GetAlgClass(curCertSigAlg);
00924         if(prevAC != curAC)
00925         {
00926             status->SetDiagnosticCode(PATH_SIGNATURE_VERIFICATION_FAILED);
00927             return false;
00928         }
00929 
00930         //for now we are supporting MD5 and SHA1 only adjust the below code accordingly when and if that changes
00931         CPKIFAlgorithmIdentifierPtr sigAlg = curCert->SignatureAlgorithm();
00932         CPKIFOIDPtr aTmpOID = sigAlg->oid();
00933         if(!GetCACHashAlg(aTmpOID/*sigAlg->oid()*/, &hashAlg))
00934             throw CPKIFPathException(TOOLKIT_PATH_CRL_CHECKER, COMMON_UNSUPPORTED_ALG);
00935 
00936         //obtain the hash of the to-be-signed CRL
00937         if(!_GetHashOfToBeSignedCert(*curCert, cryptoMisc, hashAlg, (unsigned char*)hashResult, &nResultLen))
00938             return false;
00939         
00940         //get the cert signature in a buffer
00941         CPKIFBufferPtr sigBuf = curCert->Signature();
00942         CPKIFKeyMaterial key;
00944         CPKIFTrustRootPtr tmpTA = dynamic_pointer_cast<CPKIFTrustRoot, IPKIFNameAndKey>(prevCert);
00945         if(tmpTA != (CPKIFTrustRoot*)NULL)
00946         {
00947             CPKIFCertificatePtr tmpCert;
00948             tmpTA->GetCert(tmpCert);
00949             if(tmpCert != (CPKIFCertificate*)NULL)
00950             {
00951                 CPKIFBufferPtr certBuf = tmpCert->Encoded();
00952                 key.SetCertificate(certBuf->GetBuffer(), certBuf->GetLength());
00953             }
00954         }
00955         else
00956         {
00957             CPKIFCertificatePtr tmpCert = dynamic_pointer_cast<CPKIFCertificate, IPKIFNameAndKey>(prevCert);
00958             if(tmpCert != (CPKIFCertificate*)NULL)
00959             {
00960                 CPKIFBufferPtr certBuf = tmpCert->Encoded();
00961                 key.SetCertificate(certBuf->GetBuffer(), certBuf->GetLength());
00962             }
00963         }
00964 
00965         // GCC doesn't see the return value of GetSubjectPublicKeyInfo as a reference when included inline
00966         CPKIFSubjectPublicKeyInfoPtr spki = prevCert->GetSubjectPublicKeyInfo();
00967         key.SetSubjectPublicKeyInfo(spki);
00968         key.SetWorkingParameters(workingParams);
00969 
00970         //see if it verifies
00971         if(!crypto->Verify(key, (unsigned char*)hashResult, nResultLen, (unsigned char*)sigBuf->GetBuffer(), sigBuf->GetLength(), hashAlg))
00972         {
00973             results.SetCertificate(*pos);
00974             status->SetDiagnosticCode(PATH_SIGNATURE_VERIFICATION_FAILED);
00975             return false;
00976         }
00977         else
00978             status->SetSignatureVerified(true);
00979 
00980         //prevCert = dynamic_cast<IPKIFNameAndKey*>(&(*(curCert)));
00981         prevCert = dynamic_pointer_cast<IPKIFNameAndKey, CPKIFCertificate>(curCert);
00982         CPKIFAlgorithmIdentifierPtr prevAlgParams = prevCert->GetSubjectPublicKeyInfo()->alg();
00983         if(workingAlg != GetAlgClass(prevAlgParams))
00984         {
00985             //if the alg type changed then we need to clear the working parameters
00986             CPKIFAlgorithmIdentifierPtr tmpAI;
00987             workingParams = tmpAI;
00988             workingAlg = GetAlgClass(prevAlgParams); //added 12/2/2003
00989         }
00990         //if the alg class is the same - see if the most recent cert has params
00991         //if it does use them - if not stick with the ones that were previously set
00992         if(prevCert->GetSubjectPublicKeyInfo()->alg()->hasParameters())
00993             workingParams = prevAlgParams;
00994     }
00995 
00996     //the path has earned another check mark
00997     results.SetCertSignaturesVerified(true);
00998     results.SetWorkingParams(workingParams);
00999 
01000     return true;
01001 }
01013 void CAC_API FindErrorAndSetOnResults(
01015     const CPKIFCertificatePath& path, 
01018     CPKIFPathValidationResults& results)
01019 {
01020     CPKIFCertificateNodeList pathList;
01021     path.GetPath(pathList);
01022     bool bStatusSet = false;
01023     CPKIFCertificateNodeList::iterator pathPos;
01024     CPKIFCertificateNodeList::iterator pathEnd = pathList.end();
01025     for(pathPos = pathList.begin(); pathPos != pathEnd; ++pathPos)
01026     {
01027         CPKIFCertStatusPtr status = (*pathPos)->GetStatus();
01028         if(status)
01029         {
01030             if(results.GetRevocationStatusMostSevere() > status->GetRevocationStatus())
01031             {
01032                 results.SetRevocationStatusMostSevere(status->GetRevocationStatus());
01033 
01034                 //we want to avoid setting revocation not determined if something more interesting
01035                 //is set but want revoked to be there always
01036                 if(REVOKED == status->GetRevocationStatus() && 0 != status->GetDiagnosticCode())
01037                 {
01038                     results.SetCertificate(*pathPos);
01039                     results.SetCertStatus(status);
01040                     bStatusSet = true;
01041                 }
01042             }
01043             if(!bStatusSet && 0 != status->GetDiagnosticCode())
01044             {               
01045                 results.SetCertificate(*pathPos);
01046                 results.SetCertStatus(status);
01047                 bStatusSet = true;
01048             }
01049         }
01050     }
01051 }
01052 
01053 
01054 
01055 
01056 
01057 

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