Source code of Windows XP (NT5)
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.

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