00001
00009 #include "PKIFPathBuilder2.h"
00010 #include "PKIFBasicPathState2.h"
00011 #include "PKIFPathSettings.h"
00012 #include "IPKIFCertRepository.h"
00013 #include "IPKIFCertRepositoryUpdate.h"
00014 #include "IPKIFTrustCache.h"
00015 #include "IPKIFCRLRepository.h"
00016 #include "PKIFMediators.h"
00017
00018 #include "ToolkitUtils.h"
00019 #include "BuilderUtils.h"
00020 #include "BasicChecksUtils.h"
00021 #include "GottaMatch.h"
00022 #include "BuilderStatistics.h"
00023
00024 #include "PKIFPathException.h"
00025 #include "PKIFErrors.h"
00026 #include "PKIFCertificateNodeEntry.h"
00027 #include "Name.h"
00028 #include "Certificate.h"
00029 #include "CertificateNodeListWithSourceInfo.h"
00030 #include "PKIFDefaultScoring.h"
00031 #include "PKIFTrustRoot.h"
00032 #include "NodeInNodeList.h"
00033 #include "PKIFCertStatus.h"
00034 #include "PKIFCertificatePath.h"
00035 #include "PKIFPathLogger.h"
00036 #include "PathResults.h"
00037 #include "AuthorityKeyIdentifier.h"
00038 #include <sstream>
00039
00040 #include <boost/shared_ptr.hpp>
00041 #include "boost/numeric/conversion/cast.hpp"
00042
00043 using boost::numeric_cast;
00044 using boost::bad_numeric_cast;
00045
00046 #include <iterator>
00047
00048 using namespace std;
00049 using namespace boost;
00050
00051
00052 extern bool KeyIDsMatch(CPKIFAuthorityKeyIdentifierPtr& akid, const IPKIFTrustAnchorPtr& curCert);
00053
00054 #ifdef _DEBUG_PATH_DUMP
00055 #include <fstream>
00056 ofstream g_pathLogFile;
00057 #endif
00058
00064 class KeyIDCompare
00065 {
00066 public:
00074 bool operator()(const IPKIFTrustAnchorPtr& lhsTA, const IPKIFTrustAnchorPtr& rhsTA)
00075 {
00076 int lhsScore = 0, rhsScore = 0;
00077
00078 CPKIFAuthorityKeyIdentifierPtr akid = m_currentCert->GetExtension<CPKIFAuthorityKeyIdentifier>();
00079
00080 if(lhsTA)
00081 {
00082 if(KeyIDsMatch(akid, lhsTA))
00083 {
00084 lhsScore+=5;
00085 }
00086 }
00087 if(rhsTA)
00088 {
00089 if(KeyIDsMatch(akid, rhsTA))
00090 {
00091 rhsScore+=5;
00092 }
00093 }
00094
00095 return lhsScore > rhsScore;
00096 }
00104 void SetCurrent(
00106 const CPKIFCertificatePtr& current) {m_currentCert = current;}
00107 private:
00108 CPKIFCertificatePtr m_currentCert;
00109 };
00110
00112 struct CPKIFPathBuilder2Impl
00113 {
00114 CPKIFPathBuilder2 *m_parent;
00115
00116
00117 bool BuildOrGrowTable(CPKIFBasicPathState2* basicState, CPKIFPathSettingsPtr& settings, CPKIFCertificatePtr& curCert, CPKIFCertificateNodeList& prevPath);
00118
00119
00120 bool GrowTable(CPKIFBasicPathState2* basicState, IPKIFCertRepository* iCert,
00121 IPKIFCertRepositoryUpdate* iCertUpdate, IPKIFTrustCache* iTrust, CPKIFPathSettingsPtr& settings);
00122
00123
00124 bool CheckAlternatives(CPKIFCertificatePath& path, CPKIFBasicPathState2* basicState);
00125
00126
00127
00128 void PuntCurrentRoot(CPKIFBasicPathState2* basicState, IPKIFTrustAnchorList& roots);
00129
00130
00131 bool PuntTopRow(CPKIFBasicPathState2* basicState, CPKIFNamePtr& prevName,
00132 CPKIFCertificatePtr& curCert, IPKIFCertRepository* iCert, IPKIFCertRepositoryUpdate* iCertUpdate,
00133 IPKIFTrustCache* iTrust, CPKIFPathSettingsPtr& settings);
00134
00135
00136 void RemoveLoopMakers(CPKIFCertificateNodeList& certList, CPKIFBasicPathState2* basicState, CPKIFCertificateNodeListWithSourceInfoPtr& currPos, bool growingRow = false);
00137
00138 void SearchForFailure(CPKIFBasicPathState2* basicState, CPKIFCertificateNodeList& prevPath, CPKIFPathSettingsPtr& settings);
00139 bool PuntFailure(CPKIFBasicPathState2* basicState, CPKIFCertificateNodeEntryPtr& ppPos);
00140
00141 bool GrowRow(CPKIFCertificateNodeListWithSourceInfoPtr& pos, IPKIFCertRepository* iCert, IPKIFCertRepositoryUpdate* iCertUpdate, CPKIFBasicPathState2* basicState,
00142 CPKIFCertificatePtr& curCert, IPKIFTrustCache* iTrust, CPKIFPathSettingsPtr& settings, CPKIFCertificateNodeListWithSourceInfoPtr& posPlusOne);
00143 };
00145
00153 CPKIFPathBuilder2::CPKIFPathBuilder2(void)
00154 :m_impl(new CPKIFPathBuilder2Impl)
00155 {
00156 LOG_STRING_DEBUG("CPKIFPathBuilder2::CPKIFPathBuilder2", thisComponent, 0, this);
00157 m_impl->m_parent = this;
00158 }
00166 CPKIFPathBuilder2::~CPKIFPathBuilder2(void)
00167 {
00168 LOG_STRING_DEBUG("CPKIFPathBuilder2::~CPKIFPathBuilder2", thisComponent, 0, this);
00169
00170 delete m_impl;
00171 m_impl = 0;
00172 }
00180 void CPKIFPathBuilder2::Initialize()
00181 {
00182 LOG_STRING_DEBUG("CPKIFPathBuilder2::Initialize()", thisComponent, 0, this);
00183 }
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00205 bool CPKIFPathBuilder2Impl::GrowRow(
00207 CPKIFCertificateNodeListWithSourceInfoPtr& pos,
00209 IPKIFCertRepository* iCert,
00211 IPKIFCertRepositoryUpdate* iCertUpdate,
00213 CPKIFBasicPathState2* basicState,
00215 CPKIFCertificatePtr& curCert,
00217 IPKIFTrustCache* iTrust,
00219 CPKIFPathSettingsPtr& settings,
00221 CPKIFCertificateNodeListWithSourceInfoPtr& posPlusOne)
00222 {
00223 if(LOCAL == pos->m_maxSource)
00224 {
00225
00226
00227
00228 CPKIFCertificateNodeListWithSourceInfo::iterator nodeListPos;
00229 CPKIFCertificateNodeListWithSourceInfo::iterator nodeListEnd = pos->end();
00230 for(nodeListPos = pos->begin(); nodeListPos != nodeListEnd; ++nodeListPos)
00231 {
00232 if(LOCAL != (*nodeListPos)->GetSource())
00233 return false;
00234 }
00235 }
00236
00237 if(NULL == basicState->m_reserved)
00238 return false;
00239
00240 CPKIFCertificatePtr frontCert = pos->front()->GetCert();
00241 CPKIFNamePtr curCertSubject = frontCert->Subject();
00242 CPKIFCertificateNodeList certList;
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254 if(posPlusOne)
00255 {
00256 CPKIFCertificateNodeListWithSourceInfo::iterator tPos = posPlusOne->begin();
00257 CPKIFCertificateNodeListWithSourceInfo::iterator tEnd = posPlusOne->end();
00258 for(;tPos != tEnd; ++tPos)
00259 {
00260 CPKIFCertificatePtr tCert = (*tPos)->GetCert();
00261 iCert->GetCertificates(tCert, certList, REMOTE);
00262 }
00263 }
00264
00265
00266
00267 iCert->GetCertificates(frontCert, certList, REMOTE);
00268
00269 pos->m_maxSource = REMOTE;
00270 basicState->m_maxSource = ALL;
00271 size_t certListSize = certList.size();
00272 if(0 != certListSize)
00273 {
00274
00275 RemoveLoopMakers(certList, basicState, pos, true);
00276 certListSize = certList.size();
00277 }
00278
00279 if(0 == certListSize)
00280 return false;
00281 else
00282 {
00283 bool retval = false;
00284
00285
00286 CPKIFCertificateNodeList::iterator certListPos;
00287 CPKIFCertificateNodeList::iterator certListEnd = certList.end();
00288 for(certListPos = certList.begin(); certListPos != certListEnd; ++certListPos)
00289 {
00290
00291 if(*curCertSubject == *(*certListPos)->GetCert()->Subject())
00292 {
00293 GottaMatch<CPKIFCertificateNodeEntryPtr> gm;
00294 gm.SetRHS(*certListPos);
00295 if(pos->end() == find_if(pos->begin(), pos->end(), gm))
00296 {
00297
00298 if(iCertUpdate && LOCAL != (*certListPos)->GetSource())
00299 {
00300 try
00301 {
00302 iCertUpdate->AddCertificate(CA, *certListPos);
00303 }
00304 catch(CPKIFException&)
00305 {
00306
00307 }
00308 }
00309
00310 basicState->m_maxSource = ALL;
00311 pos->push_back(*certListPos);
00312 pos->m_maxSource = ALL;
00313 retval = true;
00314 }
00315 }
00316 }
00317
00318 if(retval)
00319 {
00320
00321 CPKIFDefaultScoring s;
00322
00323
00324
00325
00326 int size = 0;
00327 try
00328 {
00329 size = numeric_cast<int>(basicState->m_table.size());
00330 }
00331 catch(bad_numeric_cast &)
00332 {
00333 throw CPKIFException(TOOLKIT_PATH, COMMON_INVALID_INPUT, "Bable size is an impossibly long number.");
00334 }
00335 s.ScoreAndSortNodes(pos, curCert, settings, iTrust, size - 1,iCert);
00336 retval = pos->size() != 0;
00337 }
00338
00339 return retval;
00340 }
00341 }
00342
00343
00344
00345
00346
00347
00348
00349
00360 bool CPKIFPathBuilder2Impl::GrowTable(
00362 CPKIFBasicPathState2* basicState,
00364 IPKIFCertRepository* iCert,
00366 IPKIFCertRepositoryUpdate* iCertUpdate,
00368 IPKIFTrustCache* iTrust,
00370 CPKIFPathSettingsPtr& settings)
00371 {
00372 bool retVal = false;
00373
00374 CPKIFCertificatePtr curCert;
00375 if(!basicState->m_table.empty())
00376 {
00377
00378 curCert = basicState->m_table.front()->front()->GetCert();
00379 }
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401 vector<CPKIFCertificateNodeListWithSourceInfoPtr>::reverse_iterator pos = basicState->m_table.rbegin();
00402 vector<CPKIFCertificateNodeListWithSourceInfoPtr>::reverse_iterator end = basicState->m_table.rend();
00403 for(; pos != end; ++pos)
00404 {
00405
00406
00407 if(LOCAL == (*pos)->m_maxSource && !(*pos)->empty() && (pos + 1) != end)
00408 {
00409 if(GrowRow(*pos, iCert, iCertUpdate, basicState, curCert, iTrust, settings, *(pos + 1)))
00410 {
00411 retVal = true;
00412 if(basicState->m_table.rbegin() == pos)
00413 {
00414 basicState->m_curRoot = NULL;
00415 }
00416 }
00417 }
00418
00419 if(0 == (*pos)->size())
00420 return false;
00421 else
00422 curCert = (*pos)->front()->GetCert();
00423 }
00424
00425 return retVal;
00426 }
00427
00428
00429
00430
00431
00432
00440 void CPKIFPathBuilder2Impl::PuntCurrentRoot(
00442 CPKIFBasicPathState2* basicState,
00444 IPKIFTrustAnchorList& oldRoots)
00445 {
00446
00447 copy(basicState->m_rootList.begin(), basicState->m_rootList.end(), back_inserter(oldRoots));
00448
00449
00450 basicState->m_rootList.clear();
00451
00452
00453 basicState->ClearState();
00454 }
00455
00456
00457
00458
00459
00460
00461
00472 void CPKIFPathBuilder2Impl::RemoveLoopMakers(
00474 CPKIFCertificateNodeList& certList,
00476 CPKIFBasicPathState2* basicState,
00478 CPKIFCertificateNodeListWithSourceInfoPtr& currPos,
00480 bool growingRow)
00481 {
00482
00483 if(basicState->m_table.empty())
00484 return;
00485
00486
00487
00488
00489 CPKIFCertificateNodeList builtPath;
00490 vector<CPKIFCertificateNodeListWithSourceInfoPtr>::reverse_iterator pos = basicState->m_table.rbegin();
00491 vector<CPKIFCertificateNodeListWithSourceInfoPtr>::reverse_iterator end = basicState->m_table.rend();
00492 if(growingRow && pos != end)
00493 ++pos;
00494
00495 CPKIFCertificatePtr currPosCert = currPos->front()->GetCert();
00496 while(pos != end && !(*pos)->empty() && !(*(*pos)->front()->GetCert() == *currPosCert))
00497 {
00498 ++pos;
00499 }
00500
00501
00502
00503
00504 for(; pos != end; ++pos)
00505 {
00506 if(!(*pos)->empty())
00507 builtPath.push_back((*pos)->front());
00508 }
00509
00510 #ifdef _DEBUG
00511 size_t size = certList.size();
00512 #endif
00513
00514
00515 NodeInNodeList n;
00516 n.SetNodeList(&builtPath);
00517
00518
00519
00520
00521 CPKIFCertificateNodeList::iterator newEnd = remove_if(certList.begin(), certList.end(), n);
00522 certList.erase(newEnd, certList.end());
00523
00524 #ifdef _DEBUG
00525 size = certList.size();
00526 #endif
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540 }
00541
00542
00543
00544
00552 bool CPKIFPathBuilder2Impl::PuntTopRow(
00554 CPKIFBasicPathState2* basicState,
00556 CPKIFNamePtr& prevName,
00559 CPKIFCertificatePtr& curCert,
00561 IPKIFCertRepository* iCert,
00563 IPKIFCertRepositoryUpdate* iCertUpdate,
00565 IPKIFTrustCache* iTrust,
00567 CPKIFPathSettingsPtr& settings)
00568 {
00569
00570
00571
00572
00573
00574 CPKIFCertificatePtr nullCert;
00575 curCert = nullCert;
00576
00577
00578 vector<CPKIFCertificateNodeListWithSourceInfoPtr>::reverse_iterator pos = basicState->m_table.rbegin();
00579 vector<CPKIFCertificateNodeListWithSourceInfoPtr>::reverse_iterator end = basicState->m_table.rend();
00580 do
00581 {
00582
00583 for(; pos != end && (pos+1) != end; ++pos)
00584 {
00585
00586 if(LOCAL == (*pos)->m_maxSource && !(*pos)->empty() && (pos + 1) != end)
00587 {
00588 LOG_STRING_INFO("Failed to find necessary certificates using LOCAL sources. Checking REMOTE sources.", m_parent->thisComponent, 0, this);
00589 if(GrowRow(*pos, iCert, iCertUpdate, basicState, curCert, iTrust, settings, *(pos + 1)))
00590 break;
00591 }
00592
00593
00594 CPKIFNamePtr tmpName = (*pos)->front()->GetCert()->Subject();
00595
00596 #ifdef _DEBUG
00597 const char* curCertIssuerString = prevName->ToString();
00598 const char* curCertSubjectString = tmpName->ToString();
00599 size_t size = (*pos)->size();
00600 #endif
00601
00602
00603 RemoveAllIssuedBy(*pos, prevName);
00604
00605 #ifdef _DEBUG
00606 size = (*pos)->size();
00607 #endif
00608
00609
00610
00611
00612 prevName = tmpName;
00613
00614
00615 if(!(*pos)->empty())
00616 break;
00617 }
00618
00619
00620 if(pos != end && (pos+1) != end)
00621 curCert = (*pos)->front()->GetCert();
00622 else
00623 break;
00624 }while(curCert == (CPKIFCertificate*)NULL);
00625
00626
00627 vector<CPKIFCertificateNodeListWithSourceInfoPtr>::iterator newEnd = remove_if(basicState->m_table.begin(), basicState->m_table.end(), IsEmpty);
00628 basicState->m_table.erase(newEnd, basicState->m_table.end());
00629
00630
00631
00632
00633
00634
00635
00636 if(curCert == (IPKIFNameAndKey*)NULL || basicState->m_table.size() == 0)
00637 return false;
00638 else
00639 {
00640 basicState->m_bInitCompleteLocal = false;
00641 return true;
00642 }
00643 }
00644
00645
00646
00647
00655 bool CPKIFPathBuilder2Impl::PuntFailure(
00657 CPKIFBasicPathState2* basicState,
00659 CPKIFCertificateNodeEntryPtr& ppPos)
00660 {
00661
00662
00663 CPKIFNamePtr nodeName = ppPos->GetCert()->Subject();
00664 CPKIFNamePtr nextNodeName;
00665 vector<CPKIFCertificateNodeListWithSourceInfoPtr>::reverse_iterator pos = basicState->m_table.rbegin();
00666 vector<CPKIFCertificateNodeListWithSourceInfoPtr>::reverse_iterator end = basicState->m_table.rend();
00667 for(; pos != end; ++pos)
00668 {
00669 CPKIFNamePtr tmpName = (*pos)->front()->GetCert()->Subject();
00670
00671 #ifdef _DEBUG
00672 const char* curNodeString = nodeName->ToString();
00673 const char* curCertSubjectString = tmpName->ToString();
00674 #endif
00675
00676 if(*tmpName == *nodeName)
00677 {
00678 size_t size = (*pos)->size();
00679 GottaMatch<CPKIFCertificateNodeEntryPtr > gm;
00680 gm.SetRHS(ppPos);
00681
00682 CPKIFCertificateNodeListWithSourceInfo::iterator newEnd = remove_if((*pos)->begin(), (*pos)->end(), gm);
00683 (*pos)->erase(newEnd, (*pos)->end());
00684
00685 size = (*pos)->size();
00686 if(0 == size)
00687 {
00688
00689 basicState->m_rootList.clear();
00690
00691
00692 int indexer = 0;
00693
00694 do
00695 {
00696 ++indexer;
00697
00698
00699 if((pos+indexer) == end)
00700 break;
00701
00702
00703 nextNodeName = (*(pos+indexer))->front()->GetCert()->Subject();
00704
00705
00706
00707 RemoveAllIssuedBy(*(pos+indexer), nodeName);
00708
00709
00710 nodeName = nextNodeName;
00711 }while(0 == (*(pos+indexer))->size());
00712
00713 vector<CPKIFCertificateNodeListWithSourceInfoPtr>::iterator newEnd = find_if(basicState->m_table.begin(), basicState->m_table.end(), IsEmpty);
00714 basicState->m_table.erase(newEnd, basicState->m_table.end());
00715 }
00716 break;
00717 }
00718 }
00719
00720 if(0 == basicState->m_table.size())
00721 return false;
00722 else
00723 {
00724 return true;
00725 }
00726 }
00727
00728
00729
00730
00738 void CPKIFPathBuilder2Impl::SearchForFailure(
00740 CPKIFBasicPathState2* basicState,
00742 CPKIFCertificateNodeList& prevPath,
00743 CPKIFPathSettingsPtr& settings)
00744 {
00745 CPKIFGeneralSubtreeListPtr perm, excl;
00746 settings->GetInitialPermSubtrees(perm);
00747 settings->GetInitialExclSubtrees(excl);
00748 bool permHasBeenSet = false;
00749 if(perm)
00750 permHasBeenSet = true;
00751
00752 CPKIFCertificateNodeList::iterator ppPos;
00753 CPKIFCertificateNodeList::iterator ppEnd = prevPath.end();
00754 bool removeTheOffendingCert = false;
00755 for(ppPos = prevPath.begin(); ppPos != ppEnd; ++ppPos)
00756 {
00757 CPKIFCertStatusPtr status = (*ppPos)->GetStatus();
00758
00759 if(status)
00760 {
00761
00762
00763 if(PATH_NAME_CONSTRAINTS_VIOLATION == status->GetDiagnosticCode())
00764 {
00765 CPKIFCertificatePtr cert = (*ppPos)->GetCert();
00766 if(!CheckNameConstraints(cert, perm, excl, permHasBeenSet))
00767 removeTheOffendingCert = true;
00768 break;
00769 }
00770 else if(REVOKED == status->GetRevocationStatus())
00771 {
00772 removeTheOffendingCert = true;
00773 break;
00774 }
00775 else if(ppPos == ppEnd -1 &&
00776 (PATH_VALIDITY_PERIOD_VIOLATION_NOT_YET_VALID == status->GetDiagnosticCode()
00777 || PATH_VALIDITY_PERIOD_VIOLATION_EXPIRED == status->GetDiagnosticCode()))
00778 {
00779 removeTheOffendingCert = true;
00780 break;
00781 }
00782 }
00783 }
00784
00785 if(ppPos != ppEnd)
00786 {
00787 if(removeTheOffendingCert)
00788 {
00789
00790 PuntFailure(basicState, *ppPos);
00791 }
00792 else
00793 (*ppPos)->SetIgnore();
00794 }
00795 }
00796
00797
00798
00799
00812 bool CPKIFPathBuilder2Impl::BuildOrGrowTable(
00814 CPKIFBasicPathState2* basicState,
00816 CPKIFPathSettingsPtr& settings,
00818 CPKIFCertificatePtr& curCert,
00820 CPKIFCertificateNodeList& prevPath)
00821 {
00822
00823
00824
00825
00826
00827
00828
00829 IPKIFCertRepository* iCert = m_parent->GetMediatorFromParent<IPKIFCertRepository>();
00830 IPKIFTrustCache* iTrust = m_parent->GetMediatorFromParent<IPKIFTrustCache>();
00831 if(NULL == iCert || NULL == iTrust)
00832 throw CPKIFPathException(m_parent->thisComponent, COMMON_MEDIATOR_MISSING, "IPKIFCertRepository and/or IPKIFTrustCache are not available.");
00833
00834
00835 IPKIFCertRepositoryUpdate* iCertUpdate = m_parent->GetMediatorFromParent<IPKIFCertRepositoryUpdate>();
00836
00837
00838 IPKIFCRLRepository* iCRL = m_parent->GetMediatorFromParent<IPKIFCRLRepository>();
00839
00840
00841
00842
00843 bool skipRootCheck = false;
00844
00845 CPKIFDefaultScoring s;
00846
00847
00848 IPKIFTrustAnchorList oldRoots;
00849
00850
00851 if(!basicState->m_rootList.empty())
00852 {
00853
00854 if(GrowTable(basicState, iCert, iCertUpdate, iTrust, settings))
00855 return true;
00856
00857
00858 PuntCurrentRoot(basicState, oldRoots);
00859 skipRootCheck = true;
00860
00861
00862
00863 if(!basicState->m_table.empty() && !basicState->m_table.back()->empty())
00864 curCert = basicState->m_table.back()->front()->GetCert();
00865 else
00866 {
00867 return false;
00868 }
00869 }
00870 else if(curCert == (CPKIFCertificate*)NULL)
00871 {
00872 return false;
00873 }
00874
00875
00876 IPKIFTrustAnchorList trustRootList;
00877 CPKIFNamePtr curCertIssuer, curCertSubject;
00878
00879
00880 bool foundPath = false;
00881
00882 PKIInfoSource oldSource = basicState->m_maxSource;
00883
00884 size_t tableSize = 0;
00885 do
00886 {
00887
00888 tableSize = basicState->m_table.size();
00889 curCertIssuer = curCert->GetIssuerName();
00890
00891 #ifdef _DEBUG
00892 curCertSubject = curCert->GetSubjectName();
00893 const char* curCertIssuerString = curCertIssuer->ToString();
00894 const char* curCertSubjectString = curCertSubject->ToString();
00895 #endif
00896
00897
00898 if(!skipRootCheck && iTrust->GetTrustRoots(curCertIssuer, trustRootList))
00899 {
00900 KeyIDCompare keyIDComp;
00901 keyIDComp.SetCurrent(curCert);
00902 sort(trustRootList.begin(), trustRootList.end(), keyIDComp);
00903
00904
00905 basicState->SetTrustRoot(trustRootList);
00906
00907 foundPath = true;
00908 break;
00909 }
00910 else
00911 {
00912 skipRootCheck = false;
00913
00914 CPKIFCertificateNodeList certList;
00915
00916
00917
00918
00919 iCert->GetCertificates(curCert, certList, basicState->m_maxSource);
00920 size_t certListSize = certList.size();
00921 do
00922 {
00923 if((0 == certListSize || LOCAL < basicState->m_maxSource) && NULL != basicState->m_reserved )
00924 {
00925 LOG_STRING_INFO("Failed to find necessary certificates using LOCAL sources. Checking REMOTE sources.", m_parent->thisComponent, 0, this);
00926
00927
00928
00929
00930
00931
00932 iCert->GetCertificates(curCert, certList, REMOTE);
00933 certListSize = certList.size();
00934
00935 basicState->m_maxSource = ALL;
00936 }
00937
00938 if(0 != certListSize)
00939 {
00940
00941 RemoveLoopMakers(certList, basicState, *basicState->m_table.rbegin());
00942
00943
00944 IPKIFTrustAnchorList::iterator orPos;
00945 IPKIFTrustAnchorList::iterator orEnd = oldRoots.end();
00946 for(orPos = oldRoots.begin(); orPos != orEnd; ++orPos)
00947 {
00948
00949
00950 CPKIFCertificatePtr taCert = (*orPos)->GetCertificate();
00951 if(taCert)
00952 {
00953 CPKIFCertificateNodeEntryPtr newNode(new CPKIFCertificateNodeEntry);
00954 newNode->SetCert(taCert);
00955
00956 GottaMatch<CPKIFCertificateNodeEntryPtr> orGM;
00957 orGM.SetRHS(newNode);
00958
00959 CPKIFCertificateNodeList::iterator newEnd = remove_if(certList.begin(), certList.end(), orGM);
00960 certList.erase(newEnd, certList.end());
00961 }
00962 }
00963
00964 certListSize = certList.size();
00965 }
00966 }
00967 while(0 == certListSize && LOCAL == basicState->m_maxSource && NULL != basicState->m_reserved);
00968
00969 if(0 == certListSize)
00970 {
00971
00972 PuntTopRow(basicState, curCertIssuer, curCert, iCert, iCertUpdate, iTrust, settings);
00973
00974 if(basicState->m_maxSource == REMOTE)
00975 basicState->m_maxSource = ALL;
00976 }
00977 else
00978 {
00979
00980
00981
00982
00983
00984 CPKIFCertificateNodeListWithSourceInfoPtr tmpNodeList(new CPKIFCertificateNodeListWithSourceInfo);
00985 tmpNodeList->m_maxSource = basicState->m_maxSource;
00986 CPKIFCertificateNodeList::iterator pos;
00987 CPKIFCertificateNodeList::iterator end = certList.end();
00988 for(pos = certList.begin(); pos != end; ++pos)
00989 {
00990
00991 if(*curCertIssuer == *(*pos)->GetCert()->Subject())
00992 {
00993 GottaMatch<CPKIFCertificateNodeEntryPtr> gm;
00994 gm.SetRHS(*pos);
00995 if(tmpNodeList->end() == find_if(tmpNodeList->begin(), tmpNodeList->end(), gm))
00996 {
00997
00998 if(iCertUpdate && LOCAL != (*pos)->GetSource())
00999 {
01000 try
01001 {
01002 iCertUpdate->AddCertificate(CA, *pos);
01003 }
01004 catch(CPKIFException& )
01005 {
01006
01007 }
01008 }
01009
01010 tmpNodeList->push_back(*pos);
01011 }
01012 }
01013 }
01014
01015
01016
01017
01018 int size = 0;
01019 try
01020 {
01021 size = numeric_cast<int>(basicState->m_table.size());
01022 }
01023 catch(bad_numeric_cast &)
01024 {
01025 throw CPKIFException(TOOLKIT_PATH, COMMON_INVALID_INPUT, "Table size is an impossibly long number.");
01026 }
01027 s.ScoreAndSortNodes(tmpNodeList, curCert, settings, iTrust, size - 1, iCert);
01028
01029
01030 size_t stDepth = settings->GetDepth();
01031 if(0 != tmpNodeList->size() && tableSize < stDepth)
01032 {
01033 basicState->m_table.push_back(tmpNodeList);
01034 curCert = tmpNodeList->front()->GetCert();
01035 }
01036 else
01037 {
01038 PuntTopRow(basicState, curCertIssuer, curCert, iCert, iCertUpdate, iTrust, settings);
01039
01040 if(basicState->m_maxSource == REMOTE)
01041 basicState->m_maxSource = ALL;
01042 }
01043 }
01044
01045 if(curCert == (CPKIFCertificate*)NULL)
01046 break;
01047 }
01048 }while(1);
01049
01050 if(curCert == (CPKIFCertificate*)NULL)
01051 return false;
01052 else
01053 {
01054 if(oldSource != basicState->m_maxSource)
01055 {
01056
01057
01058
01059 GrowTable(basicState, iCert, iCertUpdate, iTrust, settings);
01060 }
01061 if(0 == basicState->m_nGrowCount && LOCAL == basicState->m_maxSource)
01062 basicState->m_bInitCompleteLocal = true;
01063
01064 ++basicState->m_nGrowCount;
01065
01066 vector<CPKIFCertificateNodeListWithSourceInfoPtr>::reverse_iterator pos;
01067 vector<CPKIFCertificateNodeListWithSourceInfoPtr>::reverse_iterator end = basicState->m_table.rend();
01068 CPKIFNamePtr issuerName = basicState->m_rootList.front()->GetSubjectName();
01069 for(pos = basicState->m_table.rbegin(); pos != end; ++pos)
01070 {
01071 IgnoreNotIssuedBy(*pos, issuerName);
01072 issuerName = (*pos)->front()->GetCert()->Subject();
01073 }
01074
01075 return true;
01076 }
01077 }
01078
01079
01080
01081
01093 bool CPKIFPathBuilder2Impl::CheckAlternatives(
01095 CPKIFCertificatePath& path,
01097 CPKIFBasicPathState2* basicState)
01098 {
01099
01100
01101 if(basicState->m_rootList.empty() || 0 == basicState->m_table.size())
01102 return false;
01103 CPKIFBuilderStatisticsPtr bs;
01104 path.GetBuilderStats(bs);
01105
01106 do
01107 {
01108 if(basicState->m_curRoot == NULL)
01109 {
01110
01111 basicState->m_curRoot = &basicState->m_rootList.front();
01112 }
01113 else
01114 {
01115
01116 vector<CPKIFCertificateNodeListWithSourceInfoPtr>::reverse_iterator tablePos;
01117 vector<CPKIFCertificateNodeListWithSourceInfoPtr>::reverse_iterator tableEnd = basicState->m_table.rend();
01118 for(tablePos = basicState->m_table.rbegin(); tablePos != tableEnd; ++tablePos)
01119 {
01120 if(!SetNextToIgnore(*tablePos))
01121 {
01122
01123 break;
01124 }
01125 else
01126 {
01127
01128 ClearAllIgnore(*tablePos);
01129 }
01130 }
01131 if(tablePos == tableEnd)
01132 {
01133 bool liveMore = false;
01134
01135
01136 if(basicState->m_rootList.size() > 1)
01137 {
01138 bool setNext = false;
01139 IPKIFTrustAnchorList::iterator rootPos;
01140 IPKIFTrustAnchorList::iterator rootEnd = basicState->m_rootList.end();
01141 for(rootPos = basicState->m_rootList.begin(); rootPos != rootEnd; ++rootPos)
01142 {
01143 if(setNext)
01144 {
01145 basicState->m_curRoot = &(*rootPos);
01146 liveMore = true;
01147 break;
01148 }
01149 else
01150 {
01151 if(basicState->m_curRoot == &(*rootPos))
01152 setNext = true;
01153 }
01154 }
01155 }
01156
01157 if(!liveMore)
01158 return false;
01159 }
01160 }
01161
01162
01163
01164
01165
01166
01167
01168 CPKIFCertificateNodeList builtPath;
01169 vector<CPKIFCertificateNodeListWithSourceInfoPtr>::reverse_iterator pos;
01170 vector<CPKIFCertificateNodeListWithSourceInfoPtr>::reverse_iterator end = basicState->m_table.rend();
01171 CPKIFCertificateNodeEntryPtr curEntry;
01172 bool hasCycle = false;
01173 PKIInfoSource pathMaxSource = LOCAL;
01174 CPKIFNamePtr issuerName = (*basicState->m_curRoot)->GetSubjectName();
01175
01176 IPKIFNameAndKey* lastCert = dynamic_cast<IPKIFNameAndKey*>(&(*(*basicState->m_curRoot)));
01177 IPKIFNameAndKey* taCert = lastCert;
01178
01179 CPKIFPathSettingsPtr settings;
01180 path.GetPathSettings(settings);
01181
01182 for(pos = basicState->m_table.rbegin(); pos != end; ++pos)
01183 {
01184 curEntry = GetFirstNonIgnoredNodeNotAlreadyInPathIssuedBy(*pos, builtPath,lastCert,settings);
01185 if(curEntry != (CPKIFCertificateNodeEntry*)NULL
01186 && !curEntry->GetCert()->SameDNSameKey(*taCert))
01187 {
01188 builtPath.push_back(curEntry);
01189
01190 lastCert = NULL;
01191 lastCert = dynamic_cast<IPKIFNameAndKey*>(&(*curEntry->GetCert()));
01192
01193 if(pathMaxSource < curEntry->GetSource())
01194 pathMaxSource = curEntry->GetSource();
01195 }
01196 else
01197 {
01198 if(curEntry)
01199 curEntry->SetIgnore();
01200
01201 hasCycle = true;
01202 break;
01203 }
01204 }
01205
01206
01207
01208
01209 #ifdef _DEBUG_PATH_DUMP
01210 {
01211 if(!g_pathLogFile.is_open())
01212 {
01213 g_pathLogFile.open("_DEBUG_PATH_DUMP_PathLog.txt", ios::out);
01214 }
01215 CPKIFCertificatePath dbgpath;
01216 dbgpath.SetPath(builtPath);
01217 CPKIFPathLogger pl;
01218 pl.LogPath(dbgpath, "_DEBUG_PATH_DUMP", &g_pathLogFile);
01219 if(hasCycle)
01220 g_pathLogFile << "HasCycle = true" << endl;
01221 else
01222 g_pathLogFile << "HasCycle = false" << endl;
01223 }
01224 #endif
01225
01226
01227
01228 if(hasCycle)
01229 continue;
01230
01231
01232
01233 if(pathMaxSource == LOCAL && NULL != basicState->m_reserved)
01234 continue;
01235
01236 ++bs->m_nTotalPathsDiscovered;
01237
01238
01239 CPKIFPathValidationResults tmpResults;
01240 if(settings->GetUseValidatorFilterWhenBuilding() && !PathOK(builtPath, *basicState->m_curRoot, settings, tmpResults))
01241 {
01242 ++bs->m_nPathsRejectedDueToValidationErrors;
01243 bs->m_vFailureCodes.push_back(tmpResults.DiagnosticCode());
01244 SearchForFailure(basicState, builtPath, settings);
01245
01246 CPKIFCertificatePath tmpPath;
01247 CPKIFCertificatePtr tmpTarget;
01248 path.GetTarget(tmpTarget);
01249 tmpPath.SetTrustRoot(*basicState->m_curRoot);
01250 tmpPath.SetPath(builtPath);
01251 tmpPath.SetTarget(tmpTarget);
01252
01253 CPKIFPathLogger::LogValidationResults(tmpResults, tmpPath, "Logging builder-rejected path");
01254 continue;
01255 }
01256
01257 path.SetTrustRoot(*basicState->m_curRoot);
01258 path.SetPath(builtPath);
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291 ++bs->m_nReturnedPaths;
01292 return true;
01293 }while(1);
01294 }
01295
01296
01297
01298
01299
01300
01301
01302
01303
01322 bool CPKIFPathBuilder2::BuildPath(
01326 CPKIFCertificatePath& path)
01327 {
01328 LOG_STRING_DEBUG("CPKIFPathBuilder2::BuildPath(CPKIFCertificatePath& path)", thisComponent, 0, this);
01329
01330
01331
01332
01333
01334 CPKIFPathSettingsPtr settings;
01335 path.GetPathSettings(settings);
01336 if(settings == (CPKIFPathSettings*)NULL)
01337 RAISE_PATH_EXCEPTION("Path parameter contained NULL path settings.", thisComponent, COMMON_INVALID_INPUT, this)
01338
01339
01340 CPKIFCertificatePathStatePtr state;
01341 CPKIFBasicPathState2* basicState = NULL;
01342 path.GetState(state);
01343
01344
01345 if(state != (CPKIFCertificatePathState*)NULL)
01346 basicState = dynamic_cast<CPKIFBasicPathState2* >(&(*state));
01347
01348
01349 if(NULL == basicState)
01350 {
01351
01352 basicState = new CPKIFBasicPathState2;
01353
01354
01355 CPKIFBuilderStatisticsPtr bs(new CPKIFBuilderStatistics);
01356
01357 path.SetBuilderStats(bs);
01358
01359
01360 CPKIFCertificatePathStatePtr tmpState(basicState);
01361 path.SetState(tmpState);
01362 }
01363
01364
01365
01366
01367
01368 CPKIFCertificatePtr curCert;
01369 CPKIFCertificateNodeList prevPath;
01370 path.GetPath(prevPath);
01371
01372
01373 if(prevPath.empty())
01374 {
01375
01376 path.GetTarget(curCert);
01377 if(curCert == (CPKIFCertificate*)NULL)
01378 RAISE_PATH_EXCEPTION("The path parameter did not specify a target certificate.", thisComponent, COMMON_INVALID_INPUT, this)
01379
01380
01381 CPKIFCertificateNodeListWithSourceInfoPtr targetList(new CPKIFCertificateNodeListWithSourceInfo);
01382 CPKIFCertificateNodeEntryPtr tmpNode(new CPKIFCertificateNodeEntry);
01383 tmpNode->SetCert(curCert);
01384 targetList->push_back(tmpNode);
01385
01386
01387 basicState->m_table.clear();
01388 basicState->m_table.push_back(targetList);
01389
01390
01391 IPKIFTrustCache* iTrust = GetMediatorFromParent<IPKIFTrustCache>();
01392 if(NULL == iTrust)
01393 RAISE_PATH_EXCEPTION("IPKIFTrustCache interface not available.", thisComponent, COMMON_MEDIATOR_MISSING, this)
01394
01395 IPKIFTrustAnchorList tmpRootList;
01396 iTrust->GetTrustRoots(curCert->GetSubjectName(), tmpRootList);
01397 if(!tmpRootList.empty())
01398 {
01399
01400 IPKIFTrustAnchorList::iterator rootPos;
01401 IPKIFTrustAnchorList::iterator rootEnd = tmpRootList.end();
01402 for(rootPos = tmpRootList.begin(); rootPos != rootEnd; ++rootPos)
01403 {
01404 IPKIFNameAndKey* taNameAndKey = dynamic_cast<IPKIFNameAndKey*>(&(*(*rootPos)));
01405 IPKIFNameAndKey* certNameAndKey = dynamic_cast<IPKIFNameAndKey*>(&(*curCert));
01406 if(*certNameAndKey == *taNameAndKey)
01407 {
01408
01409
01410 path.SetTrustRoot(*rootPos);
01411
01412
01413 CPKIFCertificateNodeList builtPath;
01414 CPKIFCertificateNodeEntryPtr curEntry(new CPKIFCertificateNodeEntry);
01415 curEntry->SetCert(curCert);
01416
01417 CPKIFCertStatusPtr newStatus(new CPKIFCertStatus);
01418 newStatus->SetIsTrustAnchor(true);
01419 curEntry->SetStatus(newStatus);
01420
01421 builtPath.push_back(curEntry);
01422 path.SetPath(builtPath);
01423 basicState->SetTrustRoot(tmpRootList);
01424
01425 std::ostringstream os;
01426 os << "Path building is not required. The target certificate is a trust root - subject DN = " << curCert->GetSubjectName()->ToString();
01427 LOG_STRING_INFO(os.str().c_str(), thisComponent, 0, this);
01428
01429 return true;
01430 }
01431 }
01432 }
01433 }
01434 else
01435 {
01436
01437 m_impl->SearchForFailure(basicState, prevPath, settings);
01438 }
01439
01440
01441
01442
01443 bool tableComplete = false;
01444 do
01445 {
01446
01447
01448
01449
01450 if(m_impl->CheckAlternatives(path, basicState))
01451 return true;
01452
01453
01454
01455
01456 tableComplete = m_impl->BuildOrGrowTable(basicState, settings, curCert, prevPath);
01457 if(!tableComplete && NULL == basicState->m_reserved)
01458 {
01459
01460 if(basicState->m_table.empty())
01461 return false;
01462
01463 basicState->m_rootList.clear();
01464 basicState->m_bInitCompleteLocal = false;
01465 basicState->m_nGrowCount = 0;
01466
01467 basicState->m_curRoot = NULL;
01468
01469 basicState->m_maxSource = LOCAL;
01470 basicState->m_reserved = new char[1];
01471
01472 CPKIFCertificateNodeListWithSourceInfoPtr targetList(new CPKIFCertificateNodeListWithSourceInfo);
01473 CPKIFCertificateNodeEntryPtr tmpNode(new CPKIFCertificateNodeEntry);
01474 path.GetTarget(curCert);
01475 tmpNode->SetCert(curCert);
01476 targetList->push_back(tmpNode);
01477
01478
01479 basicState->m_table.clear();
01480 basicState->m_table.push_back(targetList);
01481
01482 tableComplete = m_impl->BuildOrGrowTable(basicState, settings, curCert, prevPath);
01483 }
01484 }while(tableComplete);
01485
01486
01487 return false;
01488 }