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.

360 lines
10 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 2000
  5. //
  6. // File: ctnotify.cpp
  7. //
  8. // Contents: Cert Type Change Notification APIS
  9. //
  10. //---------------------------------------------------------------------------
  11. #include "pch.cpp"
  12. #pragma hdrstop
  13. #include <winldap.h>
  14. #include <ntldap.h>
  15. #include <cainfop.h>
  16. #include <ctnotify.h>
  17. #include <certca.h>
  18. #include "csldap.h"
  19. #define __dwFILE__ __dwFILE_CERTCLIB_CTNOTIFY_CPP__
  20. static WCHAR * s_wszLocation = L"CN=Certificate Templates,CN=Public Key Services,CN=Services,";
  21. //-----------------------------------------------------------------------
  22. //
  23. // CertTypeQueryProc
  24. //
  25. // The thread to recieve change notification from DS
  26. //
  27. //-----------------------------------------------------------------------
  28. DWORD WINAPI CertTypeQueryProc(LPVOID lpParameter)
  29. {
  30. CERTTYPE_QUERY_INFO *pCertTypeQueryInfo=NULL;
  31. ULONG ldaperr=0;
  32. BOOL fFailed=FALSE;
  33. LDAPMessage *results = NULL;
  34. if(NULL==lpParameter)
  35. return FALSE;
  36. pCertTypeQueryInfo = (CERTTYPE_QUERY_INFO *)lpParameter;
  37. //we wait for the notifications
  38. while(TRUE)
  39. {
  40. ldaperr = ldap_result(
  41. pCertTypeQueryInfo->pldap,
  42. pCertTypeQueryInfo->msgID, // message identifier
  43. LDAP_MSG_ONE, // retrieve one message at a time
  44. NULL, // no timeout
  45. &results); // receives the search results
  46. fFailed=FALSE;
  47. if ((ldaperr == (ULONG) -1) || (ldaperr == 0) || ((results) == NULL))
  48. {
  49. fFailed=TRUE;
  50. }
  51. else
  52. {
  53. if(LDAP_SUCCESS != ldap_result2error(pCertTypeQueryInfo->pldap, results, FALSE))
  54. {
  55. fFailed=TRUE;
  56. }
  57. }
  58. if(TRUE == fFailed)
  59. {
  60. pCertTypeQueryInfo->hr = myHLdapError(pCertTypeQueryInfo->pldap, ldaperr, NULL);
  61. if(!FAILED(pCertTypeQueryInfo->hr))
  62. pCertTypeQueryInfo->hr=E_FAIL;
  63. _PrintIfError(pCertTypeQueryInfo->hr, "CertTypeQueryProc");
  64. if(results)
  65. {
  66. ldap_msgfree(results);
  67. results=NULL;
  68. }
  69. break;
  70. }
  71. //some change has happened.
  72. (pCertTypeQueryInfo->dwChangeSequence)++;
  73. //make sure that we will never return 0
  74. if(0 == (pCertTypeQueryInfo->dwChangeSequence))
  75. {
  76. (pCertTypeQueryInfo->dwChangeSequence)++;
  77. }
  78. ldap_msgfree(results);
  79. results=NULL;
  80. }
  81. return TRUE;
  82. }
  83. //---------------------------------------------------------------------------
  84. //
  85. // CACertTypeRegisterQuery
  86. //
  87. //---------------------------------------------------------------------------
  88. HRESULT
  89. CACertTypeRegisterQuery(
  90. IN DWORD, // dwFlag
  91. IN LPVOID pvldap,
  92. OUT HCERTTYPEQUERY *phCertTypeQuery)
  93. {
  94. HRESULT hr=E_INVALIDARG;
  95. LDAPControl simpleControl;
  96. PLDAPControl controlArray[2];
  97. LPWSTR rgwszAttribs[2];
  98. ULONG ldaperr=0;
  99. DWORD dwThreadID=0;
  100. LDAP *pldap=NULL;
  101. CERTSTR bstrConfig = NULL;
  102. CERTSTR bstrCertTemplatesContainer = NULL;
  103. //memory is freed via the thread proc
  104. CERTTYPE_QUERY_INFO *pCertTypeQueryInfo=NULL;
  105. //assign the input parameter
  106. pldap = (LDAP *)pvldap;
  107. if(NULL==phCertTypeQuery)
  108. _JumpError(hr, error, "NULL param");
  109. pCertTypeQueryInfo=(CERTTYPE_QUERY_INFO *)LocalAlloc(LPTR, sizeof(CERTTYPE_QUERY_INFO));
  110. if(NULL==pCertTypeQueryInfo)
  111. {
  112. hr=E_OUTOFMEMORY;
  113. _JumpError(hr, error, "LocalAlloc");
  114. }
  115. memset(pCertTypeQueryInfo, 0, sizeof(CERTTYPE_QUERY_INFO));
  116. //we start the change sequence as 1
  117. pCertTypeQueryInfo->dwChangeSequence = 1;
  118. pCertTypeQueryInfo->hr=S_OK;
  119. //bind to DS
  120. if(pldap)
  121. {
  122. pCertTypeQueryInfo->pldap=pldap;
  123. }
  124. else
  125. {
  126. // retrieve the ldap handle
  127. hr = myDoesDSExist(TRUE);
  128. _JumpIfError(hr, error, "myDoesDSExist");
  129. hr = myRobustLdapBindEx(
  130. 0, // dwFlags1
  131. RLBF_REQUIRE_SECURE_LDAP, // dwFlags2
  132. 0, // uVersion
  133. NULL, // pwszDomainName
  134. &pCertTypeQueryInfo->pldap,
  135. NULL); // ppwszForestDNSName
  136. _JumpIfError(hr , error, "myRobustLdapBindEx");
  137. pCertTypeQueryInfo->fUnbind=TRUE;
  138. }
  139. // retrieve the config string
  140. hr = CAGetAuthoritativeDomainDn(pCertTypeQueryInfo->pldap, NULL, &bstrConfig);
  141. _JumpIfError(hr, error, "CAGetAuthoritativeDomainDn");
  142. //build the template container DN
  143. bstrCertTemplatesContainer = CertAllocStringLen(NULL, wcslen(bstrConfig) + wcslen(s_wszLocation));
  144. if(bstrCertTemplatesContainer == NULL)
  145. {
  146. hr = E_OUTOFMEMORY;
  147. _JumpError(hr, error, "CertAllocStringLen");
  148. }
  149. wcscpy(bstrCertTemplatesContainer, s_wszLocation);
  150. wcscat(bstrCertTemplatesContainer, bstrConfig);
  151. // Set up the change notification control.
  152. simpleControl.ldctl_oid = LDAP_SERVER_NOTIFICATION_OID_W;
  153. simpleControl.ldctl_iscritical = TRUE;
  154. simpleControl.ldctl_value.bv_len = 0;
  155. simpleControl.ldctl_value.bv_val = NULL;
  156. controlArray[0] = &simpleControl;
  157. controlArray[1] = NULL;
  158. rgwszAttribs[0] = L"cn";
  159. rgwszAttribs[1] = NULL;
  160. // Start a persistent asynchronous search.
  161. ldaperr = ldap_search_ext(
  162. pCertTypeQueryInfo->pldap,
  163. (PWCHAR) bstrCertTemplatesContainer, // Template container DN
  164. LDAP_SCOPE_ONELEVEL,
  165. L"ObjectClass=*",
  166. rgwszAttribs, // Attributes to retrieve
  167. 1, // Retrieve attributes only
  168. (PLDAPControl *) controlArray, // Server size controls
  169. NULL, // Client controls
  170. 0, // Timeout
  171. 0, // Sizelimit
  172. (PULONG)&(pCertTypeQueryInfo->msgID) // Receives identifier for results
  173. );
  174. if (LDAP_SUCCESS != ldaperr)
  175. {
  176. hr = myHLdapError(pCertTypeQueryInfo->pldap, ldaperr, NULL);
  177. _JumpError(hr, error, "ldap_search_ext");
  178. }
  179. //start a thread to wait for the notification
  180. pCertTypeQueryInfo->hThread = CreateThread(
  181. NULL,
  182. 0,
  183. CertTypeQueryProc,
  184. pCertTypeQueryInfo,
  185. 0, //execute immediately
  186. &dwThreadID);
  187. if(NULL == pCertTypeQueryInfo->hThread)
  188. {
  189. hr=myHError(GetLastError());
  190. _JumpError(hr, error, "CreateThread");
  191. }
  192. *phCertTypeQuery=pCertTypeQueryInfo;
  193. pCertTypeQueryInfo=NULL;
  194. hr=S_OK;
  195. error:
  196. if(bstrConfig)
  197. CertFreeString(bstrConfig);
  198. if(bstrCertTemplatesContainer)
  199. {
  200. CertFreeString(bstrCertTemplatesContainer);
  201. }
  202. if(pCertTypeQueryInfo)
  203. {
  204. if(pCertTypeQueryInfo->fUnbind)
  205. {
  206. if(pCertTypeQueryInfo->pldap)
  207. ldap_unbind(pCertTypeQueryInfo->pldap);
  208. }
  209. if(pCertTypeQueryInfo->hThread)
  210. CloseHandle(pCertTypeQueryInfo->hThread);
  211. LocalFree(pCertTypeQueryInfo);
  212. pCertTypeQueryInfo=NULL;
  213. }
  214. return hr;
  215. }
  216. //---------------------------------------------------------------------------
  217. //
  218. // CACertTypeQuery
  219. //
  220. //---------------------------------------------------------------------------
  221. HRESULT
  222. CACertTypeQuery(
  223. IN HCERTTYPEQUERY hCertTypeQuery,
  224. OUT DWORD *pdwChangeSequence)
  225. {
  226. CERTTYPE_QUERY_INFO *pCertTypeQueryInfo=NULL;
  227. if((NULL==pdwChangeSequence) || (NULL==hCertTypeQuery))
  228. return E_INVALIDARG;
  229. pCertTypeQueryInfo = (CERTTYPE_QUERY_INFO *)hCertTypeQuery;
  230. *pdwChangeSequence = pCertTypeQueryInfo->dwChangeSequence;
  231. return (pCertTypeQueryInfo->hr);
  232. }
  233. //---------------------------------------------------------------------------
  234. //
  235. // CACertTypeUnregisterQuery
  236. //
  237. //---------------------------------------------------------------------------
  238. HRESULT
  239. CACertTypeUnregisterQuery(
  240. IN HCERTTYPEQUERY hCertTypeQuery)
  241. {
  242. CERTTYPE_QUERY_INFO *pCertTypeQueryInfo=NULL;
  243. ULONG ldaperr=0;
  244. HRESULT hr=E_INVALIDARG;
  245. DWORD dwWait=0;
  246. if(NULL==hCertTypeQuery)
  247. _JumpError(hr, error, "NULL param");
  248. pCertTypeQueryInfo = (CERTTYPE_QUERY_INFO *)hCertTypeQuery;
  249. if(NULL == (pCertTypeQueryInfo->pldap))
  250. _JumpError(hr, error, "NULL pldap");
  251. //abandom the in-progress asynchronous ldap_result call
  252. ldaperr=ldap_abandon(pCertTypeQueryInfo->pldap, pCertTypeQueryInfo->msgID);
  253. if(LDAP_SUCCESS != ldaperr)
  254. {
  255. hr = myHLdapError(pCertTypeQueryInfo->pldap, ldaperr, NULL);
  256. _JumpError(hr, error, "ldap_abandon");
  257. }
  258. //wait for the thread to finish
  259. dwWait = WaitForSingleObject(pCertTypeQueryInfo->hThread, INFINITE);
  260. if(WAIT_OBJECT_0 != dwWait)
  261. {
  262. hr = myHError(GetLastError());
  263. _JumpError(hr, error, "WaitForSingleObject");
  264. }
  265. hr=S_OK;
  266. error:
  267. //free the memory
  268. if(pCertTypeQueryInfo)
  269. {
  270. if(pCertTypeQueryInfo->fUnbind)
  271. {
  272. if(pCertTypeQueryInfo->pldap)
  273. ldap_unbind(pCertTypeQueryInfo->pldap);
  274. }
  275. if(pCertTypeQueryInfo->hThread)
  276. CloseHandle(pCertTypeQueryInfo->hThread);
  277. LocalFree(pCertTypeQueryInfo);
  278. pCertTypeQueryInfo=NULL;
  279. }
  280. return hr;
  281. }