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.

401 lines
9.6 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1999
  5. //
  6. // File: rpc.cpp
  7. //
  8. // Contents: Cert Server RPC
  9. //
  10. // History: 03-Sep-96 larrys created
  11. //
  12. //---------------------------------------------------------------------------
  13. #include <pch.cpp>
  14. #pragma hdrstop
  15. #include <stdio.h>
  16. #include <accctrl.h>
  17. #include "certrpc.h"
  18. #include "certacl.h"
  19. #include "cscom.h"
  20. #include "resource.h"
  21. #define __dwFILE__ __dwFILE_CERTSRV_RPC_CPP__
  22. RPC_BINDING_VECTOR *pvBindings = NULL;
  23. char *pszProtSeqNp = "ncacn_np";
  24. char *pszProtSeqTcp = "ncacn_ip_tcp";
  25. typedef struct _CS_RPC_ATHN_LIST
  26. {
  27. DWORD dwAuthnLevel;
  28. DWORD dwPrinceNameService;
  29. DWORD dwAuthnService;
  30. } CS_RPC_ATHN_LIST ;
  31. CS_RPC_ATHN_LIST g_acsAthnList[] =
  32. {
  33. { RPC_C_AUTHN_LEVEL_PKT_INTEGRITY, RPC_C_AUTHN_GSS_NEGOTIATE, RPC_C_AUTHN_GSS_NEGOTIATE },
  34. { RPC_C_AUTHN_LEVEL_NONE, RPC_C_AUTHN_NONE, RPC_C_AUTHN_NONE }
  35. };
  36. DWORD g_ccsAthnList = sizeof(g_acsAthnList)/sizeof(g_acsAthnList[0]);
  37. HRESULT
  38. RPCInit(VOID)
  39. {
  40. char *pszEndpoint = "\\pipe\\cert";
  41. LPSTR pszPrincName = NULL;
  42. HRESULT hr;
  43. DWORD i;
  44. if (RPC_S_OK == RpcNetworkIsProtseqValidA((unsigned char *) pszProtSeqNp))
  45. {
  46. hr = RpcServerUseProtseqEpA(
  47. (unsigned char *) pszProtSeqNp,
  48. RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
  49. (unsigned char *) pszEndpoint,
  50. NULL);
  51. _JumpIfError(hr, error, "RpcServerUseProtseqEpA");
  52. }
  53. if (RPC_S_OK == RpcNetworkIsProtseqValidA((unsigned char *) pszProtSeqTcp))
  54. {
  55. hr = RpcServerUseProtseqA(
  56. (unsigned char *) pszProtSeqTcp,
  57. RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
  58. NULL);
  59. if ((HRESULT) ERROR_OUTOFMEMORY == hr)
  60. {
  61. OSVERSIONINFO ovi;
  62. ovi.dwOSVersionInfoSize = sizeof(ovi);
  63. if (GetVersionEx(&ovi) &&
  64. VER_PLATFORM_WIN32_NT == ovi.dwPlatformId &&
  65. 4 >= ovi.dwMajorVersion)
  66. {
  67. hr = S_OK; // Ignore IP failure
  68. }
  69. }
  70. _JumpIfError(hr, error, "RpcServerUseProtseqA");
  71. }
  72. hr = RpcServerInqBindings(&pvBindings);
  73. _JumpIfError(hr, error, "RpcServerInqBindings");
  74. hr = RpcServerRegisterIf(s_ICertPassage_v0_0_s_ifspec, NULL, NULL);
  75. _JumpIfError(hr, error, "RpcServerRegisterIf");
  76. // Register Authentication Services
  77. for (i = 0; i < g_ccsAthnList; i++)
  78. {
  79. pszPrincName = NULL;
  80. if (g_acsAthnList[i].dwPrinceNameService != RPC_C_AUTHN_NONE)
  81. {
  82. hr = RpcServerInqDefaultPrincNameA(
  83. g_acsAthnList[i].dwPrinceNameService,
  84. (BYTE **) &pszPrincName);
  85. if (hr != RPC_S_OK)
  86. {
  87. continue;
  88. }
  89. }
  90. hr = RpcServerRegisterAuthInfoA(
  91. (BYTE *) pszPrincName,
  92. g_acsAthnList[i].dwAuthnService,
  93. 0,
  94. 0);
  95. if(hr == RPC_S_UNKNOWN_AUTHN_SERVICE)
  96. {
  97. continue;
  98. }
  99. if(hr != RPC_S_OK)
  100. {
  101. break;
  102. }
  103. }
  104. if (hr != RPC_S_UNKNOWN_AUTHN_SERVICE)
  105. {
  106. _JumpIfError(hr, error, "RpcServerRegisterAuthInfoA");
  107. }
  108. hr = RpcEpRegister(s_ICertPassage_v0_0_s_ifspec, pvBindings, NULL, NULL);
  109. _JumpIfError(hr, error, "RpcEpRegister");
  110. // Listen, but don't wait...
  111. hr = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE);
  112. _JumpIfError(hr, error, "RpcServerListen");
  113. error:
  114. if (NULL != pszPrincName)
  115. {
  116. RpcStringFreeA((BYTE **) &pszPrincName);
  117. }
  118. return(hr);
  119. }
  120. HRESULT
  121. RPCTeardown(VOID)
  122. {
  123. HRESULT hr;
  124. // tear down, don't wait for calls to complete
  125. hr = RpcServerUnregisterIf(s_ICertPassage_v0_0_s_ifspec, NULL, FALSE);
  126. _JumpIfError(hr, error, "RpcServerUnregisterIf");
  127. // We have no good way of knowing if all RPC requests are done, so let it
  128. // leak on shutdown.
  129. // RPC_STATUS RPC_ENTRY RpcMgmtWaitServerListen(VOID); ??
  130. hr = S_OK;
  131. error:
  132. return(hr);
  133. }
  134. HRESULT
  135. SetTransBlobString(
  136. CERTTRANSBLOB const *pctb,
  137. WCHAR const **ppwsz)
  138. {
  139. HRESULT hr;
  140. if (NULL != pctb->pb && 0 != pctb->cb)
  141. {
  142. *ppwsz = (WCHAR const *) pctb->pb;
  143. // use lstrlen here for protection against non-zero terminated bufs!
  144. // lstrlen will catch AV's and return error
  145. if ((lstrlen(*ppwsz) + 1) * sizeof(WCHAR) != pctb->cb)
  146. {
  147. hr = E_INVALIDARG;
  148. _JumpIfError(hr, error, "Bad TransBlob string");
  149. }
  150. }
  151. hr = S_OK;
  152. error:
  153. return(hr);
  154. }
  155. /* server prototype */
  156. DWORD
  157. s_CertServerRequest(
  158. /* [in] */ handle_t h,
  159. /* [in] */ DWORD dwFlags,
  160. /* [unique][string][in] */ const wchar_t __RPC_FAR *pwszAuthority,
  161. /* [ref][out][in] */ DWORD __RPC_FAR *pdwRequestId,
  162. /* [out] */ DWORD __RPC_FAR *pdwDisposition,
  163. /* [ref][in] */ CERTTRANSBLOB const __RPC_FAR *pctbAttribs,
  164. /* [ref][in] */ CERTTRANSBLOB const __RPC_FAR *pctbRequest,
  165. /* [ref][out] */ CERTTRANSBLOB __RPC_FAR *pctbCertChain,
  166. /* [ref][out] */ CERTTRANSBLOB __RPC_FAR *pctbEncodedCert,
  167. /* [ref][out] */ CERTTRANSBLOB __RPC_FAR *pctbDispositionMessage)
  168. {
  169. HRESULT hr = S_OK;
  170. DWORD OpRequest;
  171. WCHAR const *pwszAttributes = NULL;
  172. WCHAR const *pwszSerialNumber = NULL;
  173. CERTTRANSBLOB ctbEmpty = { 0, NULL };
  174. CERTTRANSBLOB const *pctbSerial = &ctbEmpty;
  175. WCHAR *pwszUserName = NULL;
  176. DWORD dwComContextIndex = MAXDWORD;
  177. CERTSRV_COM_CONTEXT ComContext;
  178. CERTSRV_RESULT_CONTEXT ResultContext;
  179. DWORD State = 0;
  180. ZeroMemory(&ComContext, sizeof(ComContext));
  181. ZeroMemory(&ResultContext, sizeof(ResultContext));
  182. DBGPRINT((
  183. DBG_SS_CERTSRV,
  184. "s_CertServerRequest(tid=%d)\n",
  185. GetCurrentThreadId()));
  186. hr = CertSrvEnterServer(&State);
  187. _JumpIfError(hr, error, "CertSrvEnterServer");
  188. hr = CheckAuthorityName(pwszAuthority);
  189. _JumpIfError(hr, error, "No authority name");
  190. hr = RegisterComContext(&ComContext, &dwComContextIndex);
  191. _JumpIfError(hr, error, "RegisterComContext");
  192. OpRequest = CR_IN_RETRIEVE;
  193. if (NULL != pctbRequest->pb)
  194. {
  195. *pdwRequestId = 0;
  196. OpRequest = CR_IN_NEW;
  197. }
  198. else
  199. {
  200. // RetrievePending by SerialNumber in pctbAttribs
  201. pctbSerial = pctbAttribs;
  202. pctbAttribs = &ctbEmpty;
  203. }
  204. *pdwDisposition = CR_DISP_ERROR;
  205. __try
  206. {
  207. hr = CheckCertSrvAccess(
  208. pwszAuthority,
  209. h,
  210. CA_ACCESS_ENROLL,
  211. &ComContext.fInRequestGroup,
  212. &ComContext.hAccessToken);
  213. _LeaveIfError(hr, "CheckCertSrvAccess");
  214. }
  215. __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  216. {
  217. _PrintError(hr, "Exception");
  218. }
  219. _JumpIfError(hr, error, "CheckCertSrvAccess");
  220. hr = SetTransBlobString(pctbAttribs, &pwszAttributes);
  221. _JumpIfError(hr, error, "SetTransBlobString");
  222. hr = SetTransBlobString(pctbSerial, &pwszSerialNumber);
  223. _JumpIfError(hr, error, "SetTransBlobString");
  224. ResultContext.pdwRequestId = pdwRequestId;
  225. ResultContext.pdwDisposition = pdwDisposition;
  226. ResultContext.pctbDispositionMessage = pctbDispositionMessage;
  227. ResultContext.pctbCert = pctbEncodedCert;
  228. if (CR_IN_FULLRESPONSE & dwFlags)
  229. {
  230. ResultContext.pctbFullResponse = pctbCertChain;
  231. }
  232. else
  233. {
  234. ResultContext.pctbCertChain = pctbCertChain;
  235. }
  236. __try
  237. {
  238. hr = GetClientUserName(
  239. h,
  240. &pwszUserName,
  241. CR_IN_NEW == OpRequest && IsEnterpriseCA(g_CAType)?
  242. &ComContext.pwszUserDN : NULL);
  243. _LeaveIfError(hr, "GetClientUserName");
  244. hr = CoreProcessRequest(
  245. OpRequest | (dwFlags & CR_IN_FORMATMASK),
  246. pwszUserName,
  247. pctbRequest->cb, // cbRequest
  248. pctbRequest->pb, // pbRequest
  249. pwszAttributes,
  250. pwszSerialNumber,
  251. dwComContextIndex,
  252. *pdwRequestId,
  253. &ResultContext); // Allocates returned memory
  254. }
  255. __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  256. {
  257. }
  258. _JumpIfError(hr, error, "CoreProcessRequest");
  259. // Post-processing
  260. pctbDispositionMessage->cb = 0;
  261. if (NULL != pctbDispositionMessage->pb)
  262. {
  263. pctbDispositionMessage->cb =
  264. (wcslen((WCHAR *) pctbDispositionMessage->pb) + 1) * sizeof(WCHAR);
  265. }
  266. error:
  267. ReleaseResult(&ResultContext);
  268. if (NULL != pwszUserName)
  269. {
  270. LocalFree(pwszUserName);
  271. }
  272. if (NULL != ComContext.hAccessToken)
  273. {
  274. HRESULT hr2;
  275. // closehandle can throw
  276. __try
  277. {
  278. CloseHandle(ComContext.hAccessToken);
  279. }
  280. __except(hr2 = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  281. {
  282. _PrintError(hr2, "Exception");
  283. if (S_OK == hr)
  284. {
  285. hr = hr2;
  286. }
  287. }
  288. }
  289. if (MAXDWORD != dwComContextIndex)
  290. {
  291. if (NULL != ComContext.pwszUserDN)
  292. {
  293. LocalFree(ComContext.pwszUserDN);
  294. }
  295. UnregisterComContext(&ComContext, dwComContextIndex);
  296. }
  297. CertSrvExitServer(State);
  298. CSASSERT(S_OK == hr || FAILED(hr));
  299. return(hr);
  300. }
  301. //+--------------------------------------------------------------------------
  302. // MIDL_user_allocate -- Allocates memory for RPC operations.
  303. //
  304. // Parameters:
  305. // cb - # of bytes to allocate
  306. //
  307. // Returns:
  308. // Memory allocated, or NULL if not enough memory.
  309. //---------------------------------------------------------------------------
  310. void __RPC_FAR * __RPC_USER
  311. MIDL_user_allocate(
  312. IN size_t cb)
  313. {
  314. return(CoTaskMemAlloc(cb));
  315. }
  316. //+--------------------------------------------------------------------------
  317. // MIDL_user_free -- Free memory allocated via MIDL_user_allocate.
  318. //
  319. // Parameters:
  320. // pvBuffer - The buffer to free.
  321. //
  322. // Returns:
  323. // None.
  324. //---------------------------------------------------------------------------
  325. void __RPC_USER
  326. MIDL_user_free(
  327. IN void __RPC_FAR *pb)
  328. {
  329. CoTaskMemFree(pb);
  330. }