PKIFCRLDPRetrieval.cpp

Go to the documentation of this file.
00001 
00009 #include "PKIFdll.h"
00010 
00011 #include "IPKIFColleague.h"
00012 #include "PKIFCRLDPRetrieval.h"
00013 #include "LDAP_URL_Header.h"
00014 
00015 #include "Buffer.h"
00016 #include "GeneralName.h"
00017 #include "AuthorityInfoAccess.h"
00018 #include "SubjectInfoAccess.h"
00019 #include "ToolkitUtils.h"
00020 
00021 #include "CRLDistributionPoint.h"
00022 #include "CRLDistributionPoints.h"
00023 #include "DistributionPointName.h"
00024 #include "AccessDescription.h"
00025 #include "IssuerAltName.h"
00026 #include "Certificate.h"
00027 #include "GottaMatch.h"
00028 #include "CRL.h"
00029 #include "PKIFHttpCrlNode.h"
00030 #include "PKIFLdapCrlNode.h"
00031 
00032 #include "ASN1Helper.h"
00033 #include "CryptographicMessageSyntax2004.h"
00034 
00035 //#define _DEBUG_URI_DUMP 1
00036 #ifdef _DEBUG_URI_DUMP
00037 #include <fstream>
00038 extern ofstream g_uriLogFile;
00039 #endif
00040 
00042 struct CPKIFCRLDPRetrievalImpl
00043 {
00044     CPKIFOIDPtr m_oid;
00045     CPKIFBufferList m_content;
00046 };
00048 
00056 CPKIFCRLDPRetrieval::CPKIFCRLDPRetrieval(void)
00057     :m_impl (new CPKIFCRLDPRetrievalImpl)
00058 {
00059     LOG_STRING_DEBUG("CPKIFCRLDPRetrieval::CPKIFCRLDPRetrieval(void)", TOOLKIT_OCSP_CHECKER, 0, this);
00060 }
00068 CPKIFCRLDPRetrieval::~CPKIFCRLDPRetrieval(void)
00069 {
00070     LOG_STRING_DEBUG("CPKIFCRLDPRetrieval::~CPKIFCRLDPRetrieval(void)", TOOLKIT_OCSP_CHECKER, 0, this);
00071 
00072     delete m_impl;
00073     m_impl = NULL;
00074 }
00075 
00083 void CPKIFCRLDPRetrieval::Initialize(void) 
00084 {
00085 }
00086 
00094 bool RetrieveCRLGivenHTTPURL(
00096     const char* url, 
00098     CPKIFCRLList& crlList)
00099 {
00100     LOG_STRING_DEBUG("RetrieveCRLGivenHTTPURL(const char* url, CPKIFCRLList& crlList)", TOOLKIT_OCSP_CHECKER, 0, NULL);
00101 
00102     if(NULL == url || 0 == strlen(url))
00103         return false;
00104 
00105     bool allIsWell = false;
00106     try
00107     {
00108 
00109 #ifdef _DEBUG_URI_DUMP
00110     if(!g_uriLogFile.is_open())
00111     {
00112         g_uriLogFile.open("_DEBUG_URI_DUMP_URILog.txt", ios::out);
00113     }
00114     DWORD __ticks = GetTickCount();
00115 #endif
00116 
00117         CPKIFBufferPtr crlBuf;
00118         GetRequest(url, crlBuf);
00119 
00120 #ifdef _DEBUG_URI_DUMP
00121     g_uriLogFile << GetTickCount() - __ticks << " milliseconds elapsed retrieving from " << url << endl; 
00122 #endif
00123 
00124         if(!crlBuf)     
00125             return false;
00126 
00127         //if no cache entry was found - create a CRL object and add it to the cache using the URL gen name as the dp
00128         //bad_alloc caught by catch(...)
00129         CPKIFCRLPtr crl(new CPKIFCRL());
00130         try
00131         {
00132             crl->Decode(crlBuf->GetBuffer(), crlBuf->GetLength());
00133 
00134             GottaMatch<CPKIFCRLPtr> gm;
00135             gm.SetRHS(crl);
00136             if(crlList.end() == find_if(crlList.begin(), crlList.end(), gm))
00137                 crlList.push_back(crl);
00138             allIsWell = true;
00139         }
00140         catch(CPKIFException&)
00141         {
00142             //delete e;
00143             //XXX-DEFER attempt base64 decode?
00144         }
00145     }
00146     catch(...)
00147     {
00148         allIsWell = false;
00149     }
00150 
00151     return allIsWell;
00152 }
00153 
00161 void GetCertsfromP7(
00163     CPKIFBufferPtr& buf, 
00165     CPKIFCertificateList& certList)
00166 {
00167 
00168     if(buf == (CPKIFBuffer*)NULL)
00169         return; //do nothing
00170 
00171     try
00172     {
00173         CACASNWRAPPER_CREATE(CACCMSContentInfo, contentInfo);
00174         CACASNWRAPPER_CREATE(CACCMSSignedData, signedData);
00175 
00176         contentInfo.Decode(buf->GetBuffer(), buf->GetLength());
00177         signedData.Decode(contentInfo->content);
00178 
00179         if(!signedData->m.certificatesPresent || 0 >= signedData->certificates.count)
00180             return;
00181 
00182         DListNode* iter = signedData->certificates.head;
00183         while(NULL != iter)
00184         {
00185             // signedData->certificates is a list of CertificateChoices, not
00186             // a list of certificates.
00187             //ASN1OpenType* cert = (ASN1OpenType*)iter->data;
00188             CACCMSCertificateChoices* curChoice = (CACCMSCertificateChoices*)iter->data;
00189             if(T_CACCMSCertificateChoices_certificate != curChoice->t)
00190             {
00191                 iter = iter->next;
00192                 continue;
00193             }
00194             ASN1OpenType* cert = (ASN1OpenType*)curChoice->u.certificate;
00195 
00196             try
00197             {
00198                 CPKIFCertificatePtr newCert(new CPKIFCertificate());
00199                 newCert->Decode(cert->data, cert->numocts);
00200                 certList.push_back(newCert);
00201             }
00202             catch(CPKIFException&)
00203             {
00204                 //don't bother the caller with malformed certs
00205             }
00206             catch(std::bad_alloc& ba)
00207             {
00208                 //empty the list
00209                 certList.clear();
00210                 throw ba;
00211             }
00212     
00213             iter = iter->next;
00214         }
00215     }
00216     catch(CPKIFException&)
00217     {
00218         //carry on
00219     }
00220 
00221 /*  try
00222     {
00223         CPKIFContentInfo ci;
00224         ci.Decode(buf->GetBuffer(), buf->GetLength());
00225 
00226         CPKIFOIDPtr type = ci.GetContentType();
00227         if(type != NULL && *type == *g_signedData)
00228         {
00229             CPKIFBufferPtr content = ci.GetContent();
00230             if(content == NULL)
00231                 return;
00232 
00233             CPKIFSignedData sd;
00234             sd.Decode(content);
00235 
00236             CPKIFCertificateList cl;
00237             sd.GetCertificates(cl);
00238 
00239             copy(cl.begin(), cl.end(), back_inserter(certList));
00240         }
00241     }
00242     catch(CPKIFException&)
00243     {
00244         //carry on
00245     }
00246 */
00247 }
00248 
00256 bool CAC_API RetrieveCertGivenHTTPURL(
00258     const char* url, 
00260     CPKIFCertificateNodeList& certNodeList)
00261 {
00262     LOG_STRING_DEBUG("RetrieveCertGivenHTTPURL(const char* url, CPKIFCertificateNodeList& certNodeList)", TOOLKIT_OCSP_CHECKER, 0, NULL);
00263 
00264     if(NULL == url || 0 == strlen(url))
00265         return false;
00266 
00267     bool allIsWell = false;
00268     try
00269     {
00270 #ifdef _DEBUG_URI_DUMP
00271     if(!g_uriLogFile.is_open())
00272     {
00273         g_uriLogFile.open("_DEBUG_URI_DUMP_URILog.txt", ios::out);
00274     }
00275     DWORD __ticks = GetTickCount();
00276 #endif
00277 
00278         std::string strUrl = url;
00279         CPKIFBufferPtr certBuf;
00280         GetRequest(url, certBuf);
00281 
00282 #ifdef _DEBUG_URI_DUMP
00283     g_uriLogFile << GetTickCount() - __ticks << " milliseconds elapsed retrieving from " << url << endl; 
00284 #endif
00285 
00286         if(!certBuf || !certBuf->GetBuffer() || 0 >= certBuf->GetLength())
00287             return false;
00288 
00289         //if no cache entry was found - create a cert object and add it to the cache using the URL gen name as the dp
00290         //bad_alloc caught by catch(...)
00291         CPKIFCertificatePtr cert(new CPKIFCertificate());
00292         try
00293         {
00294             cert->Decode(certBuf->GetBuffer(), certBuf->GetLength());
00295 
00296             CPKIFCertificateNodeEntryPtr certNode(new CPKIFCertificateNodeEntry(cert));
00297             GottaMatch<CPKIFCertificateNodeEntryPtr> gm;
00298             gm.SetRHS(certNode);
00299             if(certNodeList.end() == find_if(certNodeList.begin(), certNodeList.end(), gm))
00300             {
00301                 certNode->AddSource(strUrl);
00302                 certNode->SetSource(REMOTE);
00303                 certNodeList.push_back(certNode);
00304             }
00305             allIsWell = true;
00306         }
00307         catch(CPKIFException&)
00308         {
00309             //delete e;
00310             //XXX-DEFER attempt base64 decode?
00311 
00312             //parse as a P7 blob if possible
00313             CPKIFCertificateList certList;
00314             GetCertsfromP7(certBuf, certList);  
00315 
00316             CPKIFCertificateList::iterator pos;
00317             CPKIFCertificateList::iterator end = certList.end();
00318             for(pos = certList.begin(); pos != end; ++pos)
00319             {
00320                 CPKIFCertificateNodeEntryPtr certNode(new CPKIFCertificateNodeEntry(*pos));
00321                 GottaMatch<CPKIFCertificateNodeEntryPtr> gm;
00322                 gm.SetRHS(certNode);
00323                 if(certNodeList.end() == find_if(certNodeList.begin(), certNodeList.end(), gm))
00324                 {
00325                     certNode->AddSource(strUrl);
00326                     certNode->SetSource(REMOTE);
00327                     certNodeList.push_back(certNode);
00328                 }
00329             }
00330         }
00331     }
00332     catch(...)
00333     {
00334         allIsWell = false;
00335     }
00336 
00337     return allIsWell;
00338 }
00339 
00353 void CAC_API GetCertsFromIssuerAltName(
00356     CPKIFCertificate& cert, 
00358     CPKIFCertificateNodeList& certNodeList, 
00360     PKIInfoSource source,
00362     PathBuildingDirection pbd)
00363 {
00364     LOG_STRING_DEBUG("GetCertsFromIssuerAltName(const CPKIFCertificatePtr& cert, CPKIFCertificateNodeList& certNodeList, PKIInfoSource source)", TOOLKIT_OCSP_CHECKER, 0, NULL);
00365 
00366     if(LOCAL == source)
00367         return;
00368 
00369     //Added AIA code 6/3/2004
00370 
00371     CPKIFCertificateNodeList certsFromIAN;
00372     CPKIFGeneralNameList genNames;
00373 
00374     if(PBD_FORWARD == pbd)
00375     {
00376         CPKIFIssuerAltNamePtr ian;
00377         CPKIFAuthorityInfoAccessPtr aia;
00378 
00379         //see if the cert has an issuer alt name - if it does not the return
00380         try
00381         {
00382             ian = cert.GetExtension<CPKIFIssuerAltName>();
00383             aia = cert.GetExtension<CPKIFAuthorityInfoAccess>();
00384             if(ian == (CPKIFIssuerAltNamePtr*)NULL && aia == (CPKIFAuthorityInfoAccess*)NULL)
00385                 return;
00386         }
00387         catch(...)
00388         {
00389             //one of these extensions is busted.  just return
00390             return;
00391         }
00392 
00393         if(ian != (CPKIFIssuerAltNamePtr*)NULL)
00394         {
00395             ian->GeneralNames(genNames);
00396         }
00397 
00398         if(aia != (CPKIFAuthorityInfoAccess*)NULL)
00399         {
00400             CPKIFAccessDescriptionListPtr adl = aia->GetAccessDescriptions();
00401             CPKIFAccessDescriptionList::iterator aPos;
00402             CPKIFAccessDescriptionList::iterator aEnd = adl->end();
00403             for(aPos = adl->begin(); aPos != aEnd; ++aPos)
00404             {
00405                 CPKIFOIDPtr aOID = (*aPos)->AccessMethod();
00406                 if(aOID != (CPKIFOID*)NULL && *aOID == *g_aiaCAIssuer)
00407                 {
00408                     CPKIFGeneralNamePtr aGN = (*aPos)->AccessLocation();
00409                     genNames.push_back(aGN);
00410                 }
00411             }
00412         }
00413     }
00414     else
00415     {
00416         CPKIFSubjectInfoAccessPtr sia;
00417         try
00418         {
00419             sia = cert.GetExtension<CPKIFSubjectInfoAccess>();
00420             if(sia == (CPKIFSubjectInfoAccess*)NULL)
00421                 return;
00422         }
00423         catch(...)
00424         {
00425             //one of these extensions is busted.  just return
00426             return;
00427         }
00428 
00429         if(sia != (CPKIFSubjectInfoAccess*)NULL)
00430         {
00431             CPKIFAccessDescriptionListPtr adl = sia->GetAccessDescriptions();
00432             CPKIFAccessDescriptionList::iterator aPos;
00433             CPKIFAccessDescriptionList::iterator aEnd = adl->end();
00434             for(aPos = adl->begin(); aPos != aEnd; ++aPos)
00435             {
00436                 CPKIFOIDPtr aOID = (*aPos)->AccessMethod();
00437                 if(aOID != (CPKIFOID*)NULL && *aOID == *g_aiaCARepository)
00438                 {
00439                     CPKIFGeneralNamePtr aGN = (*aPos)->AccessLocation();
00440                     genNames.push_back(aGN);
00441                 }
00442             }
00443         }
00444     }
00445 
00446     CPKIFGeneralNameList::iterator gnPos;
00447     CPKIFGeneralNameList::iterator gnEnd = genNames.end();
00448     for(gnPos = genNames.begin(); gnPos != gnEnd; ++gnPos)
00449     {
00450         //in search of any URI entries.
00451         const char* url = (*gnPos)->uri();
00452         if(url != NULL)
00453         {
00454             std::string urlStr = url;
00455             if(0 == urlStr.find("ldap"))
00456             {
00457                 //else try LDAP - if that fails just continue
00458                 GetCertfromLDAPURL((char*)url, certsFromIAN, pbd);
00459             }
00460             else if(0 == urlStr.find("http"))
00461             {
00462                 //if a URL entry if found grab the CRL
00463                 RetrieveCertGivenHTTPURL(url, certsFromIAN);
00464             }
00465         }
00466     }
00467 
00468     CPKIFCertificateNodeList::iterator pos;
00469     CPKIFCertificateNodeList::iterator end = certsFromIAN.end();
00470     for(pos = certsFromIAN.begin(); pos != end; ++pos)
00471     {
00472         GottaMatch<CPKIFCertificateNodeEntryPtr> gm;
00473         gm.SetRHS(*pos);
00474         if(certNodeList.end() == find_if(certNodeList.begin(), certNodeList.end(), gm))
00475         {
00476             (*pos)->SetSource(REMOTE);
00477             certNodeList.push_back(*pos);
00478         }
00479     }
00480 }
00481 
00493 void CPKIFCRLDPRetrieval::GetCRLs(
00495     const CPKIFCertificatePtr& cert,
00497     CPKIFCRLList& crlList,
00499     PKIInfoSource source)
00500 {
00501     LOG_STRING_DEBUG("CPKIFCRLDPRetrieval::GetCRLs(const CPKIFCertificatePtr& cert, CPKIFCRLList& crlList, PKIInfoSource source)", TOOLKIT_OCSP_CHECKER, 0, this);
00502 
00503     //don't respond to requests for locally stored CRLs
00504     if(LOCAL == source)
00505         return;
00506 
00507     //see if the cert has a CRL DP - if it does not the return
00508     CPKIFCRLDistributionPointsPtr crlDPs = cert->GetExtension<CPKIFCRLDistributionPoints>();
00509     if(crlDPs == (CPKIFCRLDistributionPoints*)NULL)
00510         return;
00511 
00512     //see if there are any DPs
00513     CPKIFCRLDistributionPointListPtr dps = crlDPs->DPs();
00514     if(dps == (CPKIFCRLDistributionPointList*)NULL)
00515         return;
00516 
00517     //iterate over the DPs
00518     CPKIFCRLDistributionPointList::iterator pos;
00519     CPKIFCRLDistributionPointList::iterator end = dps->end();
00520     for(pos = dps->begin(); pos != end; ++pos)
00521     {
00522         CPKIFDistributionPointNamePtr dp = (*pos)->DistributionPoint();
00523         if(dp != (CPKIFDistributionPointName*)NULL)
00524         {
00525             //get any full names...
00526             CPKIFGeneralNameList gns;
00527             dp->FullName(gns);
00528             
00529             //and iterate over them...
00530             CPKIFGeneralNameList::iterator gnPos;
00531             CPKIFGeneralNameList::iterator gnEnd = gns.end();
00532             for(gnPos = gns.begin(); gnPos != gnEnd; ++gnPos)
00533             {
00534                 //in search of any URI entries.
00535                 const char* url = (*gnPos)->uri();
00536                 if(url != NULL)
00537                 {
00538                     std::string urlStr = url;
00539                     if(0 == urlStr.find("http"))
00540                     {
00541                         //if a URL entry if found grab the CRL
00542                         RetrieveCRLGivenHTTPURL(url, crlList);
00543                     }
00544                     else
00545                     {
00546                         //else try LDAP - if that fails just continue
00547                         GetCRLfromLDAPURL(url, crlList);
00548                     }
00549                 }
00550             }
00551         }
00552 
00553         //get any full names from crlIssuer (added 12/3/2003)
00554         CPKIFGeneralNameList gns;
00555         (*pos)->CRLIssuer(gns);
00556         
00557         //and iterate over them...
00558         CPKIFGeneralNameList::iterator gnPos;
00559         CPKIFGeneralNameList::iterator gnEnd = gns.end();
00560         for(gnPos = gns.begin(); gnPos != gnEnd; ++gnPos)
00561         {
00562             //in search of any URI entries.
00563             const char* url = (*gnPos)->uri();
00564             if(url != NULL)
00565             {
00566                 std::string urlStr = url;
00567                 if(0 == urlStr.find("http"))
00568                 {
00569                     //if a URL entry if found grab the CRL
00570                     RetrieveCRLGivenHTTPURL(url, crlList);
00571                 }
00572                 else
00573                 {
00574                     //else try LDAP - if that fails just continue
00575                     GetCRLfromLDAPURL(url, crlList);
00576                 }
00577             }
00578         }
00579 
00580     }
00581 }
00590 void CPKIFCRLDPRetrieval::GetCRLSources(
00592     const CPKIFCertificatePtr& cert,
00594     CPKIFCrlSourceList& crlNodeList, 
00596     PKIInfoSource source)
00597 {
00598     LOG_STRING_DEBUG("CPKIFCRLDPRetrieval::GetCRLs(const CPKIFCertificatePtr& cert, CPKIFCRLList& crlList, PKIInfoSource source)", TOOLKIT_OCSP_CHECKER, 0, this);
00599 
00600     //don't respond to requests for locally stored CRLs
00601     if(LOCAL == source)
00602         return;
00603 
00604     //see if the cert has a CRL DP - if it does not the return
00605     CPKIFCRLDistributionPointsPtr crlDPs = cert->GetExtension<CPKIFCRLDistributionPoints>();
00606     if(crlDPs == (CPKIFCRLDistributionPoints*)NULL)
00607         return;
00608 
00609     //see if there are any DPs
00610     CPKIFCRLDistributionPointListPtr dps = crlDPs->DPs();
00611     if(dps == (CPKIFCRLDistributionPointList*)NULL)
00612         return;
00613 
00614     //iterate over the DPs
00615     CPKIFCRLDistributionPointList::iterator pos;
00616     CPKIFCRLDistributionPointList::iterator end = dps->end();
00617     for(pos = dps->begin(); pos != end; ++pos)
00618     {
00619         CPKIFDistributionPointNamePtr dp = (*pos)->DistributionPoint();
00620         if(dp != (CPKIFDistributionPointName*)NULL)
00621         {
00622             //get any full names...
00623             CPKIFGeneralNameList gns;
00624             dp->FullName(gns);
00625             
00626             //and iterate over them...
00627             CPKIFGeneralNameList::iterator gnPos;
00628             CPKIFGeneralNameList::iterator gnEnd = gns.end();
00629             for(gnPos = gns.begin(); gnPos != gnEnd; ++gnPos)
00630             {
00631                 //in search of any URI entries.
00632                 const char* url = (*gnPos)->uri();
00633                 if(url != NULL)
00634                 {
00635                     std::string urlStr = url;
00636                     if(0 == urlStr.find("http"))
00637                     {
00638                         if(!UriAlreadyInList(crlNodeList, urlStr))
00639                         {
00640                             CPKIFHttpCrlNodePtr httpCrlNode(new CPKIFHttpCrlNode);
00641                             httpCrlNode->AddSource(urlStr);
00642                             crlNodeList.push_back(httpCrlNode);
00643                         }
00644                     }
00645                     else if(0 == urlStr.find("ldap"))
00646                     {
00647                         if(!UriAlreadyInList(crlNodeList, urlStr))
00648                         {
00649                             CPKIFLdapCrlNodePtr ldapCrlNode(new CPKIFLdapCrlNode);
00650                             ldapCrlNode->AddSource(urlStr);
00651                             crlNodeList.push_back(ldapCrlNode);
00652                         }
00653                     }
00654                 }
00655             }
00656         }
00657 
00658         //get any full names from crlIssuer (added 12/3/2003)
00659         CPKIFGeneralNameList gns;
00660         (*pos)->CRLIssuer(gns);
00661         
00662         //and iterate over them...
00663         CPKIFGeneralNameList::iterator gnPos;
00664         CPKIFGeneralNameList::iterator gnEnd = gns.end();
00665         for(gnPos = gns.begin(); gnPos != gnEnd; ++gnPos)
00666         {
00667             //in search of any URI entries.
00668             const char* url = (*gnPos)->uri();
00669             if(url != NULL)
00670             {
00671                 std::string urlStr = url;
00672                 if(0 == urlStr.find("http"))
00673                 {
00674                     if(!UriAlreadyInList(crlNodeList, urlStr))
00675                     {
00676                         CPKIFHttpCrlNodePtr httpCrlNode(new CPKIFHttpCrlNode);
00677                         httpCrlNode->AddSource(urlStr);
00678                         crlNodeList.push_back(httpCrlNode);
00679                     }
00680                 }
00681                 else if(0 == urlStr.find("ldap"))
00682                 {
00683                     if(!UriAlreadyInList(crlNodeList, urlStr))
00684                     {
00685                         CPKIFLdapCrlNodePtr ldapCrlNode(new CPKIFLdapCrlNode);
00686                         ldapCrlNode->AddSource(urlStr);
00687                         crlNodeList.push_back(ldapCrlNode);
00688                     }
00689                 }
00690             }
00691         }
00692 
00693     }
00694 }

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