LDAPFunctions.cpp

Go to the documentation of this file.
00001 
00010 #include "LDAP_URL_Header.h"
00011 #include "ToolkitUtils.h"
00012 
00013 struct PKIFLDAP::lber_options ber_int_options;
00014 
00015 #include "CLDAPConnectionInfo.h"
00016 #include "CSingletonLDAPConnection.h"
00017 #include "ASN1Helper.h"
00018 #include "PKIX1Implicit88.h"
00019 #include "PKIX1Explicit88.h"
00020 #include "Certificate.h"
00021 #include "CRL.h"
00022 #include "GottaMatch.h"
00023 #include "PKIFCertificateNodeEntry.h"
00024 #include <string>
00025 
00026 
00027 #include "boost/numeric/conversion/cast.hpp"
00028 #include "boost/numeric/conversion/bounds.hpp"
00029 #include "boost/limits.hpp"
00030 
00031 using boost::numeric_cast;
00032 using boost::bad_numeric_cast;
00033 
00034 // Added during porting task.
00035 /*#if defined(_WIN32) || defined(WIN32)
00036 #define STRCASECMP stricmp
00037 #else
00038 #define STRCASECMP strcasecmp
00039 #endif*/
00040 
00041 using namespace std;
00042 //using namespace PKIFLDAP;
00043 
00044 //#define _DEBUG_URI_DUMP 1
00045 #ifdef _DEBUG_URI_DUMP
00046 #include <fstream>
00047 ofstream g_uriLogFile;
00048 #endif
00049 
00050 static int ldap_int_unhex( int c );
00051 static int str2scope( const char *p );
00052 
00053 CSingletonLDAPConnection* CSingletonLDAPConnection::m_instance = NULL;
00061 int GetCertfromLDAPURL(
00063     const char *url_in, 
00065     CPKIFCertificateNodeList& certNodeList,
00066     PathBuildingDirection pbd)
00067 {
00068 #undef CLEANUP
00069 #define CLEANUP \
00070 { \
00071     if(NULL != binaryValuesPtr)\
00072     { ldap_value_free_len(binaryValuesPtr);binaryValuesPtr = NULL;}\
00073     if(NULL != tempAttrName)\
00074     { ldap_memfree(tempAttrName);tempAttrName = NULL;}\
00075     if(NULL != ber_temp)\
00076     { ber_free(ber_temp, 0);ber_temp = NULL;}\
00077     if(NULL != results)\
00078     { ldap_msgfree(results); results = NULL;}\
00079 } 
00080 #undef RETURN
00081 #ifdef _DEBUG_URI_DUMP
00082 #define RETURN(err) \
00083 { \
00084     CLEANUP\
00085     g_uriLogFile << GetTickCount() - __ticks << " milliseconds elapsed retrieving from " << url_in << endl; \
00086     return err;\
00087 } 
00088 #else
00089 #define RETURN(err) \
00090 { \
00091     CLEANUP\
00092     if(ldapInfo != NULL){PKIFLDAP::ldap_free_urldesc( ldapInfo );ldapInfo = NULL;}\
00093     return err;\
00094 } 
00095 #endif
00096 
00097 #ifdef _DEBUG_URI_DUMP
00098     if(!g_uriLogFile.is_open())
00099     {
00100         g_uriLogFile.open("_DEBUG_URI_DUMP_URILog.txt", ios::out);
00101     }
00102     DWORD __ticks = GetTickCount();
00103 #endif
00104 
00105     int err = 0;
00106     int connectCount = 0;
00107     int bindCount = 0;
00108 
00109     PKIFLDAP::LDAPURLDesc *ldapInfo = NULL;
00110     LDAP* ldapStruct = NULL;
00111     LDAPMessage* results = NULL;    
00112     LDAPMessage* curEntry = NULL;       
00113     BerElement *ber_temp = NULL;
00114     struct berval **binaryValuesPtr = NULL;
00115     struct berval *tmpPtr = NULL;
00116 
00117     char* tempAttrName = NULL;
00118 
00119     int multiAttrIndex = 0;
00120 
00121     const char* filter = "objectclass=*";
00122     char* certAttrName = "caCertificate;binary";
00123     char* crossCertAttrName = "crosscertificatepair;binary";
00124     char* certAttrName2 = "caCertificate";
00125     char* crossCertAttrName2 = "crosscertificatepair";
00126     char* userCertAttrName = "userCertificate"; //added these two to permit discovery of crl issuers 7/18
00127     char* userCertAttrName2 = "userCertificate;binary";
00128 
00129     char* attrsOfInterest[] = {certAttrName, crossCertAttrName, certAttrName2, crossCertAttrName2, userCertAttrName, userCertAttrName2, NULL};
00130 
00131     std::string strUrl = url_in;
00132     err = PKIFLDAP::ldap_url_parse(url_in, &ldapInfo);
00133     if (0!=err)
00134     {
00135         RETURN(err);
00136     }
00137 
00138     CSingletonLDAPConnection* slc = CSingletonLDAPConnection::Instance();
00139     string lud_hostString = "";
00140     if(0 != ldapInfo->lud_host)
00141     {
00142         lud_hostString = ldapInfo->lud_host;
00143     }
00144     if(PKIFLDAP::IsBlacklisted(lud_hostString))
00145     {
00146         err = ERR_LDAP_CONNECTION;
00147         RETURN(err);
00148     }
00149     ldapStruct = slc->GetConnection(lud_hostString/*string(ldapInfo->lud_host)*/, ldapInfo->lud_port);
00150 
00151     if(!ldapStruct)
00152     {
00153         do
00154         {
00155             ldapStruct = ldap_open(ldapInfo->lud_host, ldapInfo->lud_port);
00156             if(NULL != ldapStruct) 
00157                 connectCount = 5;
00158             else
00159             {
00160                 SLEEP(10);
00161                 ++connectCount;
00162             }
00163         }while(5 > connectCount);
00164         if(NULL == ldapStruct) 
00165         {
00166             PKIFLDAP::AddBlacklistedServer(lud_hostString);
00167 
00168             err = ERR_LDAP_CONNECTION;
00169             RETURN(err);
00170         }
00171         do
00172         {
00173             ULONG timeout = 30;
00174             ldap_set_option(ldapStruct, LDAP_OPT_TIMELIMIT, &timeout);
00175 
00176             err = ldap_simple_bind_s(ldapStruct, NULL, NULL);
00177             if(0 == err)
00178                 bindCount = 5;
00179             else
00180             {
00181                 //added 06/06/2005  Armen
00182                 if(LDAP_PROTOCOL_ERROR == err)
00183                 {
00184                     int opt = LDAP_VERSION3;
00185                     ldap_set_option(ldapStruct, LDAP_OPT_PROTOCOL_VERSION, &opt);
00186                 }
00187 
00188                 SLEEP(10);
00189                 ++bindCount;
00190             }
00191         }while( 5 > bindCount);
00192         if(0 != err)
00193         {
00194             err = ERR_LDAP_CONNECTION;
00195             RETURN(err);
00196         }
00197         else
00198         {
00199             if(ldapInfo->lud_host) 
00200             {
00201                 string lud_hostString(ldapInfo->lud_host);
00202                 slc->PushConnection(lud_hostString/*string(ldapInfo->lud_host)*/, ldapInfo->lud_port, ldapStruct);
00203             }
00204         }
00205     }
00206 
00207     ldap_set_option(ldapStruct, LDAP_OPT_REFERRALS, LDAP_OPT_ON);
00208 
00209 
00210     if(ldapInfo->lud_attrs == NULL)
00211     {
00212         err = ldap_search_s(ldapStruct, ldapInfo->lud_dn, LDAP_SCOPE_BASE, (char *)filter, attrsOfInterest, 0, &results);
00213     }
00214     else
00215     {
00216         err = ldap_search_s(ldapStruct, ldapInfo->lud_dn, LDAP_SCOPE_BASE, (char *)filter, ldapInfo->lud_attrs, 0, &results);
00217     }
00218     if(0 != err || NULL == results)
00219     {
00220         CLEANUP
00221         err = ERR_LDAP_QUERY;
00222         RETURN(err);
00223     }
00224 
00225     curEntry = ldap_first_entry(ldapStruct, results);
00226     if(NULL == curEntry)
00227     {
00228         CLEANUP
00229         err = ERR_LDAP_QUERY;
00230         RETURN(err);
00231     }
00232 
00233     tempAttrName = ldap_first_attribute(ldapStruct, curEntry, &ber_temp);
00234     if(NULL == curEntry || NULL == tempAttrName)
00235     {
00236         CLEANUP
00237         err = ERR_LDAP_QUERY;
00238         RETURN(err);
00239     }
00240 
00241     do
00242     {
00243 
00244         if(0 == stricmp(crossCertAttrName, tempAttrName) ||
00245            0 == stricmp(crossCertAttrName2, tempAttrName))
00246         {
00247             multiAttrIndex = 0;
00248             if(NULL != binaryValuesPtr)
00249             {
00250                 ldap_value_free_len(binaryValuesPtr); binaryValuesPtr = NULL;
00251             }
00252             binaryValuesPtr = ldap_get_values_len(ldapStruct, curEntry, tempAttrName);
00253             const int entryCount = ldap_count_values_len(binaryValuesPtr);
00254             if(0 != entryCount && NULL != binaryValuesPtr && NULL != binaryValuesPtr[multiAttrIndex])
00255             {
00256                 while(multiAttrIndex < entryCount)
00257                 {
00258                     tmpPtr = binaryValuesPtr[multiAttrIndex];
00259                     if(NULL == tmpPtr)
00260                     {
00261                         break;
00262                     }
00263 
00264                     try
00265                     {
00266                         CACASNWRAPPER_CREATE(CACX509V3CertificatePair, objPDU);
00267                         objPDU.Decode((unsigned char*)tmpPtr->bv_val, tmpPtr->bv_len);
00268 
00269                         if((objPDU->m.forwardPresent && PBD_FORWARD == pbd) ||
00270                             (objPDU->m.reversePresent && PBD_REVERSE == pbd))
00271                         {
00272                             OOCTXT ctxt;
00273                             initContext (&ctxt);
00274                             unsigned char* buf = new unsigned char[tmpPtr->bv_len];
00275                             setBEREncBufPtr(&ctxt, buf, tmpPtr->bv_len);
00276                             if(objPDU->m.forwardPresent && PBD_FORWARD == pbd)
00277                                 BEREncCACX509V3Certificate(&ctxt, &objPDU->forward, ASN1EXPL);
00278                             else if(objPDU->m.reversePresent && PBD_REVERSE == pbd)
00279                                 BEREncCACX509V3Certificate(&ctxt, &objPDU->reverse, ASN1EXPL);
00280 
00281                             CPKIFCertificatePtr tmpCert(new CPKIFCertificate);
00282                             try
00283                             {
00284                                 int iCertLen = 0;
00285                                 try 
00286                                 {
00287                                     iCertLen = numeric_cast<int>(ctxt.buffer.size - ctxt.buffer.byteIndex - 1);
00288                                 }
00289                                 catch(bad_numeric_cast &) 
00290                                 {
00291                                     throw CPKIFException(TOOLKIT_CACHE, COMMON_INVALID_INPUT, "Certificate size is larger than maximum integer size.");
00292                                 }
00293                                 tmpCert->Decode(ctxt.buffer.data + ctxt.buffer.byteIndex, iCertLen);
00294 
00295                                 CPKIFCertificateNodeEntryPtr tmpCertNode(new CPKIFCertificateNodeEntry(tmpCert));
00296                                 GottaMatch<CPKIFCertificateNodeEntryPtr> gm;
00297                                 gm.SetRHS(tmpCertNode);
00298                                 if(certNodeList.end() == find_if(certNodeList.begin(), certNodeList.end(), gm))
00299                                 {
00300                                     tmpCertNode->SetSource(REMOTE);
00301                                     tmpCertNode->AddSource(strUrl);
00302                                     tmpCertNode->SetState(PAS_AVAILABLE);
00303                                     certNodeList.push_back(tmpCertNode);
00304                                 }
00305                             }
00306                             catch(CPKIFException& e)
00307                             {
00308 
00309                                 //ignore entries that fail to parse
00310                                 std::string logStr = "Failed to parse certificate from cross-certificate found in entry for ";
00311                                 logStr.append(url_in);
00312                                 LOG_STRING_ERROR(logStr.c_str(), TOOLKIT_UTILS, e.GetErrorCode(), NULL);
00313                             }
00314 
00315                             freeEncodeBuffer(&ctxt);
00316                             memFreeAll(&ctxt);
00317                             delete[] buf;
00318                         }
00319                     }
00320                     catch(CPKIFException& e)
00321                     {
00322                         //ignore entries that do not parse
00323                         std::string logStr = "Failed to parse cross-certificate certificate found in entry for ";
00324                         logStr.append(url_in);
00325                         LOG_STRING_ERROR(logStr.c_str(), TOOLKIT_UTILS, e.GetErrorCode(), NULL);
00326                     }
00327 
00328                     multiAttrIndex++;
00329                 }
00330             }
00331         }                       //compare the current attribute name to the certificate attribute name
00332         else //(0 == /*stricmp*/ STRCASECMP(certAttrName, tempAttrName))
00333         {
00334             multiAttrIndex = 0;
00335             if(NULL != binaryValuesPtr)
00336             {
00337                 ldap_value_free_len(binaryValuesPtr); binaryValuesPtr = NULL;
00338             }
00339 
00340             binaryValuesPtr = ldap_get_values_len(ldapStruct, curEntry, tempAttrName);
00341             const int entryCount = ldap_count_values_len(binaryValuesPtr);
00342             if(0 != entryCount && NULL != binaryValuesPtr && NULL != binaryValuesPtr[multiAttrIndex])
00343             {
00344                 //iterate over all of the values
00345                 while(multiAttrIndex < entryCount)
00346                 {
00347                     tmpPtr = binaryValuesPtr[multiAttrIndex];
00348                     if(NULL == tmpPtr)
00349                     {
00350                         break;
00351                     }
00352 
00353                     //create cert using tmpPtr->bv_val, tmpPtr->bv_len
00354                     CPKIFCertificatePtr tmpCert(new CPKIFCertificate());
00355                     try
00356                     {
00357                         tmpCert->Decode((unsigned char*)tmpPtr->bv_val, tmpPtr->bv_len);                        
00358                         CPKIFCertificateNodeEntryPtr tmpCertNode(new CPKIFCertificateNodeEntry(tmpCert));
00359                         GottaMatch<CPKIFCertificateNodeEntryPtr> gm;
00360                         gm.SetRHS(tmpCertNode);
00361                         if(certNodeList.end() == find_if(certNodeList.begin(), certNodeList.end(), gm))
00362                         {
00363                             tmpCertNode->SetSource(REMOTE);
00364                             tmpCertNode->AddSource(strUrl);
00365                             tmpCertNode->SetState(PAS_AVAILABLE);
00366                             certNodeList.push_back(tmpCertNode);
00367                         }
00368                     }
00369                     catch(CPKIFException& e)
00370                     {
00371                         //ignore entries that fail to parse
00372                         std::string logStr = "Failed to parse certificate found in entry for ";
00373                         logStr.append(url_in);                          
00374                         LOG_STRING_ERROR(logStr.c_str(), TOOLKIT_UTILS, e.GetErrorCode(), NULL);
00375                     }
00376 
00377                     multiAttrIndex++;
00378                 }
00379             }
00380         }
00381 
00382         //inspect the next attribute
00383         ldap_memfree(tempAttrName); tempAttrName = NULL;
00384         tempAttrName = ldap_next_attribute(ldapStruct, curEntry, ber_temp);
00385 
00386     }while(NULL != tempAttrName);
00387 
00388     //if(ldapStruct != NULL)
00389     //{ 
00390     //  ldap_unbind(ldapStruct); 
00391     //  ldapStruct = NULL;
00392     //}
00393 
00394     RETURN(err);
00395 }
00403 int GetCRLfromLDAPURL(
00405     const char *url_in,
00407     CPKIFCRLList& crlList)
00408 {
00409 #undef CLEANUP
00410 #define CLEANUP \
00411 { \
00412     if(NULL != binaryValuesPtr)\
00413     { ldap_value_free_len(binaryValuesPtr);binaryValuesPtr = NULL;}\
00414     if(NULL != tempAttrName)\
00415     { ldap_memfree(tempAttrName);tempAttrName = NULL;}\
00416     if(NULL != ber_temp)\
00417     { ber_free(ber_temp, 0);ber_temp = NULL;}\
00418     if(NULL != results)\
00419     { ldap_msgfree(results); results = NULL;}\
00420 } 
00421 #undef RETURN
00422 #ifdef _DEBUG_URI_DUMP
00423 #define RETURN(err) \
00424 { \
00425     CLEANUP\
00426     g_uriLogFile << GetTickCount() - __ticks << " milliseconds elapsed retrieving from " << url_in << endl; \
00427     return err;\
00428 } 
00429 #else
00430 #define RETURN(err) \
00431 { \
00432     CLEANUP\
00433     if(ldapInfo != NULL){PKIFLDAP::ldap_free_urldesc( ldapInfo );ldapInfo = NULL;}\
00434     return err;\
00435 } 
00436 #endif
00437 
00438     int err = 0;
00439     int connectCount = 0;
00440     int bindCount = 0;
00441 
00442     PKIFLDAP::LDAPURLDesc *ldapInfo = NULL;
00443     LDAP* ldapStruct = NULL;
00444     LDAPMessage* results = NULL;    
00445     LDAPMessage* curEntry = NULL;       
00446     BerElement *ber_temp = NULL;
00447     struct berval **binaryValuesPtr = NULL;
00448     struct berval *tmpPtr = NULL;
00449 
00450     char* tempAttrName = NULL;
00451 
00452     int multiAttrIndex = 0;
00453 
00454     const char* filter = "objectclass=*";
00455     char* crlName = "certificateRevocationList;binary";
00456     char* arlName = "authorityRevocationList;binary";
00457     char* crlName2 = "certificateRevocationList";
00458     char* arlName2 = "authorityRevocationList";
00459     char* deltaName = "deltaRevocationList;binary";
00460     char* deltaName2 = "deltaRevocationList";
00461 
00462     char* attrsOfInterest[] = {crlName, arlName, crlName2, arlName2, deltaName, deltaName2, NULL};
00463 
00464 #ifdef _DEBUG_URI_DUMP
00465     if(!g_uriLogFile.is_open())
00466     {
00467         g_uriLogFile.open("_DEBUG_URI_DUMP_URILog.txt", ios::out);
00468     }
00469     DWORD __ticks = GetTickCount();
00470 #endif
00471 
00472     err = PKIFLDAP::ldap_url_parse(url_in, &ldapInfo);
00473     if (0!=err)
00474     {
00475         RETURN(err);
00476     }
00477 
00478     CSingletonLDAPConnection* slc = CSingletonLDAPConnection::Instance();
00479     string lud_hostString = "";
00480     if(0 != ldapInfo->lud_host)
00481     {
00482         lud_hostString = ldapInfo->lud_host;
00483     }
00484     if(PKIFLDAP::IsBlacklisted(lud_hostString))
00485     {
00486         err = ERR_LDAP_CONNECTION;
00487         RETURN(err);
00488     }
00489 
00490     ldapStruct = slc->GetConnection(lud_hostString/*string(ldapInfo->lud_host)*/, ldapInfo->lud_port);
00491 
00492     if(!ldapStruct)
00493     {
00494         do
00495         {
00496             ldapStruct = ldap_open(ldapInfo->lud_host, ldapInfo->lud_port);
00497             if(NULL != ldapStruct) 
00498                 connectCount = 5;
00499             else
00500             {
00501                 SLEEP(10);
00502                 ++connectCount;
00503             }
00504         }while(5 > connectCount);
00505         if(NULL == ldapStruct) 
00506         {
00507             err = ERR_LDAP_CONNECTION;
00508             RETURN(err);
00509         }
00510         do
00511         {
00512             ULONG timeout = 30;
00513             ldap_set_option(ldapStruct, LDAP_OPT_TIMELIMIT, &timeout);
00514 
00515             err = ldap_simple_bind_s(ldapStruct, NULL, NULL);
00516             if(0 == err)
00517                 bindCount = 5;
00518             else
00519             {
00520                 //added 06/06/2005  Armen
00521                 if(LDAP_PROTOCOL_ERROR == err)
00522                 {
00523                     int opt = LDAP_VERSION3;
00524                     ldap_set_option(ldapStruct, LDAP_OPT_PROTOCOL_VERSION, &opt);
00525                 }
00526                 SLEEP(10);
00527                 ++bindCount;
00528             }
00529         }while( 5 > bindCount);
00530         if(0 != err)
00531         {
00532             CLEANUP
00533             PKIFLDAP::AddBlacklistedServer(lud_hostString);
00534             err = ERR_LDAP_CONNECTION;
00535             RETURN(err);
00536         }
00537         else
00538         {
00539             if(ldapInfo->lud_host) {
00540                 string lud_hostString(ldapInfo->lud_host);
00541                 slc->PushConnection(lud_hostString/*string(ldapInfo->lud_host)*/, ldapInfo->lud_port, ldapStruct);
00542             }
00543         }
00544     }
00545 
00546     ldap_set_option(ldapStruct, LDAP_OPT_REFERRALS, LDAP_OPT_ON);
00547 
00548 
00549     if(ldapInfo->lud_attrs == NULL)
00550     {
00551         err = ldap_search_s(ldapStruct, ldapInfo->lud_dn, LDAP_SCOPE_BASE, (char *)filter, attrsOfInterest, 0, &results);
00552     }
00553     else
00554     {
00555         err = ldap_search_s(ldapStruct, ldapInfo->lud_dn, LDAP_SCOPE_BASE, (char *)filter, ldapInfo->lud_attrs, 0, &results);
00556     }
00557     if(0 != err || NULL == results)
00558     {
00559         CLEANUP
00560         err = ERR_LDAP_QUERY;
00561         RETURN(err);
00562     }
00563 
00564     curEntry = ldap_first_entry(ldapStruct, results);
00565     if(NULL == curEntry)
00566     {
00567         CLEANUP
00568         err = ERR_LDAP_QUERY;
00569         RETURN(err);
00570     }
00571 
00572     tempAttrName = ldap_first_attribute(ldapStruct, curEntry, &ber_temp);
00573     if(NULL == curEntry || NULL == tempAttrName)
00574     {
00575         CLEANUP
00576         err = ERR_LDAP_QUERY;
00577         RETURN(err);
00578     }
00579 
00580     do
00581     {
00582             
00583             multiAttrIndex = 0;
00584             if(NULL != binaryValuesPtr)
00585             {
00586                 ldap_value_free_len(binaryValuesPtr);binaryValuesPtr = NULL;
00587             }
00588             binaryValuesPtr = ldap_get_values_len(ldapStruct, curEntry, tempAttrName);
00589             const int entryCount = ldap_count_values_len(binaryValuesPtr);
00590             if(0 == entryCount || NULL == binaryValuesPtr || NULL == binaryValuesPtr[multiAttrIndex])
00591             {
00592                 //throw CPKIFException();
00593             }
00594 
00595             while(multiAttrIndex < entryCount)
00596             {
00597                 tmpPtr = binaryValuesPtr[multiAttrIndex];
00598                 if(NULL == tmpPtr)
00599                 {
00600                     break;
00601                 }
00602 
00603                 CPKIFCRLPtr tmpCRL(new CPKIFCRL());
00604                 try
00605                 {
00606                     tmpCRL->Decode((unsigned char*)tmpPtr->bv_val, tmpPtr->bv_len);
00607                     GottaMatch<CPKIFCRLPtr> gm;
00608                     gm.SetRHS(tmpCRL);
00609                     if(crlList.end() == find_if(crlList.begin(), crlList.end(), gm))
00610                         crlList.push_back(tmpCRL);
00611                 }
00612                 catch(CPKIFException&)
00613                 {
00614                     //delete e;
00615                 }
00616 
00617                 multiAttrIndex++;
00618             }
00619         
00620 
00621             ldap_memfree(tempAttrName); tempAttrName = NULL;
00622             tempAttrName = ldap_next_attribute(ldapStruct, curEntry, ber_temp);
00623     }while(NULL != tempAttrName);
00624 
00625     //if(ldapStruct != NULL)
00626     //{ 
00627     //  ldap_unbind(ldapStruct); 
00628     //  ldapStruct = NULL;
00629     //}
00630 
00631     RETURN(err);
00632 }
00633 
00641 int PKIFLDAP::ldap_url_parse( 
00643     const char *url_in,
00645     LDAPURLDesc **ludpp )
00646 {
00647     int rc = ldap_url_parse_ext( url_in, ludpp );
00648 
00649     if( rc != LDAP_URL_SUCCESS ) {
00650         return rc;
00651     }
00652 
00653     if ((*ludpp)->lud_scope == LDAP_SCOPE_DEFAULT) {
00654         (*ludpp)->lud_scope = LDAP_SCOPE_BASE;
00655     }
00656 
00657     if ((*ludpp)->lud_host != NULL && *(*ludpp)->lud_host == '\0') {
00658         LDAP_FREE( (*ludpp)->lud_host );
00659         (*ludpp)->lud_host = NULL;
00660     }
00661 
00662     if ((*ludpp)->lud_port == 0) {
00663         if( strcmp((*ludpp)->lud_scheme, "ldap") == 0 ) {
00664             (*ludpp)->lud_port = LDAP_PORT;
00665 #ifdef LDAP_CONNECTIONLESS
00666         } else if( strcmp((*ludpp)->lud_scheme, "cldap") == 0 ) {
00667             (*ludpp)->lud_port = LDAP_PORT;
00668 #endif
00669         } else if( strcmp((*ludpp)->lud_scheme, "ldaps") == 0 ) {
00670             (*ludpp)->lud_port = LDAPS_PORT;
00671         }
00672     }
00673 
00674     return rc;
00675 }
00676 
00684 int PKIFLDAP::ldap_url_parse_ext( 
00686     const char *url_in,
00688     LDAPURLDesc **ludpp )
00689 {
00690 /*
00691  *  Pick apart the pieces of an LDAP URL.
00692  */
00693 
00694     LDAPURLDesc *ludp;
00695     char    *p, *q, *r;
00696     int     i, enclosed;
00697     const char *scheme = NULL;
00698     const char *url_tmp;
00699     char *url;
00700 
00701     if( url_in == NULL || ludpp == NULL ) {
00702         return LDAP_URL_ERR_PARAM;
00703     }
00704 
00705 
00706     *ludpp = NULL;  
00707 
00708     url_tmp = skip_url_prefix( url_in, &enclosed, &scheme );
00709 
00710     if ( url_tmp == NULL ) {
00711         return LDAP_URL_ERR_BADSCHEME;
00712     }
00713 
00714 //  ASSERT( scheme );
00715 
00716     /* make working copy of the remainder of the URL */
00717     url = LDAP_STRDUP( url_tmp );
00718     if ( url == NULL ) {
00719         return LDAP_URL_ERR_MEM;
00720     }
00721 
00722     if ( enclosed ) {
00723         p = &url[strlen(url)-1];
00724 
00725         if( *p != '>' ) {
00726             LDAP_FREE( url );
00727             return LDAP_URL_ERR_BADENCLOSURE;
00728         }
00729 
00730         *p = '\0';
00731     }
00732 
00733     /* allocate return struct */
00734     ludp = (LDAPURLDesc *)LDAP_CALLOC( 1, sizeof( LDAPURLDesc ));
00735 
00736     if ( ludp == NULL ) {
00737         LDAP_FREE( url );
00738         return LDAP_URL_ERR_MEM;
00739     }
00740 
00741     ludp->lud_next = NULL;
00742     ludp->lud_host = NULL;
00743     ludp->lud_port = 0;
00744     ludp->lud_dn = NULL;
00745     ludp->lud_attrs = NULL;
00746     ludp->lud_filter = NULL;
00747     ludp->lud_scope = LDAP_SCOPE_DEFAULT;
00748     ludp->lud_filter = NULL;
00749     ludp->lud_exts = NULL;
00750 
00751     ludp->lud_scheme = LDAP_STRDUP( scheme );
00752 
00753     if ( ludp->lud_scheme == NULL ) {
00754         LDAP_FREE( url );
00755         PKIFLDAP::ldap_free_urldesc( ludp );
00756         return LDAP_URL_ERR_MEM;
00757     }
00758 
00759         /* scan forward for '/' that marks end of hostport and begin. of dn */
00760     p = strchr( url, '/' );
00761 
00762     if( p != NULL ) {
00763         /* terminate hostport; point to start of dn */
00764         *p++ = '\0';
00765     }
00766 
00767     /* IPv6 syntax with [ip address]:port */
00768     if ( *url == '[' ) {
00769         r = strchr( url, ']' );
00770         if ( r == NULL ) {
00771             LDAP_FREE( url );
00772             PKIFLDAP::ldap_free_urldesc( ludp );
00773             return LDAP_URL_ERR_BADURL;
00774         }
00775         *r++ = '\0';
00776         q = strchr( r, ':' );
00777     } else {
00778         q = strchr( url, ':' );
00779     }
00780     if ( q != NULL ) {
00781         *q++ = '\0';
00782         ldap_pvt_hex_unescape( q );
00783 
00784         if( *q == '\0' ) {
00785             LDAP_FREE( url );
00786             PKIFLDAP::ldap_free_urldesc( ludp );
00787             return LDAP_URL_ERR_BADURL;
00788         }
00789 
00790         ludp->lud_port = atoi( q );
00791     }
00792 
00793     ldap_pvt_hex_unescape( url );
00794 
00795     /* If [ip address]:port syntax, url is [ip and we skip the [ */
00796     ludp->lud_host = LDAP_STRDUP( url + ( *url == '[' ) );
00797 
00798     if( ludp->lud_host == NULL ) {
00799         LDAP_FREE( url );
00800         PKIFLDAP::ldap_free_urldesc( ludp );
00801         return LDAP_URL_ERR_MEM;
00802     }
00803     /*
00804      * Kludge.  ldap://111.222.333.444:389??cn=abc,o=company
00805      *
00806      * On early Novell releases, search references/referrals were returned
00807      * in this format, i.e., the dn was kind of in the scope position,
00808      * but the required slash is missing. The whole thing is illegal syntax,
00809      * but we need to account for it. Fortunately it can't be confused with
00810      * anything real.
00811      */
00812     if( (p == NULL) && (q != NULL) && ((q = strchr( q, '?')) != NULL)) {
00813         q++;        
00814         /* ? immediately followed by question */
00815         if( *q == '?') {
00816             q++;
00817             if( *q != '\0' ) {
00818                 /* parse dn part */
00819                 ldap_pvt_hex_unescape( q );
00820                 ludp->lud_dn = LDAP_STRDUP( q );
00821             } else {
00822                 ludp->lud_dn = LDAP_STRDUP( "" );
00823             }
00824 
00825             if( ludp->lud_dn == NULL ) {
00826                 LDAP_FREE( url );
00827                 PKIFLDAP::ldap_free_urldesc( ludp );
00828                 return LDAP_URL_ERR_MEM;
00829             }
00830         }
00831     }
00832     if( p == NULL ) {
00833         LDAP_FREE( url );
00834         *ludpp = ludp;
00835         return LDAP_URL_SUCCESS;
00836     }
00837 
00838     /* scan forward for '?' that may marks end of dn */
00839     q = strchr( p, '?' );
00840 
00841     if( q != NULL ) {
00842         /* terminate dn part */
00843         *q++ = '\0';
00844     }
00845 
00846     if( *p != '\0' ) {
00847         /* parse dn part */
00848         ldap_pvt_hex_unescape( p );
00849         ludp->lud_dn = LDAP_STRDUP( p );
00850     } else {
00851         ludp->lud_dn = LDAP_STRDUP( "" );
00852     }
00853 
00854     if( ludp->lud_dn == NULL ) {
00855         LDAP_FREE( url );
00856         PKIFLDAP::ldap_free_urldesc( ludp );
00857         return LDAP_URL_ERR_MEM;
00858     }
00859 
00860     if( q == NULL ) {
00861         /* no more */
00862         LDAP_FREE( url );
00863         *ludpp = ludp;
00864         return LDAP_URL_SUCCESS;
00865     }
00866 
00867     /* scan forward for '?' that may marks end of attributes */
00868     p = q;
00869     q = strchr( p, '?' );
00870 
00871     if( q != NULL ) {
00872         /* terminate attributes part */
00873         *q++ = '\0';
00874     }
00875 
00876     if( *p != '\0' ) {
00877         /* parse attributes */
00878         ldap_pvt_hex_unescape( p );
00879         ludp->lud_attrs = ldap_str2charray( p, "," );
00880 
00881         if( ludp->lud_attrs == NULL ) {
00882             LDAP_FREE( url );
00883             PKIFLDAP::ldap_free_urldesc( ludp );
00884             return LDAP_URL_ERR_BADATTRS;
00885         }
00886     }
00887 
00888     if ( q == NULL ) {
00889         /* no more */
00890         LDAP_FREE( url );
00891         *ludpp = ludp;
00892         return LDAP_URL_SUCCESS;
00893     }
00894 
00895     /* scan forward for '?' that may marks end of scope */
00896     p = q;
00897     q = strchr( p, '?' );
00898 
00899     if( q != NULL ) {
00900         /* terminate the scope part */
00901         *q++ = '\0';
00902     }
00903 
00904     if( *p != '\0' ) {
00905         /* parse the scope */
00906         ldap_pvt_hex_unescape( p );
00907         ludp->lud_scope = str2scope( p );
00908 
00909         if( ludp->lud_scope == -1 ) {
00910             LDAP_FREE( url );
00911             PKIFLDAP::ldap_free_urldesc( ludp );
00912             return LDAP_URL_ERR_BADSCOPE;
00913         }
00914     }
00915 
00916     if ( q == NULL ) {
00917         /* no more */
00918         LDAP_FREE( url );
00919         *ludpp = ludp;
00920         return LDAP_URL_SUCCESS;
00921     }
00922 
00923     /* scan forward for '?' that may marks end of filter */
00924     p = q;
00925     q = strchr( p, '?' );
00926 
00927     if( q != NULL ) {
00928         /* terminate the filter part */
00929         *q++ = '\0';
00930     }
00931 
00932     if( *p != '\0' ) {
00933         /* parse the filter */
00934         ldap_pvt_hex_unescape( p );
00935 
00936         if( ! *p ) {
00937             /* missing filter */
00938             LDAP_FREE( url );
00939             PKIFLDAP::ldap_free_urldesc( ludp );
00940             return LDAP_URL_ERR_BADFILTER;
00941         }
00942 
00943         LDAP_FREE( ludp->lud_filter );
00944         ludp->lud_filter = LDAP_STRDUP( p );
00945 
00946         if( ludp->lud_filter == NULL ) {
00947             LDAP_FREE( url );
00948             PKIFLDAP::ldap_free_urldesc( ludp );
00949             return LDAP_URL_ERR_MEM;
00950         }
00951     }
00952 
00953     if ( q == NULL ) {
00954         /* no more */
00955         LDAP_FREE( url );
00956         *ludpp = ludp;
00957         return LDAP_URL_SUCCESS;
00958     }
00959 
00960     /* scan forward for '?' that may marks end of extensions */
00961     p = q;
00962     q = strchr( p, '?' );
00963 
00964     if( q != NULL ) {
00965         /* extra '?' */
00966         LDAP_FREE( url );
00967         PKIFLDAP::ldap_free_urldesc( ludp );
00968         return LDAP_URL_ERR_BADURL;
00969     }
00970 
00971     /* parse the extensions */
00972     ludp->lud_exts = ldap_str2charray( p, "," );
00973 
00974     if( ludp->lud_exts == NULL ) {
00975         LDAP_FREE( url );
00976         PKIFLDAP::ldap_free_urldesc( ludp );
00977         return LDAP_URL_ERR_BADEXTS;
00978     }
00979 
00980     for( i=0; ludp->lud_exts[i] != NULL; i++ ) {
00981         ldap_pvt_hex_unescape( ludp->lud_exts[i] );
00982 
00983         if( *ludp->lud_exts[i] == '!' ) {
00984             /* count the number of critical extensions */
00985             ludp->lud_crit_exts++;
00986         }
00987     }
00988 
00989     if( i == 0 ) {
00990         /* must have 1 or more */
00991         LDAP_FREE( url );
00992         PKIFLDAP::ldap_free_urldesc( ludp );
00993         return LDAP_URL_ERR_BADEXTS;
00994     }
00995 
00996     /* no more */
00997     *ludpp = ludp;
00998     LDAP_FREE( url );
00999 
01000     return LDAP_URL_SUCCESS;
01001 }
01002 
01004 
01012 const char* PKIFLDAP::skip_url_prefix(const char *url,int *enclosedp,const char **scheme )
01013 {
01014     /*
01015      * return non-zero if this looks like a LDAP URL; zero if not
01016      * if non-zero returned, *urlp will be moved past "ldap://" part of URL
01017      */
01018     const char *p;
01019 
01020     if ( url == NULL ) {
01021         return( NULL );
01022     }
01023 
01024     p = url;
01025 
01026     /* skip leading '<' (if any) */
01027     if ( *p == '<' ) {
01028         *enclosedp = 1;
01029         ++p;
01030     } else {
01031         *enclosedp = 0;
01032     }
01033 
01034     /* skip leading "URL:" (if any) */
01035     if ( strnicmp( p, LDAP_URL_URLCOLON, LDAP_URL_URLCOLON_LEN ) == 0 ) {
01036         p += LDAP_URL_URLCOLON_LEN;
01037     }
01038 
01039     /* skip leading "URL=" (if any) */
01040     if ( strnicmp( p, LDAP_URL_URLEQUALTO, LDAP_URL_URLEQUALTO_LEN ) == 0 ) {
01041         p += LDAP_URL_URLEQUALTO_LEN;
01042     }
01043 
01044 
01045     /* check for "ldap://" prefix */
01046     if ( strnicmp( p, LDAP_URL_PREFIX, LDAP_URL_PREFIX_LEN ) == 0 ) {
01047         /* skip over "ldap://" prefix and return success */
01048         p += LDAP_URL_PREFIX_LEN;
01049         *scheme = "ldap";
01050         return( p );
01051     }
01052 
01053     /* check for "ldaps://" prefix */
01054     if ( strnicmp( p, LDAPS_URL_PREFIX, LDAPS_URL_PREFIX_LEN ) == 0 ) {
01055         /* skip over "ldaps://" prefix and return success */
01056         p += LDAPS_URL_PREFIX_LEN;
01057         *scheme = "ldaps";
01058         return( p );
01059     }
01060 
01061     /* check for "ldapi://" prefix */
01062     if ( strnicmp( p, LDAPI_URL_PREFIX, LDAPI_URL_PREFIX_LEN ) == 0 ) {
01063         /* skip over "ldapi://" prefix and return success */
01064         p += LDAPI_URL_PREFIX_LEN;
01065         *scheme = "ldapi";
01066         return( p );
01067     }
01068 
01069 #ifdef LDAP_CONNECTIONLESS
01070     /* check for "cldap://" prefix */
01071     if ( strnicmp( p, LDAPC_URL_PREFIX, LDAPC_URL_PREFIX_LEN ) == 0 ) {
01072         /* skip over "cldap://" prefix and return success */
01073         p += LDAPC_URL_PREFIX_LEN;
01074         *scheme = "cldap";
01075         return( p );
01076     }
01077 #endif
01078 
01079     return( NULL );
01080 }
01081 
01089 void PKIFLDAP::ldap_free_urldesc(
01091     LDAPURLDesc *ludp )
01092 {
01093     if ( ludp == NULL ) {
01094         return;
01095     }
01096     
01097     if ( ludp->lud_scheme != NULL ) {
01098         LDAP_FREE( ludp->lud_scheme );
01099     }
01100 
01101     if ( ludp->lud_host != NULL ) {
01102         LDAP_FREE( ludp->lud_host );
01103     }
01104 
01105     if ( ludp->lud_dn != NULL ) {
01106         LDAP_FREE( ludp->lud_dn );
01107     }
01108 
01109     if ( ludp->lud_filter != NULL ) {
01110         LDAP_FREE( ludp->lud_filter);
01111     }
01112 
01113     if ( ludp->lud_attrs != NULL ) {
01114         LDAP_VFREE( ludp->lud_attrs );
01115     }
01116 
01117     if ( ludp->lud_exts != NULL ) {
01118         LDAP_VFREE( ludp->lud_exts );
01119     }
01120 
01121     LDAP_FREE( ludp );
01122 }
01123 
01131 void PKIFLDAP::ber_memvfree( void **vec )
01132 {
01133     int i;
01134 
01135     ber_int_options.lbo_valid = LBER_INITIALIZED;
01136 
01137     if( vec == NULL ) {
01138         return;
01139     }
01140 
01141     BER_MEM_VALID( vec );
01142 
01143     for ( i = 0; vec[i] != NULL; i++ ) {
01144         LBER_FREE( vec[i] );
01145     }
01146 
01147     LBER_FREE( vec );
01148 }
01149 
01158 void PKIFLDAP::ldap_pvt_hex_unescape( 
01160     char *s )
01161 {
01162     /*
01163      * Remove URL hex escapes from s... done in place.  The basic concept for
01164      * this routine is borrowed from the WWW library HTUnEscape() routine.
01165      */
01166     char    *p;
01167 
01168     for ( p = s; *s != '\0'; ++s ) {
01169         if ( *s == '%' ) {
01170             if ( *++s == '\0' ) {
01171                 break;
01172             }
01173             *p = ldap_int_unhex( *s ) << 4;
01174             if ( *++s == '\0' ) {
01175                 break;
01176             }
01177             *p++ += ldap_int_unhex( *s );
01178         } else {
01179             *p++ = *s;
01180         }
01181     }
01182 
01183     *p = '\0';
01184 }
01192 static int ldap_int_unhex( int c )
01193 {
01194     return( c >= '0' && c <= '9' ? c - '0'
01195         : c >= 'A' && c <= 'F' ? c - 'A' + 10
01196         : c - 'a' + 10 );
01197 }
01205 static int str2scope( const char *p )
01206 {
01207     if ( stricmp( p, "one" ) == 0 ) {
01208         return LDAP_SCOPE_ONELEVEL;
01209 
01210     } else if ( stricmp( p, "onetree" ) == 0 ) {
01211         return LDAP_SCOPE_ONELEVEL;
01212 
01213     } else if ( stricmp( p, "base" ) == 0 ) {
01214         return LDAP_SCOPE_BASE;
01215 
01216     } else if ( stricmp( p, "sub" ) == 0 ) {
01217         return LDAP_SCOPE_SUBTREE;
01218 
01219     } else if ( stricmp( p, "subtree" ) == 0 ) {
01220         return LDAP_SCOPE_SUBTREE;
01221     }
01222 
01223     return( -1 );
01224 }
01232 char ** PKIFLDAP::ldap_str2charray( const char *str_in, const char *brkstr )
01233 {
01234     char    **res;
01235     char    *str, *s;
01236     char    *lasts;
01237     int i;
01238 
01239     /* protect the input string from strtok */
01240     str = LDAP_STRDUP( str_in );
01241     if( str == NULL ) {
01242         return NULL;
01243     }
01244 
01245     i = 1;
01246     for ( s = str; *s; s++ ) {
01247         if ( ldap_utf8_strchr( brkstr, s ) != NULL ) {
01248             i++;
01249         }
01250     }
01251 
01252     res = (char **) LDAP_MALLOC( (i + 1) * sizeof(char *) );
01253 
01254     if( res == NULL ) {
01255         LDAP_FREE( str );
01256         return NULL;
01257     }
01258 
01259     i = 0;
01260 
01261     for ( s = ldap_utf8_strtok( str, brkstr, &lasts );
01262         s != NULL;
01263         s = ldap_utf8_strtok( NULL, brkstr, &lasts ) )
01264     {
01265         res[i] = LDAP_STRDUP( s );
01266 
01267         if(res[i] == NULL) {
01268             for( --i ; i >= 0 ; i-- ) {
01269                 LDAP_FREE( res[i] );
01270             }
01271             LDAP_FREE( res );
01272             LDAP_FREE( str );
01273             return NULL;
01274         }
01275 
01276         i++;
01277     }
01278 
01279     res[i] = NULL;
01280 
01281     LDAP_FREE( str );
01282     return( res );
01283 }
01284 
01285 
01286 /* like strtok_r(), not strtok() */
01294 char *(PKIFLDAP::ldap_utf8_strtok)(char *str, const char *sep, char **last)
01295 {
01296     char *begin;
01297     char *end;
01298 
01299     if( last == NULL ) return NULL;
01300 
01301     begin = str ? str : *last;
01302 
01303     begin += ldap_utf8_strspn( begin, sep );
01304 
01305     if( *begin == '\0' ) {
01306         *last = NULL;
01307         return NULL;
01308     }
01309 
01310     end = &begin[ ldap_utf8_strcspn( begin, sep ) ];
01311 
01312     if( *end != '\0' ) {
01313         char *next = LDAP_UTF8_NEXT( end );
01314         *end = '\0';
01315         end = next;
01316     }
01317 
01318     *last = end;
01319     return begin;
01320 }
01328 char * (PKIFLDAP::ldap_utf8_strchr)( const char *str, const char *chr )
01329 {
01330     for( ; *str != '\0'; LDAP_UTF8_INCR(str) ) {
01331         if( ldap_x_utf8_to_ucs4( str ) == ldap_x_utf8_to_ucs4( chr ) ) {
01332             return (char *) str;
01333         } 
01334     }
01335 
01336     return NULL;
01337 }
01338 
01339 /* like strcspn() but returns number of bytes, not characters */
01348 PKIFLDAP::ber_len_t (PKIFLDAP::ldap_utf8_strcspn)( const char *str, const char *set )
01349 {
01350     const char *cstr;
01351     const char *cset;
01352 
01353     for( cstr = str; *cstr != '\0'; LDAP_UTF8_INCR(cstr) ) {
01354         for( cset = set; *cset != '\0'; LDAP_UTF8_INCR(cset) ) {
01355             if( ldap_x_utf8_to_ucs4( cstr ) == ldap_x_utf8_to_ucs4( cset ) ) {
01356                 return static_cast<PKIFLDAP::ber_len_t>(cstr - str);
01357             } 
01358         }
01359     }
01360 
01361     //reviewed this and above - 4/25 - pointer is 4 bytes, difference fits in unsigned long
01362     return static_cast<PKIFLDAP::ber_len_t>(cstr - str);
01363 }
01364 
01365 /* like strspn() but returns number of bytes, not characters */
01374 PKIFLDAP::ber_len_t (PKIFLDAP::ldap_utf8_strspn)( const char *str, const char *set )
01375 {
01376     const char *cstr;
01377     const char *cset;
01378 
01379     for( cstr = str; *cstr != '\0'; LDAP_UTF8_INCR(cstr) ) {
01380         for( cset = set; ; LDAP_UTF8_INCR(cset) ) {
01381             if( *cset == '\0' ) {
01382                 return static_cast<PKIFLDAP::ber_len_t>(cstr - str);
01383             }
01384 
01385             if( ldap_x_utf8_to_ucs4( cstr ) == ldap_x_utf8_to_ucs4( cset ) ) {
01386                 break;
01387             } 
01388         }
01389     }
01390 
01391     //reviewed this and above - 4/25 - pointer is 4 bytes, difference fits in unsigned long
01392     return static_cast<PKIFLDAP::ber_len_t>(cstr - str);
01393 }
01394 
01395 /* conv UTF-8 to UCS-4, useful for comparisons */
01403 PKIFLDAP::ldap_ucs4_t PKIFLDAP::ldap_x_utf8_to_ucs4( const char * p )
01404 {
01405     const unsigned char *c = (const unsigned char *)p;
01406     ldap_ucs4_t ch;
01407     int len, i;
01408     static unsigned char mask[] = {
01409         0, 0x7f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
01410 
01411     len = LDAP_UTF8_CHARLEN2(p, len);
01412 
01413     if( len == 0 ) return LDAP_UCS4_INVALID;
01414 
01415     ch = c[0] & mask[len];
01416 
01417     for(i=1; i < len; i++) {
01418         if ((c[i] & 0xc0) != 0x80) {
01419             return LDAP_UCS4_INVALID;
01420         }
01421 
01422         ch <<= 6;
01423         ch |= c[i] & 0x3f;
01424     }
01425 
01426     return ch;
01427 }
01435 char* PKIFLDAP::ldap_utf8_next( const char * p )
01436 {
01437     int i;
01438     const unsigned char *u = (const unsigned char *)p;
01439 
01440     if( LDAP_UTF8_ISASCII(u) ) {
01441         return (char *) &p[1];
01442     }
01443 
01444     for( i=1; i<6; i++ ) {
01445         if ( ( u[i] & 0xc0 ) != 0x80 ) {
01446             return (char *) &p[i];
01447         }
01448     }
01449 
01450     return (char *) &p[i];
01451 }

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