00001
00009 #include "PKIFCAPITrustStore2.h"
00010 #include "CAPIUtils.h"
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
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;
00130 }
00131
00132 USES_CONVERSION;
00133
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
00183 CPKIFCertificatePtr tmpCert(new CPKIFCertificate());
00184 try
00185 {
00186 tmpCert->Decode(cert->pbCertEncoded, cert->cbCertEncoded);
00187 }
00188 catch(CPKIFException& )
00189 {
00190
00191
00192
00193
00194
00195
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
00233 }
00234 pPrevCertContext = CertEnumCertificatesInStore(m_impl->m_hSto, pPrevCertContext);
00235 }
00236 }
00237 catch(...)
00238 {
00239 if(NULL != pPrevCertContext)
00240 {
00241
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
00252
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
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
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
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
00402
00403 }
00404 catch(CPKIFException&)
00405 {
00406
00407
00408
00409
00410
00411 LOG_STRING_ERROR("Failed to parse certificate from CAPI store." , thisComponent, CACHE_PARSE_ERROR, this)
00412 }
00413 }while(NULL != cert);
00414
00415
00416 if(NULL != nameBlob.pbData)
00417 PKIFDelete(nameBlob.pbData);
00418 if(NULL != certID.IssuerSerialNumber.Issuer.pbData)
00419 PKIFDelete(certID.IssuerSerialNumber.Issuer.pbData);
00420 if(NULL != certID.IssuerSerialNumber.SerialNumber.pbData)
00421 PKIFDelete(certID.IssuerSerialNumber.SerialNumber.pbData);
00422 }