PKIFCAPITrustStore2.cpp

Go to the documentation of this file.
00001 
00009 #include "PKIFCAPITrustStore2.h"
00010 #include "CAPIUtils.h" //added here 7/29/2004
00011 
00012 #include <atlbase.h>
00013 
00014 #include "ToolkitUtils.h"
00015 #include "components.h"
00016 #include "PKIFCacheErrors.h"
00017 #include "Buffer.h"
00018 #include "Certificate.h"
00019 #include "Name.h"
00020 #include "PKIFTrustRoot.h"
00021 #include "PKIFCacheException.h"
00022 #include "GottaMatch.h"
00023 
00024 #include "IPKIFSearchCriteria.h"
00025 #include "KeyIDBasedSearch.h"
00026 #include "NameBasedSearch.h"
00027 #include "IssuerNameAndSerialNumberBasedSearch.h"
00028 
00029 
00030 #include "boost/numeric/conversion/cast.hpp"
00031 #include "boost/numeric/conversion/bounds.hpp"
00032 #include "boost/limits.hpp"
00033 
00034 using boost::numeric_cast;
00035 using boost::bad_numeric_cast;
00036 
00037 #include <sstream>
00038 
00040 struct CPKIFCAPITrustStore2Impl
00041 {
00042     HCERTSTORE m_hSto;
00043     int m_nSysStoRegLoc;
00044     char* m_szStore;
00045 };
00047 
00065 CPKIFCAPITrustStore2::CPKIFCAPITrustStore2(
00067     int sysStoRegLoc,
00069     const char* store)
00070     :m_impl (new CPKIFCAPITrustStore2Impl), IPKIFCAPISource(sysStoRegLoc, store)
00071 {
00072     LOG_STRING_DEBUG("CPKIFCAPITrustStore2::CPKIFCAPITrustStore2(void)", TOOLKIT_SR_CAPITRUSTSTORE, 0, this);
00073 
00074     m_impl->m_hSto = NULL;
00075 
00076     m_impl->m_nSysStoRegLoc = sysStoRegLoc;
00077 
00078     m_impl->m_szStore = NULL;
00079     size_t len = 0;
00080     if(store)
00081         len = strlen(store);
00082     m_impl->m_szStore = new char[len + 1];
00083 
00084     //reviewed 4/24
00085     strcpy(m_impl->m_szStore, store);
00086 }
00094 CPKIFCAPITrustStore2::~CPKIFCAPITrustStore2(void)
00095 {
00096     LOG_STRING_DEBUG("CPKIFCAPITrustStore2::~CPKIFCAPITrustStore2(void)", TOOLKIT_SR_CAPITRUSTSTORE, 0, this);
00097 
00098     if(m_impl->m_szStore)
00099         delete[] m_impl->m_szStore;
00100 
00101     if(NULL != m_impl->m_hSto)
00102     {
00103         CertCloseStore(m_impl->m_hSto, 0); m_impl->m_hSto = NULL;
00104     }
00105 
00106     delete m_impl;
00107     m_impl = NULL;
00108 }
00122 void CPKIFCAPITrustStore2::Initialize(void)
00123 {
00124     LOG_STRING_DEBUG("CPKIFCAPITrustStore2::Initialize(void)", TOOLKIT_SR_CAPITRUSTSTORE, 0, this);
00125 
00126     if(NULL != m_impl->m_hSto)
00127     {
00128         LOG_STRING_WARN("Skipping initialization - CPKIFCAPITrustStore2 instance already initialized", thisComponent, COMMON_ALREADY_INITIALIZED, this);
00129         return; //already initialized - just log it, return and don't bother with exception
00130     }
00131 
00132     USES_CONVERSION;
00133     //read only access - 8/26/2004
00134     m_impl->m_hSto =  CertOpenStore(CERT_STORE_PROV_SYSTEM, X509_ASN_ENCODING, NULL, 
00135                                 CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG  | m_impl->m_nSysStoRegLoc , T2OLE(m_impl->m_szStore));
00136     if(NULL == m_impl->m_hSto)
00137     {
00138         std::ostringstream os;
00139         os << "CertOpenStore failed: " << GetLastError();
00140         RAISE_CACHE_EXCEPTION(os.str().c_str(), thisComponent, CACHE_CERT_STORE_OPEN_FAILED, this)
00141     }
00142 }
00153 bool CPKIFCAPITrustStore2::GetTrustRoots(const CPKIFNamePtr& subDN, IPKIFTrustAnchorList& rootList)
00154 {
00155     LOG_STRING_DEBUG("CPKIFCAPITrustStore2::GetTrustRoots(const CPKIFNamePtr& subDN, IPKIFTrustAnchorList& rootList)", TOOLKIT_SR_CAPITRUSTSTORE, 0, this);
00156 
00157     if(NULL == m_impl->m_hSto)
00158     {
00159         RAISE_CACHE_EXCEPTION("CPKIFCAPITrustStore2 instance not initialized.", thisComponent, COMMON_NOT_INITIALIZED, this)
00160     }
00161 
00162     const size_t origSize = rootList.size();
00163 
00164     PCCERT_CONTEXT cert = NULL;
00165     CERT_NAME_BLOB nameBlob; 
00166     nameBlob.cbData = 0; 
00167     nameBlob.pbData = NULL;
00168 
00169     if(subDN != (CPKIFName*)NULL)
00170     {
00171         CPKIFBufferPtr encName = subDN->Encoded();
00172         nameBlob.pbData = (BYTE*)encName->GetBuffer();
00173         nameBlob.cbData = encName->GetLength();
00174 
00175         do
00176         {
00177             cert = CertFindCertificateInStore(m_impl->m_hSto, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 
00178                 0, CERT_FIND_SUBJECT_NAME, &nameBlob, cert);
00179             if(NULL == cert)
00180                 break;
00181 
00182             //create a CCACCert and stuff it into the list
00183             CPKIFCertificatePtr tmpCert(new CPKIFCertificate());
00184             try
00185             {
00186                 tmpCert->Decode(cert->pbCertEncoded, cert->cbCertEncoded);
00187             }
00188             catch(CPKIFException& )
00189             {
00190                 //EXCEPTION DELETION
00191                 //don't fail due to parse errors - log the failure and continue searching
00192                 //if nothing is found that actually parses then an error will be generated
00193                 //delete e;
00194 
00195                 //ignore parse failure
00196                 std::ostringstream os;
00197                 os << "Failed to parse certificate from CAPI store searching for certificates issued to: " << subDN->ToString();
00198                 LOG_STRING_ERROR(os.str().c_str(), thisComponent, CACHE_PARSE_ERROR, this)
00199             }
00200             
00201             CPKIFTrustRootPtr tmpRoot(new CPKIFTrustRoot());
00202             tmpRoot->SetCert(tmpCert);
00203 
00204             GottaMatch<IPKIFTrustAnchorPtr> gm;
00205             gm.SetRHS(tmpRoot);
00206             if(rootList.end() == find_if(rootList.begin(), rootList.end(), gm))
00207                 rootList.push_back(tmpRoot);
00208         }while(NULL != cert);
00209     }
00210     else
00211     {
00212         PCCERT_CONTEXT pPrevCertContext = NULL;
00213 
00214         try
00215         {
00216             pPrevCertContext = CertEnumCertificatesInStore(m_impl->m_hSto, pPrevCertContext);
00217             while(NULL != pPrevCertContext)
00218             {
00219                 try
00220                 {
00221                     CPKIFCertificatePtr tmpCert(new CPKIFCertificate);
00222                     tmpCert->Decode(pPrevCertContext->pbCertEncoded, pPrevCertContext->cbCertEncoded);
00223                     CPKIFTrustRootPtr tmpTA(new CPKIFTrustRoot);
00224                     tmpTA->SetCert(tmpCert);
00225                     GottaMatch<IPKIFTrustAnchorPtr> gm;
00226                     gm.SetRHS(tmpTA);
00227                     if(rootList.end() == find_if(rootList.begin(), rootList.end(), gm))
00228                         rootList.push_back(tmpTA);
00229                 }
00230                 catch(...)
00231                 {
00232                     //ignore decoding errors
00233                 }
00234                 pPrevCertContext = CertEnumCertificatesInStore(m_impl->m_hSto, pPrevCertContext);
00235             }
00236         }
00237         catch(...)
00238         {
00239             if(NULL != pPrevCertContext)
00240             {
00241                 //if we threw before freeing cert context, clean up
00242                 CertFreeCertificateContext(pPrevCertContext); pPrevCertContext = NULL;
00243             }
00244 
00245             std::ostringstream os;
00246             os << "Unknown failure in GetTrustRoots while enumerating all trust anchors in the certificate store.  GetLastError returns: " << GetLastError();
00247             RAISE_CACHE_EXCEPTION(os.str().c_str(), thisComponent, COMMON_UNKNOWN_ERROR, this);
00248         }
00249     }
00250 
00251     //if origSize is different from current size then a trust root was found and true should be returned
00252     //otherwise return false
00253     if(origSize != rootList.size())
00254     {
00255         std::ostringstream os;
00256         if(subDN != (CPKIFName*)NULL)
00257             os << "Found one or more trusted certificates with subject name: " << subDN->ToString();
00258         else
00259             os << "Found all trust anchors in certificate store";
00260         LOG_STRING_DEBUG(os.str().c_str(), thisComponent, 0, this);
00261         return true;
00262     }
00263     else
00264     {
00265         std::ostringstream os;
00266         if(subDN != (CPKIFName*)NULL)
00267             os << "Failed to find a trusted certificate with subject name: " << subDN->ToString();
00268         else
00269             os << "Failed to find a trust anchor in certificate store";
00270         LOG_STRING_INFO(os.str().c_str(), thisComponent, 0, this);
00271         return false;
00272     }
00273 }
00274 
00275 
00276 void CPKIFCAPITrustStore2::FindCertificates(
00278     IPKIFSearchCriteria* searchCriteria,
00280     CPKIFCertificateList& certList,
00282     PKIInfoSource source)
00283 {
00284     LOG_STRING_DEBUG("CPKIFCAPIUserRepository2::FindCertificates", TOOLKIT_SR_CAPIUSERREPOSITORY, 0, this);
00285 
00286     //ignore requests for remote certificates
00287     if(REMOTE == source || NULL == searchCriteria)
00288     {
00289         LOG_STRING_DEBUG("Skipping CPKIFCAPIUserRepository2 - searching REMOTE sources only or NULL search criteria", thisComponent, 0, this);
00290         return;
00291     }
00292 
00293     void* ptrToSearchCriteria = NULL;
00294     DWORD findType = 0;
00295 
00296     //possible structures
00297     PCCERT_CONTEXT cert = NULL;
00298     CERT_NAME_BLOB nameBlob; 
00299     nameBlob.cbData = 0; 
00300     nameBlob.pbData = NULL;
00301 
00302     CERT_ID certID;
00303     certID.IssuerSerialNumber.Issuer.pbData = NULL;
00304     certID.IssuerSerialNumber.SerialNumber.pbData = NULL;
00305 
00306     switch(searchCriteria->GetSearchType())
00307     {
00308     case ALLCERTS:
00309         findType = CERT_FIND_ANY;
00310         break;
00311     case ISSUERNAME:
00312         {
00313             CPKIFNameBasedSearch* nbs = dynamic_cast<CPKIFNameBasedSearch*>(searchCriteria);
00314             StrToName(nbs->GetStringName(), &nameBlob.pbData, &nameBlob.cbData);
00315             if(0 != nameBlob.cbData)
00316             {
00317                 ptrToSearchCriteria = &nameBlob;
00318                 findType = CERT_FIND_ISSUER_NAME;
00319             }
00320             else
00321                 return;
00322         }
00323         break;
00324     case SUBJECTNAME:
00325         {
00326             CPKIFNameBasedSearch* nbs = dynamic_cast<CPKIFNameBasedSearch*>(searchCriteria);
00327             StrToName(nbs->GetStringName(), &nameBlob.pbData, &nameBlob.cbData);
00328             if(0 != nameBlob.cbData)
00329             {
00330                 ptrToSearchCriteria = &nameBlob;
00331                 findType = CERT_FIND_SUBJECT_NAME;
00332             }
00333             else
00334                 return;
00335         }
00336         break;
00337     case ISSUERSERIAL:
00338         {
00339             CPKIFIssuerNameAndSerialNumberBasedSearch* inasnbs = dynamic_cast<CPKIFIssuerNameAndSerialNumberBasedSearch*>(searchCriteria);
00340             CPKIFNamePtr issuerName = inasnbs->GetIssuerName();
00341             certID.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
00342             StrToName(issuerName->ToString(), &certID.IssuerSerialNumber.Issuer.pbData, &certID.IssuerSerialNumber.Issuer.cbData);
00343             const char* sn = inasnbs->GetSerialNumber();
00344 
00345             size_t len = strlen(sn) - 2;
00346             unsigned int iLen = 0;
00347             if(len > boost::numeric::bounds<unsigned int>::highest())
00348             {
00349                 throw CPKIFCacheException(TOOLKIT_SR_CAPIUSERREPOSITORY, COMMON_INVALID_INPUT, "Serial number too big.");
00350             }
00351             else
00352                 iLen = numeric_cast<unsigned int>(len);
00353 
00354             unsigned char* binSN = new unsigned char[iLen];
00355             atob((char*)binSN, (char*)sn+2, &iLen);
00356             ReverseBytes(binSN, iLen);
00357             certID.IssuerSerialNumber.SerialNumber.cbData = iLen;
00358             certID.IssuerSerialNumber.SerialNumber.pbData = binSN;
00359             ptrToSearchCriteria = &certID;
00360             findType = CERT_FIND_CERT_ID;
00361             break;
00362         }
00363     case KEYID:
00364         {
00365             CPKIFKeyIDBasedSearch* kidbs = dynamic_cast<CPKIFKeyIDBasedSearch*>(searchCriteria);
00366             if(!kidbs)
00367                 return;
00368 
00369             CPKIFBufferPtr kid = kidbs->GetKeyID();
00370 
00371             CRYPT_HASH_BLOB chb;
00372             chb.cbData = kid->GetLength();
00373             chb.pbData = (BYTE*)kid->GetBuffer();
00374 
00375             ptrToSearchCriteria = &chb;
00376             findType = CERT_FIND_KEY_IDENTIFIER;
00377             break;
00378         }
00379     default:
00380         return;
00381     };
00382 
00383     do
00384     {
00385         cert = CertFindCertificateInStore(m_impl->m_hSto, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 
00386             0, findType, ptrToSearchCriteria, cert);
00387         if(NULL == cert)
00388             break;
00389 
00390         //create a CCACCert and stuff it into the list
00391         CPKIFCertificatePtr tmpCert(new CPKIFCertificate);
00392         try
00393         {
00394             tmpCert->Decode(cert->pbCertEncoded, cert->cbCertEncoded);
00395 
00396             GottaMatch<CPKIFCertificatePtr> gm;
00397             gm.SetRHS(tmpCert);
00398             if(certList.end() == find_if(certList.begin(), certList.end(), gm))
00399                 certList.push_back(tmpCert);
00400 
00401 //          certList.push_back(tmpCert); //moved this here from below catch block
00402                                         //else non-parsed certs end up in the list
00403         }
00404         catch(CPKIFException&)
00405         {
00406             //EXCEPTION DELETION
00407             //don't fail due to parse errors - log the failure and continue searching
00408             //if nothing is found that actually parses then an error will be generated
00409             //delete e;
00410 
00411             LOG_STRING_ERROR("Failed to parse certificate from CAPI store." , thisComponent, CACHE_PARSE_ERROR, this)
00412         }
00413     }while(NULL != cert);
00414 
00415     //free the memory allocated in call to StrToName
00416     if(NULL != nameBlob.pbData)
00417         PKIFDelete(nameBlob.pbData); //changed to PKIFDelete 12/7/2003
00418     if(NULL != certID.IssuerSerialNumber.Issuer.pbData)
00419         PKIFDelete(certID.IssuerSerialNumber.Issuer.pbData); //changed to PKIFDelete 12/7/2003
00420     if(NULL != certID.IssuerSerialNumber.SerialNumber.pbData)
00421         PKIFDelete(certID.IssuerSerialNumber.SerialNumber.pbData); //changed to PKIFDelete 12/7/2003
00422 }

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