CACLDAPRepository.cpp

Go to the documentation of this file.
00001 
00009 #include "PKIFLDAPRepository.h"
00010 #include "ToolkitUtils.h"
00011 #include "Name.h"
00012 #include "GeneralName.h"
00013 #include "Certificate.h"
00014 #include "GottaMatch.h"
00015 #include "CRL.h"
00016 #include "PKIFCRLNodeEntry.h"
00017 #include "PKIFLdapCertNode.h"
00018 #include "PKIFLdapCrlNode.h"
00019 #include "PKIFCacheMediator2.h"
00020 #include "GeneralSubtree.h"
00021 
00022 #include "PKIFCacheErrors.h"
00023 #include "PKIFCacheException.h"
00024 #include "CSingletonLDAPConnection.h"
00025 
00026 #include "ASN1Helper.h"
00027 #include "PKIX1Implicit88.h"
00028 #include "PKIX1Explicit88.h"
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 using namespace boost;
00038 
00039 #include "curl/curl.h"
00040 
00041 #ifdef _WIN32
00042 #include "winldap.h"
00043 #include "winber.h"
00044 #else
00045 #include "ldap.h"
00046 #include <sys/unistd.h>
00047 #endif 
00048 
00049 #include <sstream>
00050 #include <strstream>
00051 using namespace std;
00052 
00053 
00054 //these definitions placed here as a convenience (it's a cpp file in the same component - these
00055 //are used by CACCAPIRepository, which is a template class defined in CACCAPIRepository.h)
00056 CAC_API char g_defCACCAPIStore[] = "CA";
00057 CAC_API char g_defCACCAPIEEStore[] = "AddressBook";
00058 
00060 struct CPKIFLDAPRepositoryImpl {
00061     bool m_bSuppressConnectionErrors;
00062     int m_nPort;
00064     CPKIFStringPtr m_strHost;
00066     CPKIFStringPtr m_strUsername;
00068     CPKIFStringPtr m_strPassword;
00069 
00071     LDAP* m_ldapStruct;
00072 
00073     bool m_bDeferFetch;
00074 
00075     CPKIFGeneralSubtreeList m_namespaces;
00076     bool CheckNamespaces(const CPKIFNamePtr& name);
00077 
00081     LDAP* ConnectAndBind(std::string& strHost, int port, std::string& strUsername, std::string& strPassword);
00082 
00083 };
00091 bool CPKIFLDAPRepositoryImpl::CheckNamespaces(
00093     const CPKIFNamePtr& name)
00094 {
00095     CPKIFGeneralSubtreeList::iterator pos;
00096     CPKIFGeneralSubtreeList::iterator end = m_namespaces.end();
00097     for(pos = m_namespaces.begin(); pos != end; ++pos)
00098     {
00099         if(CPKIFGeneralSubtree::MATCH == (*pos)->IsInSubtree(name))
00100             return true;
00101     }
00102 
00103     //if we get here then either it's not a match (cause the list isn't empty)
00104     //or it is a match (cause the list is empty).  when the list is empty, we
00105     //accept all comers.
00106     return m_namespaces.empty();
00107 }
00108 
00110 
00111 
00119 CAC_API CPKIFLDAPRepositoryPtr MakeLDAPRepository()
00120 {
00121     CPKIFLDAPRepositoryPtr ldap(new CPKIFLDAPRepository());
00122     return ldap;
00123 }
00131 CAC_API void FreeLDAPRepository(
00133     CPKIFLDAPRepository* ldap)
00134 {
00135     if(ldap)
00136     {
00137         delete ldap;
00138     }
00139 }
00155 CPKIFLDAPRepository::CPKIFLDAPRepository(void)
00156 :m_impl(new struct CPKIFLDAPRepositoryImpl)
00157 {
00158     LOG_STRING_DEBUG("CPKIFLDAPRepository::CPKIFLDAPRepository(void)", TOOLKIT_SR_LDAPREPOSITORY, 0, this);
00159 
00160     CPKIFStringPtr tmpPS1(new std::string(""));
00161     m_impl->m_strPassword = tmpPS1;
00162     CPKIFStringPtr tmpPS2(new std::string(""));
00163     m_impl->m_strUsername = tmpPS2;
00164     CPKIFStringPtr tmpPS3(new std::string(""));
00165     m_impl->m_strHost = tmpPS3;
00166     m_impl->m_nPort = 389;
00167     m_impl->m_bSuppressConnectionErrors = false;
00168     m_impl->m_ldapStruct = NULL;
00169     m_impl->m_bDeferFetch = true;
00170 }
00178 CPKIFLDAPRepository::~CPKIFLDAPRepository(void)
00179 {
00180     LOG_STRING_DEBUG("CPKIFLDAPRepository::~CPKIFLDAPRepository(void)", TOOLKIT_SR_LDAPREPOSITORY, 0, this);
00181 
00182     if(NULL != m_impl->m_ldapStruct)
00183     { 
00184         //ldap_unbind(m_impl->m_ldapStruct); 
00185         m_impl->m_ldapStruct = NULL;
00186     }
00187     if(0 != m_impl)
00188     {
00189         delete m_impl;
00190         m_impl = 0;
00191     }
00192 }
00200 void CPKIFLDAPRepository::Initialize() 
00201 {
00202     LOG_STRING_DEBUG("CPKIFLDAPRepository::Initialize()", TOOLKIT_SR_LDAPREPOSITORY, 0, this);
00203 }
00204 
00216 int CPKIFLDAPRepository::GetPort() const 
00217 {
00218     return m_impl->m_nPort;
00219 }
00237 void CPKIFLDAPRepository::Set_Port(
00239     int port) 
00240 {
00241     if(65535 < port)
00242     {
00243         RAISE_CACHE_EXCEPTION("Port greater than 65535 passed to CPKIFLDAPRepository::Set_Port.", thisComponent, COMMON_INVALID_INPUT, this)
00244     }
00245     m_impl->m_nPort = port;
00246 }
00259 const char* CPKIFLDAPRepository::GetHost() const 
00260 {
00261     return m_impl->m_strHost->c_str();
00262 }
00279 void CPKIFLDAPRepository::SetHost(
00281     const char* host) 
00282 {
00283     //added check for NULL  2/23/2005
00284     if(NULL == host)
00285     {
00286         RAISE_CACHE_EXCEPTION("NULL host passed to CPKIFLDAPRepository::SetHost.", thisComponent, COMMON_INVALID_INPUT, this)
00287     }
00288     m_impl->m_strHost->assign(host);
00289 }
00303 const char*CPKIFLDAPRepository::GetUsername() const 
00304 {
00305     return m_impl->m_strUsername->c_str();
00306 }
00316 void CPKIFLDAPRepository::SetUsername(
00318     const char* username) 
00319 {
00320     m_impl->m_strUsername->assign(username);
00321 }
00331 void CPKIFLDAPRepository::SetPassword(
00333     const char* password) 
00334 {
00335     m_impl->m_strPassword->assign(password);
00336 }
00348 void CPKIFLDAPRepository::SetSuppressConnectionErrors(
00350     bool b)
00351 {
00352     m_impl->m_bSuppressConnectionErrors = b;
00353 }
00365 bool CPKIFLDAPRepository::GetSuppressConnectionErrors() const
00366 {
00367     return m_impl->m_bSuppressConnectionErrors;
00368 }
00369 
00370 
00380 LDAP* CPKIFLDAPRepositoryImpl::ConnectAndBind(
00382     std::string& strHost, 
00384     int port,
00386     std::string& strUsername, 
00388     std::string& strPassword)
00389 {
00390     LOG_STRING_DEBUG("CPKIFLDAPRepository::ConnectAndBind(std::string& strHost, int port, std::string& strUsername, std::string& strPassword)", TOOLKIT_SR_LDAPREPOSITORY, 0, this);
00391 
00392     if(NULL != m_ldapStruct)
00393         return m_ldapStruct;
00394 
00395     if(strHost.empty())
00396         return NULL;
00397 
00398     int ret = 0;
00399 
00400     const char* host = strHost.c_str();
00401     string lud_hostString(host);
00402 
00403     CSingletonLDAPConnection* slc = CSingletonLDAPConnection::Instance();
00404     m_ldapStruct = slc->GetConnection(lud_hostString, port);
00405     if(!m_ldapStruct)
00406     {
00407         //give a few tries at connecting
00408         int connectCount = 0;
00409         do
00410         {
00411             ostrstream oss;
00412             oss << "Attempting to connect to : " << host << " on port " << port << ends;
00413             LOG_STRING_INFO(oss.str(), TOOLKIT_SR_LDAPREPOSITORY, 0, this);
00414             oss.freeze(false);
00415 
00416             m_ldapStruct = ldap_open(const_cast<char*>(host), port);
00417             if(NULL != m_ldapStruct) 
00418                 connectCount = 5;
00419             else
00420             {
00421                 oss << "Failed to connect to : " << host << " on port " << port << ends;
00422                 LOG_STRING_ERROR(oss.str(), TOOLKIT_SR_LDAPREPOSITORY, 0, this);
00423                 oss.freeze(false);
00424         
00425                 SLEEP(10);
00426                 ++connectCount;
00427             }
00428         }while(5 > connectCount);
00429 
00430         //if we failed to open a connection, i.e. ldapStruct is NULL, then return NULL
00431         if(NULL == m_ldapStruct) 
00432         {
00433             std::ostringstream os;
00434             os << "Failed to open connection to " << host << " on port " << port;;
00435             LOG_STRING_ERROR(os.str().c_str(), TOOLKIT_SR_LDAPREPOSITORY, CACHE_LDAP_CONNECT_AND_BIND_FAILED, this)
00436             return NULL;
00437         }
00438 
00439         //give a few tries at binding
00440         int bindCount = 0;
00441         char* username = NULL;
00442         char* password = NULL;
00443 
00444         //get pointers to username and password - if present
00445         if(!strUsername.empty())
00446             username = const_cast<char*>(strUsername.c_str());
00447 
00448         if(!strPassword.empty())
00449             password = const_cast<char*>(strPassword.c_str());
00450 
00451         ULONG timeout = 30;
00452         ldap_set_option(m_ldapStruct, LDAP_OPT_TIMELIMIT, &timeout);
00453 
00454         do
00455         {
00456             ret = ldap_simple_bind_s(m_ldapStruct, username, password);
00457             if(0 == ret)
00458                 bindCount = 5;
00459             else
00460             {
00461                 //added 7/29/2004
00462                 if(LDAP_PROTOCOL_ERROR == ret)
00463                 {
00464                     int opt = LDAP_VERSION3;
00465                     ldap_set_option(m_ldapStruct, LDAP_OPT_PROTOCOL_VERSION, &opt);
00466                 }
00467 
00468                 SLEEP(10);
00469                 ++bindCount;
00470             }
00471         }while( 5 > bindCount);
00472 
00473         //if we failed to bind - clean up the ldapStruct object and return NULL
00474         //otherwise simply return the ldapStruct object
00475         if(0 != ret)
00476         {
00477             std::ostringstream os;
00478             os << "Failed to bind to " << host << " on port " << port;;
00479             LOG_STRING_ERROR(os.str().c_str(), TOOLKIT_SR_LDAPREPOSITORY, CACHE_LDAP_CONNECT_AND_BIND_FAILED, this)
00480 
00481             ldap_unbind(m_ldapStruct);
00482             m_ldapStruct = NULL;
00483         }
00484         else
00485         {
00486             slc->PushConnection(lud_hostString, port, m_ldapStruct);
00487 
00488             std::ostringstream os;
00489             os << "Successfully connected to host " << host << " on port " << port;;
00490             LOG_STRING_INFO(os.str().c_str(), TOOLKIT_SR_LDAPREPOSITORY, 0, this)
00491         }
00492     }
00493 
00494     return m_ldapStruct;
00495 }
00514 void CPKIFLDAPRepository::GetCertificates(
00516     const CPKIFNamePtr& subDN,
00518     CPKIFCertificateList& certList,
00520     PKIInfoSource source)
00521 {
00522     _GetCertificates(subDN, certList, source, PBD_FORWARD);
00523 }
00542 void CPKIFLDAPRepository::_GetCertificates(
00544     const CPKIFNamePtr& subDN,
00546     CPKIFCertificateList& certList,
00548     PKIInfoSource source,
00550     PathBuildingDirection pbd)
00551 {
00552 #undef CLEANUP
00553 #define CLEANUP \
00554 { \
00555     if(NULL != binaryValuesPtr)\
00556     { ldap_value_free_len(binaryValuesPtr);binaryValuesPtr = NULL;}\
00557     if(NULL != tempAttrName)\
00558     { ldap_memfree(tempAttrName);tempAttrName = NULL;}\
00559     if(NULL != ber_temp)\
00560     { ber_free(ber_temp, 0);ber_temp = NULL;}\
00561     if(NULL != results)\
00562     { ldap_msgfree(results);results = NULL;}\
00563 } 
00564 
00565     LOG_STRING_DEBUG("CPKIFLDAPRepository::GetCertificates(const CPKIFNamePtr& subDN, CPKIFCertificateList& certList, PKIInfoSource source)", TOOLKIT_SR_LDAPREPOSITORY, 0, this);
00566 
00567     //ignore requests for locally stored certificates
00568     if(LOCAL == source)
00569     {
00570         LOG_STRING_DEBUG("Skipping CPKIFLDAPRepository - searching LOCAL sources only", thisComponent, 0, this);
00571         return;
00572     }
00573 
00574     //ignore bad input
00575     if(subDN == (CPKIFName*)NULL)
00576     {
00577         LOG_STRING_ERROR("Skipping CPKIFLDAPRepository - input NULL or empty subject DN", thisComponent, COMMON_INVALID_INPUT, this);
00578         return;
00579     }
00580 
00581     if(!m_impl->CheckNamespaces(subDN))
00582         return;
00583 
00584     //get a pointer to a string representation of the DN we will use to retrieve certs
00585     const char* tmpSubDN = subDN->ToString();
00586 
00587     size_t origSize = certList.size();
00588 
00589     int ret = 0;
00590 
00591     LDAP* ldapStruct = NULL;
00592     LDAPMessage* results = NULL;    
00593     LDAPMessage* curEntry = NULL;       //does not need to be freed (per MSDN)
00594     BerElement *ber_temp = NULL;
00595     struct berval **binaryValuesPtr = NULL;
00596     struct berval *tmpPtr = NULL;
00597 
00598     const char* filter = "objectclass=*";
00599     char* certAttrName = "caCertificate;binary";
00600     char* crossCertAttrName = "crosscertificatepair;binary";
00601     char* certAttrName2 = "caCertificate";
00602     char* crossCertAttrName2 = "crosscertificatepair";
00603     char* userCertAttrName = "userCertificate"; //added these two to permit discovery of crl issuers 7/18
00604     char* userCertAttrName2 = "userCertificate;binary";
00605 
00606     char* attrsOfInterest[] = {crossCertAttrName, crossCertAttrName2, certAttrName, certAttrName2, userCertAttrName, userCertAttrName2, NULL};
00607     if(PBD_REVERSE == pbd)
00608         attrsOfInterest[2] = NULL; //only care about cross-certs, crimp off everything else
00609 
00610     char* tempAttrName = NULL;
00611 
00612     int multiAttrIndex = 0;
00613 
00614     //log entries are created in ConnectAndBind as necessary
00615     ldapStruct = m_impl->ConnectAndBind(*m_impl->m_strHost, m_impl->m_nPort, *m_impl->m_strUsername, *m_impl->m_strPassword);
00616     if(NULL == ldapStruct)
00617     {
00618         if(!m_impl->m_bSuppressConnectionErrors)
00619         {
00620             CLEANUP
00621             RAISE_CACHE_EXCEPTION("Connect and bind failed.", thisComponent, CACHE_LDAP_CONNECT_AND_BIND_FAILED, this)
00622         }
00623         else
00624             return;
00625     }
00626 
00627     try
00628     {
00629         //turn on referral chasing (should be on by default but...)
00630         ldap_set_option(ldapStruct, LDAP_OPT_REFERRALS, LDAP_OPT_ON);
00631 
00632         //added 7/20/2004
00633         //no more than 20000 byte certs
00634         const int c_nMaxCertSize = 20000;
00635         ldap_set_option(ldapStruct, LDAP_OPT_SIZELIMIT, &c_nMaxCertSize);
00636 
00637         //retrieve the directory entry
00638         ret = ldap_search_s(ldapStruct, (char*)tmpSubDN, LDAP_SCOPE_BASE, (char *)filter, attrsOfInterest, 0, &results);
00639         if(0 != ret || NULL == results)
00640         {
00641             //exceptions are thrown simply to get us to the bottom of this function so cleanup can occur
00642             std::ostringstream os;
00643             os << "ldap_search_s failed searching entry for  " << tmpSubDN << " on host " << m_impl->m_strHost->c_str();
00644             CLEANUP
00645             RAISE_CACHE_EXCEPTION(os.str().c_str(), thisComponent, CACHE_LDAP_ERROR, this)
00646         }
00647 
00648         curEntry = ldap_first_entry(ldapStruct, results);
00649         if(NULL == curEntry)
00650         {
00651             std::ostringstream os;
00652             os << "ldap_first_entry failed searching entry for  " << tmpSubDN << " on host " << m_impl->m_strHost->c_str();
00653             CLEANUP
00654             RAISE_CACHE_EXCEPTION(os.str().c_str(), thisComponent, CACHE_LDAP_ERROR, this)
00655         }
00656         
00657         tempAttrName = ldap_first_attribute(ldapStruct, curEntry, &ber_temp);
00658         if(NULL == curEntry || NULL == tempAttrName)
00659         {
00660             std::ostringstream os;
00661             os << "ldap_first_attribute failed searching entry for  " << tmpSubDN << " on host " << m_impl->m_strHost->c_str();
00662             CLEANUP
00663             RAISE_CACHE_EXCEPTION(os.str().c_str(), thisComponent, CACHE_LDAP_ERROR, this)
00664         }
00665 
00666         do
00667         {
00668             //compare the current attribute name to the certificate attribute name
00669             if(0 == stricmp(certAttrName, tempAttrName) || 0 == stricmp(userCertAttrName, tempAttrName) ||
00670                 0 == stricmp(certAttrName2, tempAttrName) || 0 == stricmp(userCertAttrName2, tempAttrName))
00671             {
00672                 multiAttrIndex = 0;
00673                 if(NULL != binaryValuesPtr)
00674                 {
00675                     ldap_value_free_len(binaryValuesPtr); binaryValuesPtr = NULL;
00676                 }
00677 
00678                 binaryValuesPtr = ldap_get_values_len(ldapStruct, curEntry, tempAttrName);
00679                 const int entryCount = ldap_count_values_len(binaryValuesPtr);
00680                 if(0 != entryCount && NULL != binaryValuesPtr && NULL != binaryValuesPtr[multiAttrIndex])
00681                 {
00682                     //iterate over all of the values
00683                     while(multiAttrIndex < entryCount)
00684                     {
00685                         tmpPtr = binaryValuesPtr[multiAttrIndex];
00686                         if(NULL == tmpPtr)
00687                         {
00688                             break;
00689                         }
00690 
00691                         //bad_alloc caught by catch(...); cleanup executed
00692                         CPKIFCertificatePtr tmpCert(new CPKIFCertificate()); 
00693                         try
00694                         {
00695                             //create cert using tmpPtr->bv_val, tmpPtr->bv_len
00696                             tmpCert->Decode((unsigned char*)tmpPtr->bv_val, tmpPtr->bv_len);                        
00697 
00698                             GottaMatch<CPKIFCertificatePtr> gm;
00699                             gm.SetRHS(tmpCert);
00700                             if(certList.end() == find_if(certList.begin(), certList.end(), gm))
00701                                 certList.push_back(tmpCert);
00702                         }
00703                         catch(CPKIFException&)
00704                         {
00705                             //EXCEPTION DELETION
00706                             //we don't need to pass this exception up - we should log the fact
00707                             //that a busted (or non) cert was found and keeping sifting through
00708                             //the remaining values, if any
00709                             //delete e;
00710 
00711                             //ignore entries that fail to parse
00712                             std::ostringstream os;
00713                             os << "Failed to parse certificate found in entry for " << tmpSubDN << " on host " << m_impl->m_strHost->c_str();
00714                             LOG_STRING_ERROR(os.str().c_str(), thisComponent, CACHE_PARSE_ERROR, this)
00715                         }
00716 
00717                         multiAttrIndex++;
00718                     }
00719                 }
00720             }
00721             else if(0 == stricmp(crossCertAttrName, tempAttrName) || 0 == stricmp(crossCertAttrName2, tempAttrName))
00722             {
00723                 multiAttrIndex = 0;
00724                 if(NULL != binaryValuesPtr)
00725                 {
00726                     ldap_value_free_len(binaryValuesPtr); binaryValuesPtr = NULL;
00727                 }
00728                 binaryValuesPtr = ldap_get_values_len(ldapStruct, curEntry, tempAttrName);
00729                 const int entryCount = ldap_count_values_len(binaryValuesPtr);
00730                 if(0 != entryCount && NULL != binaryValuesPtr && NULL != binaryValuesPtr[multiAttrIndex])
00731                 {
00732                     while(multiAttrIndex < entryCount)
00733                     {
00734                         tmpPtr = binaryValuesPtr[multiAttrIndex];
00735                         if(NULL == tmpPtr)
00736                         {
00737                             break;
00738                         }
00739 
00740                         try
00741                         {
00742                             CACASNWRAPPER_CREATE(CACX509V3CertificatePair, objPDU);
00743                             objPDU.Decode((unsigned char*)tmpPtr->bv_val, tmpPtr->bv_len);
00744 
00745                             if((objPDU->m.forwardPresent && PBD_FORWARD == pbd) ||
00746                                 (objPDU->m.reversePresent && PBD_REVERSE == pbd))
00747                             {
00748                                 //bad_alloc caught by catch(...); cleanup executed
00749                                 CPKIFCertificatePtr tmpCert(new CPKIFCertificate);
00750 
00751                                 //bad_alloc caught by catch(...); cleanup executed
00752                                 unsigned char* buf = new unsigned char[tmpPtr->bv_len];
00753 
00754                                 OOCTXT ctxt;
00755                                 initContext (&ctxt);
00756                                 setBEREncBufPtr(&ctxt, buf, tmpPtr->bv_len);
00757                                 if(objPDU->m.forwardPresent && PBD_FORWARD == pbd)
00758                                     BEREncCACX509V3Certificate(&ctxt, &objPDU->forward, ASN1EXPL);
00759                                 else if(objPDU->m.reversePresent && PBD_REVERSE == pbd)
00760                                     BEREncCACX509V3Certificate(&ctxt, &objPDU->reverse, ASN1EXPL);
00761 
00762                                 try
00763                                 {
00764                                     int iCertLen = 0;
00765                                     try 
00766                                     {
00767                                         iCertLen = numeric_cast<int>(ctxt.buffer.size - ctxt.buffer.byteIndex - 1);
00768                                     }
00769                                     catch(bad_numeric_cast &) 
00770                                     {
00771                                         throw CPKIFException(TOOLKIT_CACHE, COMMON_INVALID_INPUT, "Certificate size is larger than maximum integer size.");
00772                                     }
00773 
00774                                     tmpCert->Decode(ctxt.buffer.data + ctxt.buffer.byteIndex, iCertLen);
00775 
00776                                     GottaMatch<CPKIFCertificatePtr> gm;
00777                                     gm.SetRHS(tmpCert);
00778                                     if(certList.end() == find_if(certList.begin(), certList.end(), gm))
00779                                         certList.push_back(tmpCert);
00780                                 }
00781                                 catch(CPKIFException&)
00782                                 {
00783                                     //EXCEPTION DELETION
00784                                     //we don't need to pass this exception up - we should log the fact
00785                                     //that a busted (or non) cert was found and keeping sifting through
00786                                     //the remaining values, if any
00787                                     //delete e;
00788 
00789                                     //ignore entries that fail to parse
00790                                     std::ostringstream os;
00791                                     os << "Failed to parse certificate from cross-certificate found in entry for " << tmpSubDN << " on host " << m_impl->m_strHost->c_str();
00792                                     LOG_STRING_ERROR(os.str().c_str(), thisComponent, CACHE_PARSE_ERROR, this)
00793                                 }
00794 
00795                                 freeEncodeBuffer(&ctxt);
00796                                 memFreeAll(&ctxt);
00797                                 delete[] buf;
00798                             }
00799                         }
00800                         catch(CPKIFException&)
00801                         {
00802                             //EXCEPTION DELETION
00803                             //we don't need to pass this exception up - we should log the fact
00804                             //that a busted (or non) cert was found and keeping sifting through
00805                             //the remaining values, if any
00806                             //delete e;
00807 
00808                             //ignore entries that do not parse
00809                             std::ostringstream os;
00810                             os << "Failed to parse certificate from cross-certificate found in entry for " << tmpSubDN << " on host " << m_impl->m_strHost->c_str();
00811                             LOG_STRING_ERROR(os.str().c_str(), thisComponent, CACHE_PARSE_ERROR, this)
00812                         }
00813 
00814                         multiAttrIndex++;
00815                     }
00816                 }
00817             }
00818 
00819             //inspect the next attribute
00820             ldap_memfree(tempAttrName); tempAttrName = NULL;
00821             tempAttrName = ldap_next_attribute(ldapStruct, curEntry, ber_temp);
00822 
00823         }while(NULL != tempAttrName);
00824     }
00825     catch(CPKIFException&)
00826     {
00827         //EXCEPTION DELETION
00828         //do nothing - we used these exceptions essentially as a goto
00829         //delete e;
00830     }
00831     catch(...)
00832     {
00833         CLEANUP;
00834         throw;
00835     }
00836 
00837     if(origSize != certList.size())
00838     {
00839         std::ostringstream os;
00840         os << "Found one or more certificates issued to: " << tmpSubDN << " on host " << m_impl->m_strHost->c_str();
00841         LOG_STRING_DEBUG(os.str().c_str(), thisComponent, 0, this);
00842     }
00843     else
00844     {
00845         std::ostringstream os;
00846         os << "Failed to find a certificate issued to: " << tmpSubDN << " on host " << m_impl->m_strHost->c_str();
00847         LOG_STRING_INFO(os.str().c_str(), thisComponent, 0, this);
00848     }
00849 
00850     CLEANUP;
00851 }
00859 void CPKIFLDAPRepository::GetCertificates(const CPKIFCertificatePtr& cert, CPKIFCertificateList& certList, PKIInfoSource source, PathBuildingDirection pbd)
00860 {
00861     if(PBD_FORWARD == pbd)
00862     {
00863         _GetCertificates(cert->Issuer(), certList, source, pbd);
00864     }
00865     else
00866     {
00867         _GetCertificates(cert->Subject(), certList, source, pbd);
00868     }
00869         
00870     //_GetCertificates(cert->Subject(), certList, source, PBD_REVERSE);
00871 }
00872 
00880 bool IsNonDirName(
00882     const CPKIFGeneralNamePtr& gn)
00883 {
00884     return CPKIFGeneralName::DIRECTORYNAME != gn->GetType();
00885 }
00905 void CPKIFLDAPRepository::GetCRLs(
00907     const CPKIFCertificatePtr& cert, 
00909     CPKIFCRLList& crlList,
00911     PKIInfoSource source)
00912 {
00913 #undef CLEANUP
00914 #define CLEANUP \
00915 { \
00916     if(NULL != binaryValuesPtr)\
00917     { ldap_value_free_len(binaryValuesPtr);binaryValuesPtr = NULL;}\
00918     if(NULL != tempAttrName)\
00919     { ldap_memfree(tempAttrName);tempAttrName = NULL;}\
00920     if(NULL != ber_temp)\
00921     { ber_free(ber_temp, 0);ber_temp = NULL;}\
00922     if(NULL != results)\
00923     { ldap_msgfree(results); results = NULL;}\
00924 } 
00925 
00926     LOG_STRING_DEBUG("CPKIFLDAPRepository::GetCRLs(const CPKIFCertificatePtr& cert, CPKIFCRLList& crlList, PKIInfoSource source)", TOOLKIT_SR_LDAPREPOSITORY, 0, this);
00927 
00928     if(LOCAL == source)
00929     {
00930         LOG_STRING_DEBUG("Skipping CPKIFLDAPRepository - searching LOCAL sources only", thisComponent, 0, this);
00931         return;
00932     }
00933 
00934     size_t origSize = crlList.size();
00935     CPKIFNamePtr issDN = cert->Issuer();
00936 
00937     if(!m_impl->CheckNamespaces(issDN))
00938         return;
00939 
00940     CPKIFGeneralNameList nameList;
00941     CollectNamesFromCRLDP(cert, nameList);
00942 
00943     //we don't care about non-directory names in this handler
00944     CPKIFGeneralNameList::iterator newEnd = remove_if(nameList.begin(), nameList.end(), IsNonDirName);
00945     nameList.erase(newEnd, nameList.end());
00946 
00947     try
00948     {
00949         CPKIFGeneralNamePtr tmpGN(new CPKIFGeneralName(issDN));
00950         nameList.push_back(tmpGN);
00951     }
00952     catch(std::bad_alloc*)
00953     {
00954         //nothing has been allocated yet - no need to proceed
00955         return;
00956     }
00957 
00958     int ret = 0;
00959 
00960     LDAP* ldapStruct = NULL;
00961     LDAPMessage* results = NULL;    
00962     LDAPMessage* curEntry = NULL;       //does not need to be freed (per MSDN)
00963     BerElement *ber_temp = NULL;
00964     struct berval **binaryValuesPtr = NULL;
00965     struct berval *tmpPtr = NULL;
00966 
00967     const char* filter = "objectclass=*";
00968     char* tempAttrName = NULL;
00969     char* crlName = "certificateRevocationList;binary";
00970     char* arlName = "authorityRevocationList;binary";
00971     char* crlName2 = "certificateRevocationList";
00972     char* arlName2 = "authorityRevocationList";
00973     char* deltaName = "deltaRevocationList;binary";
00974     char* deltaName2 = "deltaRevocationList";
00975 
00976     //added delta name 12/8/2003
00977     char* attrsOfInterest[] = {crlName, arlName, crlName2, arlName2, deltaName, deltaName2, NULL};
00978 
00979     int multiAttrIndex = 0;
00980 
00981     ldapStruct = m_impl->ConnectAndBind(*m_impl->m_strHost, m_impl->m_nPort, *m_impl->m_strUsername, *m_impl->m_strPassword);
00982     if(NULL == ldapStruct)
00983     {
00984         if(!m_impl->m_bSuppressConnectionErrors)
00985         {
00986             std::ostringstream os;
00987             os << "Failed to open connection to " << *m_impl->m_strHost << " on port " << m_impl->m_nPort;
00988             CLEANUP
00989             RAISE_CACHE_EXCEPTION(os.str().c_str(), thisComponent, CACHE_LDAP_CONNECT_AND_BIND_FAILED, this)
00990         }
00991         else
00992             return;
00993     }
00994 
00995     CPKIFGeneralNameList::iterator pos;
00996     CPKIFGeneralNameList::iterator end = nameList.end();
00997     for(pos = nameList.begin(); pos != end; ++pos)
00998     {
00999         try
01000         {
01001             CPKIFNamePtr tmpName = (*pos)->directoryName();
01002             const char* tmpSubDN = tmpName->ToString();
01003 
01004             //turn on referral chasing (should be on by default but...)
01005             ldap_set_option(ldapStruct, LDAP_OPT_REFERRALS, LDAP_OPT_ON);
01006 
01007             //added 7/20/2004 -> raised to 100MB 11/17/2006
01008             const int c_nMaxCRLSize = 100000000;
01009             ldap_set_option(ldapStruct, LDAP_OPT_SIZELIMIT, &c_nMaxCRLSize);
01010 
01011             //retrieve the directory entry
01012             ret = ldap_search_s(ldapStruct, (char*)tmpSubDN, LDAP_SCOPE_BASE, (char *)filter, attrsOfInterest, 0, &results);
01013             if(0 != ret || NULL == results)
01014             {
01015                 //exceptions are thrown simply to get us to the bottom of this function so cleanup can occur
01016                 std::ostringstream os;
01017                 os << "ldap_search_s failed searching entry for  " << tmpSubDN << " on host " << m_impl->m_strHost->c_str();
01018                 CLEANUP
01019                 RAISE_CACHE_EXCEPTION(os.str().c_str(), thisComponent, CACHE_LDAP_ERROR, this)
01020             }
01021 
01022             curEntry = ldap_first_entry(ldapStruct, results);
01023             if(NULL == curEntry)
01024             {
01025                 std::ostringstream os;
01026                 os << "ldap_first_entry failed searching entry for  " << tmpSubDN << " on host " << m_impl->m_strHost->c_str();
01027                 CLEANUP
01028                 RAISE_CACHE_EXCEPTION(os.str().c_str(), thisComponent, CACHE_LDAP_ERROR, this)
01029             }
01030             
01031             tempAttrName = ldap_first_attribute(ldapStruct, curEntry, &ber_temp);
01032             if(NULL == curEntry || NULL == tempAttrName)
01033             {
01034                 std::ostringstream os;
01035                 os << "ldap_first_attribute failed searching entry for  " << tmpSubDN << " on host " << m_impl->m_strHost->c_str();
01036                 CLEANUP
01037                 RAISE_CACHE_EXCEPTION(os.str().c_str(), thisComponent, CACHE_LDAP_ERROR, this)
01038             }
01039 
01040             do
01041             {
01042                 if(0 == stricmp(crlName, tempAttrName) || 0 == stricmp(arlName, tempAttrName) ||
01043                     0 == stricmp(crlName2, tempAttrName) || 0 == stricmp(arlName2, tempAttrName) ||
01044                     0 == stricmp(deltaName2, tempAttrName) || 0 == stricmp(deltaName, tempAttrName))
01045                 {
01046                     multiAttrIndex = 0;
01047                     if(NULL != binaryValuesPtr)
01048                     {
01049                         ldap_value_free_len(binaryValuesPtr);binaryValuesPtr = NULL;
01050                     }
01051                     binaryValuesPtr = ldap_get_values_len(ldapStruct, curEntry, tempAttrName);
01052                     const int entryCount = ldap_count_values_len(binaryValuesPtr);
01053                     if(0 == entryCount || NULL == binaryValuesPtr || NULL == binaryValuesPtr[multiAttrIndex])
01054                     {
01055                         throw CPKIFCacheException(thisComponent, -1);
01056                     }
01057 
01058                     while(multiAttrIndex < entryCount)
01059                     {
01060                         tmpPtr = binaryValuesPtr[multiAttrIndex];
01061                         if(NULL == tmpPtr)
01062                         {
01063                             break;
01064                         }
01065 
01066                         //bad_alloc caught by catch(...); cleanup executed
01067                         CPKIFCRLPtr tmpCRL(new CPKIFCRL());
01068                         try
01069                         {
01070                             
01071                             //create cert using tmpPtr->bv_val, tmpPtr->bv_len
01072                             tmpCRL->Decode((unsigned char*)tmpPtr->bv_val, tmpPtr->bv_len);
01073 
01074                             GottaMatch<CPKIFCRLPtr> gm;
01075                             gm.SetRHS(tmpCRL);
01076                             if(crlList.end() == find_if(crlList.begin(), crlList.end(), gm))
01077                                 crlList.push_back(tmpCRL);
01078                         }
01079                         catch(CPKIFException&)
01080                         {
01081                             //EXCEPTION DELETION
01082                             //we don't need to pass this exception up - we should log the fact
01083                             //that a busted (or non) crl was found and keeping sifting through
01084                             //the remaining values, if any
01085                             //delete e;
01086 
01087                             //ignore entries that fail to parse
01088                             std::ostringstream os;
01089                             os << "Failed to parse CRL found in entry for " << tmpSubDN << " on host " << m_impl->m_strHost->c_str();
01090                             LOG_STRING_ERROR(os.str().c_str(), thisComponent, CACHE_PARSE_ERROR, this)
01091                         }
01092 
01093 
01094                         multiAttrIndex++;
01095                     }
01096                 }
01097 
01098                 ldap_memfree(tempAttrName); tempAttrName = NULL;
01099                 tempAttrName = ldap_next_attribute(ldapStruct, curEntry, ber_temp);
01100             }while(NULL != tempAttrName);
01101         }
01102         catch(CPKIFException&)
01103         {
01104             //EXCEPTION DELETION
01105             //do nothing except clean up loop variables - we used these exceptions essentially as a goto
01106             CLEANUP;
01107             //delete e;
01108         }
01109         catch(...)
01110         {
01111             CLEANUP;
01112             throw;
01113         }
01114 
01115         if(origSize != crlList.size())
01116         {
01117             std::ostringstream os;
01118             //added ->string after issDN 12/3/2003
01119             os << "Found one or more CRLs issued by: " << issDN->ToString() << " on host " << m_impl->m_strHost->c_str();
01120             LOG_STRING_DEBUG(os.str().c_str(), thisComponent, 0, this);
01121         }
01122         else
01123         {
01124             std::ostringstream os;
01125             //added ->string after issDN 12/3/2003
01126             os << "Failed to find a CRL issued by: " << issDN->ToString() << " on host " << m_impl->m_strHost->c_str();
01127             LOG_STRING_INFO(os.str().c_str(), thisComponent, 0, this);
01128         }
01129 
01130         CLEANUP;
01131     }
01132 }
01133 
01162 std::string GetLdapUriMultiAttr(
01164     const char* host,
01166     int port,
01168     const char* entryDn,
01170     vector<string>& attributeList)
01171 {
01172     ostringstream unescapedUriStream;
01173     unescapedUriStream << entryDn;
01174     std::string unescapedUriString = unescapedUriStream.str();
01175 
01176     int strLen = 0;
01177     try 
01178     {
01179         strLen = numeric_cast<int>(unescapedUriString.length());
01180     }
01181     catch(bad_numeric_cast &) 
01182     {
01183         throw CPKIFException(TOOLKIT_CACHE, COMMON_INVALID_INPUT, "Str length is an impossibly long number.");
01184     }
01185 
01186     char* fromCurl = curl_escape(unescapedUriString.c_str(), strLen);
01187 
01188     ostringstream escapedUriStream;
01189 
01190     escapedUriStream << "ldap://" << host << ":" << port << "/" << fromCurl << "?";
01191 
01192     if(fromCurl)
01193         curl_free(fromCurl);
01194     
01195     vector<string>::iterator pos;
01196     vector<string>::iterator end = attributeList.end();
01197     for(pos = attributeList.begin(); pos != end; ++pos)
01198     {
01199         if(pos != end-1)
01200             escapedUriStream << *pos << ",";
01201         else
01202             escapedUriStream << *pos;
01203     }
01204 
01205     std::string escapedUriString = escapedUriStream.str();
01206     return escapedUriString;
01207 }
01235 std::string GetLdapUri(
01237     const char* host,
01239     int port,
01241     const char* entryDn,
01243     const char* attribute)
01244 {
01245     ostringstream unescapedUriStream;
01246     unescapedUriStream << entryDn;
01247     std::string unescapedUriString = unescapedUriStream.str();
01248 
01249     int strLen = 0;
01250     try 
01251     {
01252         strLen = numeric_cast<int>(unescapedUriString.length());
01253     }
01254     catch(bad_numeric_cast &) 
01255     {
01256         throw CPKIFException(TOOLKIT_CACHE, COMMON_INVALID_INPUT, "Str length is an impossibly long number.");
01257     }
01258 
01259 
01260     char* fromCurl = curl_escape(unescapedUriString.c_str(), strLen);
01261 
01262     ostringstream escapedUriStream;
01263 
01264     escapedUriStream << "ldap://" << host << ":" << port << "/" << fromCurl << "?" << attribute;
01265 
01266     if(fromCurl)
01267         curl_free(fromCurl);
01268 
01269     std::string escapedUriString = escapedUriStream.str();
01270     return escapedUriString;
01271 }
01279 void CPKIFLDAPRepository::GetCRLSources(
01281     const CPKIFCertificatePtr& cert, 
01283     CPKIFCrlSourceList& crlList,
01285     PKIInfoSource source
01286 )
01287 {
01288 #undef CLEANUP
01289 #define CLEANUP \
01290 { \
01291     if(NULL != binaryValuesPtr)\
01292     { ldap_value_free_len(binaryValuesPtr);binaryValuesPtr = NULL;}\
01293     if(NULL != tempAttrName)\
01294     { ldap_memfree(tempAttrName);tempAttrName = NULL;}\
01295     if(NULL != ber_temp)\
01296     { ber_free(ber_temp, 0);ber_temp = NULL;}\
01297     if(NULL != results)\
01298     { ldap_msgfree(results); results = NULL;}\
01299 } 
01300 
01301     LOG_STRING_DEBUG("CPKIFLDAPRepository::GetCRLs(const CPKIFCertificatePtr& cert, CPKIFCRLList& crlList, PKIInfoSource source)", TOOLKIT_SR_LDAPREPOSITORY, 0, this);
01302 
01303     if(LOCAL == source)
01304     {
01305         LOG_STRING_DEBUG("Skipping CPKIFLDAPRepository - searching LOCAL sources only", thisComponent, 0, this);
01306         return;
01307     }
01308 
01309     size_t origSize = crlList.size();
01310     CPKIFNamePtr issDN = cert->Issuer();
01311 
01312     if(!m_impl->CheckNamespaces(issDN))
01313         return;
01314 
01315     CPKIFGeneralNameList nameList;
01316     CollectNamesFromCRLDP(cert, nameList);
01317 
01318     //we don't care about non-directory names in this handler
01319     CPKIFGeneralNameList::iterator newEnd = remove_if(nameList.begin(), nameList.end(), IsNonDirName);
01320     nameList.erase(newEnd, nameList.end());
01321 
01322     try
01323     {
01324         CPKIFGeneralNamePtr tmpGN(new CPKIFGeneralName(issDN));
01325         GottaMatch<CPKIFGeneralNamePtr> gm;
01326         gm.SetRHS(tmpGN);
01327         if(nameList.end() == find_if(nameList.begin(), nameList.end(), gm))
01328             nameList.push_back(tmpGN);
01329     }
01330     catch(std::bad_alloc*)
01331     {
01332         //nothing has been allocated yet - no need to proceed
01333         return;
01334     }
01335 
01336     //Find self
01337     CPKIFLDAPRepositoryPtr thisSP;
01338     std::vector<IPKIFMediator*>::iterator mPos = this->m_parents.begin();
01339     std::vector<IPKIFMediator*>::iterator mEnd = this->m_parents.end();
01340     for(;mPos != mEnd; ++mPos)
01341     {
01342         CPKIFCacheMediator2* cm =dynamic_cast<CPKIFCacheMediator2*>(*mPos);
01343         if(cm)
01344         {
01345             std::vector<IPKIFColleaguePtr> cl;
01346             cm->GetColleagues(cl);
01347 
01348             std::vector<IPKIFColleaguePtr>::iterator cPos;
01349             std::vector<IPKIFColleaguePtr>::iterator cEnd = cl.end();
01350             for(cPos = cl.begin(); cPos != cEnd; ++cPos)
01351             {
01352                 IPKIFColleague* tmpP = &(*(*cPos));
01353                 if(this == dynamic_cast<CPKIFLDAPRepository*>(tmpP))
01354                 {
01355                     thisSP = boost::dynamic_pointer_cast<CPKIFLDAPRepository, IPKIFColleague>(*cPos);
01356                     break;
01357                 }
01358             }
01359         }
01360     }
01361 
01362     vector<std::string> attrsOfInterest;
01363     attrsOfInterest.push_back("certificateRevocationList;binary");
01364     attrsOfInterest.push_back("authorityRevocationList;binary");
01365     attrsOfInterest.push_back("certificateRevocationList");
01366     attrsOfInterest.push_back("authorityRevocationList");
01367     attrsOfInterest.push_back("deltaRevocationList;binary");
01368     attrsOfInterest.push_back("deltaRevocationList");
01369 
01370     for(CPKIFGeneralNameList::iterator pos = nameList.begin(); pos != nameList.end(); ++pos)
01371     {
01372         CPKIFNamePtr tmpDN = (*pos)->directoryName();
01373 
01374         std::string uri1 = GetLdapUriMultiAttr(m_impl->m_strHost->c_str(), m_impl->m_nPort, tmpDN->ToString(), attrsOfInterest);
01375         if(!UriAlreadyInList(crlList, uri1))
01376         {
01377             CPKIFLdapCrlNodePtr newNode(new CPKIFLdapCrlNode(thisSP, tmpDN, attrsOfInterest));
01378             newNode->AddSource(uri1);
01379             crlList.push_back(newNode);
01380         }
01381     }
01382 }
01383 
01389 class CaseInsensitiveFind
01390 {
01391 public:
01392     bool operator()(const string& t);
01400     void SetRHS(const string& rhs) {m_rhs = rhs;}
01401 private:
01402     string m_rhs;
01403 };
01411 bool CaseInsensitiveFind::operator()(const string& t)
01412 {
01413     return 0 == stricmp(m_rhs.c_str(), t.c_str());      
01414 }
01422 void CPKIFLDAPRepository::GetCertificates(const CPKIFNamePtr& issDN, std::vector<std::string>& attributes, CPKIFCertificateNodeList& certNodeList, PathBuildingDirection pbd)
01423 {
01424 #undef CLEANUP
01425 #define CLEANUP \
01426 { \
01427     if(NULL != binaryValuesPtr)\
01428     { ldap_value_free_len(binaryValuesPtr);binaryValuesPtr = NULL;}\
01429     if(NULL != tempAttrName)\
01430     { ldap_memfree(tempAttrName);tempAttrName = NULL;}\
01431     if(NULL != ber_temp)\
01432     { ber_free(ber_temp, 0);ber_temp = NULL;}\
01433     if(NULL != results)\
01434     { ldap_msgfree(results); results = NULL;}\
01435     if(attrsOfInterest) {delete attrsOfInterest; attrsOfInterest = NULL;}\
01436 } 
01437 
01438     LOG_STRING_DEBUG("CPKIFLDAPRepository::GetCertificates(const CPKIFNamePtr& entry, std::vector<std::string>& attributes, CPKIFCertificateNodeList& certNodeList)", TOOLKIT_SR_LDAPREPOSITORY, 0, this);
01439 
01440     if(!m_impl->CheckNamespaces(issDN))
01441         return;
01442 
01443     size_t origSize = certNodeList.size();
01444 
01445     int ret = 0;
01446 
01447     LDAP* ldapStruct = NULL;
01448     LDAPMessage* results = NULL;    
01449     LDAPMessage* curEntry = NULL;       //does not need to be freed (per MSDN)
01450     BerElement *ber_temp = NULL;
01451     struct berval **binaryValuesPtr = NULL;
01452     struct berval *tmpPtr = NULL;
01453 
01454     const char* filter = "objectclass=*";
01455     char* certAttrName = "caCertificate;binary";
01456     char* crossCertAttrName = "crosscertificatepair;binary";
01457     char* certAttrName2 = "caCertificate";
01458     char* crossCertAttrName2 = "crosscertificatepair";
01459     char* userCertAttrName = "userCertificate"; //added these two to permit discovery of crl issuers 7/18
01460     char* userCertAttrName2 = "userCertificate;binary";
01461     char* tempAttrName = NULL;
01462 
01463     //added delta name 12/8/2003
01464     char** attrsOfInterest = new char*[attributes.size()+1];
01465 
01466     std::vector<std::string>::iterator pos;
01467     std::vector<std::string>::iterator end = attributes.end();
01468     int ii = 0;
01469     for(pos = attributes.begin(); pos != end; ++pos, ++ii)
01470         attrsOfInterest[ii] = const_cast<char*>((*pos).c_str());
01471 
01472     attrsOfInterest[ii] = NULL;
01473 
01474     int multiAttrIndex = 0;
01475 
01476     std::string strSource = *m_impl->m_strHost;
01477     ldapStruct = m_impl->ConnectAndBind(*m_impl->m_strHost, m_impl->m_nPort, *m_impl->m_strUsername, *m_impl->m_strPassword);
01478     if(NULL == ldapStruct)
01479     {
01480         if(!m_impl->m_bSuppressConnectionErrors)
01481         {
01482             std::ostringstream os;
01483             os << "Failed to connect and bind to LDAP directory on host " << m_impl->m_strHost->c_str();
01484             CLEANUP
01485             RAISE_CACHE_EXCEPTION(os.str().c_str(), thisComponent, CACHE_LDAP_CONNECT_AND_BIND_FAILED, this)
01486         }
01487         else
01488             return;
01489     }
01490 
01491     try
01492     {
01493         const char* tmpSubDN = issDN->ToString();
01494 
01495         //turn on referral chasing (should be on by default but...)
01496         ldap_set_option(ldapStruct, LDAP_OPT_REFERRALS, LDAP_OPT_ON);
01497 
01498         //1MB ought to do for certs
01499         const int c_nMaxCertSize = 1000000;
01500         ldap_set_option(ldapStruct, LDAP_OPT_SIZELIMIT, &c_nMaxCertSize);
01501 
01502         //retrieve the directory entry
01503         ret = ldap_search_s(ldapStruct, (char*)tmpSubDN, LDAP_SCOPE_BASE, (char *)filter, attrsOfInterest, 0, &results);
01504         if(0 != ret || NULL == results)
01505         {
01506             //exceptions are thrown simply to get us to the bottom of this function so cleanup can occur
01507             std::ostringstream os;
01508             os << "ldap_search_s failed searching entry for  " << tmpSubDN << " on host " << m_impl->m_strHost->c_str();
01509             CLEANUP
01510             RAISE_CACHE_EXCEPTION(os.str().c_str(), thisComponent, CACHE_LDAP_ERROR, this)
01511         }
01512 
01513         curEntry = ldap_first_entry(ldapStruct, results);
01514         if(NULL == curEntry)
01515         {
01516             std::ostringstream os;
01517             os << "ldap_first_entry failed searching entry for  " << tmpSubDN << " on host " << m_impl->m_strHost->c_str();
01518             CLEANUP
01519             RAISE_CACHE_EXCEPTION(os.str().c_str(), thisComponent, CACHE_LDAP_ERROR, this)
01520         }
01521         
01522         tempAttrName = ldap_first_attribute(ldapStruct, curEntry, &ber_temp);
01523         if(NULL == curEntry || NULL == tempAttrName)
01524         {
01525             std::ostringstream os;
01526             os << "ldap_first_attribute failed searching entry for  " << tmpSubDN << " on host " << m_impl->m_strHost->c_str();
01527             CLEANUP
01528             RAISE_CACHE_EXCEPTION(os.str().c_str(), thisComponent, CACHE_LDAP_ERROR, this)
01529         }
01530 
01531         do
01532         {
01533             CaseInsensitiveFind csf;
01534             csf.SetRHS(tempAttrName);
01535             if(attributes.end() != find_if(attributes.begin(), attributes.end(), csf))
01536             {
01537                 //compare the current attribute name to the certificate attribute name
01538                 if(0 == stricmp(certAttrName, tempAttrName) || 0 == stricmp(userCertAttrName, tempAttrName) ||
01539                     0 == stricmp(certAttrName2, tempAttrName) || 0 == stricmp(userCertAttrName2, tempAttrName))
01540                 {
01541                     multiAttrIndex = 0;
01542                     if(NULL != binaryValuesPtr)
01543                     {
01544                         ldap_value_free_len(binaryValuesPtr); binaryValuesPtr = NULL;
01545                     }
01546 
01547                     binaryValuesPtr = ldap_get_values_len(ldapStruct, curEntry, tempAttrName);
01548                     const int entryCount = ldap_count_values_len(binaryValuesPtr);
01549                     if(0 != entryCount && NULL != binaryValuesPtr && NULL != binaryValuesPtr[multiAttrIndex])
01550                     {
01551                         //iterate over all of the values
01552                         while(multiAttrIndex < entryCount)
01553                         {
01554                             tmpPtr = binaryValuesPtr[multiAttrIndex];
01555                             if(NULL == tmpPtr)
01556                             {
01557                                 break;
01558                             }
01559 
01560                             //bad_alloc caught by catch(...); cleanup executed
01561                             CPKIFCertificatePtr tmpCert(new CPKIFCertificate()); 
01562                             try
01563                             {
01564                                 //create cert using tmpPtr->bv_val, tmpPtr->bv_len
01565                                 tmpCert->Decode((unsigned char*)tmpPtr->bv_val, tmpPtr->bv_len);                        
01566 
01567                                 CPKIFCertificateNodeEntryPtr tmpCertNode(new CPKIFCertificateNodeEntry(tmpCert));
01568                                 GottaMatch<CPKIFCertificateNodeEntryPtr> gm;
01569                                 gm.SetRHS(tmpCertNode);
01570                                 if(certNodeList.end() == find_if(certNodeList.begin(), certNodeList.end(), gm))
01571                                 {
01572                                     std::string uri1 = GetLdapUriMultiAttr(m_impl->m_strHost->c_str(), m_impl->m_nPort, tmpSubDN, attributes);
01573 
01574                                     vector<string> tmpAttrsOfInterest;
01575                                     tmpAttrsOfInterest.push_back(tempAttrName);
01576                                     std::string uri2 = GetLdapUriMultiAttr(m_impl->m_strHost->c_str(), m_impl->m_nPort, tmpSubDN, tmpAttrsOfInterest);
01577 
01578                                     //tmpCertNode->AddSource(strSource);
01579                                     tmpCertNode->AddSource(uri1);
01580                                     tmpCertNode->AddSource(uri2);
01581                                     tmpCertNode->SetSource(REMOTE);
01582                                     tmpCertNode->SetState(PAS_AVAILABLE);
01583                                     certNodeList.push_back(tmpCertNode);
01584                                 }
01585                             }
01586                             catch(CPKIFException&)
01587                             {
01588                                 //EXCEPTION DELETION
01589                                 //we don't need to pass this exception up - we should log the fact
01590                                 //that a busted (or non) cert was found and keeping sifting through
01591                                 //the remaining values, if any
01592                                 //delete e;
01593 
01594                                 //ignore entries that fail to parse
01595                                 std::ostringstream os;
01596                                 os << "Failed to parse certificate found in entry for " << tmpSubDN << " on host " << m_impl->m_strHost->c_str();
01597                                 LOG_STRING_ERROR(os.str().c_str(), thisComponent, CACHE_PARSE_ERROR, this)
01598                             }
01599 
01600                             multiAttrIndex++;
01601                         }
01602                     }
01603                 }
01604                 else if(0 == stricmp(crossCertAttrName, tempAttrName) || 0 == stricmp(crossCertAttrName2, tempAttrName))
01605                 {
01606                     multiAttrIndex = 0;
01607                     if(NULL != binaryValuesPtr)
01608                     {
01609                         ldap_value_free_len(binaryValuesPtr); binaryValuesPtr = NULL;
01610                     }
01611                     binaryValuesPtr = ldap_get_values_len(ldapStruct, curEntry, tempAttrName);
01612                     const int entryCount = ldap_count_values_len(binaryValuesPtr);
01613                     if(0 != entryCount && NULL != binaryValuesPtr && NULL != binaryValuesPtr[multiAttrIndex])
01614                     {
01615                         while(multiAttrIndex < entryCount)
01616                         {
01617                             tmpPtr = binaryValuesPtr[multiAttrIndex];
01618                             if(NULL == tmpPtr)
01619                             {
01620                                 break;
01621                             }
01622 
01623                             try
01624                             {
01625                                 CACASNWRAPPER_CREATE(CACX509V3CertificatePair, objPDU);
01626                                 objPDU.Decode((unsigned char*)tmpPtr->bv_val, tmpPtr->bv_len);
01627 
01628                                 if((objPDU->m.forwardPresent && PBD_FORWARD == pbd) ||
01629                                     (objPDU->m.reversePresent && PBD_REVERSE == pbd))
01630                                 {
01631                                     //bad_alloc caught by catch(...); cleanup executed
01632                                     CPKIFCertificatePtr tmpCert(new CPKIFCertificate);
01633 
01634                                     //bad_alloc caught by catch(...); cleanup executed
01635                                     unsigned char* buf = new unsigned char[tmpPtr->bv_len];
01636 
01637                                     OOCTXT ctxt;
01638                                     initContext (&ctxt);
01639                                     setBEREncBufPtr(&ctxt, buf, tmpPtr->bv_len);
01640                                     if(objPDU->m.forwardPresent && PBD_FORWARD == pbd)
01641                                         BEREncCACX509V3Certificate(&ctxt, &objPDU->forward, ASN1EXPL);
01642                                     else if(objPDU->m.reversePresent && PBD_REVERSE == pbd)
01643                                         BEREncCACX509V3Certificate(&ctxt, &objPDU->reverse, ASN1EXPL);
01644 
01645                                     try
01646                                     {
01647                                         int iCertLen = 0;
01648                                         try 
01649                                         {
01650                                             iCertLen = numeric_cast<int>(ctxt.buffer.size - ctxt.buffer.byteIndex - 1);
01651                                         }
01652                                         catch(bad_numeric_cast &) 
01653                                         {
01654                                             throw CPKIFException(TOOLKIT_CACHE, COMMON_INVALID_INPUT, "Certificate size is larger than maximum integer size.");
01655                                         }
01656 
01657                                         tmpCert->Decode(ctxt.buffer.data + ctxt.buffer.byteIndex, iCertLen);
01658 
01659                                         CPKIFCertificateNodeEntryPtr tmpCertNode(new CPKIFCertificateNodeEntry(tmpCert));
01660                                         GottaMatch<CPKIFCertificateNodeEntryPtr> gm;
01661                                         gm.SetRHS(tmpCertNode);
01662                                         if(certNodeList.end() == find_if(certNodeList.begin(), certNodeList.end(), gm))
01663                                         {
01664                                             std::string uri1 = GetLdapUriMultiAttr(m_impl->m_strHost->c_str(), m_impl->m_nPort, tmpSubDN, attributes);
01665 
01666                                             vector<string> tmpAttrsOfInterest;
01667                                             tmpAttrsOfInterest.push_back(tempAttrName);
01668                                             std::string uri2 = GetLdapUriMultiAttr(m_impl->m_strHost->c_str(), m_impl->m_nPort, tmpSubDN, tmpAttrsOfInterest);
01669 
01670                                             tmpCertNode->AddSource(uri1);
01671                                             tmpCertNode->AddSource(uri2);
01672                                             //tmpCertNode->AddSource(strSource);
01673                                             tmpCertNode->SetSource(REMOTE);
01674                                             tmpCertNode->SetState(PAS_AVAILABLE);
01675                                             certNodeList.push_back(tmpCertNode);
01676                                         }
01677                                     }
01678                                     catch(CPKIFException&)
01679                                     {
01680                                         //EXCEPTION DELETION
01681                                         //we don't need to pass this exception up - we should log the fact
01682                                         //that a busted (or non) cert was found and keeping sifting through
01683                                         //the remaining values, if any
01684                                         //delete e;
01685 
01686                                         //ignore entries that fail to parse
01687                                         std::ostringstream os;
01688                                         os << "Failed to parse certificate from cross-certificate found in entry for " << tmpSubDN << " on host " << m_impl->m_strHost->c_str();
01689                                         LOG_STRING_ERROR(os.str().c_str(), thisComponent, CACHE_PARSE_ERROR, this)
01690                                     }
01691 
01692                                     freeEncodeBuffer(&ctxt);
01693                                     memFreeAll(&ctxt);
01694                                     delete[] buf;
01695                                 }
01696                             }
01697                             catch(CPKIFException&)
01698                             {
01699                                 //EXCEPTION DELETION
01700                                 //we don't need to pass this exception up - we should log the fact
01701                                 //that a busted (or non) cert was found and keeping sifting through
01702                                 //the remaining values, if any
01703                                 //delete e;
01704 
01705                                 //ignore entries that do not parse
01706                                 std::ostringstream os;
01707                                 os << "Failed to parse certificate from cross-certificate found in entry for " << tmpSubDN << " on host " << m_impl->m_strHost->c_str();
01708                                 LOG_STRING_ERROR(os.str().c_str(), thisComponent, CACHE_PARSE_ERROR, this)
01709                             }
01710 
01711                             multiAttrIndex++;
01712                         }
01713                     }
01714                 }
01715             }
01716 
01717             ldap_memfree(tempAttrName); tempAttrName = NULL;
01718             tempAttrName = ldap_next_attribute(ldapStruct, curEntry, ber_temp);
01719         }while(NULL != tempAttrName);
01720     }
01721     catch(CPKIFException&)
01722     {
01723         //EXCEPTION DELETION
01724         //do nothing except clean up loop variables - we used these exceptions essentially as a goto
01725         CLEANUP;
01726         //delete e;
01727     }
01728     catch(...)
01729     {
01730         CLEANUP;
01731         throw;
01732     }
01733 
01734     if(origSize != certNodeList.size())
01735     {
01736         std::ostringstream os;
01737         //added ->string after issDN 12/3/2003
01738         os << "Found one or more certificates issued to: " << issDN->ToString() << " on host " << m_impl->m_strHost->c_str();
01739         LOG_STRING_DEBUG(os.str().c_str(), thisComponent, 0, this);
01740     }
01741     else
01742     {
01743         std::ostringstream os;
01744         //added ->string after issDN 12/3/2003
01745         os << "Failed to find a CRL issued by: " << issDN->ToString() << " on host " << m_impl->m_strHost->c_str();
01746         LOG_STRING_INFO(os.str().c_str(), thisComponent, 0, this);
01747     }
01748 
01749     CLEANUP;
01750 }
01758 void CPKIFLDAPRepository::GetCRLs(const CPKIFNamePtr& issDN, std::vector<std::string>& attributes, CPKIFCRLNodeList& crlList)
01759 {
01760 #undef CLEANUP
01761 #define CLEANUP \
01762 { \
01763     if(NULL != binaryValuesPtr)\
01764     { ldap_value_free_len(binaryValuesPtr);binaryValuesPtr = NULL;}\
01765     if(NULL != tempAttrName)\
01766     { ldap_memfree(tempAttrName);tempAttrName = NULL;}\
01767     if(NULL != ber_temp)\
01768     { ber_free(ber_temp, 0);ber_temp = NULL;}\
01769     if(NULL != results)\
01770     { ldap_msgfree(results); results = NULL;}\
01771 } 
01772 
01773     LOG_STRING_DEBUG("CPKIFLDAPRepository::GetCRLs(const CPKIFNamePtr& entry, std::vector<std::string>& attributes, CPKIFCRLNodeList& crlList)", TOOLKIT_SR_LDAPREPOSITORY, 0, this);
01774 
01775     size_t origSize = crlList.size();
01776 
01777     int ret = 0;
01778 
01779     LDAP* ldapStruct = NULL;
01780     LDAPMessage* results = NULL;    
01781     LDAPMessage* curEntry = NULL;       //does not need to be freed (per MSDN)
01782     BerElement *ber_temp = NULL;
01783     struct berval **binaryValuesPtr = NULL;
01784     struct berval *tmpPtr = NULL;
01785 
01786     const char* filter = "objectclass=*";
01787     char* tempAttrName = NULL;
01788 
01789     //added delta name 12/8/2003
01790     char** attrsOfInterest = new char*[attributes.size()+1];
01791 
01792     if(!m_impl->CheckNamespaces(issDN))
01793         return;
01794 
01795     std::vector<std::string>::iterator pos;
01796     std::vector<std::string>::iterator end = attributes.end();
01797     int ii = 0;
01798     for(pos = attributes.begin(); pos != end; ++pos, ++ii)
01799         attrsOfInterest[ii] = const_cast<char*>((*pos).c_str());
01800 
01801     attrsOfInterest[attributes.size()] = 0x00;
01802 
01803     int multiAttrIndex = 0;
01804 
01805     ldapStruct = m_impl->ConnectAndBind(*m_impl->m_strHost, m_impl->m_nPort, *m_impl->m_strUsername, *m_impl->m_strPassword);
01806     if(NULL == ldapStruct)
01807     {
01808         if(!m_impl->m_bSuppressConnectionErrors)
01809         {
01810             std::ostringstream os;
01811             os << "Failed to open connection to " << *m_impl->m_strHost << " on port " << m_impl->m_nPort;
01812             CLEANUP
01813             RAISE_CACHE_EXCEPTION(os.str().c_str(), thisComponent, CACHE_LDAP_CONNECT_AND_BIND_FAILED, this)
01814         }
01815         else
01816             return;
01817     }
01818 
01819     try
01820     {
01821         const char* tmpSubDN = issDN->ToString();
01822 
01823         //turn on referral chasing (should be on by default but...)
01824         ldap_set_option(ldapStruct, LDAP_OPT_REFERRALS, LDAP_OPT_ON);
01825 
01826         //added 7/20/2004 -> raised to 100MB 11/17/2006
01827         const int c_nMaxCRLSize = 100000000;
01828         ldap_set_option(ldapStruct, LDAP_OPT_SIZELIMIT, &c_nMaxCRLSize);
01829 
01830         //retrieve the directory entry
01831         ret = ldap_search_s(ldapStruct, (char*)tmpSubDN, LDAP_SCOPE_BASE, (char *)filter, attrsOfInterest, 0, &results);
01832         if(0 != ret || NULL == results)
01833         {
01834             //exceptions are thrown simply to get us to the bottom of this function so cleanup can occur
01835             std::ostringstream os;
01836             os << "ldap_search_s failed searching entry for  " << tmpSubDN << " on host " << m_impl->m_strHost->c_str();
01837             CLEANUP
01838             RAISE_CACHE_EXCEPTION(os.str().c_str(), thisComponent, CACHE_LDAP_ERROR, this)
01839         }
01840 
01841         curEntry = ldap_first_entry(ldapStruct, results);
01842         if(NULL == curEntry)
01843         {
01844             std::ostringstream os;
01845             os << "ldap_first_entry failed searching entry for  " << tmpSubDN << " on host " << m_impl->m_strHost->c_str();
01846             CLEANUP
01847             RAISE_CACHE_EXCEPTION(os.str().c_str(), thisComponent, CACHE_LDAP_ERROR, this)
01848         }
01849         
01850         tempAttrName = ldap_first_attribute(ldapStruct, curEntry, &ber_temp);
01851         if(NULL == curEntry || NULL == tempAttrName)
01852         {
01853             std::ostringstream os;
01854             os << "ldap_first_attribute failed searching entry for  " << tmpSubDN << " on host " << m_impl->m_strHost->c_str();
01855             CLEANUP
01856             RAISE_CACHE_EXCEPTION(os.str().c_str(), thisComponent, CACHE_LDAP_ERROR, this)
01857         }
01858 
01859         do
01860         {
01861             if(attributes.end() != find(attributes.begin(), attributes.end(), tempAttrName))
01862             {
01863                 multiAttrIndex = 0;
01864                 if(NULL != binaryValuesPtr)
01865                 {
01866                     ldap_value_free_len(binaryValuesPtr);binaryValuesPtr = NULL;
01867                 }
01868                 binaryValuesPtr = ldap_get_values_len(ldapStruct, curEntry, tempAttrName);
01869                 const int entryCount = ldap_count_values_len(binaryValuesPtr);
01870                 if(0 == entryCount || NULL == binaryValuesPtr || NULL == binaryValuesPtr[multiAttrIndex])
01871                 {
01872                     throw CPKIFCacheException(thisComponent, -1);
01873                 }
01874 
01875                 while(multiAttrIndex < entryCount)
01876                 {
01877                     tmpPtr = binaryValuesPtr[multiAttrIndex];
01878                     if(NULL == tmpPtr)
01879                     {
01880                         break;
01881                     }
01882 
01883                     //bad_alloc caught by catch(...); cleanup executed
01884                     CPKIFCRLPtr tmpCRL(new CPKIFCRL());
01885                     try
01886                     {
01887                         //create cert using tmpPtr->bv_val, tmpPtr->bv_len
01888                         tmpCRL->Decode((unsigned char*)tmpPtr->bv_val, tmpPtr->bv_len);
01889 
01890                         CPKIFCRLNodeEntryPtr tmpCRLNode(new CPKIFCRLNodeEntry(tmpCRL));
01891                         GottaMatch<CPKIFCRLNodeEntryPtr> gm;
01892                         gm.SetRHS(tmpCRLNode);
01893                         if(crlList.end() == find_if(crlList.begin(), crlList.end(), gm))
01894                         {
01895                             std::string uri1 = GetLdapUriMultiAttr(m_impl->m_strHost->c_str(), m_impl->m_nPort, tmpSubDN, attributes);
01896 
01897                             vector<string> attrsOfInterest;
01898                             attrsOfInterest.push_back(tempAttrName);
01899                             std::string uri2 = GetLdapUriMultiAttr(m_impl->m_strHost->c_str(), m_impl->m_nPort, tmpSubDN, attrsOfInterest);
01900                             tmpCRLNode->AddSource(uri1);
01901                             tmpCRLNode->AddSource(uri2);
01902                             crlList.push_back(tmpCRLNode);
01903                         }
01904                     }
01905                     catch(CPKIFException&)
01906                     {
01907                         //EXCEPTION DELETION
01908                         //we don't need to pass this exception up - we should log the fact
01909                         //that a busted (or non) crl was found and keeping sifting through
01910                         //the remaining values, if any
01911                         //delete e;
01912 
01913                         //ignore entries that fail to parse
01914                         std::ostringstream os;
01915                         os << "Failed to parse CRL found in entry for " << tmpSubDN << " on host " << m_impl->m_strHost->c_str();
01916                         LOG_STRING_ERROR(os.str().c_str(), thisComponent, CACHE_PARSE_ERROR, this)
01917                     }
01918 
01919                     multiAttrIndex++;
01920                 }
01921             }
01922 
01923             ldap_memfree(tempAttrName); tempAttrName = NULL;
01924             tempAttrName = ldap_next_attribute(ldapStruct, curEntry, ber_temp);
01925         }while(NULL != tempAttrName);
01926     }
01927     catch(CPKIFException&)
01928     {
01929         //EXCEPTION DELETION
01930         //do nothing except clean up loop variables - we used these exceptions essentially as a goto
01931         CLEANUP;
01932         //delete e;
01933     }
01934     catch(...)
01935     {
01936         CLEANUP;
01937         throw;
01938     }
01939 
01940     if(origSize != crlList.size())
01941     {
01942         std::ostringstream os;
01943         //added ->string after issDN 12/3/2003
01944         os << "Found one or more CRLs issued by: " << issDN->ToString() << " on host " << m_impl->m_strHost->c_str();
01945         LOG_STRING_DEBUG(os.str().c_str(), thisComponent, 0, this);
01946     }
01947     else
01948     {
01949         std::ostringstream os;
01950         //added ->string after issDN 12/3/2003
01951         os << "Failed to find a CRL issued by: " << issDN->ToString() << " on host " << m_impl->m_strHost->c_str();
01952         LOG_STRING_INFO(os.str().c_str(), thisComponent, 0, this);
01953     }
01954 
01955     CLEANUP;
01956 }
01964 void CPKIFLDAPRepository::GetCertificateSources(
01966     const CPKIFCertificatePtr& cert, 
01968     CPKIFCertificateSourceList& certs, 
01970     PathBuildingDirection pbd)
01971 {
01972     vector<std::string> attrsOfInterest;
01973     attrsOfInterest.push_back("crosscertificatepair;binary");
01974     attrsOfInterest.push_back("crosscertificatepair");
01975 
01976     CPKIFNamePtr tmpDN;
01977     if(PBD_FORWARD == pbd)
01978     {
01979         tmpDN = cert->Issuer();
01980         attrsOfInterest.push_back("caCertificate;binary");
01981         attrsOfInterest.push_back("caCertificate");
01982     }
01983     else
01984         tmpDN = cert->Subject();
01985 
01986     if(!m_impl->CheckNamespaces(tmpDN))
01987         return;
01988 
01989     std::string uri1 = GetLdapUriMultiAttr(m_impl->m_strHost->c_str(), m_impl->m_nPort, tmpDN->ToString(), attrsOfInterest);
01990     //Find self
01991     CPKIFLDAPRepositoryPtr thisSP;
01992     std::vector<IPKIFMediator*>::iterator mPos = this->m_parents.begin();
01993     std::vector<IPKIFMediator*>::iterator mEnd = this->m_parents.end();
01994     for(;mPos != mEnd; ++mPos)
01995     {
01996         CPKIFCacheMediator2* cm =dynamic_cast<CPKIFCacheMediator2*>(*mPos);
01997         if(cm)
01998         {
01999             std::vector<IPKIFColleaguePtr> cl;
02000             cm->GetColleagues(cl);
02001 
02002             std::vector<IPKIFColleaguePtr>::iterator cPos;
02003             std::vector<IPKIFColleaguePtr>::iterator cEnd = cl.end();
02004             for(cPos = cl.begin(); cPos != cEnd; ++cPos)
02005             {
02006                 IPKIFColleague* tmpP = &(*(*cPos));
02007                 if(this == dynamic_cast<CPKIFLDAPRepository*>(tmpP))
02008                 {
02009                     thisSP = dynamic_pointer_cast<CPKIFLDAPRepository, IPKIFColleague>(*cPos);
02010                     break;
02011                 }
02012             }
02013         }
02014     }
02015 
02016     if(!UriAlreadyInList(certs, uri1))
02017     {
02018         CPKIFLdapCertNodePtr newNode(new CPKIFLdapCertNode(thisSP, tmpDN, attrsOfInterest));
02019         newNode->AddSource(uri1);
02020         certs.push_back(newNode);
02021     }
02022 }
02030 void CPKIFLDAPRepository::AddNamespace(CPKIFGeneralSubtreePtr& name)
02031 {
02032     m_impl->m_namespaces.push_back(name);
02033 }
02041 CPKIFGeneralSubtreeList CPKIFLDAPRepository::GetNamespaces()
02042 {
02043     return m_impl->m_namespaces;
02044 }

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