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.

982 lines
21 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996-1996
  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 <ese.h>
  16. #include <lmaccess.h>
  17. #include <lmapibuf.h>
  18. #include <lmerr.h>
  19. #include <stdio.h>
  20. #include "certrpc.h"
  21. #include "certcli.h"
  22. #include "certlib.h"
  23. #include "cs.h"
  24. #include "csext.h"
  25. #include "csprop.h"
  26. #include "ese.h"
  27. #include "dbtable.h"
  28. CRITICAL_SECTION g_RPCCriticalSection;
  29. CERT_CONTEXT const *pPrevCertContext = NULL;
  30. RPC_BINDING_VECTOR *pvBindings = NULL;
  31. #define USE_NP 1
  32. #ifdef USE_NP
  33. char *pszProtSeq = "ncacn_np";
  34. #else
  35. char *pszProtSeq = "ncacn_ip_tcp";
  36. #endif
  37. SERVICE_STATUS g_ssStatus;
  38. SERVICE_STATUS_HANDLE g_sshStatusHandle;
  39. HANDLE g_hServiceDoneEvent = NULL;
  40. VOID ServiceControlHandler(DWORD dwCtrlCode);
  41. BOOL
  42. ReportStatusToSCMgr(
  43. DWORD dwCurrentState,
  44. DWORD dwWin32ExitCode,
  45. DWORD dwCheckPoint,
  46. DWORD dwWaitHint);
  47. typedef struct _ATTRIBVALUETABLE
  48. {
  49. WCHAR *pwAttrib;
  50. DWORD cbAttrib;
  51. WCHAR *pwValue;
  52. DWORD cbValue;
  53. } ATTRIBVALUETABLE;
  54. DWORD
  55. RPCInit(VOID)
  56. {
  57. #ifdef USE_NP
  58. char * pszEndpoint = "\\pipe\\cert";
  59. #endif
  60. SECURITY_DESCRIPTOR *psd;
  61. DWORD err;
  62. if ((psd = (SECURITY_DESCRIPTOR *) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT,
  63. SECURITY_DESCRIPTOR_MIN_LENGTH)) == 0)
  64. {
  65. DBGERRORPRINTLINE("LocalAlloc", ERROR_NOT_ENOUGH_MEMORY);
  66. goto fail;
  67. }
  68. #ifdef USE_NP
  69. err = RpcServerUseProtseqEpA(
  70. (unsigned char *) pszProtSeq,
  71. RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
  72. (unsigned char *) pszEndpoint,
  73. NULL);
  74. #else
  75. err = RpcServerUseProtseqA(
  76. (unsigned char *) pszProtSeq,
  77. RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
  78. NULL);
  79. #endif
  80. if (err != RPC_S_OK)
  81. {
  82. DBGERRORPRINTLINE("RpcServerUseProtseqA", err);
  83. goto fail;
  84. }
  85. err = RpcServerInqBindings(&pvBindings);
  86. if (err != RPC_S_OK)
  87. {
  88. DBGERRORPRINTLINE("RpcServerInqBindings", err);
  89. goto fail;
  90. }
  91. err = RpcServerRegisterIf(s_ICertPassage_v0_0_s_ifspec, NULL, NULL);
  92. if (err != RPC_S_OK)
  93. {
  94. DBGERRORPRINTLINE("RpcServerRegisterIf", err);
  95. goto fail;
  96. }
  97. err = RpcEpRegister(s_ICertPassage_v0_0_s_ifspec, pvBindings, NULL, NULL);
  98. if (err != RPC_S_OK)
  99. {
  100. DBGERRORPRINTLINE("RpcEpRegister", err);
  101. goto fail;
  102. }
  103. // Listen, but don't wait...
  104. err = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE);
  105. if (err != RPC_S_OK)
  106. {
  107. DBGERRORPRINTLINE("RpcServerListen", err);
  108. goto fail;
  109. }
  110. fail:
  111. return(err);
  112. }
  113. DWORD
  114. IsRpcClientAllowed(
  115. handle_t h,
  116. WCHAR *pwszUserName,
  117. DWORD cbUserName,
  118. BOOL *pbAllowed)
  119. {
  120. DWORD entriesread;
  121. DWORD totalentries;
  122. DWORD resumehandle = 0;
  123. LOCALGROUP_MEMBERS_INFO_1 *plgmi = NULL;
  124. LOCALGROUP_MEMBERS_INFO_1 *plgmiT;
  125. DWORD cnt;
  126. DWORD Totalcnt;
  127. DWORD err;
  128. *pbAllowed = FALSE;
  129. do
  130. {
  131. err = RpcImpersonateClient((RPC_BINDING_HANDLE) h);
  132. if (RPC_S_OK != err)
  133. {
  134. continue; // error exit
  135. }
  136. if (!GetUserName(pwszUserName, &cbUserName))
  137. {
  138. err = GetLastError();
  139. }
  140. RpcRevertToSelf();
  141. if (ERROR_SUCCESS != err)
  142. {
  143. continue; // error exit
  144. }
  145. Totalcnt = 0;
  146. do
  147. {
  148. err = NetLocalGroupGetMembers(
  149. NULL,
  150. g_wszRequestGroupName,
  151. 1,
  152. (LPBYTE *) &plgmi,
  153. 0xffff,
  154. &entriesread,
  155. &totalentries,
  156. &resumehandle);
  157. if (NERR_Success != err)
  158. {
  159. break;
  160. }
  161. plgmiT = plgmi;
  162. for (cnt = 0; cnt < entriesread; cnt++)
  163. {
  164. if (lstrcmpi(plgmiT->lgrmi1_name, pwszUserName) == 0)
  165. {
  166. CONSOLEPRINT2((
  167. DBG_SS_CERTSRV,
  168. "Found user %ws in group %ws\n",
  169. pwszUserName,
  170. g_wszRequestGroupName));
  171. *pbAllowed = TRUE;
  172. break;
  173. }
  174. Totalcnt++;
  175. plgmiT++;
  176. }
  177. NetApiBufferFree(plgmi);
  178. } while (!*pbAllowed && Totalcnt < totalentries);
  179. } while (FALSE);
  180. return(err);
  181. }
  182. BOOL
  183. IsValidAttributeChar(TCHAR chChar)
  184. {
  185. BOOL fRetVal=TRUE;
  186. switch(chChar)
  187. {
  188. case TEXT('\r'):
  189. case TEXT('\n'):
  190. case TEXT(' '):
  191. case TEXT('-'):
  192. fRetVal = FALSE;
  193. break;
  194. }
  195. return fRetVal;
  196. }
  197. DWORD
  198. ParseAttributes(
  199. IN ICertDBRow *prow,
  200. IN WCHAR const *pwszAttributes)
  201. {
  202. HRESULT hr = S_OK;
  203. WCHAR *pwb = NULL;
  204. WCHAR *pwbEnd;
  205. WCHAR *pwAttrib = NULL;
  206. WCHAR *pwValue = NULL;
  207. WCHAR *pwszTemp = NULL;
  208. WCHAR const *pwszPropName;
  209. WCHAR *pwbtmp;
  210. WCHAR *pwbtmp2;
  211. WCHAR *pwbtmp3;
  212. WCHAR *pwbtmp4;
  213. DWORD cwc;
  214. DWORD i;
  215. DWORD cwcAttributes;
  216. DWORD cbProp;
  217. if (NULL == pwszAttributes)
  218. {
  219. goto error; // silently ignore empty string
  220. }
  221. cwcAttributes = wcslen(pwszAttributes);
  222. // Allocate and copy bytes to null terminate
  223. pwb = (WCHAR *) LocalAlloc(LMEM_FIXED, (cwcAttributes + 1) * sizeof(WCHAR));
  224. if (NULL == pwb)
  225. {
  226. hr = E_OUTOFMEMORY;
  227. _JumpError(hr, error, "LocalAlloc");
  228. }
  229. wcscpy(pwb, pwszAttributes);
  230. pwbEnd = &pwb[cwcAttributes];
  231. pwbtmp = pwb;
  232. while(TRUE)
  233. {
  234. pwbtmp2 = pwbtmp;
  235. pwbtmp = wcschr(pwbtmp, TEXT(':'));
  236. if (NULL == pwbtmp)
  237. {
  238. break;
  239. }
  240. // If there's a newline before the next colon, start over.
  241. pwbtmp3 = wcschr(pwbtmp2, TEXT('\n'));
  242. if (NULL != pwbtmp3 && pwbtmp3 < pwbtmp)
  243. {
  244. pwbtmp = pwbtmp3 + 1;
  245. continue;
  246. }
  247. // Find beginning of Attrib string
  248. while(iswspace(*pwbtmp2))
  249. {
  250. pwbtmp2++;
  251. }
  252. // Count size of Attrib string
  253. cwc = pwbtmp - pwbtmp2;
  254. pwbtmp3 = pwbtmp;
  255. // move before :
  256. pwbtmp3--;
  257. while (iswspace(*pwbtmp3) && pwbtmp3 > pwbtmp2)
  258. {
  259. cwc--;
  260. pwbtmp3--;
  261. }
  262. pwAttrib = (WCHAR *) LocalAlloc(LMEM_FIXED, (cwc + 1) * sizeof(WCHAR));
  263. if (NULL == pwAttrib)
  264. {
  265. hr = E_OUTOFMEMORY;
  266. _JumpError(hr, error, "LocalAlloc");
  267. }
  268. pwbtmp3 = pwAttrib;
  269. for (i = 0; i < cwc; i++, pwbtmp2++)
  270. {
  271. if (IsValidAttributeChar(*pwbtmp2))
  272. {
  273. *pwbtmp3++ = *pwbtmp2;
  274. }
  275. }
  276. *pwbtmp3 = L'\0';
  277. // Skip over the colon
  278. pwbtmp2 = pwbtmp + 1;
  279. // Find beginning of Value string
  280. while(L'\n' != *pwbtmp2 && iswspace(*pwbtmp2))
  281. {
  282. pwbtmp2++;
  283. }
  284. pwbtmp3 = pwbtmp2;
  285. // find end of Value string
  286. pwbtmp4 = wcschr(pwbtmp3, TEXT('\n'));
  287. if (NULL == pwbtmp4)
  288. {
  289. // Check for case when last Value isn't newline terminated
  290. if (pwbtmp3 >= pwbEnd)
  291. {
  292. break;
  293. }
  294. pwbtmp4 = pwbEnd;
  295. }
  296. cwc = pwbtmp4 - pwbtmp3;
  297. pwbtmp3 = pwbtmp4;
  298. // move before '\n' or '\0'
  299. pwbtmp3--;
  300. while (iswspace(*pwbtmp3) && pwbtmp3 > pwbtmp2)
  301. {
  302. cwc--;
  303. pwbtmp3--;
  304. }
  305. pwValue = (WCHAR *) LocalAlloc(LMEM_FIXED, (cwc + 1) * sizeof(WCHAR));
  306. if (NULL == pwValue)
  307. {
  308. hr = E_OUTOFMEMORY;
  309. _JumpError(hr, error, "LocalAlloc");
  310. }
  311. memcpy(pwValue, pwbtmp2, cwc * sizeof(WCHAR));
  312. pwValue[cwc] = L'\0';
  313. // if the attribute name and value are both non-empty ...
  314. if (L'\0' != *pwValue && L'\0' != *pwAttrib)
  315. {
  316. DWORD dwTable = PROPTABLE_REQUEST;
  317. // See if the attribute name can be mapped to a standard property.
  318. pwszPropName = DBMapAttributeName(pwAttrib);
  319. if (NULL == pwszPropName || NULL == g_pwszNameSeparator)
  320. {
  321. if (NULL == pwszPropName)
  322. {
  323. dwTable = PROPTABLE_ATTRIBUTES;
  324. }
  325. pwszPropName = pwAttrib;
  326. }
  327. else
  328. {
  329. cbProp = 0;
  330. hr = prow->GetProperty(
  331. pwszPropName,
  332. PROPTYPE_STRING |
  333. PROPCALLER_SERVER |
  334. PROPTABLE_REQUEST,
  335. &cbProp,
  336. NULL);
  337. if (CERTSRV_E_PROPERTY_EMPTY != hr)
  338. {
  339. _JumpIfError(hr, error, "GetProperty");
  340. pwszTemp = (WCHAR *) LocalAlloc(
  341. LMEM_FIXED,
  342. (cbProp + 2 + wcslen(pwValue)) *
  343. sizeof(WCHAR));
  344. if (NULL == pwszTemp)
  345. {
  346. hr = E_OUTOFMEMORY;
  347. _JumpError(hr, error, "LocalAlloc");
  348. }
  349. hr = prow->GetProperty(
  350. pwszPropName,
  351. PROPTYPE_STRING |
  352. PROPCALLER_SERVER |
  353. PROPTABLE_REQUEST,
  354. &cbProp,
  355. (BYTE *) pwszTemp);
  356. _JumpIfError(hr, error, "GetProperty");
  357. wcscat(pwszTemp, g_pwszNameSeparator);
  358. wcscat(pwszTemp, L" ");
  359. wcscat(pwszTemp, pwValue);
  360. LocalFree(pwValue);
  361. pwValue = pwszTemp;
  362. pwszTemp = NULL;
  363. }
  364. }
  365. hr = prow->SetProperty(
  366. pwszPropName,
  367. dwTable | PROPTYPE_STRING | PROPCALLER_SERVER,
  368. MAXDWORD,
  369. (BYTE const *) pwValue);
  370. _JumpIfError(hr, error, "SetProperty");
  371. if (NULL != pwszTemp)
  372. {
  373. LocalFree(pwszTemp);
  374. pwszTemp = NULL;
  375. }
  376. }
  377. LocalFree(pwValue);
  378. pwValue = NULL;
  379. LocalFree(pwAttrib);
  380. pwAttrib = NULL;
  381. if (pwbtmp4 >= pwbEnd)
  382. {
  383. break;
  384. }
  385. pwbtmp = pwbtmp4 + 1;
  386. }
  387. error:
  388. if (NULL != pwAttrib)
  389. {
  390. LocalFree(pwAttrib);
  391. }
  392. if (NULL != pwValue)
  393. {
  394. LocalFree(pwValue);
  395. }
  396. if (NULL != pwb)
  397. {
  398. LocalFree(pwb);
  399. }
  400. if (NULL != pwszTemp)
  401. {
  402. LocalFree(pwszTemp);
  403. }
  404. return(hr);
  405. }
  406. /* server prototype */
  407. DWORD
  408. s_CertServerRequest(
  409. /* [in] */ handle_t h,
  410. /* [in] */ DWORD dwFlags,
  411. /* [unique][string][in] */ const wchar_t __RPC_FAR *pwszAuthority,
  412. /* [ref][out][in] */ DWORD __RPC_FAR *pdwRequestId,
  413. /* [out] */ DWORD __RPC_FAR *pdwDisposition,
  414. /* [unique][string][in] */ const wchar_t __RPC_FAR *pwszAttributes,
  415. /* [ref][in] */ CERTTRANSBLOB const __RPC_FAR *pctbRequest,
  416. /* [ref][out] */ CERTTRANSBLOB __RPC_FAR *pctbCertChain,
  417. /* [ref][out] */ CERTTRANSBLOB __RPC_FAR *pctbEncodedCert,
  418. /* [ref][out] */ CERTTRANSBLOB __RPC_FAR *pctbDispositionMessage)
  419. {
  420. HRESULT hr = S_OK;
  421. BOOL bAllowed = TRUE;
  422. WCHAR UserName[MAX_PATH];
  423. DWORD OpRequest;
  424. EnterCriticalSection(&g_RPCCriticalSection);
  425. // Set up default output parameters:
  426. OpRequest = CR_IN_RETRIEVE;
  427. if (NULL != pctbRequest->pb)
  428. {
  429. *pdwRequestId = 0;
  430. OpRequest = CR_IN_NEW;
  431. }
  432. *pdwDisposition = CR_DISP_ERROR;
  433. if (0 != lstrcmpi(pwszAuthority, g_wszAuthority))
  434. {
  435. hr = E_INVALIDARG;
  436. _JumpError(hr, error, "Bad Authority name");
  437. }
  438. //BUGBUG: do something with the error: pass it in the policy module flags?
  439. hr = IsRpcClientAllowed(h, UserName, sizeof(UserName), &bAllowed);
  440. hr = CoreProcessRequest(
  441. OpRequest | (dwFlags & CR_IN_FORMATMASK),
  442. UserName,
  443. pctbRequest->cb, // cbRequest
  444. pctbRequest->pb, // pbRequest
  445. pwszAttributes,
  446. (WCHAR **) &pctbDispositionMessage->pb,
  447. pdwRequestId,
  448. pdwDisposition,
  449. &pctbCertChain->pb, // Allocates returned memory
  450. &pctbCertChain->cb,
  451. &pctbEncodedCert->pb,// Allocates returned memory
  452. &pctbEncodedCert->cb);
  453. _JumpIfError(hr, error, "CoreProcessRequest");
  454. error:
  455. pctbDispositionMessage->cb = 0;
  456. if (NULL != pctbDispositionMessage->pb)
  457. {
  458. pctbDispositionMessage->cb =
  459. (wcslen((WCHAR *) pctbDispositionMessage->pb) + 1) * sizeof(WCHAR);
  460. }
  461. LeaveCriticalSection(&g_RPCCriticalSection);
  462. PKCSCRLTimerProc(NULL, 0, 0, 0);
  463. return(hr);
  464. }
  465. typedef struct _CRLELEMENT
  466. {
  467. LIST_ENTRY Next;
  468. CRYPT_INTEGER_BLOB SerialNumber;
  469. FILETIME RevocationDate;
  470. } CRLELEMENT;
  471. VOID
  472. FreeCRLArray(
  473. IN DWORD cCRL,
  474. IN OUT CRL_ENTRY *aCRL)
  475. {
  476. if (NULL != aCRL)
  477. {
  478. CRL_ENTRY *pCRL = &aCRL[cCRL];
  479. while (--pCRL >= aCRL)
  480. {
  481. if (NULL != pCRL->SerialNumber.pbData)
  482. {
  483. LocalFree(pCRL->SerialNumber.pbData);
  484. }
  485. }
  486. LocalFree(aCRL);
  487. }
  488. }
  489. // Convert linked list of CRL_ENTRYs to an array.
  490. // If the output array pointer is NULL, just free the list.
  491. HRESULT
  492. ConvertOrFreeCRLList(
  493. IN OUT LIST_ENTRY *pleCRL,
  494. IN DWORD cCRL,
  495. OPTIONAL OUT CRL_ENTRY **paCRL)
  496. {
  497. HRESULT hr;
  498. CRL_ENTRY *aCRL = NULL;
  499. CRL_ENTRY *pCRL;
  500. CRL_ENTRY *pCRLT;
  501. DWORD i;
  502. LIST_ENTRY *pleNext;
  503. CRLELEMENT *pElement;
  504. if (NULL != paCRL)
  505. {
  506. aCRL = (CRL_ENTRY *) LocalAlloc(LMEM_ZEROINIT, sizeof(aCRL[0]) * cCRL);
  507. if (NULL == aCRL)
  508. {
  509. hr = E_OUTOFMEMORY;
  510. _JumpError(hr, error, "LocalAlloc");
  511. }
  512. }
  513. pCRL = aCRL;
  514. pleNext = pleCRL->Flink;
  515. for (i = 0; pleNext != pleCRL; i++)
  516. {
  517. pElement = CONTAINING_RECORD(pleNext, CRLELEMENT, Next);
  518. pleNext = pleNext->Flink;
  519. if (NULL != pElement)
  520. {
  521. if (NULL != pCRL)
  522. {
  523. pCRL->SerialNumber.pbData = pElement->SerialNumber.pbData;
  524. pCRL->SerialNumber.cbData = pElement->SerialNumber.cbData;
  525. pCRL->RevocationDate = pElement->RevocationDate;
  526. pCRL++;
  527. }
  528. else
  529. {
  530. if (NULL != pElement->SerialNumber.pbData)
  531. {
  532. LocalFree(pElement->SerialNumber.pbData);
  533. }
  534. }
  535. RemoveEntryList(&pElement->Next);
  536. LocalFree(pElement);
  537. }
  538. }
  539. CSASSERT(i == cCRL);
  540. if (NULL != paCRL)
  541. {
  542. *paCRL = aCRL;
  543. aCRL = NULL;
  544. }
  545. hr = S_OK;
  546. error:
  547. if (NULL != aCRL)
  548. {
  549. FreeCRLArray(cCRL, aCRL);
  550. }
  551. return(hr);
  552. }
  553. HRESULT
  554. AddCRLElement(
  555. IN OUT LIST_ENTRY *pleCRL,
  556. WCHAR const *pwszSerialNumber,
  557. FILETIME const *pftRevokedEffectiveWhen)
  558. {
  559. HRESULT hr = S_OK;
  560. CRLELEMENT *pElement = NULL;
  561. pElement = (CRLELEMENT *) LocalAlloc(LMEM_ZEROINIT, sizeof(CRLELEMENT));
  562. if (NULL == pElement)
  563. {
  564. hr = ERROR_NOT_ENOUGH_MEMORY;
  565. goto error;
  566. }
  567. hr = myWszToMultiByteInteger(
  568. pwszSerialNumber,
  569. &pElement->SerialNumber.cbData,
  570. &pElement->SerialNumber.pbData);
  571. _JumpIfError(hr, error, "myWszToMultiByteInteger");
  572. pElement->RevocationDate = *pftRevokedEffectiveWhen;
  573. InsertTailList(pleCRL, &pElement->Next);
  574. pElement = NULL;
  575. error:
  576. if (NULL != pElement)
  577. {
  578. LocalFree(pElement);
  579. }
  580. return(hr);
  581. }
  582. DWORD g_aColCRL[] = {
  583. #define ICOL_REQUESTID 0
  584. DTI_CERTIFICATETABLE | DTC_REQUESTID,
  585. #define ICOL_EFFECTIVEWHEN 1
  586. DTI_REQUESTTABLE | DTR_REQUESTREVOKEDEFFECTIVEWHEN,
  587. #define ICOL_SERIAL 2
  588. DTI_CERTIFICATETABLE | DTC_CERTIFICATESERIALNUMBER,
  589. #define ICOL_NOTAFTER 3
  590. DTI_CERTIFICATETABLE | DTC_CERTIFICATENOTAFTERDATE,
  591. };
  592. #define CCOL_CRLVIEW (sizeof(g_aColCRL)/sizeof(g_aColCRL[0]))
  593. HRESULT
  594. BuildCRLList(
  595. OUT LIST_ENTRY *pleCRL,
  596. IN DWORD *pcCRL,
  597. IN FILETIME ThisUpdate)
  598. {
  599. HRESULT hr;
  600. CERTVIEWRESTRICTION cvr;
  601. IEnumCERTDBRESULTROW *pView = NULL;
  602. DWORD celtFetched;
  603. DWORD Disposition;
  604. DWORD i;
  605. BOOL fCoInitialized = FALSE;
  606. DWORD cCRL = 0;
  607. CERTDBRESULTROW Result;
  608. BOOL fResultActive = FALSE;
  609. Disposition = CR_DISP_REVOKED;
  610. cvr.ColumnIndex = DTI_REQUESTTABLE | DTR_REQUESTDISPOSITION;
  611. cvr.dwSeek = CVR_SEEK_EQ;
  612. cvr.pbValue = (BYTE *) &Disposition;
  613. cvr.cbValue = sizeof(Disposition);
  614. hr = CoInitialize(NULL);
  615. if (S_OK != hr && S_FALSE != hr)
  616. {
  617. _JumpError(hr, error, "CoInitialize");
  618. }
  619. fCoInitialized = TRUE;
  620. hr = g_pCertDB->OpenView(
  621. 1,
  622. &cvr,
  623. CCOL_CRLVIEW,
  624. g_aColCRL,
  625. &pView);
  626. _JumpIfError(hr, error, "OpenView");
  627. while (TRUE)
  628. {
  629. hr = pView->Next(1, &Result, &celtFetched);
  630. if (S_FALSE == hr)
  631. {
  632. break;
  633. }
  634. _JumpIfError(hr, error, "Next");
  635. fResultActive = TRUE;
  636. CSASSERT(1 == celtFetched);
  637. CSASSERT(CCOL_CRLVIEW == Result.ccol);
  638. CSASSERT(PROPTYPE_LONG == Result.acol[ICOL_REQUESTID].Type);
  639. CSASSERT(PROPTYPE_DATE == Result.acol[ICOL_EFFECTIVEWHEN].Type);
  640. CSASSERT(PROPTYPE_STRING == Result.acol[ICOL_SERIAL].Type);
  641. CSASSERT(PROPTYPE_DATE == Result.acol[ICOL_NOTAFTER].Type);
  642. CSASSERT(NULL != Result.acol[ICOL_REQUESTID].pbValue);
  643. CSASSERT(NULL != Result.acol[ICOL_SERIAL].pbValue);
  644. CSASSERT(NULL != Result.acol[ICOL_NOTAFTER].pbValue);
  645. CSASSERT(sizeof(DWORD) == Result.acol[ICOL_REQUESTID].cbValue);
  646. CSASSERT(
  647. sizeof(FILETIME) == Result.acol[ICOL_EFFECTIVEWHEN].cbValue ||
  648. NULL == Result.acol[ICOL_EFFECTIVEWHEN].pbValue);
  649. CSASSERT(0 < Result.acol[ICOL_SERIAL].cbValue);
  650. CSASSERT(sizeof(FILETIME) == Result.acol[ICOL_NOTAFTER].cbValue);
  651. if (NULL != Result.acol[ICOL_NOTAFTER].pbValue &&
  652. NULL != Result.acol[ICOL_EFFECTIVEWHEN].pbValue &&
  653. NULL != Result.acol[ICOL_SERIAL].pbValue &&
  654. CompareFileTime(
  655. (FILETIME *) Result.acol[ICOL_NOTAFTER].pbValue,
  656. &ThisUpdate) > 0 &&
  657. CompareFileTime(
  658. (FILETIME *) Result.acol[ICOL_EFFECTIVEWHEN].pbValue,
  659. &ThisUpdate) < 0)
  660. {
  661. hr = AddCRLElement(
  662. pleCRL,
  663. (WCHAR const *) Result.acol[ICOL_SERIAL].pbValue,
  664. (FILETIME const *) Result.acol[ICOL_EFFECTIVEWHEN].pbValue);
  665. _JumpIfError(hr, error, "AddCRLElement");
  666. CONSOLEPRINT1((
  667. DBG_SS_CERTSRV,
  668. "Cert is revoked: %ws\n",
  669. Result.acol[ICOL_SERIAL].pbValue));
  670. cCRL++;
  671. }
  672. pView->ReleaseResultRow(1, &Result);
  673. fResultActive = FALSE;
  674. }
  675. *pcCRL = cCRL;
  676. hr = S_OK;
  677. error:
  678. if (NULL != pView)
  679. {
  680. if (fResultActive)
  681. {
  682. pView->ReleaseResultRow(1, &Result);
  683. }
  684. pView->Release();
  685. }
  686. if (fCoInitialized)
  687. {
  688. CoUninitialize();
  689. }
  690. return(hr);
  691. }
  692. HRESULT
  693. BuildCRLArray(
  694. IN FILETIME ThisUpdate,
  695. OUT DWORD *pcCRL,
  696. OUT CRL_ENTRY **paCRL)
  697. {
  698. HRESULT hr;
  699. LIST_ENTRY leCRL;
  700. *pcCRL = 0;
  701. *paCRL = NULL;
  702. InitializeListHead(&leCRL);
  703. hr = BuildCRLList(&leCRL, pcCRL, ThisUpdate);
  704. _JumpIfError(hr, error, "BuildCRLList");
  705. hr = ConvertOrFreeCRLList(&leCRL, *pcCRL, paCRL);
  706. _JumpIfError(hr, error, "ConvertOrFreeCRLList");
  707. error:
  708. ConvertOrFreeCRLList(&leCRL, 0, NULL);
  709. return(hr);
  710. }
  711. void __RPC_FAR *
  712. __RPC_USER MIDL_user_allocate(size_t cb)
  713. {
  714. return(LocalAlloc(LMEM_ZEROINIT, cb));
  715. }
  716. void __RPC_USER
  717. MIDL_user_free( void __RPC_FAR * pb)
  718. {
  719. LocalFree(pb);
  720. }
  721. VOID
  722. ServiceMain(
  723. IN DWORD dwArgc,
  724. IN LPWSTR *lpszArgv)
  725. {
  726. HRESULT hr = S_OK;
  727. g_sshStatusHandle = RegisterServiceCtrlHandler(
  728. g_wszCertSrvServiceName,
  729. ServiceControlHandler);
  730. if (NULL == g_sshStatusHandle)
  731. {
  732. hr = GetLastError();
  733. _JumpError(hr, error, "RegisterServiceCtrlHandler");
  734. }
  735. g_ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
  736. g_ssStatus.dwServiceSpecificExitCode = 0;
  737. ReportStatusToSCMgr(SERVICE_START_PENDING, hr, 1, 3000);
  738. g_hServiceDoneEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  739. if (NULL == g_hServiceDoneEvent)
  740. {
  741. hr = GetLastError();
  742. _JumpError(hr, error, "CreateEvent");
  743. }
  744. if (0 != g_dwDelay2)
  745. {
  746. DBGPRINT((
  747. DBG_SS_CERTSRV,
  748. "ServiceMain: sleeping %u seconds\n",
  749. g_dwDelay2));
  750. Sleep(1000 * g_dwDelay2);
  751. }
  752. hr = certsrvStartServerThread((VOID *) 0);
  753. _JumpIfError(hr, error, "certsrvStartServer");
  754. ReportStatusToSCMgr(SERVICE_RUNNING, hr, 0, 0);
  755. WaitForSingleObject(g_hServiceDoneEvent, INFINITE);
  756. DBGPRINT((DBG_SS_CERTSRV, "ServiceMain: Service Done\n"));
  757. error:
  758. ReportStatusToSCMgr(SERVICE_STOPPED, hr, 0, 0);
  759. if (NULL != g_hServiceDoneEvent)
  760. {
  761. CloseHandle(g_hServiceDoneEvent);
  762. }
  763. DBGPRINT((DBG_SS_CERTSRV, "ServiceMain: Exit: %x\n", hr));
  764. }
  765. VOID
  766. ServiceControlHandler(
  767. IN DWORD dwCtrlCode)
  768. {
  769. DWORD dwState = SERVICE_RUNNING;
  770. switch (dwCtrlCode)
  771. {
  772. case SERVICE_CONTROL_PAUSE:
  773. if (SERVICE_RUNNING == g_ssStatus.dwCurrentState)
  774. {
  775. dwState = SERVICE_PAUSED;
  776. }
  777. break;
  778. case SERVICE_CONTROL_CONTINUE:
  779. if (SERVICE_PAUSED == g_ssStatus.dwCurrentState)
  780. {
  781. dwState = SERVICE_RUNNING;
  782. }
  783. break;
  784. case SERVICE_CONTROL_STOP:
  785. ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 1, 3000);
  786. certsrvStopServer(FALSE);
  787. SetEvent(g_hServiceDoneEvent);
  788. return;
  789. case SERVICE_CONTROL_INTERROGATE:
  790. break;
  791. }
  792. ReportStatusToSCMgr(dwState, NO_ERROR, 0, 0);
  793. }
  794. BOOL
  795. ReportStatusToSCMgr(
  796. IN DWORD dwCurrentState,
  797. IN DWORD dwWin32ExitCode,
  798. IN DWORD dwCheckPoint,
  799. IN DWORD dwWaitHint)
  800. {
  801. BOOL fResult;
  802. HRESULT hr;
  803. g_ssStatus.dwControlsAccepted = SERVICE_START_PENDING == dwCurrentState?
  804. 0 : SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
  805. g_ssStatus.dwCurrentState = dwCurrentState;
  806. g_ssStatus.dwWin32ExitCode = dwWin32ExitCode;
  807. g_ssStatus.dwCheckPoint = dwCheckPoint;
  808. g_ssStatus.dwWaitHint = dwWaitHint;
  809. fResult = SetServiceStatus(g_sshStatusHandle, &g_ssStatus);
  810. if (!fResult)
  811. {
  812. hr = GetLastError();
  813. _JumpError(hr, error, "SetServiceStatus");
  814. }
  815. DBGPRINT((
  816. DBG_SS_CERTSRV,
  817. "ReportStatusToSCMgr(state=%x, hr=%x, ckpt=%x, wait=%x)\n",
  818. dwCurrentState,
  819. dwWin32ExitCode,
  820. dwCheckPoint,
  821. dwWaitHint));
  822. error:
  823. return(fResult);
  824. }