PKIFNSSCertUpdate.cpp

Go to the documentation of this file.
00001 
00009 #include "PKIFNSSCertUpdate.h"
00010 
00011 #include "PKIFNSSDatabase.h"
00012 #include "ToolkitUtils.h"
00013 #include "components.h"
00014 #include "PKIFCacheErrors.h"
00015 #include "Buffer.h"
00016 #include "Certificate.h"
00017 #include "CRL.h"
00018 #include "Name.h"
00019 #include "GeneralName.h"
00020 #include "PKIFCacheException.h"
00021 #include "GottaMatch.h"
00022 
00023 #include "PKIFNSSConfig.h"
00024 
00025 #include <sstream>
00026 using namespace std;
00027 
00029 struct PKIFNSSCertUpdateImpl
00030 {
00031     CERTCertDBHandle * m_certDbHandle; //WEAK
00032     CPKIFNSSDatabase * m_db; //WEAK
00033 };
00035 
00036 
00048 CPKIFNSSCertUpdate::CPKIFNSSCertUpdate(
00050     const std::string & dbdir)
00051 :m_impl(new PKIFNSSCertUpdateImpl)
00052 {
00053     LOG_STRING_DEBUG(__FUNCTION__,TOOLKIT_SR_NSSCERTUPDATE,0,this);
00054     m_impl->m_certDbHandle = 0;
00055     m_impl->m_db = 0;
00056     // since it doesn't make sense in SR to use NSS without a DB,
00057     // if no dbdir is specified, we'll use whatever is open already
00058     if(dbdir == "") {
00059         m_impl->m_db = CPKIFNSSDatabase::GetInstance();
00060     } else {
00061         // this will throw if the database has already been opened
00062         // with a diferent directory, as we can only have one open
00063         // at a time
00064         m_impl->m_db = CPKIFNSSDatabase::GetInstance(dbdir);
00065     }
00066 }
00074 CPKIFNSSCertUpdate::~CPKIFNSSCertUpdate(void)
00075 {
00076     LOG_STRING_DEBUG(__FUNCTION__,TOOLKIT_SR_NSSCERTUPDATE,0,this);
00077     PKIFDelete(m_impl);
00078     m_impl = 0;
00079 }
00097 void CPKIFNSSCertUpdate::AddCertificate(
00098                                         
00099     CertType certType, 
00100     
00101     const CPKIFCertificatePtr& cert)
00102 {   
00103     LOG_STRING_DEBUG(__FUNCTION__,TOOLKIT_SR_NSSCERTUPDATE,0,this);
00104     if(0 == m_impl->m_certDbHandle)
00105     {
00106         RAISE_CACHE_EXCEPTION("CPKIFNSSCertUpdate instance not initialized.", thisComponent, COMMON_NOT_INITIALIZED, this);
00107     }
00108 
00109     SECItem siCert;
00110     siCert.type = siBuffer;
00111     CPKIFBufferPtr encoded = cert->Encoded();
00112     siCert.data = (unsigned char *)encoded->GetBuffer();
00113     siCert.len = encoded->GetLength();
00114     
00115     CERTCertificate * nssCert = 0;
00116 
00117     // NSS will happily overwrite trust settings on import. Check first
00118     // to be sure that doesn't happen.
00119     nssCert = CERT_FindCertByDERCert(m_impl->m_certDbHandle, &siCert);
00120     if(nssCert) {
00121         CERT_DestroyCertificate(nssCert);
00122         return;
00123     }
00124 
00125     SECItem * encCerts[1];
00126     encCerts[0] = &siCert;
00127 
00128     CERTCertTrust * trust = 0;
00129 
00130     trust = (CERTCertTrust *)PORT_ZAlloc(sizeof(CERTCertTrust));
00131     if(!trust) {
00132         RAISE_CACHE_EXCEPTION("CPKIFNSSCertUpdate unable to allocate trust structure for NSS.", thisComponent, COMMON_MEMORY_ALLOC_FAILURE, this);
00133     }
00134 
00135     // an array of CERTCertificate pointers that will hold the one decoded object
00136     CERTCertificate ** certs = 0;
00137     
00138     // Import certs into a temporary NSS database... an ugly way to do this, but
00139     // otherwise we need to pull in the whole NSS s/mime library
00140     SECStatus rv = CERT_ImportCerts(CERT_GetDefaultCertDB(),certUsageUserCertImport,
00141         1,encCerts,&certs,PR_FALSE,PR_FALSE,NULL);
00142 
00143     if(SECSuccess != rv) {
00144         // this is really no big deal...
00145         PORT_Free(trust);
00146         LOG_STRING_INFO("Unable to import Cert into NSS",TOOLKIT_SR_NSSCERTUPDATE,
00147             CACHE_UPDATE_FAILED,this);
00148         return;
00149     }
00150     nssCert = certs[0];
00151     // import the cert as a "valid CA" but not a trusted one
00152     rv = CERT_DecodeTrustString(trust,"c,c,c");
00153     if(rv != SECSuccess) {
00154         CERT_DestroyCertificate(nssCert);
00155         PORT_Free(certs);
00156         PORT_Free(trust);
00157         RAISE_CACHE_EXCEPTION("CPKIFNSSCertUpdate unable to allocate trust structure for NSS.", thisComponent, COMMON_MEMORY_ALLOC_FAILURE, this);
00158     }
00159     PK11SlotInfo * internalslot = PK11_GetInternalKeySlot();
00160     if(!internalslot) {
00161         CERT_DestroyCertificate(nssCert);
00162         PORT_Free(certs);
00163         PORT_Free(trust);
00164         LOG_STRING_INFO("Unable to access NSS internal slot",TOOLKIT_SR_NSSCERTUPDATE,
00165             CACHE_UPDATE_FAILED,this);
00166     }
00167     // import the cert with the subj DN as its nickname, for ease of manipulation
00168     // with standard NSS utilities
00169     rv = PK11_ImportCert(internalslot,nssCert,CK_INVALID_HANDLE,
00170         (char *)cert->Subject()->ToString(),PR_FALSE);
00171 
00172     if(SECSuccess == rv) {
00173         rv = CERT_ChangeCertTrust(m_impl->m_certDbHandle,nssCert,trust);
00174         if(SECSuccess != rv) {
00175             LOG_STRING_INFO("Unable to set NSS cert trust",TOOLKIT_SR_NSSCERTUPDATE,
00176                 CACHE_UPDATE_FAILED,this);
00177         }
00178     }
00179     PORT_Free(trust);
00180     CERT_DestroyCertificate(nssCert);
00181     PORT_Free(certs);
00182     PK11_FreeSlot(internalslot);
00183 }
00192 void CPKIFNSSCertUpdate::Initialize(void)
00193 {
00194     LOG_STRING_DEBUG(__FUNCTION__,TOOLKIT_SR_NSSCERTUPDATE,0,this);
00195     m_impl->m_certDbHandle = CERT_GetDefaultCertDB();
00196 }

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