Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1860 lines
49 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1999
  5. //
  6. // File: oidmgr.cpp
  7. //
  8. // Contents: DS OID management functions.
  9. //
  10. //---------------------------------------------------------------------------
  11. #include "pch.cpp"
  12. #pragma hdrstop
  13. #include <winldap.h>
  14. #include <ntldap.h>
  15. #include <cainfop.h>
  16. #include <oidmgr.h>
  17. #include <certca.h>
  18. #include "csldap.h"
  19. #define __dwFILE__ __dwFILE_CERTCLIB_OIDMGR_CPP__
  20. //the global critical section
  21. CRITICAL_SECTION g_csOidURL;
  22. extern BOOL g_fOidURL;
  23. ULARGE_INTEGER g_ftOidTime;
  24. BOOL g_fFailedTime=FALSE;
  25. //the # of seconds in which we will not re-find a DC
  26. #define CA_OID_MGR_FAIL_PERIOD 5
  27. #define FILETIME_TICKS_PER_SECOND 10000000
  28. //the cache of the enterprise root oid
  29. LPWSTR g_pwszEnterpriseRootOID=NULL;
  30. static WCHAR * s_wszOIDContainerSearch = L"(&(CN=OID)(objectCategory=" wszDSOIDCLASSNAME L"))";
  31. static WCHAR * s_wszOIDContainerDN = L"CN=OID,CN=Public Key Services,CN=Services,";
  32. WCHAR *g_awszOIDContainerAttrs[] = {OID_CONTAINER_PROP_OID,
  33. OID_CONTAINER_PROP_GUID,
  34. NULL};
  35. //---------------------------------------------------------------------------
  36. //
  37. // myTimeOutRobustBind
  38. //
  39. // We will not attempt a LDAP bind if we have failed in the past pre-defined
  40. // seconds.
  41. //
  42. //---------------------------------------------------------------------------
  43. HRESULT
  44. myTimeOutRobustLdapBind(OUT LDAP **ppldap)
  45. {
  46. HRESULT hr=E_FAIL;
  47. FILETIME ftTime;
  48. //the critical section has to be initalized
  49. if (!g_fOidURL)
  50. return(HRESULT_FROM_WIN32(ERROR_DLL_INIT_FAILED));
  51. EnterCriticalSection(&g_csOidURL);
  52. //check if the previous failure has happened with 10 seconds
  53. if(TRUE == g_fFailedTime)
  54. {
  55. //get the current time
  56. GetSystemTimeAsFileTime(&ftTime);
  57. g_ftOidTime.QuadPart += FILETIME_TICKS_PER_SECOND * CA_OID_MGR_FAIL_PERIOD;
  58. if(0 > CompareFileTime(&ftTime, (LPFILETIME)&g_ftOidTime))
  59. {
  60. g_ftOidTime.QuadPart -= FILETIME_TICKS_PER_SECOND * CA_OID_MGR_FAIL_PERIOD;
  61. hr=HRESULT_FROM_WIN32(ERROR_NO_SUCH_DOMAIN);
  62. _JumpError2(hr , error, "myDoesDSExist", HRESULT_FROM_WIN32(ERROR_NO_SUCH_DOMAIN));
  63. }
  64. else
  65. {
  66. //clear up the error recording
  67. g_fFailedTime=FALSE;
  68. }
  69. }
  70. //retrieve the ldap handle and the config string
  71. hr = myDoesDSExist(TRUE);
  72. _JumpIfError2(hr, error, "myDoesDSExist", HRESULT_FROM_WIN32(ERROR_NO_SUCH_DOMAIN));
  73. hr = myRobustLdapBindEx(
  74. 0, // dwFlags1
  75. RLBF_REQUIRE_SECURE_LDAP, // dwFlags2
  76. LDAP_VERSION2, // uVersion
  77. NULL, // pwszDomainName
  78. ppldap,
  79. NULL); // ppwszForestDNSName
  80. _JumpIfError(hr, error, "myRobustLdapBindEx");
  81. error:
  82. //remember the time if we failed due to lack of domain
  83. if((S_OK != hr) && (FALSE==g_fFailedTime))
  84. {
  85. GetSystemTimeAsFileTime((LPFILETIME)&(g_ftOidTime));
  86. g_fFailedTime=TRUE;
  87. }
  88. LeaveCriticalSection(&g_csOidURL);
  89. return hr;
  90. }
  91. //---------------------------------------------------------------------------
  92. //
  93. // CAOIDIsValidRootOID
  94. //
  95. //
  96. // Pre .Net RC1, the enterprise root OID is derived from the GUID of CN=OID
  97. // container in the format of DWORD.DWORD.DWORD.DWORD. The new Son of RFC2459
  98. // defines a mandatory maximum length to the element of an OID of 2^28.
  99. //
  100. // The new format will be xxx.xxx.xxx.xxx.xxx.xxx, each element is a 3 byte
  101. // date from the GUID (16 bytes). The last element is one byte only.
  102. //
  103. //---------------------------------------------------------------------------
  104. BOOL CAOIDIsValidRootOID(LPWSTR pwszOID)
  105. {
  106. BOOL fValid=FALSE;
  107. LPWSTR pwsz=NULL;
  108. DWORD dwCount=0;
  109. if(NULL == pwszOID)
  110. goto error;
  111. pwsz=pwszOID;
  112. while(L'\0' != (*pwsz))
  113. {
  114. if(L'.' == (*pwsz))
  115. {
  116. dwCount++;
  117. }
  118. pwsz++;
  119. }
  120. if(14 != dwCount)
  121. goto error;
  122. fValid=TRUE;
  123. error:
  124. return fValid;
  125. }
  126. //---------------------------------------------------------------------------
  127. //
  128. // CAOIDAllocAndCopy
  129. //
  130. //---------------------------------------------------------------------------
  131. HRESULT CAOIDAllocAndCopy(LPWSTR pwszSrc,
  132. LPWSTR *ppwszDest)
  133. {
  134. if((NULL==ppwszDest) || (NULL==pwszSrc))
  135. return E_INVALIDARG;
  136. *ppwszDest=(LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR) * (wcslen(pwszSrc) + 1));
  137. if(NULL==(*ppwszDest))
  138. return E_OUTOFMEMORY;
  139. wcscpy(*ppwszDest, pwszSrc);
  140. return S_OK;
  141. }
  142. //---------------------------------------------------------------------------
  143. //
  144. // CAOIDGetRandom
  145. //
  146. // We build a random x1.x2 string. X is a 32 bit unsigned integer. x1 > 1
  147. // and x2 > 500.
  148. //---------------------------------------------------------------------------
  149. HRESULT CAOIDGetRandom(LPWSTR *ppwszRandom)
  150. {
  151. HRESULT hr=E_FAIL;
  152. DWORD dwRandom1=0;
  153. DWORD dwRandom2=0;
  154. DWORD cbData=sizeof(DWORD);
  155. WCHAR wszRandom1[DWORD_STRING_LENGTH];
  156. WCHAR wszRandom2[DWORD_STRING_LENGTH];
  157. HCRYPTPROV hProv=NULL;
  158. //there is a bug in cryptAcquireContextW that if container is NULL, provider
  159. //can not be ansi.
  160. if(!CryptAcquireContextA(
  161. &hProv,
  162. NULL,
  163. MS_DEF_PROV_A,
  164. PROV_RSA_FULL,
  165. CRYPT_VERIFYCONTEXT))
  166. {
  167. hr= myHLastError();
  168. _JumpError(hr, error, "CryptAcquireContextA");
  169. }
  170. //accoring to RFC2459 which bounds the OID size,
  171. //elements in an arc must be between 0->2^28.
  172. if(cbData > 3)
  173. cbData=3;
  174. if(!CryptGenRandom(hProv, cbData, (BYTE *)&dwRandom1))
  175. {
  176. hr= myHLastError();
  177. _JumpError(hr, error, "CryptGenRandom");
  178. }
  179. if(!CryptGenRandom(hProv, cbData, (BYTE *)&dwRandom2))
  180. {
  181. hr= myHLastError();
  182. _JumpError(hr, error, "CryptGenRandom");
  183. }
  184. if(dwRandom1 <= OID_RESERVE_DEFAULT_ONE)
  185. dwRandom1 +=OID_RESERVE_DEFAULT_ONE;
  186. if(dwRandom2 <= OID_RESERVR_DEFAULT_TWO)
  187. dwRandom2 += OID_RESERVR_DEFAULT_TWO;
  188. wszRandom1[0]=L'\0';
  189. wsprintf(wszRandom1, L"%lu", dwRandom1);
  190. wszRandom2[0]=L'\0';
  191. wsprintf(wszRandom2, L"%lu", dwRandom2);
  192. *ppwszRandom=(LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR) *
  193. (wcslen(wszRandom1) + wcslen(wszOID_DOT) + wcslen(wszRandom2) + 1));
  194. if(NULL==(*ppwszRandom))
  195. {
  196. hr= E_OUTOFMEMORY;
  197. _JumpError(hr, error, "CryptGenRandom");
  198. }
  199. wcscpy(*ppwszRandom, wszRandom1);
  200. wcscat(*ppwszRandom, wszOID_DOT);
  201. wcscat(*ppwszRandom, wszRandom2);
  202. hr=S_OK;
  203. error:
  204. if(hProv)
  205. CryptReleaseContext(hProv, 0);
  206. return hr;
  207. }
  208. //----------------------------------------------------------------------------------
  209. //
  210. // CAOIDMapGUIDToOID
  211. //
  212. // GUID (16 byte) string is in the form of 3_Byte.3_Byte.3_Byte.3_Byte.3_Byte.1_Byte
  213. // 12 characters are sufficient to present a 2^32 value.
  214. //----------------------------------------------------------------------------------
  215. HRESULT CAOIDMapGUIDToOID(LDAP_BERVAL *pGuidVal, LPWSTR *ppwszGUID)
  216. {
  217. HRESULT hr=E_INVALIDARG;
  218. DWORD iIndex=0;
  219. WCHAR wszString[DWORD_STRING_LENGTH];
  220. DWORD dwData=0;
  221. BYTE *pbData=NULL;
  222. *ppwszGUID=NULL;
  223. //a GUID should be 16 byte
  224. if(16 != (pGuidVal->bv_len))
  225. _JumpError(hr, error, "ArgumentCheck");
  226. *ppwszGUID=(LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR) * GUID_STRING_LENGTH);
  227. if(NULL==(*ppwszGUID))
  228. {
  229. hr = E_OUTOFMEMORY;
  230. _JumpError(hr, error, "LocalAlloc");
  231. }
  232. pbData=(BYTE *)(pGuidVal->bv_val);
  233. for(iIndex=0; iIndex < 6; iIndex++)
  234. {
  235. wszString[0]=L'\0';
  236. dwData=0;
  237. //the 5th index (6th element) is only one byte 15th index (16th) bypte
  238. if(iIndex == 5)
  239. {
  240. dwData=(DWORD)(pbData[iIndex * 3]);
  241. }
  242. else
  243. {
  244. dwData=(((DWORD)(pbData[iIndex * 3])) << 16) +
  245. (((DWORD)(pbData[iIndex * 3 + 1])) << 8) +
  246. ((DWORD)(pbData[iIndex * 3 + 2]));
  247. }
  248. wsprintf(wszString, L"%lu", dwData);
  249. if(0==iIndex)
  250. {
  251. wcscpy(*ppwszGUID, wszString);
  252. }
  253. else
  254. {
  255. wcscat(*ppwszGUID, wszOID_DOT);
  256. wcscat(*ppwszGUID, wszString);
  257. }
  258. }
  259. hr = S_OK;
  260. error:
  261. return hr;
  262. }
  263. //--------------------------------------------------------------------------
  264. //
  265. // FormatMessageUnicode
  266. //
  267. //--------------------------------------------------------------------------
  268. HRESULT FormatMessageUnicode(LPWSTR *ppwszFormat,LPWSTR pwszString,...)
  269. {
  270. va_list argList;
  271. DWORD cbMsg=0;
  272. // format message into requested buffer
  273. va_start(argList, pwszString);
  274. cbMsg = FormatMessageW(
  275. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
  276. pwszString,
  277. 0, // dwMessageId
  278. 0, // dwLanguageId
  279. (LPWSTR) (ppwszFormat),
  280. 0, // minimum size to allocate
  281. &argList);
  282. va_end(argList);
  283. if(0 != cbMsg)
  284. return S_OK;
  285. return E_INVALIDARG;
  286. }
  287. //---------------------------------------------------------------------------
  288. //
  289. // DoesOIDExist
  290. //
  291. //
  292. //---------------------------------------------------------------------------
  293. BOOL DoesOIDExist(LDAP *pld,
  294. LPWSTR bstrConfig,
  295. LPCWSTR pwszOID)
  296. {
  297. BOOL fExit=FALSE;
  298. struct l_timeval timeout;
  299. ULONG ldaperr=0;
  300. DWORD dwCount=0;
  301. LPWSTR awszAttr[2];
  302. CERTSTR bstrDN = NULL;
  303. LDAPMessage *SearchResult = NULL;
  304. LPWSTR pwszFilter = NULL;
  305. if(NULL==pwszOID)
  306. goto error;
  307. bstrDN = CertAllocStringLen(NULL, wcslen(bstrConfig) + wcslen(s_wszOIDContainerDN));
  308. if(NULL == bstrDN)
  309. goto error;
  310. wcscpy(bstrDN, s_wszOIDContainerDN);
  311. wcscat(bstrDN, bstrConfig);
  312. timeout.tv_sec = csecLDAPTIMEOUT;
  313. timeout.tv_usec = 0;
  314. awszAttr[0]=OID_PROP_OID;
  315. awszAttr[1]=NULL;
  316. if(S_OK != FormatMessageUnicode(&pwszFilter, L"(%1!s!=%2!s!)",
  317. OID_PROP_OID, pwszOID))
  318. goto error;
  319. __try
  320. {
  321. ldaperr = ldap_search_stW(
  322. pld,
  323. (LPWSTR)bstrDN,
  324. LDAP_SCOPE_ONELEVEL,
  325. pwszFilter,
  326. awszAttr,
  327. 0,
  328. &timeout,
  329. &SearchResult);
  330. if(LDAP_SUCCESS != ldaperr)
  331. goto error;
  332. dwCount = ldap_count_entries(pld, SearchResult);
  333. if(0 != dwCount)
  334. fExit=TRUE;
  335. }
  336. __except(EXCEPTION_EXECUTE_HANDLER)
  337. {
  338. }
  339. error:
  340. if(pwszFilter)
  341. LocalFree((HLOCAL)pwszFilter);
  342. if(SearchResult)
  343. ldap_msgfree(SearchResult);
  344. if(bstrDN)
  345. CertFreeString(bstrDN);
  346. return fExit;
  347. }
  348. //---------------------------------------------------------------------------
  349. //
  350. // CAOIDUpdateDS
  351. //
  352. //
  353. //---------------------------------------------------------------------------
  354. HRESULT CAOIDUpdateDS(LDAP *pld,
  355. LPWSTR pwszConfig,
  356. ENT_OID_INFO *pOidInfo)
  357. {
  358. HRESULT hr=E_INVALIDARG;
  359. BOOL fNew=FALSE;
  360. ULONG ldaperr=0;
  361. LDAPMod modObjectClass,
  362. modCN,
  363. modType,
  364. modOID,
  365. modDisplayName,
  366. modCPS;
  367. LDAPMod *mods[OID_ATTR_COUNT + 1];
  368. DWORD cMod=0;
  369. WCHAR wszType[DWORD_STRING_LENGTH];
  370. LPWSTR awszObjectClass[3],
  371. awszCN[2],
  372. awszType[2],
  373. awszOID[2],
  374. awszDisplayName[2],
  375. awszCPS[2];
  376. CHAR sdBerValue[] = {0x30, 0x03, 0x02, 0x01, DACL_SECURITY_INFORMATION |
  377. OWNER_SECURITY_INFORMATION |
  378. GROUP_SECURITY_INFORMATION};
  379. LDAPControl se_info_control =
  380. {
  381. LDAP_SERVER_SD_FLAGS_OID_W,
  382. {
  383. 5, sdBerValue
  384. },
  385. TRUE
  386. };
  387. LDAPControl permissive_modify_control =
  388. {
  389. LDAP_SERVER_PERMISSIVE_MODIFY_OID_W,
  390. {
  391. 0, NULL
  392. },
  393. FALSE
  394. };
  395. PLDAPControl server_controls[3] =
  396. {
  397. &se_info_control,
  398. &permissive_modify_control,
  399. NULL
  400. };
  401. CHAR sdBerValueDaclOnly[] = {0x30, 0x03, 0x02, 0x01, DACL_SECURITY_INFORMATION};
  402. LDAPControl se_info_control_dacl_only =
  403. {
  404. LDAP_SERVER_SD_FLAGS_OID_W,
  405. {
  406. 5, sdBerValueDaclOnly
  407. },
  408. TRUE
  409. };
  410. PLDAPControl server_controls_dacl_only[3] =
  411. {
  412. &se_info_control_dacl_only,
  413. &permissive_modify_control,
  414. NULL
  415. };
  416. CERTSTR bstrDN = NULL;
  417. LPWSTR pwszCN = NULL;
  418. if(NULL== (pOidInfo->pwszOID))
  419. _JumpError(hr , error, "ArgumentCheck");
  420. //if we are changing the OID value, we are creating a new oid
  421. fNew = OID_ATTR_OID & (pOidInfo->dwAttr);
  422. //set up the base DN
  423. if(S_OK != (hr = myOIDHashOIDToString(pOidInfo->pwszOID, &pwszCN)))
  424. _JumpError(hr , error, "myOIDHashOIDToString");
  425. bstrDN = CertAllocStringLen(NULL, wcslen(pwszConfig) + wcslen(s_wszOIDContainerDN)+wcslen(pwszCN)+4);
  426. if(bstrDN == NULL)
  427. {
  428. hr = E_OUTOFMEMORY;
  429. _JumpError(hr, error, "CertAllocStringLen");
  430. }
  431. wcscpy(bstrDN, L"CN=");
  432. wcscat(bstrDN, pwszCN);
  433. wcscat(bstrDN, L",");
  434. wcscat(bstrDN, s_wszOIDContainerDN);
  435. wcscat(bstrDN, pwszConfig);
  436. //set up all the mods
  437. modObjectClass.mod_op = LDAP_MOD_REPLACE;
  438. modObjectClass.mod_type = L"objectclass";
  439. modObjectClass.mod_values = awszObjectClass;
  440. awszObjectClass[0] = wszDSTOPCLASSNAME;
  441. awszObjectClass[1] = wszDSOIDCLASSNAME;
  442. awszObjectClass[2] = NULL;
  443. mods[cMod++] = &modObjectClass;
  444. modCN.mod_op = LDAP_MOD_REPLACE;
  445. modCN.mod_type = L"cn";
  446. modCN.mod_values = awszCN;
  447. awszCN[0] = pwszCN;
  448. awszCN[1] = NULL;
  449. mods[cMod++] = &modCN;
  450. modOID.mod_op = LDAP_MOD_REPLACE;
  451. modOID.mod_type = OID_PROP_OID;
  452. modOID.mod_values = awszOID;
  453. awszOID[0] = pOidInfo->pwszOID;
  454. awszOID[1] = NULL;
  455. mods[cMod++] = &modOID;
  456. if(OID_ATTR_DISPLAY_NAME & (pOidInfo->dwAttr))
  457. {
  458. modDisplayName.mod_op = LDAP_MOD_REPLACE;
  459. modDisplayName.mod_type = OID_PROP_DISPLAY_NAME;
  460. if(pOidInfo->pwszDisplayName)
  461. {
  462. modDisplayName.mod_values = awszDisplayName;
  463. awszDisplayName[0] = pOidInfo->pwszDisplayName;
  464. awszDisplayName[1] = NULL;
  465. }
  466. else
  467. modDisplayName.mod_values = NULL;
  468. if(!fNew)
  469. mods[cMod++] = &modDisplayName;
  470. }
  471. if(OID_ATTR_CPS & (pOidInfo->dwAttr))
  472. {
  473. modCPS.mod_op = LDAP_MOD_REPLACE;
  474. modCPS.mod_type = OID_PROP_CPS;
  475. if(pOidInfo->pwszCPS)
  476. {
  477. modCPS.mod_values = awszCPS;
  478. awszCPS[0] = pOidInfo->pwszCPS;
  479. awszCPS[1] = NULL;
  480. }
  481. else
  482. modCPS.mod_values = NULL;
  483. if(!fNew)
  484. mods[cMod++] = &modCPS;
  485. }
  486. if(OID_ATTR_TYPE & (pOidInfo->dwAttr))
  487. {
  488. modType.mod_op = LDAP_MOD_REPLACE;
  489. modType.mod_type = OID_PROP_TYPE;
  490. modType.mod_values = awszType;
  491. awszType[0] = wszType;
  492. awszType[1] = NULL;
  493. wsprintf(wszType, L"%d", pOidInfo->dwType);
  494. mods[cMod++] = &modType;
  495. }
  496. mods[cMod++]=NULL;
  497. //update the DS
  498. __try
  499. {
  500. if(fNew)
  501. {
  502. ldaperr = ldap_add_ext_sW(pld, bstrDN, mods, server_controls, NULL);
  503. _PrintIfError(ldaperr, "ldap_add_s");
  504. }
  505. else
  506. {
  507. ldaperr = ldap_modify_ext_sW(
  508. pld,
  509. bstrDN,
  510. &mods[2],
  511. server_controls_dacl_only,
  512. NULL); // skip past objectClass and cn
  513. if(LDAP_ATTRIBUTE_OR_VALUE_EXISTS == ldaperr)
  514. ldaperr = LDAP_SUCCESS;
  515. _PrintIfError(ldaperr, "ldap_modify_ext_sW");
  516. }
  517. if ((LDAP_SUCCESS != ldaperr) && (LDAP_ALREADY_EXISTS != ldaperr))
  518. {
  519. hr = myHLdapError(pld, ldaperr, NULL);
  520. _JumpError(ldaperr, error, fNew? "ldap_add_s" : "ldap_modify_sW");
  521. }
  522. hr=S_OK;
  523. }
  524. __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  525. {
  526. }
  527. error:
  528. if(pwszCN)
  529. LocalFree(pwszCN);
  530. if(bstrDN)
  531. CertFreeString(bstrDN);
  532. return hr;
  533. }
  534. //---------------------------------------------------------------------------
  535. //
  536. // CAOIDRetrieveEnterpriseRootWithConfig
  537. //
  538. // Get the enterpriseRoot from the displayName attribute of the container.
  539. // If the attribute is missing, add the one with GUID of the container.
  540. //
  541. // Free memory via LocalFree().
  542. //---------------------------------------------------------------------------
  543. HRESULT
  544. CAOIDRetrieveEnterpriseRootWithConfig(
  545. LDAP *pld,
  546. LPWSTR pwszConfig,
  547. DWORD, // dwFlag
  548. LPWSTR *ppwszOID)
  549. {
  550. HRESULT hr=E_INVALIDARG;
  551. struct l_timeval timeout;
  552. ULONG ldaperr=0;
  553. DWORD dwCount=0;
  554. LDAPMessage *Entry=NULL;
  555. LDAPMod *mods[2];
  556. LDAPMod modOIDName;
  557. LPWSTR valOIDName[2];
  558. CHAR sdBerValueDaclOnly[] = {0x30, 0x03, 0x02, 0x01, DACL_SECURITY_INFORMATION};
  559. LDAPControl se_info_control_dacl_only =
  560. {
  561. LDAP_SERVER_SD_FLAGS_OID_W,
  562. {
  563. 5, sdBerValueDaclOnly
  564. },
  565. TRUE
  566. };
  567. LDAPControl permissive_modify_control =
  568. {
  569. LDAP_SERVER_PERMISSIVE_MODIFY_OID_W,
  570. {
  571. 0, NULL
  572. },
  573. FALSE
  574. };
  575. PLDAPControl server_controls_dacl_only[3] =
  576. {
  577. &se_info_control_dacl_only,
  578. &permissive_modify_control,
  579. NULL
  580. };
  581. CERTSTR bstrOIDContainer = NULL;
  582. LDAPMessage *SearchResult = NULL;
  583. WCHAR **wszLdapVal = NULL;
  584. LDAP_BERVAL **pGuidVal = NULL;
  585. LPWSTR pwszGUID = NULL;
  586. __try
  587. {
  588. if(NULL==ppwszOID)
  589. _JumpError(hr , error, "ArgumentCheck");
  590. *ppwszOID=NULL;
  591. //retrive the displayName attribute of the container if available
  592. bstrOIDContainer = CertAllocStringLen(NULL, wcslen(pwszConfig) + wcslen(s_wszOIDContainerDN));
  593. if(NULL == bstrOIDContainer)
  594. {
  595. hr = E_OUTOFMEMORY;
  596. _JumpError(hr, error, "CertAllocStringLen");
  597. }
  598. wcscpy(bstrOIDContainer, s_wszOIDContainerDN);
  599. wcscat(bstrOIDContainer, pwszConfig);
  600. timeout.tv_sec = csecLDAPTIMEOUT;
  601. timeout.tv_usec = 0;
  602. ldaperr = ldap_search_stW(
  603. pld,
  604. (LPWSTR)bstrOIDContainer,
  605. LDAP_SCOPE_BASE,
  606. s_wszOIDContainerSearch,
  607. g_awszOIDContainerAttrs,
  608. 0,
  609. &timeout,
  610. &SearchResult);
  611. if(LDAP_SUCCESS != ldaperr)
  612. {
  613. hr = myHLdapError(pld, ldaperr, NULL);
  614. _JumpError(hr, error, "ldap_search_stW");
  615. }
  616. dwCount = ldap_count_entries(pld, SearchResult);
  617. //we should only find one container
  618. if((1 != dwCount) || (NULL == (Entry = ldap_first_entry(pld, SearchResult))))
  619. {
  620. // No entries were found.
  621. hr = myHLdapError(pld, LDAP_NO_SUCH_OBJECT, NULL);
  622. _JumpError(hr, error, "ldap_search_stW");
  623. }
  624. wszLdapVal = ldap_get_values(pld, Entry, OID_CONTAINER_PROP_OID);
  625. //make sure the displayName is a valud enterprise OID
  626. if(wszLdapVal && wszLdapVal[0])
  627. {
  628. if(CAOIDIsValidRootOID(wszLdapVal[0]))
  629. {
  630. hr=CAOIDAllocAndCopy(wszLdapVal[0], ppwszOID);
  631. //cache the enterprise root
  632. if((S_OK == hr) && (g_fOidURL))
  633. {
  634. EnterCriticalSection(&g_csOidURL);
  635. CAOIDAllocAndCopy(*ppwszOID, &g_pwszEnterpriseRootOID);
  636. LeaveCriticalSection(&g_csOidURL);
  637. }
  638. goto error;
  639. }
  640. }
  641. //no displayName is present or valid, we have to derive the displayName
  642. //from the GUID of the container
  643. pGuidVal = ldap_get_values_len(pld, Entry, OID_CONTAINER_PROP_GUID);
  644. if((NULL==pGuidVal) || (NULL==pGuidVal[0]))
  645. {
  646. hr = myHLdapError(pld, LDAP_NO_SUCH_ATTRIBUTE, NULL);
  647. _JumpError(hr, error, "getGUIDFromDS");
  648. }
  649. if(S_OK != (hr=CAOIDMapGUIDToOID(pGuidVal[0], &pwszGUID)))
  650. _JumpError(hr, error, "CAOIDMapGUIDToOID");
  651. //contantenate the strings
  652. *ppwszOID=(LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR) *
  653. (wcslen(wszOID_ENTERPRISE_ROOT) + wcslen(wszOID_DOT) + wcslen(pwszGUID) + 1));
  654. if(NULL==(*ppwszOID))
  655. {
  656. hr=E_OUTOFMEMORY;
  657. _JumpError(hr, error, "LocalAlloc");
  658. }
  659. wcscpy(*ppwszOID, wszOID_ENTERPRISE_ROOT);
  660. wcscat(*ppwszOID, wszOID_DOT);
  661. wcscat(*ppwszOID, pwszGUID);
  662. //cache the newly created displayName to the DS
  663. //no need to check for error since this is just a performance enhancement
  664. valOIDName[0]=*ppwszOID;
  665. valOIDName[1]=NULL;
  666. modOIDName.mod_op = LDAP_MOD_REPLACE;
  667. modOIDName.mod_type = OID_CONTAINER_PROP_OID;
  668. modOIDName.mod_values = valOIDName;
  669. mods[0]=&modOIDName;
  670. mods[1]=NULL;
  671. ldap_modify_ext_sW(
  672. pld,
  673. bstrOIDContainer,
  674. mods,
  675. server_controls_dacl_only,
  676. NULL);
  677. //cache the oid root in memory
  678. if (g_fOidURL)
  679. {
  680. EnterCriticalSection(&g_csOidURL);
  681. CAOIDAllocAndCopy(*ppwszOID, &g_pwszEnterpriseRootOID);
  682. LeaveCriticalSection(&g_csOidURL);
  683. }
  684. hr = S_OK;
  685. }
  686. __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  687. {
  688. }
  689. error:
  690. if(pwszGUID)
  691. LocalFree(pwszGUID);
  692. if(pGuidVal)
  693. ldap_value_free_len(pGuidVal);
  694. if(wszLdapVal)
  695. ldap_value_free(wszLdapVal);
  696. if(SearchResult)
  697. ldap_msgfree(SearchResult);
  698. if (bstrOIDContainer)
  699. CertFreeString(bstrOIDContainer);
  700. return hr;
  701. }
  702. //---------------------------------------------------------------------------
  703. //
  704. // CAOIDRetrieveEnterpriseRoot
  705. //
  706. // Get the enterpriseRoot from the displayName attribute of the container.
  707. // If the attribute is missing, add the one with GUID of the container.
  708. //
  709. // Free memory via LocalFree().
  710. //---------------------------------------------------------------------------
  711. HRESULT CAOIDRetrieveEnterpriseRoot(DWORD dwFlag, LPWSTR *ppwszOID)
  712. {
  713. HRESULT hr=E_INVALIDARG;
  714. LDAP *pld = NULL;
  715. CERTSTR bstrConfig = NULL;
  716. if(NULL==ppwszOID)
  717. _JumpError(hr , error, "ArgumentCheck");
  718. *ppwszOID=NULL;
  719. //retrieve the memory cache if available
  720. if (g_fOidURL)
  721. {
  722. EnterCriticalSection(&g_csOidURL);
  723. if(g_pwszEnterpriseRootOID)
  724. {
  725. hr=CAOIDAllocAndCopy(g_pwszEnterpriseRootOID, ppwszOID);
  726. LeaveCriticalSection(&g_csOidURL);
  727. goto error;
  728. }
  729. LeaveCriticalSection(&g_csOidURL);
  730. }
  731. //retrieve the ldap handle and the config string
  732. if(S_OK != (hr = myTimeOutRobustLdapBind(&pld)))
  733. _JumpError(hr , error, "myTimeRobustLdapBind");
  734. hr = CAGetAuthoritativeDomainDn(pld, NULL, &bstrConfig);
  735. if(S_OK != hr)
  736. {
  737. _JumpError(hr , error, "CAGetAuthoritativeDomainDn");
  738. }
  739. hr = CAOIDRetrieveEnterpriseRootWithConfig(pld, bstrConfig,
  740. dwFlag, ppwszOID);
  741. error:
  742. if(bstrConfig)
  743. CertFreeString(bstrConfig);
  744. if (pld)
  745. ldap_unbind(pld);
  746. return hr;
  747. }
  748. //---------------------------------------------------------------------------
  749. //
  750. // CAOIDBuildOIDWithRoot
  751. //
  752. //
  753. // Free memory via LocalFree().
  754. //---------------------------------------------------------------------------
  755. HRESULT
  756. CAOIDBuildOIDWithRoot(
  757. DWORD, // dwFlag
  758. LPCWSTR pwszRoot,
  759. LPCWSTR pwszEndOID,
  760. LPWSTR *ppwszOID)
  761. {
  762. HRESULT hr=E_INVALIDARG;
  763. if(NULL==pwszRoot)
  764. _JumpError(hr , error, "ArgumentCheck");
  765. *ppwszOID=NULL;
  766. *ppwszOID=(LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR) *
  767. (wcslen(pwszRoot) + wcslen(wszOID_DOT) + wcslen(pwszEndOID) + 1));
  768. if(NULL==(*ppwszOID))
  769. {
  770. hr = E_OUTOFMEMORY;
  771. _JumpError(hr , error, "LocalAlloc");
  772. }
  773. wcscpy(*ppwszOID, pwszRoot);
  774. wcscat(*ppwszOID, wszOID_DOT);
  775. wcscat(*ppwszOID, pwszEndOID);
  776. hr= S_OK;
  777. error:
  778. return hr;
  779. }
  780. //---------------------------------------------------------------------------
  781. //
  782. // CAOIDBuildOID
  783. //
  784. //
  785. // Free memory via LocalFree().
  786. //---------------------------------------------------------------------------
  787. HRESULT CAOIDBuildOID(DWORD dwFlag, LPCWSTR pwszEndOID, LPWSTR *ppwszOID)
  788. {
  789. HRESULT hr=E_INVALIDARG;
  790. LPWSTR pwszRoot=NULL;
  791. if((NULL==ppwszOID) || (NULL==pwszEndOID))
  792. _JumpError(hr , error, "ArgumentCheck");
  793. *ppwszOID=NULL;
  794. if(S_OK != (hr=CAOIDRetrieveEnterpriseRoot(0, &pwszRoot)))
  795. _JumpError(hr , error, "RetrieveEnterpriseRoot");
  796. hr= CAOIDBuildOIDWithRoot(dwFlag, pwszRoot, pwszEndOID, ppwszOID);
  797. error:
  798. if(pwszRoot)
  799. LocalFree(pwszRoot);
  800. return hr;
  801. }
  802. //------------------------------------------------------------------------
  803. // Convert the byte to its Hex presentation.
  804. //
  805. //
  806. //------------------------------------------------------------------------
  807. ULONG ByteToHex(BYTE byte, LPWSTR wszZero, LPWSTR wszA)
  808. {
  809. ULONG uValue=0;
  810. if(((ULONG)byte)<=9)
  811. {
  812. uValue=((ULONG)byte)+ULONG(*wszZero);
  813. }
  814. else
  815. {
  816. uValue=(ULONG)byte-10+ULONG(*wszA);
  817. }
  818. return uValue;
  819. }
  820. //--------------------------------------------------------------------------
  821. //
  822. // ConvertByteToWstr
  823. //
  824. // If fSpace is TRUE, we add a space every 2 bytes.
  825. //--------------------------------------------------------------------------
  826. HRESULT ConvertByteToWstr(BYTE *pbData,
  827. DWORD cbData,
  828. LPWSTR *ppwsz)
  829. {
  830. HRESULT hr=E_INVALIDARG;
  831. DWORD dwBufferSize=0;
  832. DWORD dwBufferIndex=0;
  833. DWORD dwEncodedIndex=0;
  834. LPWSTR pwszZero=L"0";
  835. LPWSTR pwszA=L"A";
  836. if(!pbData || !ppwsz)
  837. _JumpError(hr , error, "ArgumentCheck");
  838. //calculate the memory needed, in bytes
  839. //we need 2 wchars per byte, along with the NULL terminator
  840. dwBufferSize=sizeof(WCHAR)*(cbData*2+1);
  841. *ppwsz=(LPWSTR)LocalAlloc(LPTR, dwBufferSize);
  842. if(NULL==(*ppwsz))
  843. {
  844. hr=E_OUTOFMEMORY;
  845. _JumpError(hr , error, "LocalAlloc");
  846. }
  847. dwBufferIndex=0;
  848. //format the wchar buffer one byte at a time
  849. for(dwEncodedIndex=0; dwEncodedIndex<cbData; dwEncodedIndex++)
  850. {
  851. //format the higher 4 bits
  852. (*ppwsz)[dwBufferIndex]=(WCHAR)ByteToHex(
  853. (pbData[dwEncodedIndex]&UPPER_BITS)>>4,
  854. pwszZero, pwszA);
  855. dwBufferIndex++;
  856. //format the lower 4 bits
  857. (*ppwsz)[dwBufferIndex]=(WCHAR)ByteToHex(
  858. pbData[dwEncodedIndex]&LOWER_BITS,
  859. pwszZero, pwszA);
  860. dwBufferIndex++;
  861. }
  862. //add the NULL terminator to the string
  863. (*ppwsz)[dwBufferIndex]=L'\0';
  864. hr=S_OK;
  865. error:
  866. return hr;
  867. }
  868. //---------------------------------------------------------------------------
  869. // myOIDHashOIDToString
  870. //
  871. // Map the OID to a hash string in the format of oid.hash.
  872. //---------------------------------------------------------------------------
  873. HRESULT
  874. myOIDHashOIDToString(
  875. IN WCHAR const *pwszOID,
  876. OUT WCHAR **ppwsz)
  877. {
  878. HRESULT hr=E_INVALIDARG;
  879. BYTE pbHash[CERT_OID_MD5_HASH_SIZE];
  880. DWORD cbData=CERT_OID_MD5_HASH_SIZE;
  881. LPCWSTR pwszChar=NULL;
  882. DWORD dwIDLength=CERT_OID_IDENTITY_LENGTH;
  883. LPWSTR pwszHash=NULL;
  884. if((NULL==pwszOID) || (NULL==ppwsz))
  885. _JumpError(hr , error, "ArgumentCheck");
  886. *ppwsz=NULL;
  887. hr = myVerifyObjId(pwszOID);
  888. _JumpIfErrorStr2(hr, error, "myVerifyObjId", pwszOID, E_INVALIDARG);
  889. if(!CryptHashCertificate(
  890. NULL,
  891. CALG_MD5,
  892. 0,
  893. (BYTE * )pwszOID,
  894. sizeof(WCHAR) * wcslen(pwszOID),
  895. pbHash,
  896. &cbData))
  897. {
  898. hr= myHLastError();
  899. _JumpError(hr , error, "CryptHashCertificate");
  900. }
  901. //convert the hash to a string
  902. if(S_OK != (hr=ConvertByteToWstr(pbHash, CERT_OID_MD5_HASH_SIZE, &pwszHash)))
  903. _JumpError(hr , error, "ConvertByteToWstr");
  904. //find the last component of the oid. Take the first 16 characters
  905. pwszChar=wcsrchr(pwszOID, L'.');
  906. if(NULL==pwszChar)
  907. pwszChar=pwszOID;
  908. else
  909. pwszChar++;
  910. if(dwIDLength > wcslen(pwszChar))
  911. dwIDLength=wcslen(pwszChar);
  912. //the result string is oid.hash
  913. *ppwsz=(LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR) *
  914. (dwIDLength + wcslen(pwszHash) + wcslen(wszOID_DOT) +1));
  915. if(NULL==*ppwsz)
  916. {
  917. hr= E_OUTOFMEMORY;
  918. _JumpError(hr , error, "LocalAlloc");
  919. }
  920. wcsncpy(*ppwsz, pwszChar, dwIDLength);
  921. (*ppwsz)[dwIDLength]=L'\0';
  922. wcscat(*ppwsz, wszOID_DOT);
  923. wcscat(*ppwsz, pwszHash);
  924. hr=S_OK;
  925. error:
  926. if(pwszHash)
  927. LocalFree(pwszHash);
  928. return hr;
  929. }
  930. //---------------------------------------------------------------------------
  931. // I_CAOIDCreateNew
  932. // Create a new OID based on the enterprise base
  933. //
  934. // Returns S_OK if successful.
  935. //---------------------------------------------------------------------------
  936. HRESULT
  937. I_CAOIDCreateNew(
  938. DWORD dwType,
  939. DWORD, // dwFlag
  940. LPWSTR *ppwszOID)
  941. {
  942. HRESULT hr=E_INVALIDARG;
  943. ENT_OID_INFO oidInfo;
  944. DWORD iIndex=0;
  945. LDAP *pld = NULL;
  946. CERTSTR bstrConfig = NULL;
  947. LPWSTR pwszRoot = NULL;
  948. LPWSTR pwszNewOID = NULL;
  949. LPWSTR pwszRandom = NULL;
  950. if(NULL==ppwszOID)
  951. _JumpError(hr , error, "ArgumentCheck");
  952. *ppwszOID=NULL;
  953. //retrieve the root oid if available
  954. if (g_fOidURL)
  955. {
  956. EnterCriticalSection(&g_csOidURL);
  957. if(g_pwszEnterpriseRootOID)
  958. {
  959. if(S_OK != (hr=CAOIDAllocAndCopy(g_pwszEnterpriseRootOID, &pwszRoot)))
  960. {
  961. LeaveCriticalSection(&g_csOidURL);
  962. goto error;
  963. }
  964. }
  965. LeaveCriticalSection(&g_csOidURL);
  966. }
  967. //retrieve the ldap handle and the config string
  968. if(S_OK != (hr = myTimeOutRobustLdapBind(&pld)))
  969. _JumpError(hr , error, "myTimeRobustLdapBind");
  970. hr = CAGetAuthoritativeDomainDn(pld, NULL, &bstrConfig);
  971. if(S_OK != hr)
  972. {
  973. _JumpError(hr , error, "CAGetAuthoritativeDomainDn");
  974. }
  975. if(NULL==pwszRoot)
  976. {
  977. if(S_OK != (hr = CAOIDRetrieveEnterpriseRootWithConfig(pld, bstrConfig, 0, &pwszRoot)))
  978. _JumpError(hr , error, "CAOIDRetrieveEnterpriseRootWithConfig");
  979. }
  980. //we try to generate a random x1.x2 oid. x > 1 and x2 > 500
  981. for(iIndex=0; iIndex < OID_RANDOM_CREATION_TRIAL; iIndex++)
  982. {
  983. if(S_OK != (hr = CAOIDGetRandom(&pwszRandom)))
  984. _JumpError(hr , error, "CAOIDGetRandom");
  985. if(S_OK != (hr = CAOIDBuildOIDWithRoot(0, pwszRoot, pwszRandom, &pwszNewOID)))
  986. _JumpError(hr , error, "CAOIDBuildOIDWithRoot");
  987. if(!DoesOIDExist(pld, bstrConfig, pwszNewOID))
  988. break;
  989. LocalFree(pwszRandom);
  990. pwszRandom=NULL;
  991. LocalFree(pwszNewOID);
  992. pwszNewOID=NULL;
  993. }
  994. if(iIndex == OID_RANDOM_CREATION_TRIAL)
  995. {
  996. hr=E_FAIL;
  997. _JumpError(hr , error, "CAOIDGetRandom");
  998. }
  999. //update the oid information on the DS
  1000. memset(&oidInfo, 0, sizeof(ENT_OID_INFO));
  1001. oidInfo.dwAttr=OID_ATTR_ALL;
  1002. oidInfo.dwType=dwType;
  1003. oidInfo.pwszOID=pwszNewOID;
  1004. if(S_OK != (hr=CAOIDUpdateDS(pld, bstrConfig, &oidInfo)))
  1005. _JumpError(hr , error, "CAOIDUpdateDS");
  1006. *ppwszOID=pwszNewOID;
  1007. pwszNewOID=NULL;
  1008. hr=S_OK;
  1009. error:
  1010. if(pwszRandom)
  1011. LocalFree(pwszRandom);
  1012. if(pwszNewOID)
  1013. LocalFree(pwszNewOID);
  1014. if(pwszRoot)
  1015. LocalFree(pwszRoot);
  1016. if(bstrConfig)
  1017. CertFreeString(bstrConfig);
  1018. if (pld)
  1019. ldap_unbind(pld);
  1020. return hr;
  1021. }
  1022. //---------------------------------------------------------------------------
  1023. //
  1024. // CAOIDCreateNew
  1025. //
  1026. //---------------------------------------------------------------------------
  1027. HRESULT
  1028. CAOIDCreateNew(
  1029. IN DWORD dwType,
  1030. IN DWORD dwFlag,
  1031. OUT LPWSTR *ppwszOID)
  1032. {
  1033. return I_CAOIDCreateNew(dwType, dwFlag, ppwszOID);
  1034. }
  1035. //---------------------------------------------------------------------------
  1036. // I_CAOIDSetProperty
  1037. // Set a property on an oid.
  1038. //
  1039. //
  1040. // Returns S_OK if successful.
  1041. //---------------------------------------------------------------------------
  1042. HRESULT
  1043. I_CAOIDSetProperty(
  1044. IN LPCWSTR pwszOID,
  1045. IN DWORD dwProperty,
  1046. IN LPVOID pPropValue)
  1047. {
  1048. HRESULT hr=E_INVALIDARG;
  1049. ENT_OID_INFO oidInfo;
  1050. LDAP *pld = NULL;
  1051. CERTSTR bstrConfig = NULL;
  1052. if(NULL==pwszOID)
  1053. _JumpError(hr , error, "ArgumentCheck");
  1054. //retrieve the ldap handle and the config string
  1055. if(S_OK != (hr = myTimeOutRobustLdapBind(&pld)))
  1056. _JumpError(hr , error, "myTimeRobustLdapBind");
  1057. hr = CAGetAuthoritativeDomainDn(pld, NULL, &bstrConfig);
  1058. if(S_OK != hr)
  1059. {
  1060. _JumpError(hr , error, "CAGetAuthoritativeDomainDn");
  1061. }
  1062. //make sure the OID exist on the DS
  1063. if(!DoesOIDExist(pld, bstrConfig, pwszOID))
  1064. {
  1065. hr=NTE_NOT_FOUND;
  1066. _JumpErrorStr(hr, error, "DoesOIDExist", pwszOID);
  1067. }
  1068. //update the oid information on the DS
  1069. memset(&oidInfo, 0, sizeof(ENT_OID_INFO));
  1070. oidInfo.pwszOID=(LPWSTR)pwszOID;
  1071. switch(dwProperty)
  1072. {
  1073. case CERT_OID_PROPERTY_DISPLAY_NAME:
  1074. oidInfo.dwAttr = OID_ATTR_DISPLAY_NAME;
  1075. oidInfo.pwszDisplayName=(LPWSTR)pPropValue;
  1076. break;
  1077. case CERT_OID_PROPERTY_CPS:
  1078. oidInfo.dwAttr = OID_ATTR_CPS;
  1079. oidInfo.pwszCPS=(LPWSTR)pPropValue;
  1080. break;
  1081. default:
  1082. hr=E_INVALIDARG;
  1083. _JumpError(hr , error, "ArgumentCheck");
  1084. }
  1085. hr=CAOIDUpdateDS(pld, bstrConfig, &oidInfo);
  1086. error:
  1087. if(bstrConfig)
  1088. CertFreeString(bstrConfig);
  1089. if (pld)
  1090. ldap_unbind(pld);
  1091. return hr;
  1092. }
  1093. //---------------------------------------------------------------------------
  1094. //
  1095. // CAOIDSetProperty
  1096. //
  1097. //---------------------------------------------------------------------------
  1098. HRESULT
  1099. CAOIDSetProperty(
  1100. IN LPCWSTR pwszOID,
  1101. IN DWORD dwProperty,
  1102. IN LPVOID pPropValue)
  1103. {
  1104. return I_CAOIDSetProperty(pwszOID, dwProperty, pPropValue);
  1105. }
  1106. //---------------------------------------------------------------------------
  1107. // I_CAOIDAdd
  1108. //
  1109. // Returns S_OK if successful.
  1110. // Returns CRYPT_E_EXISTS if the OID alreay exits in the DS repository
  1111. //---------------------------------------------------------------------------
  1112. HRESULT
  1113. I_CAOIDAdd(
  1114. IN DWORD dwType,
  1115. IN DWORD, // dwFlag
  1116. IN LPCWSTR pwszOID)
  1117. {
  1118. HRESULT hr=E_INVALIDARG;
  1119. ENT_OID_INFO oidInfo;
  1120. LDAP *pld = NULL;
  1121. CERTSTR bstrConfig = NULL;
  1122. if(NULL==pwszOID)
  1123. _JumpError(hr , error, "ArgumentCheck");
  1124. //retrieve the ldap handle and the config string
  1125. if(S_OK != (hr = myTimeOutRobustLdapBind(&pld)))
  1126. _JumpError(hr , error, "myTimeRobustLdapBind");
  1127. hr = CAGetAuthoritativeDomainDn(pld, NULL, &bstrConfig);
  1128. if(S_OK != hr)
  1129. {
  1130. _JumpError(hr , error, "CAGetAuthoritativeDomainDn");
  1131. }
  1132. //make sure the OID does not exist on the DS
  1133. if(DoesOIDExist(pld, bstrConfig, pwszOID))
  1134. {
  1135. hr=CRYPT_E_EXISTS;
  1136. _JumpErrorStr(hr, error, "OID Exists", pwszOID);
  1137. }
  1138. //update the oid information on the DS
  1139. memset(&oidInfo, 0, sizeof(ENT_OID_INFO));
  1140. oidInfo.dwAttr=OID_ATTR_ALL;
  1141. oidInfo.dwType=dwType;
  1142. oidInfo.pwszOID=(LPWSTR)pwszOID;
  1143. hr=CAOIDUpdateDS(pld, bstrConfig, &oidInfo);
  1144. error:
  1145. if(bstrConfig)
  1146. CertFreeString(bstrConfig);
  1147. if (pld)
  1148. ldap_unbind(pld);
  1149. return hr;
  1150. }
  1151. //---------------------------------------------------------------------------
  1152. // CAOIDAdd
  1153. //
  1154. // Returns S_OK if successful.
  1155. // Returns CRYPT_E_EXISTS if the OID alreay exits in the DS repository
  1156. //---------------------------------------------------------------------------
  1157. HRESULT
  1158. CAOIDAdd(
  1159. IN DWORD dwType,
  1160. IN DWORD dwFlag,
  1161. IN LPCWSTR pwszOID)
  1162. {
  1163. return I_CAOIDAdd(dwType, dwFlag, pwszOID);
  1164. }
  1165. //---------------------------------------------------------------------------
  1166. //
  1167. // I_CAOIDDelete
  1168. //
  1169. //---------------------------------------------------------------------------
  1170. HRESULT
  1171. I_CAOIDDelete(
  1172. IN LPCWSTR pwszOID)
  1173. {
  1174. HRESULT hr=E_INVALIDARG;
  1175. ULONG ldaperr=0;
  1176. LDAP *pld = NULL;
  1177. CERTSTR bstrConfig = NULL;
  1178. CERTSTR bstrDN = NULL;
  1179. LPWSTR pwszCN = NULL;
  1180. if(NULL==pwszOID)
  1181. _JumpError(hr , error, "ArgumentCheck");
  1182. //retrieve the ldap handle and the config string
  1183. if(S_OK != (hr = myTimeOutRobustLdapBind(&pld)))
  1184. _JumpError(hr , error, "myTimeRobustLdapBind");
  1185. hr = CAGetAuthoritativeDomainDn(pld, NULL, &bstrConfig);
  1186. if(S_OK != hr)
  1187. {
  1188. _JumpError(hr , error, "CAGetAuthoritativeDomainDn");
  1189. }
  1190. //set up the base DN
  1191. if(S_OK != (hr = myOIDHashOIDToString((LPWSTR)pwszOID, &pwszCN)))
  1192. _JumpError(hr , error, "myOIDHashOIDToString");
  1193. bstrDN = CertAllocStringLen(NULL, wcslen(bstrConfig) + wcslen(s_wszOIDContainerDN)+wcslen(pwszCN)+4);
  1194. if(bstrDN == NULL)
  1195. {
  1196. hr = E_OUTOFMEMORY;
  1197. _JumpError(hr, error, "CertAllocStringLen");
  1198. }
  1199. wcscpy(bstrDN, L"CN=");
  1200. wcscat(bstrDN, pwszCN);
  1201. wcscat(bstrDN, L",");
  1202. wcscat(bstrDN, s_wszOIDContainerDN);
  1203. wcscat(bstrDN, bstrConfig);
  1204. ldaperr = ldap_delete_s(pld, bstrDN);
  1205. if(LDAP_NO_SUCH_OBJECT == ldaperr)
  1206. ldaperr = LDAP_SUCCESS;
  1207. hr = myHLdapError(pld, ldaperr, NULL);
  1208. error:
  1209. if(pwszCN)
  1210. LocalFree(pwszCN);
  1211. if(bstrDN)
  1212. CertFreeString(bstrDN);
  1213. if(bstrConfig)
  1214. CertFreeString(bstrConfig);
  1215. if (pld)
  1216. ldap_unbind(pld);
  1217. return hr;
  1218. }
  1219. //---------------------------------------------------------------------------
  1220. //
  1221. // CAOIDDelete
  1222. //
  1223. //---------------------------------------------------------------------------
  1224. HRESULT
  1225. CAOIDDelete(
  1226. IN LPCWSTR pwszOID)
  1227. {
  1228. return I_CAOIDDelete(pwszOID);
  1229. }
  1230. //---------------------------------------------------------------------------
  1231. //
  1232. // I_CAOIDGetProperty
  1233. //
  1234. //---------------------------------------------------------------------------
  1235. HRESULT
  1236. I_CAOIDGetProperty(
  1237. IN LPCWSTR pwszOID,
  1238. IN DWORD dwProperty,
  1239. OUT LPVOID pPropValue)
  1240. {
  1241. HRESULT hr=E_INVALIDARG;
  1242. ULONG ldaperr=0;
  1243. DWORD dwCount=0;
  1244. struct l_timeval timeout;
  1245. LPWSTR awszAttr[4];
  1246. LDAPMessage *Entry=NULL;
  1247. WCHAR **wszLdapVal = NULL;
  1248. LPWSTR pwszFilter = NULL;
  1249. LDAPMessage *SearchResult = NULL;
  1250. LDAP *pld = NULL;
  1251. CERTSTR bstrConfig = NULL;
  1252. CERTSTR bstrDN = NULL;
  1253. LPWSTR pwszCN = NULL;
  1254. if((NULL==pwszOID) || (NULL==pPropValue))
  1255. _JumpError(hr , error, "ArgumentCheck");
  1256. //retrieve the ldap handle and the config string
  1257. if(S_OK != (hr = myTimeOutRobustLdapBind(&pld)))
  1258. _JumpError(hr , error, "myTimeRobustLdapBind");
  1259. hr = CAGetAuthoritativeDomainDn(pld, NULL, &bstrConfig);
  1260. if(S_OK != hr)
  1261. {
  1262. _JumpError(hr , error, "CAGetAuthoritativeDomainDn");
  1263. }
  1264. //set up the base DN
  1265. if(S_OK != (hr = myOIDHashOIDToString((LPWSTR)pwszOID, &pwszCN)))
  1266. _JumpError(hr , error, "myOIDHashOIDToString");
  1267. bstrDN = CertAllocStringLen(NULL, wcslen(bstrConfig) + wcslen(s_wszOIDContainerDN)+wcslen(pwszCN)+4);
  1268. if(bstrDN == NULL)
  1269. {
  1270. hr = E_OUTOFMEMORY;
  1271. _JumpError(hr, error, "CertAllocStringLen");
  1272. }
  1273. wcscpy(bstrDN, L"CN=");
  1274. wcscat(bstrDN, pwszCN);
  1275. wcscat(bstrDN, L",");
  1276. wcscat(bstrDN, s_wszOIDContainerDN);
  1277. wcscat(bstrDN, bstrConfig);
  1278. //search for the OID, asking for all its attributes
  1279. timeout.tv_sec = csecLDAPTIMEOUT;
  1280. timeout.tv_usec = 0;
  1281. awszAttr[0]=OID_PROP_TYPE;
  1282. awszAttr[1]=OID_PROP_DISPLAY_NAME;
  1283. awszAttr[2]=OID_PROP_CPS;
  1284. awszAttr[3]=NULL;
  1285. if(S_OK != (hr=FormatMessageUnicode(&pwszFilter, L"(%1!s!=%2!s!)",
  1286. OID_PROP_OID, pwszOID)))
  1287. _JumpError(hr , error, "FormatMessageUnicode");
  1288. ldaperr = ldap_search_stW(
  1289. pld,
  1290. (LPWSTR)bstrDN,
  1291. LDAP_SCOPE_BASE,
  1292. pwszFilter,
  1293. awszAttr,
  1294. 0,
  1295. &timeout,
  1296. &SearchResult);
  1297. if(LDAP_SUCCESS != ldaperr)
  1298. {
  1299. hr = myHLdapError2(pld, ldaperr, LDAP_NO_SUCH_OBJECT, NULL);
  1300. _JumpErrorStr2(
  1301. hr,
  1302. error,
  1303. "ldap_search_stW",
  1304. pwszFilter,
  1305. HRESULT_FROM_WIN32(ERROR_DS_OBJ_NOT_FOUND));
  1306. }
  1307. dwCount = ldap_count_entries(pld, SearchResult);
  1308. //we should only find one container
  1309. if((1 != dwCount) || (NULL == (Entry = ldap_first_entry(pld, SearchResult))))
  1310. {
  1311. // No entries were found.
  1312. hr = myHLdapError(pld, LDAP_NO_SUCH_OBJECT, NULL);
  1313. _JumpError(hr, error, "ldap_search_stW");
  1314. }
  1315. switch(dwProperty)
  1316. {
  1317. case CERT_OID_PROPERTY_DISPLAY_NAME:
  1318. wszLdapVal = ldap_get_values(pld, Entry, OID_PROP_DISPLAY_NAME);
  1319. if(wszLdapVal && wszLdapVal[0])
  1320. {
  1321. hr=CAOIDAllocAndCopy(wszLdapVal[0], (LPWSTR *)pPropValue);
  1322. }
  1323. else
  1324. hr = myHLdapError(pld, LDAP_NO_SUCH_ATTRIBUTE, NULL);
  1325. break;
  1326. case CERT_OID_PROPERTY_CPS:
  1327. wszLdapVal = ldap_get_values(pld, Entry, OID_PROP_CPS);
  1328. if(wszLdapVal && wszLdapVal[0])
  1329. {
  1330. hr=CAOIDAllocAndCopy(wszLdapVal[0], (LPWSTR *)pPropValue);
  1331. }
  1332. else
  1333. hr = myHLdapError(pld, LDAP_NO_SUCH_ATTRIBUTE, NULL);
  1334. break;
  1335. case CERT_OID_PROPERTY_TYPE:
  1336. wszLdapVal = ldap_get_values(pld, Entry, OID_PROP_TYPE);
  1337. if(wszLdapVal && wszLdapVal[0])
  1338. {
  1339. *((DWORD *)pPropValue)=_wtol(wszLdapVal[0]);
  1340. hr=S_OK;
  1341. }
  1342. else
  1343. hr = myHLdapError(pld, LDAP_NO_SUCH_ATTRIBUTE, NULL);
  1344. break;
  1345. default:
  1346. hr=E_INVALIDARG;
  1347. }
  1348. if(hr != S_OK)
  1349. _JumpError(hr , error, "GetAttibuteValue");
  1350. error:
  1351. if(wszLdapVal)
  1352. ldap_value_free(wszLdapVal);
  1353. if(pwszFilter)
  1354. LocalFree((HLOCAL)pwszFilter);
  1355. if(SearchResult)
  1356. ldap_msgfree(SearchResult);
  1357. if(pwszCN)
  1358. LocalFree(pwszCN);
  1359. if(bstrDN)
  1360. CertFreeString(bstrDN);
  1361. if(bstrConfig)
  1362. CertFreeString(bstrConfig);
  1363. if (pld)
  1364. ldap_unbind(pld);
  1365. return hr;
  1366. }
  1367. //---------------------------------------------------------------------------
  1368. //
  1369. // CAOIDGetProperty
  1370. //
  1371. //---------------------------------------------------------------------------
  1372. HRESULT
  1373. CAOIDGetProperty(
  1374. IN LPCWSTR pwszOID,
  1375. IN DWORD dwProperty,
  1376. OUT LPVOID pPropValue)
  1377. {
  1378. return I_CAOIDGetProperty(pwszOID, dwProperty, pPropValue);
  1379. }
  1380. //---------------------------------------------------------------------------
  1381. //
  1382. // I_CAOIDFreeProperty
  1383. //
  1384. //---------------------------------------------------------------------------
  1385. HRESULT
  1386. I_CAOIDFreeProperty(
  1387. IN LPVOID pPropValue)
  1388. {
  1389. if(pPropValue)
  1390. LocalFree(pPropValue);
  1391. return S_OK;
  1392. }
  1393. //---------------------------------------------------------------------------
  1394. //
  1395. // CAOIDFreeProperty
  1396. //
  1397. //---------------------------------------------------------------------------
  1398. HRESULT
  1399. CAOIDFreeProperty(
  1400. IN LPVOID pPropValue)
  1401. {
  1402. return I_CAOIDFreeProperty(pPropValue);
  1403. }
  1404. //---------------------------------------------------------------------------
  1405. //
  1406. // CAOIDGetLdapURL
  1407. //
  1408. // Get the LDAP URL for the DS OID repository in the format of
  1409. // LDAP:///DN of the Repository/all attributes?one?filter.
  1410. //---------------------------------------------------------------------------
  1411. HRESULT
  1412. CAOIDGetLdapURL(
  1413. IN DWORD dwType,
  1414. IN DWORD, // dwFlag
  1415. OUT LPWSTR *ppwszURL)
  1416. {
  1417. HRESULT hr=E_INVALIDARG;
  1418. LPWSTR wszFilterFormat=L"ldap:///%1!s!%2!s!?%3!s!,%4!s!,%5!s!,%6!s!,%7!s!?one?%8!s!=%9!d!";
  1419. LPWSTR pwsz=NULL;
  1420. LPWSTR pwszURL=NULL;
  1421. LDAP *pld = NULL;
  1422. CERTSTR bstrConfig = NULL;
  1423. if(NULL==ppwszURL)
  1424. _JumpError(hr , error, "ArgumentCheck");
  1425. //retrieve the ldap handle and the config string
  1426. if(S_OK != (hr = myTimeOutRobustLdapBind(&pld)))
  1427. _JumpError(hr , error, "myTimeRobustLdapBind");
  1428. hr = CAGetAuthoritativeDomainDn(pld, NULL, &bstrConfig);
  1429. if(S_OK != hr)
  1430. {
  1431. _JumpError(hr , error, "CAGetAuthoritativeDomainDn");
  1432. }
  1433. if(S_OK != (hr=FormatMessageUnicode(
  1434. &pwszURL,
  1435. wszFilterFormat,
  1436. s_wszOIDContainerDN,
  1437. bstrConfig,
  1438. OID_PROP_TYPE,
  1439. OID_PROP_OID,
  1440. OID_PROP_DISPLAY_NAME,
  1441. OID_PROP_CPS,
  1442. OID_PROP_LOCALIZED_NAME,
  1443. OID_PROP_TYPE,
  1444. dwType
  1445. )))
  1446. _JumpError(hr , error, "FormatMessageUnicode");
  1447. //we eliminate the filter if dwType is CERT_OID_TYPE_ALL
  1448. if(CERT_OID_TYPE_ALL == dwType)
  1449. {
  1450. pwsz=wcsrchr(pwszURL, L'?');
  1451. if(NULL==pwsz)
  1452. {
  1453. //something serious is wrong
  1454. hr=E_UNEXPECTED;
  1455. _JumpError(hr , error, "FormatMessageUnicode");
  1456. }
  1457. *pwsz=L'\0';
  1458. }
  1459. *ppwszURL=pwszURL;
  1460. pwszURL=NULL;
  1461. hr=S_OK;
  1462. error:
  1463. if(pwszURL)
  1464. LocalFree((HLOCAL)pwszURL);
  1465. if(bstrConfig)
  1466. CertFreeString(bstrConfig);
  1467. if (pld)
  1468. ldap_unbind(pld);
  1469. return hr;
  1470. }
  1471. //---------------------------------------------------------------------------
  1472. //
  1473. // CAOIDFreeLdapURL
  1474. //
  1475. //---------------------------------------------------------------------------
  1476. HRESULT
  1477. CAOIDFreeLdapURL(
  1478. IN LPCWSTR pwszURL)
  1479. {
  1480. if(pwszURL)
  1481. LocalFree((HLOCAL)pwszURL);
  1482. return S_OK;
  1483. }