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
00055
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
00104
00105
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
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
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
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
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
00440 int bindCount = 0;
00441 char* username = NULL;
00442 char* password = NULL;
00443
00444
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
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
00474
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
00568 if(LOCAL == source)
00569 {
00570 LOG_STRING_DEBUG("Skipping CPKIFLDAPRepository - searching LOCAL sources only", thisComponent, 0, this);
00571 return;
00572 }
00573
00574
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
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;
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";
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;
00609
00610 char* tempAttrName = NULL;
00611
00612 int multiAttrIndex = 0;
00613
00614
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
00630 ldap_set_option(ldapStruct, LDAP_OPT_REFERRALS, LDAP_OPT_ON);
00631
00632
00633
00634 const int c_nMaxCertSize = 20000;
00635 ldap_set_option(ldapStruct, LDAP_OPT_SIZELIMIT, &c_nMaxCertSize);
00636
00637
00638 ret = ldap_search_s(ldapStruct, (char*)tmpSubDN, LDAP_SCOPE_BASE, (char *)filter, attrsOfInterest, 0, &results);
00639 if(0 != ret || NULL == results)
00640 {
00641
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
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
00683 while(multiAttrIndex < entryCount)
00684 {
00685 tmpPtr = binaryValuesPtr[multiAttrIndex];
00686 if(NULL == tmpPtr)
00687 {
00688 break;
00689 }
00690
00691
00692 CPKIFCertificatePtr tmpCert(new CPKIFCertificate());
00693 try
00694 {
00695
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
00706
00707
00708
00709
00710
00711
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
00749 CPKIFCertificatePtr tmpCert(new CPKIFCertificate);
00750
00751
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
00784
00785
00786
00787
00788
00789
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
00803
00804
00805
00806
00807
00808
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
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
00828
00829
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
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
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
00955 return;
00956 }
00957
00958 int ret = 0;
00959
00960 LDAP* ldapStruct = NULL;
00961 LDAPMessage* results = NULL;
00962 LDAPMessage* curEntry = NULL;
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
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
01005 ldap_set_option(ldapStruct, LDAP_OPT_REFERRALS, LDAP_OPT_ON);
01006
01007
01008 const int c_nMaxCRLSize = 100000000;
01009 ldap_set_option(ldapStruct, LDAP_OPT_SIZELIMIT, &c_nMaxCRLSize);
01010
01011
01012 ret = ldap_search_s(ldapStruct, (char*)tmpSubDN, LDAP_SCOPE_BASE, (char *)filter, attrsOfInterest, 0, &results);
01013 if(0 != ret || NULL == results)
01014 {
01015
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
01067 CPKIFCRLPtr tmpCRL(new CPKIFCRL());
01068 try
01069 {
01070
01071
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
01082
01083
01084
01085
01086
01087
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
01105
01106 CLEANUP;
01107
01108 }
01109 catch(...)
01110 {
01111 CLEANUP;
01112 throw;
01113 }
01114
01115 if(origSize != crlList.size())
01116 {
01117 std::ostringstream os;
01118
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
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
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
01333 return;
01334 }
01335
01336
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;
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";
01460 char* userCertAttrName2 = "userCertificate;binary";
01461 char* tempAttrName = NULL;
01462
01463
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
01496 ldap_set_option(ldapStruct, LDAP_OPT_REFERRALS, LDAP_OPT_ON);
01497
01498
01499 const int c_nMaxCertSize = 1000000;
01500 ldap_set_option(ldapStruct, LDAP_OPT_SIZELIMIT, &c_nMaxCertSize);
01501
01502
01503 ret = ldap_search_s(ldapStruct, (char*)tmpSubDN, LDAP_SCOPE_BASE, (char *)filter, attrsOfInterest, 0, &results);
01504 if(0 != ret || NULL == results)
01505 {
01506
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
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
01552 while(multiAttrIndex < entryCount)
01553 {
01554 tmpPtr = binaryValuesPtr[multiAttrIndex];
01555 if(NULL == tmpPtr)
01556 {
01557 break;
01558 }
01559
01560
01561 CPKIFCertificatePtr tmpCert(new CPKIFCertificate());
01562 try
01563 {
01564
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
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
01589
01590
01591
01592
01593
01594
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
01632 CPKIFCertificatePtr tmpCert(new CPKIFCertificate);
01633
01634
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
01673 tmpCertNode->SetSource(REMOTE);
01674 tmpCertNode->SetState(PAS_AVAILABLE);
01675 certNodeList.push_back(tmpCertNode);
01676 }
01677 }
01678 catch(CPKIFException&)
01679 {
01680
01681
01682
01683
01684
01685
01686
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
01700
01701
01702
01703
01704
01705
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
01724
01725 CLEANUP;
01726
01727 }
01728 catch(...)
01729 {
01730 CLEANUP;
01731 throw;
01732 }
01733
01734 if(origSize != certNodeList.size())
01735 {
01736 std::ostringstream os;
01737
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
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;
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
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
01824 ldap_set_option(ldapStruct, LDAP_OPT_REFERRALS, LDAP_OPT_ON);
01825
01826
01827 const int c_nMaxCRLSize = 100000000;
01828 ldap_set_option(ldapStruct, LDAP_OPT_SIZELIMIT, &c_nMaxCRLSize);
01829
01830
01831 ret = ldap_search_s(ldapStruct, (char*)tmpSubDN, LDAP_SCOPE_BASE, (char *)filter, attrsOfInterest, 0, &results);
01832 if(0 != ret || NULL == results)
01833 {
01834
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
01884 CPKIFCRLPtr tmpCRL(new CPKIFCRL());
01885 try
01886 {
01887
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
01908
01909
01910
01911
01912
01913
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
01930
01931 CLEANUP;
01932
01933 }
01934 catch(...)
01935 {
01936 CLEANUP;
01937 throw;
01938 }
01939
01940 if(origSize != crlList.size())
01941 {
01942 std::ostringstream os;
01943
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
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
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 }