00001
00010 #include "PKIFNSSRepository.h"
00011 #include "PKIFNSSHelper.h"
00012
00013 #include "PKIFNSSDatabase.h"
00014 #include "PKIFNSSErrors.h"
00015 #include "ToolkitUtils.h"
00016 #include "components.h"
00017 #include "PKIFCacheErrors.h"
00018 #include "Buffer.h"
00019 #include "Certificate.h"
00020 #include "CRL.h"
00021 #include "Name.h"
00022 #include "PKIFTrustRoot.h"
00023 #include "PKIFCacheException.h"
00024 #include "GottaMatch.h"
00025
00026 #include "IPKIFSearchCriteria.h"
00027 #include "KeyIDBasedSearch.h"
00028 #include "NameBasedSearch.h"
00029 #include "IssuerNameAndSerialNumberBasedSearch.h"
00030
00031 #include "PKIFNSSConfig.h"
00032
00033 #include "boost/numeric/conversion/cast.hpp"
00034 #include "boost/numeric/conversion/bounds.hpp"
00035 #include "boost/limits.hpp"
00036
00037 using boost::numeric_cast;
00038 using boost::bad_numeric_cast;
00039
00040 #include <sstream>
00041 using namespace std;
00042
00044 struct PKIFNSSRepositoryImpl
00045 {
00046 CERTCertDBHandle * m_certDbHandle;
00047 CPKIFNSSDatabase * m_db;
00048 };
00050
00051
00063 CPKIFNSSRepository::CPKIFNSSRepository(
00065 const std::string & dbdir)
00066 :m_impl(new PKIFNSSRepositoryImpl)
00067 {
00068 LOG_STRING_DEBUG(__FUNCTION__,TOOLKIT_SR_NSSREPOSITORY,0,this);
00069 m_impl->m_certDbHandle = 0;
00070 m_impl->m_db = 0;
00071
00072
00073 if(dbdir == "") {
00074 m_impl->m_db = CPKIFNSSDatabase::GetInstance();
00075 } else {
00076
00077
00078
00079 m_impl->m_db = CPKIFNSSDatabase::GetInstance(dbdir);
00080 }
00081 }
00089 CPKIFNSSRepository::~CPKIFNSSRepository(void)
00090 {
00091 LOG_STRING_DEBUG(__FUNCTION__,TOOLKIT_SR_NSSREPOSITORY,0,this);
00092 PKIFDelete(m_impl);
00093 m_impl = 0;
00094 }
00106 void CPKIFNSSRepository::GetCertificates(
00108 const CPKIFNamePtr& subDN,
00110 CPKIFCertificateList& certList,
00112 PKIInfoSource source)
00113 {
00114 LOG_STRING_DEBUG(__FUNCTION__,TOOLKIT_SR_NSSREPOSITORY,0,this);
00115 if(0 == m_impl->m_certDbHandle)
00116 {
00117 RAISE_CACHE_EXCEPTION("CPKIFNSSRepository instance not initialized.", thisComponent, COMMON_NOT_INITIALIZED, this)
00118 }
00119 if(source == REMOTE) return;
00120 CERTCertList *certs = 0;
00121 SECItem nameItem;
00122 nameItem.type = siBuffer;
00123
00124 CPKIFBufferPtr encName = subDN->Encoded();
00125 nameItem.data = (unsigned char *)encName->GetBuffer();
00126 nameItem.len = encName->GetLength();
00127
00128
00129 certs = CERT_CreateSubjectCertList(0,m_impl->m_certDbHandle,&nameItem,
00130 PR_Now(),PR_FALSE);
00131
00132
00133 #if 0
00134 if(!certs) {
00135 CERTCertificate * found = CERT_FindCertByNameString(m_impl->m_certDbHandle,subDN->string());
00136 if(found) {
00137 certs = CERT_CertListFromCert(found);
00138 }
00139 }
00140 #endif
00141
00142 if(!certs) {
00143 return;
00144 }
00145
00146 CERTCertListNode *node = CERT_LIST_HEAD(certs);
00147 while(!CERT_LIST_END(node,certs)) {
00148 CERTCertificate * foundCert = node->cert;
00149 CPKIFCertificatePtr tmpCert(new CPKIFCertificate());
00150 try {
00151 tmpCert->Decode(foundCert->derCert.data, foundCert->derCert.len);
00152 }catch(CPKIFException &){
00153
00154 std::ostringstream os;
00155 os << "Failed to parse certificate from NSS store searching for certificates issued to: " << subDN->ToString();
00156 LOG_STRING_ERROR(os.str().c_str(), thisComponent, CACHE_PARSE_ERROR, this);
00157 }
00158 GottaMatch<CPKIFCertificatePtr> gm;
00159 gm.SetRHS(tmpCert);
00160 if(certList.end() == find_if(certList.begin(), certList.end(), gm)) {
00161 certList.push_back(tmpCert);
00162 }
00163 node = CERT_LIST_NEXT(node);
00164 }
00165 CERT_DestroyCertList(certs);
00166 }
00178 void CPKIFNSSRepository::GetCRLs(
00180 const CPKIFCertificatePtr& cert,
00182 CPKIFCRLList& crlList,
00184 PKIInfoSource source)
00185 {
00186
00187 LOG_STRING_DEBUG(__FUNCTION__,TOOLKIT_SR_NSSREPOSITORY,0,this);
00188 if(0 == m_impl->m_certDbHandle)
00189 {
00190 RAISE_CACHE_EXCEPTION("CPKIFNSSRepository instance not initialized.", thisComponent, COMMON_NOT_INITIALIZED, this)
00191 }
00192 if(source == REMOTE) return;
00193
00194
00195
00196 CERTSignedCrl *crl = 0;
00197 SECItem derIssName;
00198 CPKIFBufferPtr tmpIssName = cert->Issuer()->Encoded();
00199 derIssName.type = siBuffer;
00200 derIssName.data = (unsigned char *)tmpIssName->GetBuffer();
00201 derIssName.len = tmpIssName->GetLength();
00202 crl = SEC_FindCrlByName(m_impl->m_certDbHandle,&derIssName,SEC_CRL_TYPE);
00203 if(!crl) {
00204 return;
00205 }
00206 CPKIFCRLPtr tmpCRL(new CPKIFCRL());
00207 try {
00208 tmpCRL->Decode(crl->derCrl->data,crl->derCrl->len);
00209 }catch(CPKIFException &){
00210 std::ostringstream os;
00211 os << "Failed to parse CRL from NSS store searching for CRLs issued for: " << cert->Issuer()->ToString();
00212 LOG_STRING_ERROR(os.str().c_str(), thisComponent, CACHE_PARSE_ERROR, this);
00213 }
00214 SEC_DestroyCrl(crl);
00215 GottaMatch<CPKIFCRLPtr> gm;
00216 gm.SetRHS(tmpCRL);
00217 if(crlList.end() == find_if(crlList.begin(), crlList.end(), gm)) {
00218 crlList.push_back(tmpCRL);
00219 }
00220 }
00228 void CPKIFNSSRepository::Initialize(void)
00229 {
00230 LOG_STRING_DEBUG(__FUNCTION__,TOOLKIT_SR_NSSREPOSITORY,0,this);
00231 if(!CPKIFNSSHelper::NSSAvaliable()) {
00232 RAISE_CACHE_EXCEPTION("NSS could not be loaded.",thisComponent,PKIFNSS_INIT_FAILED,this);
00233 }
00234 m_impl->m_certDbHandle = CERT_GetDefaultCertDB();
00235 }
00236
00237
00238 void CPKIFNSSRepository::FindCertificates(
00240 IPKIFSearchCriteria* searchCriteria,
00242 CPKIFCertificateList& certList,
00244 PKIInfoSource source)
00245 {
00246 LOG_STRING_DEBUG(__FUNCTION__,TOOLKIT_SR_NSSREPOSITORY,0,this);
00247 if(0 == m_impl->m_certDbHandle)
00248 {
00249 RAISE_CACHE_EXCEPTION("CPKIFNSSRepository instance not initialized.", thisComponent, COMMON_NOT_INITIALIZED, this)
00250 }
00251 if(source == REMOTE) return;
00252 CERTCertificate * found = 0;
00253 SECItem nameItem;
00254
00255
00256 switch(searchCriteria->GetSearchType())
00257 {
00258 case ALLCERTS:
00259 break;
00260 case ISSUERNAME:
00261 break;
00262 case SUBJECTNAME:
00263 {
00264 nameItem.type = siBuffer;
00265
00266 CPKIFNameBasedSearch* nbs = dynamic_cast<CPKIFNameBasedSearch*>(searchCriteria);
00267 CPKIFBufferPtr encName = nbs->GetName()->Encoded();
00268 nameItem.data = (unsigned char *)encName->GetBuffer();
00269 nameItem.len = encName->GetLength();
00270 if(0 != nameItem.data)
00271 {
00272 found = CERT_FindCertByName(m_impl->m_certDbHandle,&nameItem);
00273
00274 }
00275 else
00276 return;
00277 }
00278 break;
00279 case ISSUERSERIAL:
00280 {
00281 CERTIssuerAndSN issuerSN;
00282 CPKIFIssuerNameAndSerialNumberBasedSearch* inasnbs = dynamic_cast<CPKIFIssuerNameAndSerialNumberBasedSearch*>(searchCriteria);
00283 CPKIFNamePtr issuerName = inasnbs->GetIssuerName();
00284 CPKIFBufferPtr encName = issuerName->Encoded();
00285 issuerSN.derIssuer.data = (unsigned char *)encName->GetBuffer();
00286 issuerSN.derIssuer.len = encName->GetLength();
00287 issuerSN.derIssuer.type = siBuffer;
00288
00289 const char* sn = inasnbs->GetSerialNumber();
00290
00291 size_t len = strlen(sn) - 2;
00292 unsigned int iLen = 0;
00293 if(len > boost::numeric::bounds<unsigned int>::highest())
00294 {
00295 throw CPKIFCacheException(TOOLKIT_SR_CAPIUSERREPOSITORY, COMMON_INVALID_INPUT, "Serial number too big.");
00296 }
00297 else
00298 iLen = numeric_cast<unsigned int>(len);
00299
00300 unsigned char* binSN = new unsigned char[iLen];
00301 atob((char*)binSN, (char*)sn+2, &iLen);
00302
00303 issuerSN.serialNumber.data = binSN;
00304 issuerSN.serialNumber.len = iLen;
00305 issuerSN.serialNumber.type = siBuffer;
00306
00307
00308 if(0 != issuerSN.serialNumber.data && issuerSN.derIssuer.data)
00309 {
00310 found = CERT_FindCertByIssuerAndSN(m_impl->m_certDbHandle,&issuerSN);
00311 }
00312 else
00313 return;
00314 break;
00315 }
00316 case KEYID:
00317 {
00318 CPKIFKeyIDBasedSearch* kidbs = dynamic_cast<CPKIFKeyIDBasedSearch*>(searchCriteria);
00319 if(!kidbs)
00320 return;
00321
00322 CPKIFBufferPtr kid = kidbs->GetKeyID();
00323 nameItem.data = (unsigned char *)kid->GetBuffer();
00324 nameItem.len = kid->GetLength();
00325 if(0 != nameItem.data)
00326 {
00327 found = CERT_FindCertBySubjectKeyID(m_impl->m_certDbHandle,&nameItem);
00328
00329 }
00330 else
00331 return;
00332 break;
00333 }
00334 default:
00335 return;
00336 };
00337
00338 if(!found) {
00339 return;
00340 }
00341
00342
00343 CPKIFCertificatePtr tmpCert(new CPKIFCertificate());
00344 try {
00345 tmpCert->Decode(found->derCert.data, found->derCert.len);
00346 }catch(CPKIFException &){
00347
00348 std::ostringstream os;
00349 os << "Failed to parse certificate from NSS store.";
00350 LOG_STRING_ERROR(os.str().c_str(), thisComponent, CACHE_PARSE_ERROR, this);
00351 }
00352 GottaMatch<CPKIFCertificatePtr> gm;
00353 gm.SetRHS(tmpCert);
00354 if(certList.end() == find_if(certList.begin(), certList.end(), gm)) {
00355 certList.push_back(tmpCert);
00356 }
00357 }