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.

428 lines
10 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. if ((HRESULT) RPC_S_ALREADY_LISTENING == hr)
  113. {
  114. hr = S_OK;
  115. }
  116. _JumpIfError(hr, error, "RpcServerListen");
  117. error:
  118. if (NULL != pszPrincName)
  119. {
  120. RpcStringFreeA((BYTE **) &pszPrincName);
  121. }
  122. return(hr);
  123. }
  124. HRESULT
  125. RPCTeardown(VOID)
  126. {
  127. HRESULT hr;
  128. // tear down, don't wait for calls to complete
  129. hr = RpcServerUnregisterIf(s_ICertPassage_v0_0_s_ifspec, NULL, FALSE);
  130. _JumpIfError(hr, error, "RpcServerUnregisterIf");
  131. // We have no good way of knowing if all RPC requests are done, so let it
  132. // leak on shutdown.
  133. // RPC_STATUS RPC_ENTRY RpcMgmtWaitServerListen(VOID); ??
  134. hr = S_OK;
  135. error:
  136. return(hr);
  137. }
  138. HRESULT
  139. SetTransBlobString(
  140. CERTTRANSBLOB const *pctb,
  141. WCHAR const **ppwsz)
  142. {
  143. HRESULT hr;
  144. if (NULL != pctb->pb && 0 != pctb->cb)
  145. {
  146. *ppwsz = (WCHAR const *) pctb->pb;
  147. // use lstrlen here for protection against non-zero terminated bufs!
  148. // lstrlen will catch AV's and return error
  149. if ((lstrlen(*ppwsz) + 1) * sizeof(WCHAR) != pctb->cb)
  150. {
  151. hr = E_INVALIDARG;
  152. _JumpIfError(hr, error, "Bad TransBlob string");
  153. }
  154. }
  155. hr = S_OK;
  156. error:
  157. return(hr);
  158. }
  159. /* server prototype */
  160. DWORD
  161. s_CertServerRequest(
  162. /* [in] */ handle_t h,
  163. /* [in] */ DWORD dwFlags,
  164. /* [unique][string][in] */ const wchar_t __RPC_FAR *pwszAuthority,
  165. /* [ref][out][in] */ DWORD __RPC_FAR *pdwRequestId,
  166. /* [out] */ DWORD __RPC_FAR *pdwDisposition,
  167. /* [ref][in] */ CERTTRANSBLOB const __RPC_FAR *pctbAttribs,
  168. /* [ref][in] */ CERTTRANSBLOB const __RPC_FAR *pctbRequest,
  169. /* [ref][out] */ CERTTRANSBLOB __RPC_FAR *pctbCertChain,
  170. /* [ref][out] */ CERTTRANSBLOB __RPC_FAR *pctbEncodedCert,
  171. /* [ref][out] */ CERTTRANSBLOB __RPC_FAR *pctbDispositionMessage)
  172. {
  173. HRESULT hr = S_OK;
  174. DWORD OpRequest;
  175. WCHAR const *pwszAttributes = NULL;
  176. WCHAR const *pwszSerialNumber = NULL;
  177. CERTTRANSBLOB ctbEmpty = { 0, NULL };
  178. CERTTRANSBLOB const *pctbSerial = &ctbEmpty;
  179. WCHAR *pwszUserName = NULL;
  180. DWORD dwComContextIndex = MAXDWORD;
  181. CERTSRV_COM_CONTEXT ComContext;
  182. CERTSRV_RESULT_CONTEXT ResultContext;
  183. DWORD State = 0;
  184. ZeroMemory(&ComContext, sizeof(ComContext));
  185. ZeroMemory(&ResultContext, sizeof(ResultContext));
  186. DBGPRINT((
  187. DBG_SS_CERTSRV,
  188. "s_CertServerRequest(tid=%d)\n",
  189. GetCurrentThreadId()));
  190. hr = CertSrvEnterServer(&State);
  191. _JumpIfError(hr, error, "CertSrvEnterServer");
  192. hr = CheckAuthorityName(pwszAuthority);
  193. _JumpIfError(hr, error, "No authority name");
  194. hr = RegisterComContext(&ComContext, &dwComContextIndex);
  195. _JumpIfError(hr, error, "RegisterComContext");
  196. OpRequest = CR_IN_RETRIEVE;
  197. if (NULL != pctbRequest->pb)
  198. {
  199. *pdwRequestId = 0;
  200. OpRequest = CR_IN_NEW;
  201. }
  202. else
  203. {
  204. // RetrievePending by SerialNumber in pctbAttribs
  205. pctbSerial = pctbAttribs;
  206. pctbAttribs = &ctbEmpty;
  207. }
  208. *pdwDisposition = CR_DISP_ERROR;
  209. __try
  210. {
  211. BOOL fInRequestGroup;
  212. hr = CheckCertSrvAccess(
  213. pwszAuthority,
  214. h,
  215. CA_ACCESS_ENROLL,
  216. &fInRequestGroup,
  217. &ComContext.hAccessToken);
  218. _LeaveIfError(hr, "CheckCertSrvAccess");
  219. ComContext.dwFlags |= CCCF_INREQUESTGROUPSET;
  220. if (fInRequestGroup)
  221. {
  222. ComContext.dwFlags |= CCCF_INREQUESTGROUP;
  223. }
  224. }
  225. __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  226. {
  227. _PrintError(hr, "Exception");
  228. }
  229. _JumpIfError(hr, error, "CheckCertSrvAccess");
  230. hr = SetTransBlobString(pctbAttribs, &pwszAttributes);
  231. _JumpIfError(hr, error, "SetTransBlobString");
  232. hr = SetTransBlobString(pctbSerial, &pwszSerialNumber);
  233. _JumpIfError(hr, error, "SetTransBlobString");
  234. ResultContext.pdwRequestId = pdwRequestId;
  235. ResultContext.pdwDisposition = pdwDisposition;
  236. ResultContext.pctbDispositionMessage = pctbDispositionMessage;
  237. ResultContext.pctbCert = pctbEncodedCert;
  238. if (CR_IN_FULLRESPONSE & dwFlags)
  239. {
  240. ResultContext.pctbFullResponse = pctbCertChain;
  241. }
  242. else
  243. {
  244. ResultContext.pctbCertChain = pctbCertChain;
  245. }
  246. __try
  247. {
  248. hr = GetClientUserName(
  249. h,
  250. &pwszUserName,
  251. CR_IN_NEW == OpRequest && IsEnterpriseCA(g_CAType)?
  252. &ComContext.pwszUserDN : NULL);
  253. _LeaveIfError(hr, "GetClientUserName");
  254. hr = CoreProcessRequest(
  255. OpRequest | (dwFlags & CR_IN_FORMATMASK),
  256. pwszUserName,
  257. pctbRequest->cb, // cbRequest
  258. pctbRequest->pb, // pbRequest
  259. pwszAttributes,
  260. pwszSerialNumber,
  261. dwComContextIndex,
  262. *pdwRequestId,
  263. &ResultContext); // Allocates returned memory
  264. }
  265. __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  266. {
  267. }
  268. _JumpIfError(hr, error, "CoreProcessRequest");
  269. // Post-processing
  270. pctbDispositionMessage->cb = 0;
  271. if (NULL != pctbDispositionMessage->pb)
  272. {
  273. pctbDispositionMessage->cb =
  274. (wcslen((WCHAR *) pctbDispositionMessage->pb) + 1) * sizeof(WCHAR);
  275. }
  276. error:
  277. ReleaseResult(&ResultContext);
  278. if (NULL != pwszUserName)
  279. {
  280. LocalFree(pwszUserName);
  281. }
  282. if (NULL != ComContext.hAccessToken)
  283. {
  284. HRESULT hr2 = S_OK;
  285. // closehandle can throw
  286. __try
  287. {
  288. CloseHandle(ComContext.hAccessToken);
  289. }
  290. __except(hr2 = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  291. {
  292. _PrintError(hr2, "Exception");
  293. if (S_OK == hr)
  294. {
  295. hr = hr2;
  296. }
  297. }
  298. }
  299. ReleaseComContext(&ComContext);
  300. if (MAXDWORD != dwComContextIndex)
  301. {
  302. UnregisterComContext(&ComContext, dwComContextIndex);
  303. }
  304. CertSrvExitServer(
  305. State,
  306. (S_OK == hr &&
  307. NULL != pdwDisposition &&
  308. FAILED(*pdwDisposition))?
  309. *pdwDisposition : hr);
  310. CSASSERT(S_OK == hr || FAILED(hr));
  311. CSASSERT(S_OK == hr || FAILED(hr));
  312. return(hr);
  313. }
  314. //+--------------------------------------------------------------------------
  315. // MIDL_user_allocate -- Allocates memory for RPC operations.
  316. //
  317. // Parameters:
  318. // cb - # of bytes to allocate
  319. //
  320. // Returns:
  321. // Memory allocated, or NULL if not enough memory.
  322. //---------------------------------------------------------------------------
  323. void __RPC_FAR * __RPC_USER
  324. MIDL_user_allocate(
  325. IN size_t cb)
  326. {
  327. void *pv;
  328. if (cb > g_cbMaxIncomingAllocSize)
  329. {
  330. _PrintError(MEM_E_INVALID_SIZE, "g_cbMaxIncomingAllocSize");
  331. SetLastError((DWORD) MEM_E_INVALID_SIZE);
  332. pv = NULL;
  333. }
  334. else
  335. {
  336. pv = CoTaskMemAlloc(cb);
  337. }
  338. return(pv);
  339. }
  340. //+--------------------------------------------------------------------------
  341. // MIDL_user_free -- Free memory allocated via MIDL_user_allocate.
  342. //
  343. // Parameters:
  344. // pvBuffer - The buffer to free.
  345. //
  346. // Returns:
  347. // None.
  348. //---------------------------------------------------------------------------
  349. void __RPC_USER
  350. MIDL_user_free(
  351. IN void __RPC_FAR *pb)
  352. {
  353. CoTaskMemFree(pb);
  354. }