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
00035
00036
00037
00038
00039
00040
00041 using namespace std;
00042
00043
00044
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";
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, 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
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, 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
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
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 }
00332 else
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
00345 while(multiAttrIndex < entryCount)
00346 {
00347 tmpPtr = binaryValuesPtr[multiAttrIndex];
00348 if(NULL == tmpPtr)
00349 {
00350 break;
00351 }
00352
00353
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
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
00383 ldap_memfree(tempAttrName); tempAttrName = NULL;
00384 tempAttrName = ldap_next_attribute(ldapStruct, curEntry, ber_temp);
00385
00386 }while(NULL != tempAttrName);
00387
00388
00389
00390
00391
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, 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
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, 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
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
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
00626
00627
00628
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
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
00715
00716
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
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
00760 p = strchr( url, '/' );
00761
00762 if( p != NULL ) {
00763
00764 *p++ = '\0';
00765 }
00766
00767
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
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
00805
00806
00807
00808
00809
00810
00811
00812 if( (p == NULL) && (q != NULL) && ((q = strchr( q, '?')) != NULL)) {
00813 q++;
00814
00815 if( *q == '?') {
00816 q++;
00817 if( *q != '\0' ) {
00818
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
00839 q = strchr( p, '?' );
00840
00841 if( q != NULL ) {
00842
00843 *q++ = '\0';
00844 }
00845
00846 if( *p != '\0' ) {
00847
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
00862 LDAP_FREE( url );
00863 *ludpp = ludp;
00864 return LDAP_URL_SUCCESS;
00865 }
00866
00867
00868 p = q;
00869 q = strchr( p, '?' );
00870
00871 if( q != NULL ) {
00872
00873 *q++ = '\0';
00874 }
00875
00876 if( *p != '\0' ) {
00877
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
00890 LDAP_FREE( url );
00891 *ludpp = ludp;
00892 return LDAP_URL_SUCCESS;
00893 }
00894
00895
00896 p = q;
00897 q = strchr( p, '?' );
00898
00899 if( q != NULL ) {
00900
00901 *q++ = '\0';
00902 }
00903
00904 if( *p != '\0' ) {
00905
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
00918 LDAP_FREE( url );
00919 *ludpp = ludp;
00920 return LDAP_URL_SUCCESS;
00921 }
00922
00923
00924 p = q;
00925 q = strchr( p, '?' );
00926
00927 if( q != NULL ) {
00928
00929 *q++ = '\0';
00930 }
00931
00932 if( *p != '\0' ) {
00933
00934 ldap_pvt_hex_unescape( p );
00935
00936 if( ! *p ) {
00937
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
00955 LDAP_FREE( url );
00956 *ludpp = ludp;
00957 return LDAP_URL_SUCCESS;
00958 }
00959
00960
00961 p = q;
00962 q = strchr( p, '?' );
00963
00964 if( q != NULL ) {
00965
00966 LDAP_FREE( url );
00967 PKIFLDAP::ldap_free_urldesc( ludp );
00968 return LDAP_URL_ERR_BADURL;
00969 }
00970
00971
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
00985 ludp->lud_crit_exts++;
00986 }
00987 }
00988
00989 if( i == 0 ) {
00990
00991 LDAP_FREE( url );
00992 PKIFLDAP::ldap_free_urldesc( ludp );
00993 return LDAP_URL_ERR_BADEXTS;
00994 }
00995
00996
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
01016
01017
01018 const char *p;
01019
01020 if ( url == NULL ) {
01021 return( NULL );
01022 }
01023
01024 p = url;
01025
01026
01027 if ( *p == '<' ) {
01028 *enclosedp = 1;
01029 ++p;
01030 } else {
01031 *enclosedp = 0;
01032 }
01033
01034
01035 if ( strnicmp( p, LDAP_URL_URLCOLON, LDAP_URL_URLCOLON_LEN ) == 0 ) {
01036 p += LDAP_URL_URLCOLON_LEN;
01037 }
01038
01039
01040 if ( strnicmp( p, LDAP_URL_URLEQUALTO, LDAP_URL_URLEQUALTO_LEN ) == 0 ) {
01041 p += LDAP_URL_URLEQUALTO_LEN;
01042 }
01043
01044
01045
01046 if ( strnicmp( p, LDAP_URL_PREFIX, LDAP_URL_PREFIX_LEN ) == 0 ) {
01047
01048 p += LDAP_URL_PREFIX_LEN;
01049 *scheme = "ldap";
01050 return( p );
01051 }
01052
01053
01054 if ( strnicmp( p, LDAPS_URL_PREFIX, LDAPS_URL_PREFIX_LEN ) == 0 ) {
01055
01056 p += LDAPS_URL_PREFIX_LEN;
01057 *scheme = "ldaps";
01058 return( p );
01059 }
01060
01061
01062 if ( strnicmp( p, LDAPI_URL_PREFIX, LDAPI_URL_PREFIX_LEN ) == 0 ) {
01063
01064 p += LDAPI_URL_PREFIX_LEN;
01065 *scheme = "ldapi";
01066 return( p );
01067 }
01068
01069 #ifdef LDAP_CONNECTIONLESS
01070
01071 if ( strnicmp( p, LDAPC_URL_PREFIX, LDAPC_URL_PREFIX_LEN ) == 0 ) {
01072
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
01164
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
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
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
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
01362 return static_cast<PKIFLDAP::ber_len_t>(cstr - str);
01363 }
01364
01365
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
01392 return static_cast<PKIFLDAP::ber_len_t>(cstr - str);
01393 }
01394
01395
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 }