00001
00010 #include "CAPIUtils.h"
00011 #include "PKIFCAPIUserRepository2.h"
00012 #include "ToolkitUtils.h"
00013 #include "PKIFCacheErrors.h"
00014 #include "PKIFCacheException.h"
00015
00016 #include "Certificate.h"
00017 #include "GottaMatch.h"
00018 #include "Name.h"
00019 #include "Buffer.h"
00020 #include "KeyIDBasedSearch.h"
00021 #include "NameBasedSearch.h"
00022 #include "IssuerNameAndSerialNumberBasedSearch.h"
00023
00024 #include "boost/numeric/conversion/cast.hpp"
00025 #include "boost/numeric/conversion/bounds.hpp"
00026 #include "boost/limits.hpp"
00027
00028 using boost::numeric_cast;
00029 using boost::bad_numeric_cast;
00030
00031 #include <atlbase.h>
00032 #include <sstream>
00033
00035 struct CPKIFCAPIUserRepository2Impl
00036 {
00037 HCERTSTORE m_hSto;
00038 int m_nSysStoRegLoc;
00039 char* m_szStore;
00040 };
00042
00060 CPKIFCAPIUserRepository2::CPKIFCAPIUserRepository2(
00062 int sysStoRegLoc,
00064 const char* store)
00065 : m_impl(new CPKIFCAPIUserRepository2Impl), IPKIFCAPISource(sysStoRegLoc, store)
00066 {
00067 LOG_STRING_DEBUG("CPKIFCAPIUserRepository2::CPKIFCAPIUserRepository2(void)", TOOLKIT_SR_CAPIUSERREPOSITORY, 0, this);
00068
00069 m_impl->m_hSto = NULL;
00070
00071 m_impl->m_nSysStoRegLoc = sysStoRegLoc;
00072
00073 m_impl->m_szStore = NULL;
00074 size_t len = 0;
00075 if(store)
00076 {
00077 len = strlen(store);
00078 m_impl->m_szStore = new char[len + 1];
00079
00080
00081 strcpy(m_impl->m_szStore, store);
00082 }
00083 }
00091 CPKIFCAPIUserRepository2::~CPKIFCAPIUserRepository2(void)
00092 {
00093 LOG_STRING_DEBUG("CPKIFCAPIUserRepository2::~CPKIFCAPIUserRepository2(void)", TOOLKIT_SR_CAPIUSERREPOSITORY, 0, this);
00094
00095 if(m_impl->m_szStore)
00096 delete[] m_impl->m_szStore;
00097
00098 if(NULL != m_impl->m_hSto)
00099 {
00100 CertCloseStore(m_impl->m_hSto, 0); m_impl->m_hSto = NULL;
00101 }
00102 delete m_impl;
00103 m_impl = NULL;
00104 }
00116 void CPKIFCAPIUserRepository2::Initialize(void)
00117 {
00118 LOG_STRING_DEBUG("CPKIFCAPIUserRepository2::Initialize(void)", TOOLKIT_SR_CAPIUSERREPOSITORY, 0, this);
00119
00120 if(NULL != m_impl->m_hSto)
00121 {
00122 LOG_STRING_WARN("Skipping initialization - CPKIFCAPIUserRepository2 instance already initialized", TOOLKIT_SR_CAPIREPOSITORY, COMMON_ALREADY_INITIALIZED, this);
00123 return;
00124 }
00125
00126 USES_CONVERSION;
00127 m_impl->m_hSto = CertOpenStore(CERT_STORE_PROV_SYSTEM, X509_ASN_ENCODING, NULL,
00128 CERT_STORE_OPEN_EXISTING_FLAG | m_impl->m_nSysStoRegLoc , T2OLE(m_impl->m_szStore));
00129 if(NULL == m_impl->m_hSto)
00130 {
00131 std::ostringstream os;
00132 os << "CertOpenStore failed: " << GetLastError();
00133 RAISE_CACHE_EXCEPTION(os.str().c_str(), thisComponent, CACHE_CERT_STORE_OPEN_FAILED, this)
00134 }
00135 }
00150 void CPKIFCAPIUserRepository2::FindCertificates(
00152 IPKIFSearchCriteria* searchCriteria,
00154 CPKIFCertificateList& certList,
00156 PKIInfoSource source)
00157 {
00158 LOG_STRING_DEBUG("CPKIFCAPIUserRepository2::FindCertificates", TOOLKIT_SR_CAPIUSERREPOSITORY, 0, this);
00159
00160
00161 if(REMOTE == source || NULL == searchCriteria)
00162 {
00163 LOG_STRING_DEBUG("Skipping CPKIFCAPIUserRepository2 - searching REMOTE sources only or NULL search criteria", thisComponent, 0, this);
00164 return;
00165 }
00166
00167 void* ptrToSearchCriteria = NULL;
00168 DWORD findType = 0;
00169
00170
00171 PCCERT_CONTEXT cert = NULL;
00172 CERT_NAME_BLOB nameBlob;
00173 nameBlob.cbData = 0;
00174 nameBlob.pbData = NULL;
00175
00176 CERT_ID certID;
00177 certID.IssuerSerialNumber.Issuer.pbData = NULL;
00178 certID.IssuerSerialNumber.SerialNumber.pbData = NULL;
00179
00180 switch(searchCriteria->GetSearchType())
00181 {
00182 case ALLCERTS:
00183 findType = CERT_FIND_ANY;
00184 break;
00185 case ISSUERNAME:
00186 {
00187 CPKIFNameBasedSearch* nbs = dynamic_cast<CPKIFNameBasedSearch*>(searchCriteria);
00188 StrToName(nbs->GetStringName(), &nameBlob.pbData, &nameBlob.cbData);
00189 if(0 != nameBlob.cbData)
00190 {
00191 ptrToSearchCriteria = &nameBlob;
00192 findType = CERT_FIND_ISSUER_NAME;
00193 }
00194 else
00195 return;
00196 }
00197 break;
00198 case SUBJECTNAME:
00199 {
00200 CPKIFNameBasedSearch* nbs = dynamic_cast<CPKIFNameBasedSearch*>(searchCriteria);
00201 StrToName(nbs->GetStringName(), &nameBlob.pbData, &nameBlob.cbData);
00202 if(0 != nameBlob.cbData)
00203 {
00204 ptrToSearchCriteria = &nameBlob;
00205 findType = CERT_FIND_SUBJECT_NAME;
00206 }
00207 else
00208 return;
00209 }
00210 break;
00211 case ISSUERSERIAL:
00212 {
00213 CPKIFIssuerNameAndSerialNumberBasedSearch* inasnbs = dynamic_cast<CPKIFIssuerNameAndSerialNumberBasedSearch*>(searchCriteria);
00214 CPKIFNamePtr issuerName = inasnbs->GetIssuerName();
00215 certID.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
00216 StrToName(issuerName->ToString(), &certID.IssuerSerialNumber.Issuer.pbData, &certID.IssuerSerialNumber.Issuer.cbData);
00217 const char* sn = inasnbs->GetSerialNumber();
00218
00219 size_t len = strlen(sn) - 2;
00220 unsigned int iLen = 0;
00221 if(len > boost::numeric::bounds<unsigned int>::highest())
00222 {
00223 throw CPKIFCacheException(TOOLKIT_SR_CAPIUSERREPOSITORY, COMMON_INVALID_INPUT, "Serial number too big.");
00224 }
00225 else
00226 iLen = numeric_cast<unsigned int>(len);
00227
00228 unsigned char* binSN = new unsigned char[iLen];
00229 atob((char*)binSN, (char*)sn+2, &iLen);
00230 ReverseBytes(binSN, iLen);
00231 certID.IssuerSerialNumber.SerialNumber.cbData = iLen;
00232 certID.IssuerSerialNumber.SerialNumber.pbData = binSN;
00233 ptrToSearchCriteria = &certID;
00234 findType = CERT_FIND_CERT_ID;
00235 break;
00236 }
00237 case KEYID:
00238 {
00239 CPKIFKeyIDBasedSearch* kidbs = dynamic_cast<CPKIFKeyIDBasedSearch*>(searchCriteria);
00240 if(!kidbs)
00241 return;
00242
00243 CPKIFBufferPtr kid = kidbs->GetKeyID();
00244
00245 CRYPT_HASH_BLOB chb;
00246 chb.cbData = kid->GetLength();
00247 chb.pbData = (BYTE*)kid->GetBuffer();
00248
00249 ptrToSearchCriteria = &chb;
00250 findType = CERT_FIND_KEY_IDENTIFIER;
00251 break;
00252 }
00253 default:
00254 return;
00255 };
00256
00257 do
00258 {
00259 cert = CertFindCertificateInStore(m_impl->m_hSto, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
00260 0, findType, ptrToSearchCriteria, cert);
00261 if(NULL == cert)
00262 break;
00263
00264
00265 CPKIFCertificatePtr tmpCert(new CPKIFCertificate);
00266 try
00267 {
00268 tmpCert->Decode(cert->pbCertEncoded, cert->cbCertEncoded);
00269
00270 GottaMatch<CPKIFCertificatePtr> gm;
00271 gm.SetRHS(tmpCert);
00272 if(certList.end() == find_if(certList.begin(), certList.end(), gm))
00273 certList.push_back(tmpCert);
00274
00275
00276
00277 }
00278 catch(CPKIFException&)
00279 {
00280
00281
00282
00283
00284
00285 LOG_STRING_ERROR("Failed to parse certificate from CAPI store." , thisComponent, CACHE_PARSE_ERROR, this)
00286 }
00287 }while(NULL != cert);
00288
00289
00290 if(NULL != nameBlob.pbData)
00291 PKIFDelete(nameBlob.pbData);
00292 if(NULL != certID.IssuerSerialNumber.Issuer.pbData)
00293 PKIFDelete(certID.IssuerSerialNumber.Issuer.pbData);
00294 if(NULL != certID.IssuerSerialNumber.SerialNumber.pbData)
00295 PKIFDelete(certID.IssuerSerialNumber.SerialNumber.pbData);
00296 }