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.

324 lines
7.3 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1999
  5. //
  6. // File: certsrvd.cpp
  7. //
  8. // Contents: Implementation of DCOM object for RPC services
  9. //
  10. // History: July-97 xtan created
  11. //
  12. //---------------------------------------------------------------------------
  13. #include <pch.cpp>
  14. #pragma hdrstop
  15. #define SECURITY_WIN32
  16. #include <security.h>
  17. #include <lmcons.h>
  18. #include <accctrl.h>
  19. #include "certsrvd.h"
  20. #include "admin.h"
  21. #include "request.h"
  22. #include "certacl.h"
  23. //temporary
  24. #include <msaudite.h>
  25. using namespace CertSrv;
  26. // Global Access List
  27. CCertificateAuthoritySD g_CASD;
  28. AUTHZ_RESOURCE_MANAGER_HANDLE g_AuthzCertSrvRM;
  29. DWORD g_dwAuditFilter;
  30. COfficerRightsSD g_OfficerRightsSD;
  31. CConfigStorage g_ConfigStorage;
  32. GENERIC_MAPPING g_CertGenericMapping = {
  33. READ_CONTROL | ACTRL_DS_READ_PROP,
  34. WRITE_DAC | WRITE_OWNER | ACTRL_DS_WRITE_PROP,
  35. 0,
  36. ACTRL_DS_READ_PROP |
  37. ACTRL_DS_WRITE_PROP |
  38. READ_CONTROL |
  39. WRITE_DAC |
  40. WRITE_OWNER
  41. };
  42. // GetClientUserName() impersonates the client
  43. HRESULT
  44. GetClientUserName(
  45. IN handle_t hRpc,
  46. OPTIONAL OUT WCHAR **ppwszUserSamName,
  47. OPTIONAL OUT WCHAR **ppwszUserDN)
  48. {
  49. HRESULT hr;
  50. IServerSecurity *pISS = NULL;
  51. bool fImpersonating = false;
  52. WCHAR *pwszUserSamName = NULL;
  53. if (NULL != ppwszUserSamName)
  54. {
  55. *ppwszUserSamName = NULL;
  56. }
  57. if (NULL != ppwszUserDN)
  58. {
  59. *ppwszUserDN = NULL;
  60. }
  61. if (NULL == hRpc)
  62. {
  63. // dcom impersonate
  64. // get client info and impersonate client
  65. hr = CoGetCallContext(IID_IServerSecurity, (void**)&pISS);
  66. _JumpIfError(hr, error, "CoGetCallContext");
  67. hr = pISS->ImpersonateClient();
  68. _JumpIfError(hr, error, "ImpersonateClient");
  69. }
  70. else
  71. {
  72. // rpc impersonate
  73. hr = RpcImpersonateClient((RPC_BINDING_HANDLE) hRpc);
  74. _JumpIfError(hr, error, "RpcImpersonateClient");
  75. }
  76. fImpersonating = true;
  77. if (NULL != ppwszUserSamName)
  78. {
  79. hr = myGetUserNameEx(NameSamCompatible, &pwszUserSamName);
  80. _JumpIfError(hr, error, "myGetUserNameEx");
  81. }
  82. if (NULL != ppwszUserDN)
  83. {
  84. hr = myGetUserNameEx(NameFullyQualifiedDN, ppwszUserDN);
  85. _JumpIfError(hr, error, "myGetUserNameEx");
  86. }
  87. if (NULL != ppwszUserSamName)
  88. {
  89. *ppwszUserSamName = pwszUserSamName;
  90. pwszUserSamName = NULL;
  91. }
  92. hr = S_OK;
  93. error:
  94. if (fImpersonating)
  95. {
  96. if (NULL != hRpc)
  97. {
  98. RpcRevertToSelf();
  99. }
  100. else // dcom
  101. {
  102. pISS->RevertToSelf();
  103. }
  104. }
  105. if (NULL != pISS)
  106. {
  107. pISS->Release();
  108. }
  109. if (NULL != pwszUserSamName)
  110. {
  111. LocalFree(pwszUserSamName);
  112. }
  113. return(hr);
  114. }
  115. STDMETHODIMP
  116. CheckCertSrvAccess(
  117. OPTIONAL IN LPCWSTR pwszAuthority,
  118. IN handle_t hRpc,
  119. IN ACCESS_MASK Mask,
  120. OUT BOOL *pfAccessAllowed,
  121. OPTIONAL OUT HANDLE *phToken)
  122. {
  123. HRESULT hr = S_OK;
  124. DWORD dwErr = ERROR_SUCCESS;
  125. HANDLE hClientToken = NULL;
  126. HANDLE hThread = NULL;
  127. IServerSecurity *pISS = NULL;
  128. PRIVILEGE_SET ps;
  129. DWORD dwPSSize = sizeof(PRIVILEGE_SET);
  130. DWORD grantAccess;
  131. DWORD dwType;
  132. WCHAR **ppwszGroup;
  133. PSECURITY_DESCRIPTOR pCASD = NULL;
  134. *pfAccessAllowed = FALSE;
  135. // If, for some reason, a certsrv call is made after we've shut down
  136. // security, we need to fail.
  137. if (!g_CASD.IsInitialized())
  138. {
  139. hr = HRESULT_FROM_WIN32(ERROR_NOT_READY);
  140. _JumpError(hr, error, "Security not enabled");
  141. }
  142. if (NULL != pwszAuthority)
  143. {
  144. if (0 != lstrcmpi(pwszAuthority, g_wszCommonName))
  145. {
  146. if (0 != lstrcmpi(pwszAuthority, g_wszSanitizedName) &&
  147. 0 != lstrcmpi(pwszAuthority, g_pwszSanitizedDSName))
  148. {
  149. hr = E_INVALIDARG;
  150. _PrintErrorStr(
  151. hr,
  152. "CheckCertSrvAccess: invalid authority name",
  153. pwszAuthority);
  154. _JumpErrorStr(hr, error, "expected CA name", g_wszCommonName);
  155. }
  156. #ifdef DBG_CERTSRV_DEBUG_PRINT
  157. if (0 == lstrcmpi(pwszAuthority, g_wszSanitizedName))
  158. {
  159. DBGPRINT((
  160. DBG_SS_CERTSRV,
  161. "'%ws' called with Sanitized Name: '%ws'\n",
  162. g_wszCommonName,
  163. pwszAuthority));
  164. }
  165. else
  166. if (0 == lstrcmpi(pwszAuthority, g_pwszSanitizedDSName))
  167. {
  168. DBGPRINT((
  169. DBG_SS_CERTSRV,
  170. "'%ws' called with Sanitized DS Name: '%ws'\n",
  171. g_wszCommonName,
  172. pwszAuthority));
  173. }
  174. #endif
  175. }
  176. }
  177. if(NULL == hRpc)
  178. {
  179. // dcom impersonate
  180. // get client info and impersonate client
  181. hr = CoGetCallContext(IID_IServerSecurity, (void**)&pISS);
  182. _JumpIfError(hr, error, "CoGetCallContext");
  183. //if (!pISS->IsImpersonating())
  184. {
  185. hr = pISS->ImpersonateClient();
  186. _JumpIfError(hr, error, "ImpersonateClient");
  187. }
  188. }
  189. else
  190. {
  191. // rpc impersonate
  192. hr = RpcImpersonateClient((RPC_BINDING_HANDLE) hRpc);
  193. if (S_OK != hr)
  194. {
  195. hr = myHError(hr);
  196. _JumpError(hr, error, "RpcImpersonateClient");
  197. }
  198. }
  199. hThread = GetCurrentThread();
  200. if (NULL == hThread)
  201. {
  202. hr = myHLastError();
  203. _JumpIfError(hr, error, "GetCurrentThread");
  204. }
  205. if (!OpenThreadToken(hThread,
  206. TOKEN_QUERY | TOKEN_DUPLICATE,
  207. FALSE, // client impersonation
  208. &hClientToken))
  209. {
  210. hr = myHLastError();
  211. _JumpIfError(hr, error, "OpenThreadToken");
  212. }
  213. hr = g_CASD.LockGet(&pCASD);
  214. _JumpIfError(hr, error, "CProtectedSecurityDescriptor::LockGet");
  215. if (!AccessCheck(
  216. pCASD, // security descriptor
  217. hClientToken, // handle to client access token
  218. Mask, // requested access rights
  219. &g_CertGenericMapping, // map generic to specific rights
  220. &ps, // receives privileges used
  221. &dwPSSize, // size of privilege-set buffer
  222. &grantAccess, // retrieves mask of granted rights
  223. pfAccessAllowed)) // retrieves results of access check
  224. {
  225. hr = myHLastError();
  226. _JumpError(hr, error, "AccessCheckByType");
  227. }
  228. hr = S_OK;
  229. if(phToken)
  230. {
  231. *phToken = hClientToken;
  232. hClientToken = NULL;
  233. }
  234. error:
  235. if(pCASD)
  236. {
  237. HRESULT hr1 = g_CASD.Unlock();
  238. hr = S_OK!=hr?hr:hr1;
  239. }
  240. if (NULL != hRpc) // rpc
  241. {
  242. RpcRevertToSelf();
  243. }
  244. else // dcom
  245. {
  246. if (NULL != pISS)
  247. {
  248. pISS->RevertToSelf();
  249. pISS->Release();
  250. }
  251. }
  252. if (NULL != hThread)
  253. {
  254. CloseHandle(hThread);
  255. }
  256. if (NULL != hClientToken)
  257. {
  258. CloseHandle(hClientToken);
  259. }
  260. return(hr);
  261. }
  262. HRESULT
  263. CertStartClassFactories()
  264. {
  265. HRESULT hr;
  266. BOOL fRequestStarted = FALSE;
  267. hr = CRequestFactory::StartFactory();
  268. _JumpIfError(hr, error, "CRequestFactory::StartFactory");
  269. hr = CAdminFactory::StartFactory();
  270. _JumpIfError(hr, error, "CAdminFactory::StartFactory");
  271. error:
  272. if (S_OK != hr)
  273. {
  274. CRequestFactory::StopFactory();
  275. }
  276. CSASSERT(S_OK == hr || FAILED(hr));
  277. return(hr);
  278. }
  279. VOID
  280. CertStopClassFactories()
  281. {
  282. CRequestFactory::StopFactory();
  283. CAdminFactory::StopFactory();
  284. }