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.

1238 lines
30 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1999
  5. //
  6. // File: prop.cpp
  7. //
  8. // Contents: Cert Server Property interface implementation
  9. //
  10. // History: 31-Jul-96 vich created
  11. //
  12. //---------------------------------------------------------------------------
  13. #include <pch.cpp>
  14. #pragma hdrstop
  15. #include "csprop.h"
  16. #include "cscom.h"
  17. #include "csdisp.h"
  18. #include "com.h"
  19. #include "certlog.h"
  20. #include "elog.h"
  21. #ifndef DBG_PROP
  22. # define DBG_PROP 0
  23. #endif
  24. HRESULT
  25. PropSetRequestTimeProperty(
  26. IN ICertDBRow *prow,
  27. IN WCHAR const *pwszProp)
  28. {
  29. HRESULT hr;
  30. SYSTEMTIME st;
  31. FILETIME ft;
  32. GetSystemTime(&st);
  33. if (!SystemTimeToFileTime(&st, &ft))
  34. {
  35. hr = myHLastError();
  36. _JumpError(hr, error, "SystemTimeToFileTime");
  37. }
  38. hr = prow->SetProperty(
  39. pwszProp,
  40. PROPTYPE_DATE | PROPCALLER_SERVER | PROPTABLE_REQUEST,
  41. sizeof(ft),
  42. (BYTE *) &ft);
  43. _JumpIfError(hr, error, "SetProperty");
  44. error:
  45. return(hr);
  46. }
  47. HRESULT
  48. PropParseRequest(
  49. IN ICertDBRow *prow,
  50. IN DWORD dwFlags,
  51. IN DWORD cbRequest,
  52. IN BYTE const *pbRequest,
  53. IN OUT CERTSRV_RESULT_CONTEXT *pResult)
  54. {
  55. HRESULT hr;
  56. pResult->dwFlagsTop = dwFlags;
  57. hr = PKCSParseRequest(
  58. dwFlags,
  59. prow,
  60. cbRequest,
  61. pbRequest,
  62. NULL,
  63. NULL,
  64. pResult);
  65. _JumpIfError(hr, error, "PKCSParseRequest");
  66. error:
  67. return(hr);
  68. }
  69. HRESULT
  70. propVerifyDateRange(
  71. IN ICertDBRow *prow,
  72. IN DWORD Flags,
  73. IN WCHAR const *pwszPropertyName,
  74. IN FILETIME const *pft)
  75. {
  76. HRESULT hr;
  77. DWORD cbProp;
  78. FILETIME ftNotBefore;
  79. FILETIME ftNotAfter;
  80. hr = E_INVALIDARG;
  81. CSASSERT((PROPTYPE_MASK & Flags) == PROPTYPE_DATE);
  82. if ((PROPTABLE_MASK & Flags) != PROPTABLE_CERTIFICATE)
  83. {
  84. _JumpError(hr, error, "Flags: Invalid table");
  85. }
  86. if (0 != lstrcmpi(pwszPropertyName, g_wszPropCertificateNotBeforeDate) &&
  87. 0 != lstrcmpi(pwszPropertyName, g_wszPropCertificateNotAfterDate))
  88. {
  89. _JumpError(hr, error, "pwszPropertyName: Invalid date property");
  90. }
  91. cbProp = sizeof(ftNotBefore);
  92. hr = prow->GetProperty(
  93. g_wszPropCertificateNotBeforeDate,
  94. Flags,
  95. &cbProp,
  96. (BYTE *) &ftNotBefore);
  97. _JumpIfError(hr, error, "GetProperty");
  98. cbProp = sizeof(ftNotAfter);
  99. hr = prow->GetProperty(
  100. g_wszPropCertificateNotAfterDate,
  101. Flags,
  102. &cbProp,
  103. (BYTE *) &ftNotAfter);
  104. _JumpIfError(hr, error, "GetProperty");
  105. if (0 > CompareFileTime(pft, &ftNotBefore) ||
  106. 0 < CompareFileTime(pft, &ftNotAfter))
  107. {
  108. CERTSRVDBGPRINTTIME("Old Not Before", &ftNotBefore);
  109. CERTSRVDBGPRINTTIME(" Old Not After", &ftNotAfter);
  110. CERTSRVDBGPRINTTIME(
  111. 0 == lstrcmpi(
  112. pwszPropertyName,
  113. g_wszPropCertificateNotBeforeDate)?
  114. "New Not Before" : " New Not After",
  115. pft);
  116. hr = E_INVALIDARG;
  117. _JumpErrorStr(hr, error, "FILETIME out of range", pwszPropertyName);
  118. }
  119. error:
  120. return(myHError(hr));
  121. }
  122. // Returns TRUE if names match!
  123. #define PROPNAMEMATCH(cwcNameVariable, pwszNameVariable, wszNameLiteral) \
  124. (WSZARRAYSIZE((wszNameLiteral)) == (cwcNameVariable) && \
  125. 0 == lstrcmpi((pwszNameVariable), (wszNameLiteral)))
  126. HRESULT
  127. propGetSystemProperty(
  128. IN WCHAR const *pwszPropName,
  129. IN DWORD Flags,
  130. OUT BYTE *rgbFastBuf,
  131. IN DWORD cbFastBuf,
  132. IN LONG Context,
  133. OUT BOOL *pfSystemProperty,
  134. OUT VARIANT *pvarPropertyValue)
  135. {
  136. HRESULT hr = S_OK;
  137. BYTE *pbFree = NULL;
  138. DWORD cwcPropName;
  139. DWORD cwcBaseName;
  140. WCHAR wszBaseName[32];
  141. WCHAR const *pwszIndex;
  142. WCHAR wszRenewalSuffix[cwcFILENAMESUFFIXMAX];
  143. DWORD iCert = MAXDWORD;
  144. DWORD iCRL;
  145. DWORD iDummy;
  146. DWORD State;
  147. DWORD PropType;
  148. DWORD cbCopy;
  149. DWORD cbOut;
  150. BYTE const *pbOut = NULL; // PROPTYPE_LONG or PROPTYPE_BINARY
  151. WCHAR const *pwszOut = NULL; // PROPTYPE_STRING
  152. CRL_CONTEXT const *pCRL = NULL;
  153. CERTSRV_COM_CONTEXT *pComContext;
  154. *pfSystemProperty = FALSE;
  155. wszRenewalSuffix[0] = L'\0';
  156. // Allow "PropName.#"
  157. // Copy the base part of the property name to a local buffer, so we can do
  158. // case ignore string compares.
  159. cwcPropName = wcslen(pwszPropName);
  160. cwcBaseName = wcscspn(pwszPropName, L".");
  161. if (ARRAYSIZE(wszBaseName) - 1 < cwcBaseName)
  162. {
  163. cwcBaseName = ARRAYSIZE(wszBaseName) - 1;
  164. }
  165. CopyMemory(wszBaseName, pwszPropName, cwcBaseName * sizeof(WCHAR));
  166. wszBaseName[cwcBaseName] = L'\0';
  167. pwszIndex = &pwszPropName[cwcBaseName];
  168. if (L'.' == *pwszIndex)
  169. {
  170. pwszIndex++;
  171. iCert = _wtol(pwszIndex);
  172. for ( ; L'\0' != *pwszIndex; pwszIndex++)
  173. {
  174. if (!iswdigit(*pwszIndex))
  175. {
  176. CSASSERT(S_OK == hr); // Not a system property, return S_OK
  177. goto error;
  178. }
  179. }
  180. }
  181. // Assume property type is a long:
  182. PropType = PROPTYPE_LONG;
  183. *pfSystemProperty = TRUE;
  184. if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPCATYPE))
  185. {
  186. pbOut = (BYTE const *) &g_CAType;
  187. cbOut = sizeof(g_CAType);
  188. }
  189. else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPUSEDS))
  190. {
  191. pbOut = (BYTE const *) &g_fUseDS;
  192. cbOut = sizeof(g_fUseDS);
  193. }
  194. else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPSERVERUPGRADED))
  195. {
  196. pbOut = (BYTE const *) &g_fServerUpgraded;
  197. cbOut = sizeof(g_fServerUpgraded);
  198. }
  199. else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPLOGLEVEL))
  200. {
  201. pbOut = (BYTE const *) &g_dwLogLevel;
  202. cbOut = sizeof(g_dwLogLevel);
  203. }
  204. else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPREQUESTERTOKEN))
  205. {
  206. hr = ComGetClientInfo(Context, MAXDWORD, &pComContext);
  207. _JumpIfError(hr, error, "ComGetClientInfo");
  208. if (NULL == pComContext->hAccessToken ||
  209. INVALID_HANDLE_VALUE == pComContext->hAccessToken)
  210. {
  211. hr = CERTSRV_E_PROPERTY_EMPTY;
  212. _JumpError(hr, error, "ComGetClientInfo(bad hAccessToken)");
  213. }
  214. pbOut = (BYTE const *) &pComContext->hAccessToken;
  215. cbOut = sizeof(pComContext->hAccessToken);
  216. PropType = PROPTYPE_BINARY;
  217. }
  218. else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPREQUESTERCAACCESS))
  219. {
  220. hr = ComGetClientInfo(Context, MAXDWORD, &pComContext);
  221. _JumpIfError(hr, error, "ComGetClientInfo");
  222. if (MAXDWORD == pComContext->fInRequestGroup)
  223. {
  224. hr = CERTSRV_E_PROPERTY_EMPTY;
  225. _JumpError(hr, error, "ComGetClientInfo(bad fInRequestGroup)");
  226. }
  227. pbOut = (BYTE const *) &pComContext->fInRequestGroup;
  228. cbOut = sizeof(pComContext->fInRequestGroup);
  229. }
  230. else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPUSERDN))
  231. {
  232. hr = ComGetClientInfo(Context, MAXDWORD, &pComContext);
  233. _JumpIfError(hr, error, "ComGetClientInfo");
  234. if (NULL == pComContext->pwszUserDN)
  235. {
  236. if (!g_fUseDS)
  237. {
  238. hr = CERTSRV_E_PROPERTY_EMPTY;
  239. _JumpError(hr, error, "ComGetClientInfo(bad pwszUserDN)");
  240. }
  241. hr = CoreSetComContextUserDN(
  242. pComContext->RequestId,
  243. Context,
  244. MAXDWORD,
  245. &pwszOut);
  246. _JumpIfError(hr, error, "CoreSetComContextUserDN");
  247. }
  248. pwszOut = pComContext->pwszUserDN;
  249. }
  250. else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPCERTCOUNT))
  251. {
  252. pbOut = (BYTE const *) &g_cCACerts;
  253. cbOut = sizeof(g_cCACerts);
  254. }
  255. else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPSANITIZEDCANAME))
  256. {
  257. pwszOut = g_wszSanitizedName;
  258. }
  259. else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPSANITIZEDSHORTNAME))
  260. {
  261. pwszOut = g_pwszSanitizedDSName;
  262. }
  263. else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPMACHINEDNSNAME))
  264. {
  265. pwszOut = g_pwszServerName;
  266. }
  267. else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPCONFIGDN))
  268. {
  269. pwszOut = g_strConfigDN;
  270. }
  271. else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPDOMAINDN))
  272. {
  273. pwszOut = g_strDomainDN;
  274. }
  275. else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPMODULEREGLOC))
  276. {
  277. // future: cache storage location once it is built
  278. WCHAR *pwszQuasiPath;
  279. DWORD cwcQuasiPath;
  280. WCHAR const *pwszPrefix;
  281. MarshalInterface *pIF;
  282. if ((PROPCALLER_MASK & Flags) == PROPCALLER_POLICY)
  283. {
  284. pIF = &g_miPolicy;
  285. cwcQuasiPath = ARRAYSIZE(L"Policy\\"); // includes L'\0'
  286. pwszPrefix = L"Policy\\";
  287. }
  288. else
  289. {
  290. hr = ExitGetActiveModule(Context, &pIF);
  291. _JumpIfError(hr, error, "ExitGetActiveModule");
  292. cwcQuasiPath = ARRAYSIZE(L"Exit\\"); // includes L'\0'
  293. pwszPrefix = L"Exit\\";
  294. }
  295. cwcQuasiPath += wcslen(pIF->GetProgID());
  296. pwszQuasiPath = (WCHAR *) LocalAlloc(
  297. LMEM_FIXED,
  298. cwcQuasiPath * sizeof(WCHAR));
  299. if (NULL == pwszQuasiPath)
  300. {
  301. hr = E_OUTOFMEMORY;
  302. _JumpError(hr, error, "LocalAlloc");
  303. }
  304. wcscpy(pwszQuasiPath, pwszPrefix);
  305. wcscat(pwszQuasiPath, pIF->GetProgID());
  306. hr = myRegOpenRelativeKey(
  307. pIF->GetConfig(),
  308. pwszQuasiPath,
  309. RORKF_FULLPATH | RORKF_CREATESUBKEYS,
  310. (WCHAR **) &pwszOut,
  311. NULL,
  312. NULL);
  313. LocalFree(pwszQuasiPath);
  314. _JumpIfError(hr, error, "myRegOpenRelativeKey");
  315. CSASSERT(NULL != pwszOut);
  316. pbFree = (BYTE *) pwszOut;
  317. }
  318. else if (PROPNAMEMATCH(cwcBaseName, wszBaseName, wszPROPRAWCACERTIFICATE))
  319. {
  320. hr = PKCSGetCACert(iCert, const_cast<BYTE **>(&pbOut), &cbOut); // not alloc'd
  321. _JumpIfError(hr, error, "PKCSGetCACert");
  322. PropType = PROPTYPE_BINARY;
  323. }
  324. else if (PROPNAMEMATCH(cwcBaseName, wszBaseName, wszPROPRAWCRL))
  325. {
  326. hr = CRLGetCRL(iCert, FALSE, &pCRL, NULL);
  327. _JumpIfError(hr, error, "CRLGetCRL");
  328. cbOut = pCRL->cbCrlEncoded;
  329. pbOut = pCRL->pbCrlEncoded;
  330. PropType = PROPTYPE_BINARY;
  331. }
  332. else if (PROPNAMEMATCH(cwcBaseName, wszBaseName, wszPROPRAWDELTACRL))
  333. {
  334. hr = CRLGetCRL(iCert, TRUE, &pCRL, NULL);
  335. _JumpIfError(hr, error, "CRLGetCRL");
  336. cbOut = pCRL->cbCrlEncoded;
  337. pbOut = pCRL->pbCrlEncoded;
  338. PropType = PROPTYPE_BINARY;
  339. }
  340. else if (PROPNAMEMATCH(cwcBaseName, wszBaseName, wszPROPCERTSTATE))
  341. {
  342. hr = PKCSMapCertIndex(iCert, &iCert, &State);
  343. _JumpIfError(hr, error, "PKCSMapCertIndex");
  344. pbOut = (BYTE *) &State;
  345. cbOut = sizeof(State);
  346. }
  347. else if (PROPNAMEMATCH(cwcBaseName, wszBaseName, wszPROPCERTSUFFIX))
  348. {
  349. hr = PKCSMapCertIndex(iCert, &iCert, &State);
  350. _JumpIfError(hr, error, "PKCSMapCertIndex");
  351. pwszOut = wszRenewalSuffix;
  352. }
  353. else if (PROPNAMEMATCH(cwcBaseName, wszBaseName, wszPROPCRLINDEX))
  354. {
  355. hr = PKCSMapCRLIndex(iCert, &iCert, &iCRL, &State);
  356. _JumpIfError(hr, error, "PKCSMapCRLIndex");
  357. pbOut = (BYTE *) &iCRL;
  358. cbOut = sizeof(iCRL);
  359. }
  360. else if (PROPNAMEMATCH(cwcBaseName, wszBaseName, wszPROPCRLSTATE))
  361. {
  362. hr = PKCSMapCRLIndex(iCert, &iCert, &iCRL, &State);
  363. _JumpIfError(hr, error, "PKCSMapCRLIndex");
  364. pbOut = (BYTE *) &State;
  365. cbOut = sizeof(State);
  366. }
  367. else if (PROPNAMEMATCH(cwcBaseName, wszBaseName, wszPROPCRLSUFFIX))
  368. {
  369. hr = PKCSMapCRLIndex(iCert, &iDummy, &iCert, &State);
  370. _JumpIfError(hr, error, "PKCSMapCRLIndex");
  371. pwszOut = wszRenewalSuffix;
  372. }
  373. else if(PROPNAMEMATCH(cwcBaseName, wszBaseName, wszPROPTEMPLATECHANGESEQUENCENUMBER))
  374. {
  375. pbOut = (BYTE const *) &g_cTemplateUpdateSequenceNum;
  376. cbOut = sizeof(g_cTemplateUpdateSequenceNum);
  377. }
  378. else
  379. {
  380. CSASSERT(S_OK == hr); // Not a system property, return S_OK
  381. *pfSystemProperty = FALSE;
  382. goto error;
  383. }
  384. CSASSERT((NULL != pbOut) ^ (NULL != pwszOut)); // exactly 1 must be set
  385. cbCopy = cbOut;
  386. if (NULL != pwszOut)
  387. {
  388. if (wszRenewalSuffix == pwszOut && 0 != iCert)
  389. {
  390. wsprintf(wszRenewalSuffix, L"(%u)", iCert);
  391. }
  392. PropType = PROPTYPE_STRING;
  393. cbOut = wcslen(pwszOut) * sizeof(WCHAR);
  394. cbCopy = cbOut + sizeof(WCHAR);
  395. pbOut = (BYTE *) pwszOut;
  396. }
  397. if ((PROPTYPE_MASK & Flags) != PropType)
  398. {
  399. hr = E_INVALIDARG;
  400. _JumpError(hr, error, "bad PropType");
  401. }
  402. hr = myUnmarshalVariant(
  403. PROPMARSHAL_LOCALSTRING | Flags,
  404. cbOut,
  405. pbOut,
  406. pvarPropertyValue);
  407. _JumpIfError(hr, error, "myUnmarshalVariant");
  408. error:
  409. if (NULL != pCRL)
  410. {
  411. CertFreeCRLContext(pCRL);
  412. }
  413. if (NULL != pbFree)
  414. {
  415. LocalFree(pbFree);
  416. }
  417. return(hr);
  418. }
  419. FNCIGETPROPERTY PropCIGetProperty;
  420. HRESULT
  421. PropCIGetProperty(
  422. IN LONG Context,
  423. IN DWORD Flags,
  424. IN WCHAR const *pwszPropertyName,
  425. OUT VARIANT *pvarPropertyValue)
  426. {
  427. HRESULT hr;
  428. DWORD RequestId;
  429. DWORD cbprop;
  430. BYTE *pbprop = NULL;
  431. ICertDBRow *prow = NULL;
  432. BYTE rgbFastBuf[128]; // many properties are small (128)
  433. BOOL fSystemProperty;
  434. if (NULL != pvarPropertyValue)
  435. {
  436. VariantInit(pvarPropertyValue);
  437. }
  438. if (NULL == pwszPropertyName || NULL == pvarPropertyValue)
  439. {
  440. hr = E_POINTER;
  441. _JumpError(hr, error, "NULL parm");
  442. }
  443. hr = E_INVALIDARG;
  444. if ((PROPCALLER_MASK & Flags) != PROPCALLER_POLICY &&
  445. (PROPCALLER_MASK & Flags) != PROPCALLER_EXIT &&
  446. (PROPCALLER_MASK & Flags) != PROPCALLER_SERVER)
  447. {
  448. _JumpError(hr, error, "Flags: Invalid caller");
  449. }
  450. if ((PROPTABLE_MASK & Flags) != PROPTABLE_REQUEST &&
  451. (PROPTABLE_MASK & Flags) != PROPTABLE_CERTIFICATE &&
  452. (PROPTABLE_MASK & Flags) != PROPTABLE_ATTRIBUTE)
  453. {
  454. _JumpError(hr, error, "Flags: Invalid table");
  455. }
  456. fSystemProperty = FALSE;
  457. if ((PROPTABLE_MASK & Flags) == PROPTABLE_CERTIFICATE)
  458. {
  459. hr = ComVerifyRequestContext(TRUE, Flags, Context, &RequestId);
  460. _JumpIfError(hr, error, "ComVerifyRequestContext");
  461. // Check for special, hard-coded properties first
  462. hr = propGetSystemProperty(
  463. pwszPropertyName,
  464. Flags,
  465. rgbFastBuf,
  466. sizeof(rgbFastBuf),
  467. Context,
  468. &fSystemProperty,
  469. pvarPropertyValue);
  470. _JumpIfError(hr, error, "propGetSystemProperty");
  471. }
  472. if (!fSystemProperty)
  473. {
  474. DWORD VerifyFlags = Flags;
  475. if (((PROPCALLER_MASK | PROPTABLE_MASK | PROPTYPE_MASK) & Flags) ==
  476. (PROPCALLER_SERVER | PROPTABLE_REQUEST | PROPTYPE_LONG) &&
  477. 0 == lstrcmpi(pwszPropertyName, wszPROPREQUESTREQUESTID))
  478. {
  479. VerifyFlags = PROPCALLER_EXIT | (~PROPCALLER_MASK & VerifyFlags);
  480. }
  481. hr = ComVerifyRequestContext(FALSE, VerifyFlags, Context, &RequestId);
  482. _JumpIfError(hr, error, "ComVerifyRequestContext");
  483. pbprop = rgbFastBuf;
  484. cbprop = sizeof(rgbFastBuf);
  485. // PROPCALLER_SERVER indicates this call is only for Context validation
  486. // -- return a zero RequestId. This keeps CRL publication exit module
  487. // notification from failing.
  488. if (0 == RequestId &&
  489. ((PROPCALLER_MASK | PROPTABLE_MASK | PROPTYPE_MASK) & Flags) ==
  490. (PROPCALLER_SERVER | PROPTABLE_REQUEST | PROPTYPE_LONG) &&
  491. 0 == lstrcmpi(pwszPropertyName, wszPROPREQUESTREQUESTID))
  492. {
  493. *(DWORD *) pbprop = 0;
  494. cbprop = sizeof(DWORD);
  495. }
  496. else
  497. {
  498. hr = g_pCertDB->OpenRow(
  499. PROPOPEN_READONLY | PROPTABLE_REQCERT,
  500. RequestId,
  501. NULL,
  502. &prow);
  503. _JumpIfError(hr, error, "OpenRow");
  504. hr = prow->GetProperty(
  505. pwszPropertyName,
  506. Flags,
  507. &cbprop,
  508. pbprop);
  509. if (S_OK != hr)
  510. {
  511. if (HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW) != hr)
  512. {
  513. _JumpIfError2(
  514. hr,
  515. error,
  516. "GetProperty",
  517. CERTSRV_E_PROPERTY_EMPTY);
  518. }
  519. CSASSERT(ARRAYSIZE(rgbFastBuf) < cbprop);
  520. DBGPRINT((
  521. DBG_SS_CERTSRVI,
  522. "FastBuf miss: PropCIGetProperty - pbprop %i bytes\n",
  523. cbprop));
  524. pbprop = (BYTE *) LocalAlloc(LMEM_FIXED, cbprop);
  525. if (NULL == pbprop)
  526. {
  527. hr = E_OUTOFMEMORY;
  528. _JumpError(hr, error, "LocalAlloc");
  529. }
  530. hr = prow->GetProperty(
  531. pwszPropertyName,
  532. Flags,
  533. &cbprop,
  534. pbprop);
  535. _JumpIfError(hr, error, "GetProperty");
  536. }
  537. } // property is in-hand
  538. hr = myUnmarshalVariant(
  539. PROPMARSHAL_LOCALSTRING | Flags,
  540. cbprop,
  541. pbprop,
  542. pvarPropertyValue);
  543. _JumpIfError(hr, error, "myUnmarshalVariant");
  544. }
  545. error:
  546. if (NULL != prow)
  547. {
  548. prow->Release();
  549. }
  550. if (NULL != pbprop && pbprop != rgbFastBuf)
  551. {
  552. LocalFree(pbprop);
  553. }
  554. return(myHError(hr));
  555. }
  556. HRESULT
  557. propSetSystemProperty(
  558. IN WCHAR const *pwszPropName,
  559. IN DWORD Flags,
  560. OUT BOOL *pfSystemProperty,
  561. IN VARIANT const *pvarPropertyValue)
  562. {
  563. HRESULT hr = S_OK;
  564. DWORD cbprop;
  565. BYTE *pbprop = NULL;
  566. DWORD LogLevel = MAXDWORD;
  567. DWORD infotype = EVENTLOG_INFORMATION_TYPE;
  568. DWORD LogMsg = MSG_POLICY_LOG_INFORMATION;
  569. *pfSystemProperty = FALSE;
  570. if (0 == lstrcmpi(pwszPropName, wszPROPEVENTLOGTERSE))
  571. {
  572. LogLevel = CERTLOG_TERSE;
  573. }
  574. else
  575. if (0 == lstrcmpi(pwszPropName, wszPROPEVENTLOGERROR))
  576. {
  577. LogLevel = CERTLOG_ERROR;
  578. infotype = EVENTLOG_ERROR_TYPE;
  579. LogMsg = MSG_POLICY_LOG_ERROR;
  580. }
  581. else
  582. if (0 == lstrcmpi(pwszPropName, wszPROPEVENTLOGWARNING))
  583. {
  584. LogLevel = CERTLOG_WARNING;
  585. infotype = EVENTLOG_WARNING_TYPE;
  586. LogMsg = MSG_POLICY_LOG_WARNING;
  587. }
  588. else
  589. if (0 == lstrcmpi(pwszPropName, wszPROPEVENTLOGVERBOSE))
  590. {
  591. LogLevel = CERTLOG_VERBOSE;
  592. }
  593. else
  594. {
  595. CSASSERT(S_OK == hr); // Not a system property, return S_OK
  596. goto error;
  597. }
  598. *pfSystemProperty = TRUE;
  599. if (PROPTYPE_STRING != (PROPTYPE_MASK & Flags) ||
  600. VT_BSTR != pvarPropertyValue->vt ||
  601. NULL == pvarPropertyValue->bstrVal)
  602. {
  603. hr = E_INVALIDARG;
  604. _JumpErrorStr(hr, error, "string property value/type", pwszPropName);
  605. }
  606. CSASSERT(MAXDWORD != LogLevel);
  607. if (LogLevel <= g_dwLogLevel)
  608. {
  609. WCHAR const *apwsz[2];
  610. apwsz[0] = g_strPolicyDescription;
  611. apwsz[1] = pvarPropertyValue->bstrVal;
  612. hr = LogEvent(infotype, LogMsg, ARRAYSIZE(apwsz), apwsz);
  613. _JumpIfError(hr, error, "LogEvent");
  614. }
  615. hr = S_OK;
  616. error:
  617. return(myHError(hr));
  618. }
  619. FNCISETPROPERTY PropCISetProperty;
  620. HRESULT
  621. PropCISetProperty(
  622. IN LONG Context,
  623. IN DWORD Flags,
  624. IN WCHAR const *pwszPropertyName,
  625. IN VARIANT const *pvarPropertyValue)
  626. {
  627. HRESULT hr;
  628. DWORD RequestId;
  629. DWORD cbprop;
  630. BYTE *pbprop = NULL;
  631. ICertDBRow *prow = NULL;
  632. BOOL fSubjectDot = FALSE;
  633. BOOL fSystemProperty;
  634. BOOL fCommitted = FALSE;
  635. if (NULL == pwszPropertyName || NULL == pvarPropertyValue)
  636. {
  637. hr = E_POINTER;
  638. _JumpError(hr, error, "NULL parm");
  639. }
  640. hr = E_INVALIDARG;
  641. if ((PROPCALLER_MASK & Flags) != PROPCALLER_POLICY)
  642. {
  643. _JumpError(hr, error, "Flags: Invalid caller");
  644. }
  645. if ((PROPTABLE_MASK & Flags) != PROPTABLE_CERTIFICATE)
  646. {
  647. _JumpError(hr, error, "Flags: Invalid table");
  648. }
  649. hr = ComVerifyRequestContext(TRUE, Flags, Context, &RequestId);
  650. _JumpIfError(hr, error, "ComVerifyRequestContext");
  651. // Check for special, hard-coded properties first
  652. fSystemProperty = FALSE;
  653. hr = propSetSystemProperty(
  654. pwszPropertyName,
  655. Flags,
  656. &fSystemProperty,
  657. pvarPropertyValue);
  658. _JumpIfError(hr, error, "propGetSystemProperty");
  659. if (!fSystemProperty)
  660. {
  661. hr = ComVerifyRequestContext(FALSE, Flags, Context, &RequestId);
  662. _JumpIfError(hr, error, "ComVerifyRequestContext");
  663. hr = myMarshalVariant(
  664. pvarPropertyValue,
  665. PROPMARSHAL_NULLBSTROK | PROPMARSHAL_LOCALSTRING | Flags,
  666. &cbprop,
  667. &pbprop);
  668. _JumpIfError(hr, error, "myMarshalVariant");
  669. hr = g_pCertDB->OpenRow(PROPTABLE_REQCERT, RequestId, NULL, &prow);
  670. _JumpIfError(hr, error, "OpenRow");
  671. if (PROPTYPE_DATE == (PROPTYPE_MASK & Flags))
  672. {
  673. hr = propVerifyDateRange(
  674. prow,
  675. Flags,
  676. pwszPropertyName,
  677. (FILETIME *) pbprop);
  678. _JumpIfError(hr, error, "propVerifyDateRange");
  679. }
  680. else
  681. if (PROPTYPE_STRING == (PROPTYPE_MASK & Flags) &&
  682. PROPTABLE_CERTIFICATE == (PROPTABLE_MASK & Flags))
  683. {
  684. hr = PKCSVerifySubjectRDN(
  685. prow,
  686. pwszPropertyName,
  687. (WCHAR const *) pbprop,
  688. &fSubjectDot);
  689. _JumpIfError(hr, error, "PKCSVerifySubjectRDN");
  690. }
  691. if (NULL == pbprop && fSubjectDot)
  692. {
  693. hr = PKCSDeleteAllSubjectRDNs(prow, Flags);
  694. _JumpIfError(hr, error, "PKCSDeleteAllSubjectRDNs");
  695. }
  696. else
  697. {
  698. hr = prow->SetProperty(pwszPropertyName, Flags, cbprop, pbprop);
  699. _JumpIfError(hr, error, "SetProperty");
  700. }
  701. hr = prow->CommitTransaction(TRUE);
  702. _JumpIfError(hr, error, "CommitTransaction");
  703. fCommitted = TRUE;
  704. }
  705. hr = S_OK;
  706. error:
  707. if (NULL != prow)
  708. {
  709. if (S_OK != hr && !fCommitted)
  710. {
  711. HRESULT hr2 = prow->CommitTransaction(FALSE);
  712. _PrintIfError(hr2, "CommitTransaction");
  713. }
  714. prow->Release();
  715. }
  716. if (NULL != pbprop)
  717. {
  718. LocalFree(pbprop);
  719. }
  720. return(myHError(hr));
  721. }
  722. HRESULT
  723. PropGetExtension(
  724. IN ICertDBRow *prow,
  725. IN DWORD Flags,
  726. IN WCHAR const *pwszExtensionName,
  727. OUT DWORD *pdwExtFlags,
  728. OUT DWORD *pcbValue,
  729. OUT BYTE **ppbValue) // LocalAlloc
  730. {
  731. HRESULT hr;
  732. DWORD cbprop;
  733. BYTE *pbprop = NULL;
  734. CSASSERT(
  735. PROPCALLER_EXIT == (PROPCALLER_MASK & Flags) ||
  736. PROPCALLER_POLICY == (PROPCALLER_MASK & Flags) ||
  737. PROPCALLER_SERVER == (PROPCALLER_MASK & Flags));
  738. CSASSERT(0 == (~(PROPCALLER_MASK | PROPTYPE_MASK) & Flags));
  739. hr = myVerifyObjId(pwszExtensionName);
  740. _JumpIfError(hr, error, "myVerifyObjId");
  741. cbprop = 0;
  742. hr = prow->GetExtension(pwszExtensionName, pdwExtFlags, &cbprop, NULL);
  743. _JumpIfError2(hr, error, "GetExtension(NULL)", CERTSRV_E_PROPERTY_EMPTY);
  744. pbprop = (BYTE *) LocalAlloc(LMEM_FIXED, cbprop);
  745. if (NULL == pbprop)
  746. {
  747. hr = E_OUTOFMEMORY;
  748. _JumpError(hr, error, "LocalAlloc(ExtValue)");
  749. }
  750. hr = prow->GetExtension(pwszExtensionName, pdwExtFlags, &cbprop, pbprop);
  751. _JumpIfError(hr, error, "GetExtension");
  752. if (PROPTYPE_BINARY == (PROPTYPE_MASK & Flags))
  753. {
  754. *pcbValue = cbprop;
  755. *ppbValue = pbprop;
  756. pbprop = NULL;
  757. }
  758. else
  759. {
  760. hr = myDecodeExtension(Flags, pbprop, cbprop, ppbValue, pcbValue);
  761. _JumpIfError(hr, error, "myDecodeExtension");
  762. }
  763. error:
  764. if (NULL != pbprop)
  765. {
  766. LocalFree(pbprop);
  767. }
  768. return(myHError(hr));
  769. }
  770. HRESULT
  771. PropSetExtension(
  772. IN ICertDBRow *prow,
  773. IN DWORD Flags,
  774. IN WCHAR const *pwszExtensionName,
  775. IN DWORD ExtFlags,
  776. IN DWORD cbValue,
  777. IN BYTE const *pbValue)
  778. {
  779. HRESULT hr;
  780. DWORD cbprop;
  781. BYTE *pbprop = NULL;
  782. CSASSERT(
  783. PROPCALLER_ADMIN == (PROPCALLER_MASK & Flags) ||
  784. PROPCALLER_POLICY == (PROPCALLER_MASK & Flags) ||
  785. PROPCALLER_SERVER == (PROPCALLER_MASK & Flags) ||
  786. PROPCALLER_REQUEST == (PROPCALLER_MASK & Flags));
  787. CSASSERT(0 == (~(PROPCALLER_MASK | PROPTYPE_MASK) & Flags));
  788. hr = myVerifyObjId(pwszExtensionName);
  789. _JumpIfError(hr, error, "myVerifyObjId");
  790. if (PROPTYPE_BINARY == (PROPTYPE_MASK & Flags))
  791. {
  792. cbprop = cbValue;
  793. pbprop = (BYTE *) pbValue;
  794. }
  795. else
  796. {
  797. hr = myEncodeExtension(Flags, pbValue, cbValue, &pbprop, &cbprop);
  798. _JumpIfError(hr, error, "myEncodeExtension");
  799. }
  800. hr = prow->SetExtension(pwszExtensionName, ExtFlags, cbprop, pbprop);
  801. _JumpIfError(hr, error, "SetExtension");
  802. error:
  803. if (NULL != pbprop && pbprop != pbValue)
  804. {
  805. LocalFree(pbprop);
  806. }
  807. return(hr);
  808. }
  809. FNCIGETEXTENSION PropCIGetExtension;
  810. HRESULT
  811. PropCIGetExtension(
  812. IN LONG Context,
  813. IN DWORD Flags,
  814. IN WCHAR const *pwszExtensionName,
  815. OUT DWORD *pdwExtFlags,
  816. OUT VARIANT *pvarValue)
  817. {
  818. HRESULT hr;
  819. DWORD RequestId;
  820. BYTE *pbValue = NULL;
  821. DWORD cbValue;
  822. ICertDBRow *prow = NULL;
  823. if (NULL != pvarValue)
  824. {
  825. VariantInit(pvarValue);
  826. }
  827. if (NULL == pwszExtensionName || NULL == pdwExtFlags || NULL == pvarValue)
  828. {
  829. hr = E_POINTER;
  830. _JumpError(hr, error, "NULL parm");
  831. }
  832. hr = ComVerifyRequestContext(FALSE, Flags, Context, &RequestId);
  833. _JumpIfError(hr, error, "ComVerifyRequestContext");
  834. hr = g_pCertDB->OpenRow(PROPOPEN_READONLY | PROPTABLE_REQCERT, RequestId, NULL, &prow);
  835. _JumpIfError(hr, error, "OpenRow");
  836. hr = PropGetExtension(
  837. prow,
  838. Flags,
  839. pwszExtensionName,
  840. pdwExtFlags,
  841. &cbValue,
  842. &pbValue);
  843. _JumpIfError2(hr, error, "PropGetExtension", CERTSRV_E_PROPERTY_EMPTY);
  844. hr = myUnmarshalVariant(
  845. PROPMARSHAL_LOCALSTRING | Flags,
  846. cbValue,
  847. pbValue,
  848. pvarValue);
  849. _JumpIfError(hr, error, "myUnmarshalVariant");
  850. error:
  851. if (NULL != prow)
  852. {
  853. prow->Release();
  854. }
  855. if (NULL != pbValue)
  856. {
  857. LocalFree(pbValue);
  858. }
  859. return(hr);
  860. }
  861. FNCISETPROPERTY PropCISetExtension;
  862. HRESULT
  863. PropCISetExtension(
  864. IN LONG Context,
  865. IN DWORD Flags,
  866. IN WCHAR const *pwszExtensionName,
  867. IN DWORD ExtFlags,
  868. IN VARIANT const *pvarValue)
  869. {
  870. HRESULT hr;
  871. DWORD RequestId;
  872. DWORD cbprop;
  873. BYTE *pbprop = NULL;
  874. ICertDBRow *prow = NULL;
  875. BOOL fCommitted = FALSE;
  876. if (NULL == pwszExtensionName || NULL == pvarValue)
  877. {
  878. hr = E_POINTER;
  879. _JumpError(hr, error, "NULL parm");
  880. }
  881. if ((PROPCALLER_MASK & Flags) != PROPCALLER_POLICY)
  882. {
  883. hr = E_INVALIDARG;
  884. _JumpError(hr, error, "Flags: Invalid caller");
  885. }
  886. hr = ComVerifyRequestContext(FALSE, Flags, Context, &RequestId);
  887. _JumpIfError(hr, error, "ComVerifyRequestContext");
  888. hr = myMarshalVariant(
  889. pvarValue,
  890. PROPMARSHAL_LOCALSTRING | Flags,
  891. &cbprop,
  892. &pbprop);
  893. _JumpIfError(hr, error, "myMarshalVariant");
  894. hr = g_pCertDB->OpenRow(PROPTABLE_REQCERT, RequestId, NULL, &prow);
  895. _JumpIfError(hr, error, "OpenRow");
  896. hr = PropSetExtension(
  897. prow,
  898. Flags,
  899. pwszExtensionName,
  900. ExtFlags,
  901. cbprop,
  902. pbprop);
  903. _JumpIfError(hr, error, "PropSetExtension");
  904. hr = prow->CommitTransaction(TRUE);
  905. _JumpIfError(hr, error, "CommitTransaction");
  906. fCommitted = TRUE;
  907. error:
  908. if (NULL != prow)
  909. {
  910. if (S_OK != hr && !fCommitted)
  911. {
  912. HRESULT hr2 = prow->CommitTransaction(FALSE);
  913. _PrintIfError(hr2, "CommitTransaction");
  914. }
  915. prow->Release();
  916. }
  917. if (NULL != pbprop)
  918. {
  919. LocalFree(pbprop);
  920. }
  921. return(myHError(hr));
  922. }
  923. FNCIENUMSETUP PropCIEnumSetup;
  924. HRESULT
  925. PropCIEnumSetup(
  926. IN LONG Context,
  927. IN LONG Flags,
  928. IN OUT CIENUM *pciEnum)
  929. {
  930. HRESULT hr;
  931. DWORD RequestId;
  932. CSASSERT(CIE_CALLER_POLICY == PROPCALLER_POLICY);
  933. CSASSERT(CIE_CALLER_EXIT == PROPCALLER_EXIT);
  934. CSASSERT(CIE_CALLER_MASK == PROPCALLER_MASK);
  935. hr = ComVerifyRequestContext(FALSE, Flags, Context, &RequestId);
  936. _JumpIfError(hr, error, "ComVerifyRequestContext");
  937. hr = pciEnum->EnumSetup(RequestId, Context, Flags);
  938. _JumpIfError(hr, error, "EnumSetup");
  939. error:
  940. return(hr);
  941. }
  942. FNCIENUMNEXT PropCIEnumNext;
  943. HRESULT
  944. PropCIEnumNext(
  945. IN OUT CIENUM *pciEnum,
  946. OUT BSTR *pstrPropertyName)
  947. {
  948. HRESULT hr;
  949. DWORD RequestId;
  950. CSASSERT(CIE_CALLER_POLICY == PROPCALLER_POLICY);
  951. CSASSERT(CIE_CALLER_EXIT == PROPCALLER_EXIT);
  952. CSASSERT(CIE_CALLER_MASK == PROPCALLER_MASK);
  953. hr = ComVerifyRequestContext(
  954. FALSE,
  955. pciEnum->GetFlags(),
  956. pciEnum->GetContext(),
  957. &RequestId);
  958. _JumpIfError(hr, error, "ComVerifyRequestContext");
  959. hr = pciEnum->EnumNext(pstrPropertyName);
  960. _JumpIfError2(hr, error, "EnumNext", S_FALSE);
  961. error:
  962. return(hr);
  963. }
  964. FNCIENUMCLOSE PropCIEnumClose;
  965. HRESULT
  966. PropCIEnumClose(
  967. IN OUT CIENUM *pciEnum)
  968. {
  969. HRESULT hr;
  970. hr = pciEnum->EnumClose();
  971. _JumpIfError(hr, error, "EnumClose");
  972. error:
  973. return(hr);
  974. }
  975. HRESULT
  976. PropSetAttributeProperty(
  977. IN ICertDBRow *prow,
  978. IN BOOL fConcatenateRDNs,
  979. IN DWORD dwTable,
  980. IN DWORD cwcNameMax,
  981. OPTIONAL IN WCHAR const *pwszSuffix,
  982. IN WCHAR const *pwszName,
  983. IN WCHAR const *pwszValue)
  984. {
  985. HRESULT hr = S_OK;
  986. WCHAR *pwszTemp = NULL;
  987. WCHAR const *pwszValue2 = pwszValue;
  988. DWORD cbProp;
  989. DWORD dwFlags = dwTable | PROPTYPE_STRING | PROPCALLER_SERVER;
  990. CSASSERT(
  991. PROPTABLE_ATTRIBUTE == dwTable ||
  992. PROPTABLE_REQUEST == dwTable ||
  993. PROPTABLE_CERTIFICATE == dwTable);
  994. // if the name and value are both non-empty ...
  995. if (NULL != pwszName && L'\0' != *pwszName &&
  996. NULL != pwszValue && L'\0' != *pwszValue)
  997. {
  998. if (PROPTABLE_ATTRIBUTE != dwTable)
  999. {
  1000. if (g_fEnforceRDNNameLengths && wcslen(pwszValue) > cwcNameMax)
  1001. {
  1002. hr = CERTSRV_E_BAD_REQUESTSUBJECT;
  1003. DBGPRINT((
  1004. DBG_SS_CERTSRV,
  1005. "RDN component too long: %u/%u: %ws=\"%ws\"\n",
  1006. wcslen(pwszValue),
  1007. cwcNameMax,
  1008. pwszName,
  1009. pwszValue));
  1010. _JumpErrorStr(hr, error, "RDN component too long", pwszValue);
  1011. }
  1012. if (fConcatenateRDNs)
  1013. {
  1014. cbProp = 0;
  1015. hr = prow->GetProperty(pwszName, dwFlags, &cbProp, NULL);
  1016. if (CERTSRV_E_PROPERTY_EMPTY != hr)
  1017. {
  1018. _JumpIfError(hr, error, "GetProperty");
  1019. // cbProp includes trailing L'\0' when out buffer is NULL
  1020. pwszTemp = (WCHAR *) LocalAlloc(
  1021. LMEM_FIXED,
  1022. cbProp + sizeof(WCHAR) * (1 + wcslen(pwszValue)));
  1023. if (NULL == pwszTemp)
  1024. {
  1025. hr = E_OUTOFMEMORY;
  1026. _JumpError(hr, error, "LocalAlloc");
  1027. }
  1028. hr = prow->GetProperty(
  1029. pwszName,
  1030. dwFlags,
  1031. &cbProp,
  1032. (BYTE *) pwszTemp);
  1033. _JumpIfError(hr, error, "GetProperty");
  1034. // If there are multiple RDN components for the same DB
  1035. // column, concatenate them even if the feature is disabled.
  1036. wcscat(pwszTemp, wszNAMESEPARATORDEFAULT);
  1037. wcscat(pwszTemp, pwszValue);
  1038. pwszValue2 = pwszTemp;
  1039. // cbProp now does NOT include trailing L'\0'
  1040. CSASSERT(
  1041. sizeof(WCHAR) * wcslen(pwszTemp) ==
  1042. cbProp + sizeof(WCHAR) * (1 + wcslen(pwszValue)));
  1043. }
  1044. }
  1045. else if (NULL != pwszSuffix)
  1046. {
  1047. hr = myAddNameSuffix(
  1048. pwszValue,
  1049. pwszSuffix,
  1050. cwcNameMax,
  1051. &pwszTemp);
  1052. _JumpIfError(hr, error, "myAddNameSuffix");
  1053. pwszValue2 = pwszTemp;
  1054. }
  1055. }
  1056. hr = prow->SetProperty(
  1057. pwszName,
  1058. dwFlags,
  1059. MAXDWORD,
  1060. (BYTE const *) pwszValue2);
  1061. _JumpIfError(hr, error, "SetProperty");
  1062. }
  1063. error:
  1064. if (NULL != pwszTemp)
  1065. {
  1066. LocalFree(pwszTemp);
  1067. }
  1068. return(hr);
  1069. }