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.

1607 lines
39 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 "certsrvd.h"
  21. #include "dbtable.h"
  22. #include "elog.h"
  23. #define __dwFILE__ __dwFILE_CERTSRV_PROP_CPP__
  24. #ifndef DBG_PROP
  25. # define DBG_PROP 0
  26. #endif
  27. HRESULT
  28. PropSetRequestTimeProperty(
  29. IN ICertDBRow *prow,
  30. IN WCHAR const *pwszProp)
  31. {
  32. HRESULT hr;
  33. SYSTEMTIME st;
  34. FILETIME ft;
  35. GetSystemTime(&st);
  36. if (!SystemTimeToFileTime(&st, &ft))
  37. {
  38. hr = myHLastError();
  39. _JumpError(hr, error, "SystemTimeToFileTime");
  40. }
  41. hr = prow->SetProperty(
  42. pwszProp,
  43. PROPTYPE_DATE | PROPCALLER_SERVER | PROPTABLE_REQUEST,
  44. sizeof(ft),
  45. (BYTE *) &ft);
  46. _JumpIfError(hr, error, "SetProperty");
  47. error:
  48. return(hr);
  49. }
  50. HRESULT
  51. PropParseRequest(
  52. IN ICertDBRow *prow,
  53. IN DWORD dwFlags,
  54. IN DWORD cbRequest,
  55. IN BYTE const *pbRequest,
  56. IN OUT CERTSRV_RESULT_CONTEXT *pResult)
  57. {
  58. HRESULT hr;
  59. pResult->dwFlagsTop = dwFlags;
  60. hr = PKCSParseRequest(
  61. dwFlags,
  62. prow,
  63. cbRequest,
  64. pbRequest,
  65. NULL,
  66. NULL,
  67. pResult);
  68. _JumpIfError(hr, error, "PKCSParseRequest");
  69. error:
  70. return(hr);
  71. }
  72. HRESULT
  73. propVerifyDateRange(
  74. IN ICertDBRow *prow,
  75. IN DWORD Flags,
  76. IN WCHAR const *pwszPropertyName,
  77. IN FILETIME const *pft)
  78. {
  79. HRESULT hr;
  80. DWORD cbProp;
  81. FILETIME ftNotBefore;
  82. FILETIME ftNotAfter;
  83. hr = E_INVALIDARG;
  84. CSASSERT((PROPTYPE_MASK & Flags) == PROPTYPE_DATE);
  85. if ((PROPTABLE_MASK & Flags) != PROPTABLE_CERTIFICATE)
  86. {
  87. _JumpError(hr, error, "Flags: Invalid table");
  88. }
  89. if (0 != mylstrcmpiS(pwszPropertyName, g_wszPropCertificateNotBeforeDate) &&
  90. 0 != mylstrcmpiS(pwszPropertyName, g_wszPropCertificateNotAfterDate))
  91. {
  92. _JumpError(hr, error, "pwszPropertyName: Invalid date property");
  93. }
  94. cbProp = sizeof(ftNotBefore);
  95. hr = prow->GetProperty(
  96. g_wszPropCertificateNotBeforeDate,
  97. Flags,
  98. NULL,
  99. &cbProp,
  100. (BYTE *) &ftNotBefore);
  101. _JumpIfError(hr, error, "GetProperty");
  102. cbProp = sizeof(ftNotAfter);
  103. hr = prow->GetProperty(
  104. g_wszPropCertificateNotAfterDate,
  105. Flags,
  106. NULL,
  107. &cbProp,
  108. (BYTE *) &ftNotAfter);
  109. _JumpIfError(hr, error, "GetProperty");
  110. if (0 > CompareFileTime(pft, &ftNotBefore) ||
  111. 0 < CompareFileTime(pft, &ftNotAfter))
  112. {
  113. CERTSRVDBGPRINTTIME("Old Not Before", &ftNotBefore);
  114. CERTSRVDBGPRINTTIME(" Old Not After", &ftNotAfter);
  115. CERTSRVDBGPRINTTIME(
  116. 0 == mylstrcmpiS(
  117. pwszPropertyName,
  118. g_wszPropCertificateNotBeforeDate)?
  119. "New Not Before" : " New Not After",
  120. pft);
  121. hr = E_INVALIDARG;
  122. _JumpErrorStr(hr, error, "FILETIME out of range", pwszPropertyName);
  123. }
  124. error:
  125. return(myHError(hr));
  126. }
  127. // Returns TRUE if names match!
  128. #define PROPNAMEMATCH(cwcNameVariable, pwszNameVariable, wszNameLiteral) \
  129. (WSZARRAYSIZE((wszNameLiteral)) == (cwcNameVariable) && \
  130. 0 == LSTRCMPIS((pwszNameVariable), (wszNameLiteral)))
  131. HRESULT
  132. propGetSystemProperty(
  133. IN WCHAR const *pwszPropName,
  134. IN DWORD Flags,
  135. IN LONG Context,
  136. OUT BOOL *pfSystemProperty,
  137. OUT VARIANT *pvarPropertyValue)
  138. {
  139. HRESULT hr = S_OK;
  140. BYTE *pbFree = NULL;
  141. DWORD cwcPropName;
  142. DWORD cwcBaseName;
  143. WCHAR wszBaseName[32];
  144. WCHAR const *pwszIndex;
  145. WCHAR wszRenewalSuffix[cwcFILENAMESUFFIXMAX];
  146. DWORD iCert = MAXDWORD;
  147. DWORD iCRL;
  148. DWORD iDummy;
  149. DWORD State;
  150. DWORD PropType;
  151. DWORD cbCopy;
  152. DWORD cbOut;
  153. BYTE const *pbOut = NULL; // PROPTYPE_LONG or PROPTYPE_BINARY
  154. WCHAR const *pwszOut = NULL; // PROPTYPE_STRING
  155. CRL_CONTEXT const *pCRL = NULL;
  156. CERTSRV_COM_CONTEXT *pComContext;
  157. BOOL fT;
  158. *pfSystemProperty = FALSE;
  159. wszRenewalSuffix[0] = L'\0';
  160. cbOut = 0;
  161. // Allow "PropName.#"
  162. // Copy the base part of the property name to a local buffer, so we can do
  163. // case ignore string compares.
  164. cwcPropName = wcslen(pwszPropName);
  165. cwcBaseName = wcscspn(pwszPropName, L".");
  166. if (ARRAYSIZE(wszBaseName) - 1 < cwcBaseName)
  167. {
  168. cwcBaseName = ARRAYSIZE(wszBaseName) - 1;
  169. }
  170. CopyMemory(wszBaseName, pwszPropName, cwcBaseName * sizeof(WCHAR));
  171. wszBaseName[cwcBaseName] = L'\0';
  172. pwszIndex = &pwszPropName[cwcBaseName];
  173. if (L'.' == *pwszIndex)
  174. {
  175. pwszIndex++;
  176. iCert = _wtol(pwszIndex);
  177. for ( ; L'\0' != *pwszIndex; pwszIndex++)
  178. {
  179. if (!iswdigit(*pwszIndex))
  180. {
  181. CSASSERT(S_OK == hr); // Not a system property, return S_OK
  182. goto error;
  183. }
  184. }
  185. }
  186. // Assume property type is a long:
  187. PropType = PROPTYPE_LONG;
  188. *pfSystemProperty = TRUE;
  189. if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPCATYPE))
  190. {
  191. pbOut = (BYTE const *) &g_CAType;
  192. cbOut = sizeof(g_CAType);
  193. }
  194. else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPUSEDS))
  195. {
  196. pbOut = (BYTE const *) &g_fUseDS;
  197. cbOut = sizeof(g_fUseDS);
  198. }
  199. else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPDELTACRLSDISABLED))
  200. {
  201. pbOut = (BYTE const *) &g_fDeltaCRLPublishDisabled;
  202. cbOut = sizeof(g_fDeltaCRLPublishDisabled);
  203. }
  204. else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPSERVERUPGRADED))
  205. {
  206. pbOut = (BYTE const *) &g_fServerUpgraded;
  207. cbOut = sizeof(g_fServerUpgraded);
  208. }
  209. else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPLOGLEVEL))
  210. {
  211. pbOut = (BYTE const *) &g_dwLogLevel;
  212. cbOut = sizeof(g_dwLogLevel);
  213. }
  214. else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPSESSIONCOUNT))
  215. {
  216. pbOut = (BYTE const *) &g_dwSessionCount;
  217. cbOut = sizeof(g_dwSessionCount);
  218. }
  219. else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPREQUESTERTOKEN))
  220. {
  221. hr = ComGetClientInfo(Context, MAXDWORD, &pComContext);
  222. _JumpIfError(hr, error, "ComGetClientInfo");
  223. if (NULL == pComContext->hAccessToken ||
  224. INVALID_HANDLE_VALUE == pComContext->hAccessToken)
  225. {
  226. hr = CERTSRV_E_PROPERTY_EMPTY;
  227. _JumpError(hr, error, "ComGetClientInfo(bad hAccessToken)");
  228. }
  229. pbOut = (BYTE const *) &pComContext->hAccessToken;
  230. cbOut = sizeof(pComContext->hAccessToken);
  231. PropType = PROPTYPE_BINARY;
  232. }
  233. else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPREQUESTERCAACCESS))
  234. {
  235. hr = ComGetClientInfo(Context, MAXDWORD, &pComContext);
  236. _JumpIfError(hr, error, "ComGetClientInfo");
  237. if (0 == (CCCF_INREQUESTGROUPSET & pComContext->dwFlags))
  238. {
  239. hr = CERTSRV_E_PROPERTY_EMPTY;
  240. _JumpError(hr, error, "ComGetClientInfo(fInRequestGroup not set)");
  241. }
  242. fT = (CCCF_INREQUESTGROUP & pComContext->dwFlags)? TRUE : FALSE;
  243. pbOut = (BYTE const *) &fT;
  244. cbOut = sizeof(fT);
  245. }
  246. else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPKEYARCHIVED))
  247. {
  248. hr = ComGetClientInfo(Context, MAXDWORD, &pComContext);
  249. _JumpIfError(hr, error, "ComGetClientInfo");
  250. if (0 == (CCCF_KEYARCHIVEDSET & pComContext->dwFlags))
  251. {
  252. hr = CoreSetArchivedKey(pComContext);
  253. _JumpIfError(hr, error, "CoreSetArchivedKey");
  254. CSASSERT(CCCF_KEYARCHIVEDSET & pComContext->dwFlags);
  255. }
  256. fT = (CCCF_KEYARCHIVED & pComContext->dwFlags)? TRUE : FALSE;
  257. pbOut = (BYTE const *) &fT;
  258. cbOut = sizeof(fT);
  259. }
  260. else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPUSERDN))
  261. {
  262. hr = ComGetClientInfo(Context, MAXDWORD, &pComContext);
  263. _JumpIfError(hr, error, "ComGetClientInfo");
  264. if (NULL == pComContext->pwszUserDN)
  265. {
  266. if (!g_fUseDS)
  267. {
  268. hr = CERTSRV_E_PROPERTY_EMPTY;
  269. _JumpError(hr, error, "ComGetClientInfo(bad pwszUserDN)");
  270. }
  271. hr = CoreSetComContextUserDN(
  272. pComContext->RequestId,
  273. Context,
  274. MAXDWORD,
  275. &pwszOut);
  276. _JumpIfError(hr, error, "CoreSetComContextUserDN");
  277. }
  278. pwszOut = pComContext->pwszUserDN;
  279. }
  280. else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPCERTCOUNT))
  281. {
  282. pbOut = (BYTE const *) &g_cCACerts;
  283. cbOut = sizeof(g_cCACerts);
  284. }
  285. else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPSANITIZEDCANAME))
  286. {
  287. pwszOut = g_wszSanitizedName;
  288. }
  289. else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPSANITIZEDSHORTNAME))
  290. {
  291. pwszOut = g_pwszSanitizedDSName;
  292. }
  293. else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPMACHINEDNSNAME))
  294. {
  295. pwszOut = g_pwszServerName;
  296. }
  297. else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPCONFIGDN))
  298. {
  299. pwszOut = g_strConfigDN;
  300. }
  301. else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPDOMAINDN))
  302. {
  303. pwszOut = g_strDomainDN;
  304. }
  305. else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPMODULEREGLOC))
  306. {
  307. // future: cache storage location once it is built
  308. WCHAR *pwszQuasiPath;
  309. DWORD cwcQuasiPath;
  310. WCHAR const *pwszPrefix;
  311. MarshalInterface *pIF;
  312. if ((PROPCALLER_MASK & Flags) == PROPCALLER_POLICY)
  313. {
  314. pIF = &g_miPolicy;
  315. cwcQuasiPath = ARRAYSIZE(L"Policy\\"); // includes L'\0'
  316. pwszPrefix = L"Policy\\";
  317. }
  318. else
  319. {
  320. hr = ExitGetActiveModule(Context, &pIF);
  321. _JumpIfError(hr, error, "ExitGetActiveModule");
  322. cwcQuasiPath = ARRAYSIZE(L"Exit\\"); // includes L'\0'
  323. pwszPrefix = L"Exit\\";
  324. }
  325. cwcQuasiPath += wcslen(pIF->GetProgID());
  326. pwszQuasiPath = (WCHAR *) LocalAlloc(
  327. LMEM_FIXED,
  328. cwcQuasiPath * sizeof(WCHAR));
  329. if (NULL == pwszQuasiPath)
  330. {
  331. hr = E_OUTOFMEMORY;
  332. _JumpError(hr, error, "LocalAlloc");
  333. }
  334. wcscpy(pwszQuasiPath, pwszPrefix);
  335. wcscat(pwszQuasiPath, pIF->GetProgID());
  336. hr = myRegOpenRelativeKey(
  337. pIF->GetConfig(),
  338. pwszQuasiPath,
  339. RORKF_FULLPATH | RORKF_CREATESUBKEYS,
  340. (WCHAR **) &pwszOut,
  341. NULL,
  342. NULL);
  343. LocalFree(pwszQuasiPath);
  344. _JumpIfError(hr, error, "myRegOpenRelativeKey");
  345. CSASSERT(NULL != pwszOut);
  346. pbFree = (BYTE *) pwszOut;
  347. }
  348. else if (PROPNAMEMATCH(cwcBaseName, wszBaseName, wszPROPRAWCACERTIFICATE))
  349. {
  350. hr = PKCSGetCACert(
  351. CR_PROP_CASIGCERT,
  352. iCert,
  353. const_cast<BYTE **>(&pbOut),
  354. &cbOut); // not alloc'd
  355. _JumpIfError(hr, error, "PKCSGetCACert");
  356. PropType = PROPTYPE_BINARY;
  357. }
  358. else if (PROPNAMEMATCH(cwcBaseName, wszBaseName, wszPROPRAWCRL))
  359. {
  360. hr = CRLGetCRL(iCert, FALSE, &pCRL, NULL);
  361. _JumpIfError(hr, error, "CRLGetCRL");
  362. cbOut = pCRL->cbCrlEncoded;
  363. pbOut = pCRL->pbCrlEncoded;
  364. PropType = PROPTYPE_BINARY;
  365. }
  366. else if (PROPNAMEMATCH(cwcBaseName, wszBaseName, wszPROPRAWDELTACRL))
  367. {
  368. hr = CRLGetCRL(iCert, TRUE, &pCRL, NULL);
  369. _JumpIfError2(
  370. hr,
  371. error,
  372. "CRLGetCRL",
  373. HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
  374. cbOut = pCRL->cbCrlEncoded;
  375. pbOut = pCRL->pbCrlEncoded;
  376. PropType = PROPTYPE_BINARY;
  377. }
  378. else if (PROPNAMEMATCH(cwcBaseName, wszBaseName, wszPROPCERTSTATE))
  379. {
  380. hr = PKCSMapCertIndex(iCert, &iCert, &State);
  381. _JumpIfError(hr, error, "PKCSMapCertIndex");
  382. pbOut = (BYTE *) &State;
  383. cbOut = sizeof(State);
  384. }
  385. else if (PROPNAMEMATCH(cwcBaseName, wszBaseName, wszPROPCERTSUFFIX))
  386. {
  387. hr = PKCSMapCertIndex(iCert, &iCert, &State);
  388. _JumpIfError(hr, error, "PKCSMapCertIndex");
  389. pwszOut = wszRenewalSuffix;
  390. }
  391. else if (PROPNAMEMATCH(cwcBaseName, wszBaseName, wszPROPCRLINDEX))
  392. {
  393. hr = PKCSMapCRLIndex(iCert, &iCert, &iCRL, &State);
  394. _JumpIfError(hr, error, "PKCSMapCRLIndex");
  395. pbOut = (BYTE *) &iCRL;
  396. cbOut = sizeof(iCRL);
  397. }
  398. else if (PROPNAMEMATCH(cwcBaseName, wszBaseName, wszPROPCRLSTATE))
  399. {
  400. hr = PKCSMapCRLIndex(iCert, &iCert, &iCRL, &State);
  401. _JumpIfError(hr, error, "PKCSMapCRLIndex");
  402. pbOut = (BYTE *) &State;
  403. cbOut = sizeof(State);
  404. }
  405. else if (PROPNAMEMATCH(cwcBaseName, wszBaseName, wszPROPCRLSUFFIX))
  406. {
  407. hr = PKCSMapCRLIndex(iCert, &iDummy, &iCert, &State);
  408. _JumpIfError(hr, error, "PKCSMapCRLIndex");
  409. pwszOut = wszRenewalSuffix;
  410. }
  411. else if(PROPNAMEMATCH(cwcBaseName, wszBaseName, wszPROPTEMPLATECHANGESEQUENCENUMBER))
  412. {
  413. pbOut = (BYTE const *) &g_cTemplateUpdateSequenceNum;
  414. cbOut = sizeof(g_cTemplateUpdateSequenceNum);
  415. }
  416. else
  417. {
  418. CSASSERT(S_OK == hr); // Not a system property, return S_OK
  419. *pfSystemProperty = FALSE;
  420. goto error;
  421. }
  422. CSASSERT((NULL != pbOut) ^ (NULL != pwszOut)); // exactly 1 must be set
  423. cbCopy = cbOut;
  424. if (NULL != pwszOut)
  425. {
  426. if (wszRenewalSuffix == pwszOut && 0 != iCert)
  427. {
  428. wsprintf(wszRenewalSuffix, L"(%u)", iCert);
  429. }
  430. PropType = PROPTYPE_STRING;
  431. cbOut = wcslen(pwszOut) * sizeof(WCHAR);
  432. cbCopy = cbOut + sizeof(WCHAR);
  433. pbOut = (BYTE *) pwszOut;
  434. }
  435. if ((PROPTYPE_MASK & Flags) != PropType)
  436. {
  437. hr = E_INVALIDARG;
  438. _JumpError2(hr, error, "bad PropType", hr);
  439. }
  440. hr = myUnmarshalVariant(
  441. PROPMARSHAL_LOCALSTRING | Flags,
  442. cbOut,
  443. pbOut,
  444. pvarPropertyValue);
  445. _JumpIfError(hr, error, "myUnmarshalVariant");
  446. error:
  447. if (NULL != pCRL)
  448. {
  449. CertFreeCRLContext(pCRL);
  450. }
  451. if (NULL != pbFree)
  452. {
  453. LocalFree(pbFree);
  454. }
  455. return(hr);
  456. }
  457. class CComputedProperty : public ICertDBComputedColumn
  458. {
  459. public:
  460. CComputedProperty();
  461. ~CComputedProperty();
  462. // IUnknown
  463. STDMETHODIMP QueryInterface(const IID& iid, void **ppv);
  464. ULONG STDMETHODCALLTYPE AddRef();
  465. ULONG STDMETHODCALLTYPE Release();
  466. STDMETHOD(GetAlternateColumnId)(
  467. IN DWORD ComputedColumnId,
  468. OUT DWORD *pAlternateColumnId,
  469. OUT DWORD *pPropType);
  470. STDMETHOD(ComputeColumnValue)(
  471. IN DWORD ComputedColumnId,
  472. IN DWORD AlternateColumnId,
  473. IN DWORD PropType,
  474. IN DWORD cbProp,
  475. IN BYTE const *pbProp,
  476. OUT DWORD *pdwValue);
  477. HRESULT SavePropertyArgument(
  478. IN WCHAR const *pwszPropIn,
  479. OUT WCHAR **ppwszPropOut);
  480. private:
  481. WCHAR *m_pwszArg;
  482. // Reference count
  483. long m_cRef;
  484. };
  485. CComputedProperty::CComputedProperty()
  486. {
  487. m_pwszArg = NULL;
  488. m_cRef = 1;
  489. }
  490. CComputedProperty::~CComputedProperty()
  491. {
  492. if (NULL != m_pwszArg)
  493. {
  494. LocalFree(m_pwszArg);
  495. }
  496. }
  497. STDMETHODIMP
  498. CComputedProperty::QueryInterface(
  499. const IID& iid,
  500. void **ppv)
  501. {
  502. HRESULT hr;
  503. if (NULL == ppv)
  504. {
  505. hr = E_POINTER;
  506. _JumpError(hr, error, "NULL parm");
  507. }
  508. if (iid == IID_IUnknown)
  509. {
  510. *ppv = static_cast<ICertDBComputedColumn *>(this);
  511. }
  512. else if (iid == IID_ICertDBComputedColumn)
  513. {
  514. *ppv = static_cast<ICertDBComputedColumn *>(this);
  515. }
  516. else
  517. {
  518. *ppv = NULL;
  519. hr = E_NOINTERFACE;
  520. _JumpError(hr, error, "IID");
  521. }
  522. reinterpret_cast<IUnknown *>(*ppv)->AddRef();
  523. hr = S_OK;
  524. error:
  525. return(hr);
  526. }
  527. ULONG STDMETHODCALLTYPE
  528. CComputedProperty::AddRef()
  529. {
  530. return(InterlockedIncrement(&m_cRef));
  531. }
  532. ULONG STDMETHODCALLTYPE
  533. CComputedProperty::Release()
  534. {
  535. ULONG cRef = InterlockedDecrement(&m_cRef);
  536. if (0 == cRef)
  537. {
  538. delete this;
  539. }
  540. return(cRef);
  541. }
  542. STDMETHODIMP
  543. CComputedProperty::ComputeColumnValue(
  544. IN DWORD ComputedColumnId,
  545. IN DWORD AlternateColumnId,
  546. IN DWORD PropType,
  547. IN DWORD cbProp,
  548. IN BYTE const *pbProp,
  549. OUT DWORD *pdwValue)
  550. {
  551. HRESULT hr;
  552. WCHAR const *pwszRequesterName;
  553. *pdwValue = 0;
  554. if (NULL == m_pwszArg)
  555. {
  556. hr = CERTSRV_E_PROPERTY_EMPTY;
  557. _JumpError(hr, error, "m_pwszArg NULL");
  558. }
  559. if ((DTI_REQUESTTABLE | DTR_OFFICER) != ComputedColumnId ||
  560. (DTI_REQUESTTABLE | DTR_REQUESTERNAME) != AlternateColumnId ||
  561. PROPTYPE_STRING != PropType ||
  562. 0 == cbProp ||
  563. ((sizeof(WCHAR) - 1) & cbProp))
  564. {
  565. hr = CERTSRV_E_PROPERTY_EMPTY;
  566. _JumpError(hr, error, "ComputedColumnId");
  567. }
  568. pwszRequesterName = (WCHAR const *) pbProp;
  569. CSASSERT(L'\0' == pwszRequesterName[cbProp / sizeof(WCHAR)]);
  570. CSASSERT(sizeof(WCHAR) * wcslen(pwszRequesterName) == cbProp);
  571. hr = CheckOfficerRightsFromOfficerName(m_pwszArg, pwszRequesterName);
  572. if (S_OK == hr)
  573. {
  574. *pdwValue = 1;
  575. }
  576. else if (CERTSRV_E_RESTRICTEDOFFICER == hr)
  577. {
  578. hr = S_OK;
  579. }
  580. _JumpIfError(hr, error, "CheckOfficerRightsFromOfficerName");
  581. error:
  582. DBGPRINT((
  583. DBG_SS_CERTSRV,
  584. "ComputeColumnValue(%ws) = %u hr=%x\n",
  585. (WCHAR const *) pbProp,
  586. *pdwValue,
  587. hr));
  588. return(hr);
  589. }
  590. HRESULT
  591. CComputedProperty::SavePropertyArgument(
  592. IN WCHAR const *pwszPropIn,
  593. OUT WCHAR **ppwszPropOut)
  594. {
  595. HRESULT hr;
  596. WCHAR *pwszT;
  597. CSASSERT(NULL == m_pwszArg);
  598. hr = myDupString(pwszPropIn, ppwszPropOut);
  599. _JumpIfError(hr, error, "myDupString");
  600. pwszT = wcschr(*ppwszPropOut, wcLPAREN);
  601. if (NULL != pwszT)
  602. {
  603. WCHAR *pwsz2 = pwszT;
  604. while (--pwsz2 >= *ppwszPropOut && L' ' == *pwsz2)
  605. {
  606. *pwsz2 = L'\0';
  607. }
  608. *pwszT++ = L'\0';
  609. while (L' ' == *pwszT)
  610. {
  611. pwszT++;
  612. }
  613. hr = myDupString(pwszT, &m_pwszArg);
  614. _JumpIfError(hr, error, "myDupString");
  615. pwszT = wcschr(m_pwszArg, wcRPAREN);
  616. if (NULL == pwszT)
  617. {
  618. hr = E_INVALIDARG;
  619. _JumpErrorStr(hr, error, "SavePropertyArgument", pwszPropIn);
  620. }
  621. do
  622. {
  623. *pwszT-- = L'\0';
  624. } while (pwszT >= m_pwszArg && L' ' == *pwszT);
  625. }
  626. hr = S_OK;
  627. error:
  628. return(hr);
  629. }
  630. STDMETHODIMP
  631. CComputedProperty::GetAlternateColumnId(
  632. IN DWORD ComputedColumnId,
  633. OUT DWORD *pAlternateColumnId,
  634. OUT DWORD *pPropType)
  635. {
  636. HRESULT hr;
  637. *pAlternateColumnId = 0;
  638. if ((DTI_REQUESTTABLE | DTR_OFFICER) != ComputedColumnId)
  639. {
  640. hr = CERTSRV_E_PROPERTY_EMPTY;
  641. _JumpError(hr, error, "ComputedColumnId");
  642. }
  643. *pAlternateColumnId = DTI_REQUESTTABLE | DTR_REQUESTERNAME;
  644. *pPropType = PROPTYPE_STRING;
  645. hr = S_OK;
  646. error:
  647. return(hr);
  648. }
  649. FNCIGETPROPERTY PropCIGetProperty;
  650. HRESULT
  651. PropCIGetProperty(
  652. IN LONG Context,
  653. IN DWORD Flags,
  654. IN WCHAR const *pwszPropertyName,
  655. OUT VARIANT *pvarPropertyValue)
  656. {
  657. HRESULT hr;
  658. DWORD RequestId;
  659. DWORD cbprop;
  660. BYTE *pbprop = NULL;
  661. ICertDBRow *prow = NULL;
  662. BYTE rgbFastBuf[128]; // many properties are small (128)
  663. BOOL fSystemProperty;
  664. CComputedProperty ccp;
  665. WCHAR *pwszPropAlloc = NULL;
  666. if (NULL != pvarPropertyValue)
  667. {
  668. VariantInit(pvarPropertyValue);
  669. }
  670. if (NULL == pwszPropertyName || NULL == pvarPropertyValue)
  671. {
  672. hr = E_POINTER;
  673. _JumpError(hr, error, "NULL parm");
  674. }
  675. hr = E_INVALIDARG;
  676. if ((PROPCALLER_MASK & Flags) != PROPCALLER_POLICY &&
  677. (PROPCALLER_MASK & Flags) != PROPCALLER_EXIT &&
  678. (PROPCALLER_MASK & Flags) != PROPCALLER_SERVER)
  679. {
  680. _JumpError(hr, error, "Flags: Invalid caller");
  681. }
  682. if ((PROPTABLE_MASK & Flags) != PROPTABLE_REQUEST &&
  683. (PROPTABLE_MASK & Flags) != PROPTABLE_CERTIFICATE &&
  684. (PROPTABLE_MASK & Flags) != PROPTABLE_ATTRIBUTE)
  685. {
  686. _JumpError(hr, error, "Flags: Invalid table");
  687. }
  688. fSystemProperty = FALSE;
  689. if ((PROPTABLE_MASK & Flags) == PROPTABLE_CERTIFICATE)
  690. {
  691. hr = ComVerifyRequestContext(TRUE, Flags, Context, &RequestId);
  692. _JumpIfError(hr, error, "ComVerifyRequestContext");
  693. // Check for special, hard-coded properties first
  694. hr = propGetSystemProperty(
  695. pwszPropertyName,
  696. Flags,
  697. Context,
  698. &fSystemProperty,
  699. pvarPropertyValue);
  700. _JumpIfErrorStr2(
  701. hr,
  702. error,
  703. "propGetSystemProperty",
  704. pwszPropertyName,
  705. E_INVALIDARG);
  706. }
  707. if (!fSystemProperty)
  708. {
  709. DWORD VerifyFlags = Flags;
  710. if (((PROPCALLER_MASK | PROPTABLE_MASK | PROPTYPE_MASK) & Flags) ==
  711. (PROPCALLER_SERVER | PROPTABLE_REQUEST | PROPTYPE_LONG) &&
  712. 0 == LSTRCMPIS(pwszPropertyName, wszPROPREQUESTREQUESTID))
  713. {
  714. VerifyFlags = PROPCALLER_EXIT | (~PROPCALLER_MASK & VerifyFlags);
  715. }
  716. hr = ComVerifyRequestContext(FALSE, VerifyFlags, Context, &RequestId);
  717. _JumpIfError(hr, error, "ComVerifyRequestContext");
  718. pbprop = rgbFastBuf;
  719. cbprop = sizeof(rgbFastBuf);
  720. // PROPCALLER_SERVER indicates this call is only for Context validation
  721. // -- return a zero RequestId. This keeps CRL publication exit module
  722. // notification from failing.
  723. if (0 == RequestId &&
  724. ((PROPCALLER_MASK | PROPTABLE_MASK | PROPTYPE_MASK) & Flags) ==
  725. (PROPCALLER_SERVER | PROPTABLE_REQUEST | PROPTYPE_LONG) &&
  726. 0 == LSTRCMPIS(pwszPropertyName, wszPROPREQUESTREQUESTID))
  727. {
  728. *(DWORD *) pbprop = 0;
  729. cbprop = sizeof(DWORD);
  730. }
  731. else
  732. {
  733. WCHAR const *pwszPropT;
  734. if (PROPTYPE_STRING == (PROPTYPE_MASK & Flags) &&
  735. PROPTABLE_CERTIFICATE == (PROPTABLE_MASK & Flags))
  736. {
  737. BOOL fSubjectDot;
  738. hr = PKCSVerifySubjectRDN(
  739. NULL, // prow
  740. &pwszPropertyName,
  741. NULL, // pwszPropertyValue
  742. &fSubjectDot);
  743. _JumpIfError(hr, error, "PKCSVerifySubjectRDN");
  744. }
  745. hr = g_pCertDB->OpenRow(
  746. PROPOPEN_READONLY | PROPTABLE_REQCERT,
  747. RequestId,
  748. NULL,
  749. &prow);
  750. _JumpIfError(hr, error, "OpenRow");
  751. if ((PROPTABLE_MASK & Flags) == PROPTABLE_REQUEST ||
  752. (PROPTABLE_MASK & Flags) == PROPTABLE_CERTIFICATE)
  753. {
  754. hr = ccp.SavePropertyArgument(pwszPropertyName, &pwszPropAlloc);
  755. _JumpIfError(hr, error, "SavePropertyArgument");
  756. pwszPropT = pwszPropAlloc;
  757. }
  758. else
  759. {
  760. pwszPropT = pwszPropertyName;
  761. }
  762. hr = prow->GetProperty(
  763. pwszPropT,
  764. Flags,
  765. g_OfficerRightsSD.IsEnabled()? &ccp : NULL,
  766. &cbprop,
  767. pbprop);
  768. if (S_OK != hr)
  769. {
  770. if (HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW) != hr)
  771. {
  772. _JumpIfError3(
  773. hr,
  774. error,
  775. "GetProperty",
  776. CERTSRV_E_PROPERTY_EMPTY,
  777. E_INVALIDARG);
  778. }
  779. CSASSERT(ARRAYSIZE(rgbFastBuf) < cbprop);
  780. DBGPRINT((
  781. DBG_SS_CERTSRVI,
  782. "FastBuf miss: PropCIGetProperty - pbprop %i bytes\n",
  783. cbprop));
  784. pbprop = (BYTE *) LocalAlloc(LMEM_FIXED, cbprop);
  785. if (NULL == pbprop)
  786. {
  787. hr = E_OUTOFMEMORY;
  788. _JumpError(hr, error, "LocalAlloc");
  789. }
  790. hr = prow->GetProperty(
  791. pwszPropT,
  792. Flags,
  793. g_OfficerRightsSD.IsEnabled()? &ccp : NULL,
  794. &cbprop,
  795. pbprop);
  796. _JumpIfError(hr, error, "GetProperty");
  797. }
  798. } // property is in-hand
  799. if ((((PROPTABLE_MASK | PROPTYPE_MASK) & Flags) ==
  800. (PROPTABLE_REQUEST | PROPTYPE_BINARY)) &&
  801. (0 == LSTRCMPIS(pwszPropertyName, wszPROPREQUESTRAWARCHIVEDKEY) ||
  802. 0 == LSTRCMPIS(pwszPropertyName,
  803. wszPROPREQUESTDOT wszPROPREQUESTRAWARCHIVEDKEY)))
  804. {
  805. *pbprop = 0;
  806. cbprop = sizeof(*pbprop);
  807. }
  808. hr = myUnmarshalVariant(
  809. PROPMARSHAL_LOCALSTRING | Flags,
  810. cbprop,
  811. pbprop,
  812. pvarPropertyValue);
  813. _JumpIfError(hr, error, "myUnmarshalVariant");
  814. }
  815. error:
  816. if (NULL != prow)
  817. {
  818. prow->Release();
  819. }
  820. if (NULL != pbprop && pbprop != rgbFastBuf)
  821. {
  822. LocalFree(pbprop);
  823. }
  824. if (NULL != pwszPropAlloc)
  825. {
  826. LocalFree(pwszPropAlloc);
  827. }
  828. return(myHError(hr));
  829. }
  830. HRESULT
  831. propSetSystemProperty(
  832. IN WCHAR const *pwszPropName,
  833. IN DWORD Flags,
  834. OUT BOOL *pfSystemProperty,
  835. IN VARIANT const *pvarPropertyValue)
  836. {
  837. HRESULT hr = S_OK;
  838. DWORD LogLevel = MAXDWORD;
  839. DWORD infotype = EVENTLOG_INFORMATION_TYPE;
  840. DWORD LogMsg = MSG_POLICY_LOG_INFORMATION;
  841. WCHAR *pwsz = NULL;
  842. DWORD cwcMax;
  843. *pfSystemProperty = FALSE;
  844. cwcMax = 1;
  845. if (0 == LSTRCMPIS(pwszPropName, wszPROPEVENTLOGTERSE))
  846. {
  847. LogLevel = CERTLOG_TERSE;
  848. }
  849. else
  850. if (0 == LSTRCMPIS(pwszPropName, wszPROPEVENTLOGERROR))
  851. {
  852. LogLevel = CERTLOG_ERROR;
  853. infotype = EVENTLOG_ERROR_TYPE;
  854. LogMsg = MSG_POLICY_LOG_ERROR;
  855. }
  856. else
  857. if (0 == LSTRCMPIS(pwszPropName, wszPROPEVENTLOGWARNING))
  858. {
  859. LogLevel = CERTLOG_WARNING;
  860. infotype = EVENTLOG_WARNING_TYPE;
  861. LogMsg = MSG_POLICY_LOG_WARNING;
  862. }
  863. else
  864. if (0 == LSTRCMPIS(pwszPropName, wszPROPEVENTLOGVERBOSE))
  865. {
  866. LogLevel = CERTLOG_VERBOSE;
  867. }
  868. else
  869. if (0 == LSTRCMPIS(pwszPropName, wszPROPDCNAME))
  870. {
  871. pwsz = g_wszPolicyDCName;
  872. cwcMax = g_cwcPolicyDCName;
  873. }
  874. else
  875. {
  876. CSASSERT(S_OK == hr); // Not a system property, return S_OK
  877. goto error;
  878. }
  879. *pfSystemProperty = TRUE;
  880. if (PROPTYPE_STRING != (PROPTYPE_MASK & Flags) ||
  881. VT_BSTR != pvarPropertyValue->vt ||
  882. NULL == pvarPropertyValue->bstrVal)
  883. {
  884. hr = E_INVALIDARG;
  885. _JumpErrorStr(hr, error, "string property value/type", pwszPropName);
  886. }
  887. if (NULL != pwsz)
  888. {
  889. // Terminate first to avoid problems with multi-threaded access.
  890. pwsz[cwcMax - 1] = L'\0';
  891. wcsncpy(pwsz, pvarPropertyValue->bstrVal, cwcMax - 1);
  892. }
  893. else
  894. {
  895. CSASSERT(MAXDWORD != LogLevel);
  896. if (LogLevel <= g_dwLogLevel)
  897. {
  898. WCHAR const *apwsz[2];
  899. WCHAR const *pwszMessage = pvarPropertyValue->bstrVal;
  900. HRESULT hrPrefix;
  901. if (ComParseErrorPrefix(
  902. pvarPropertyValue->bstrVal,
  903. &hrPrefix,
  904. &pwszMessage))
  905. {
  906. }
  907. else
  908. {
  909. pwszMessage = pvarPropertyValue->bstrVal;
  910. }
  911. apwsz[0] = g_strPolicyDescription;
  912. apwsz[1] = pwszMessage;
  913. hr = LogEvent(infotype, LogMsg, ARRAYSIZE(apwsz), apwsz);
  914. _JumpIfError(hr, error, "LogEvent");
  915. }
  916. }
  917. hr = S_OK;
  918. error:
  919. return(myHError(hr));
  920. }
  921. FNCISETPROPERTY PropCISetProperty;
  922. HRESULT
  923. PropCISetProperty(
  924. IN LONG Context,
  925. IN DWORD Flags,
  926. IN WCHAR const *pwszPropertyName,
  927. IN VARIANT const *pvarPropertyValue)
  928. {
  929. HRESULT hr;
  930. DWORD RequestId;
  931. DWORD cbprop;
  932. BYTE *pbprop = NULL;
  933. ICertDBRow *prow = NULL;
  934. BOOL fSubjectDot = FALSE;
  935. BOOL fSystemProperty;
  936. BOOL fCommitted = FALSE;
  937. if (NULL == pwszPropertyName || NULL == pvarPropertyValue)
  938. {
  939. hr = E_POINTER;
  940. _JumpError(hr, error, "NULL parm");
  941. }
  942. hr = E_INVALIDARG;
  943. if ((PROPCALLER_MASK & Flags) != PROPCALLER_POLICY)
  944. {
  945. _JumpError(hr, error, "Flags: Invalid caller");
  946. }
  947. if ((PROPTABLE_MASK & Flags) != PROPTABLE_CERTIFICATE)
  948. {
  949. _JumpError(hr, error, "Flags: Invalid table");
  950. }
  951. hr = ComVerifyRequestContext(TRUE, Flags, Context, &RequestId);
  952. _JumpIfError(hr, error, "ComVerifyRequestContext");
  953. // Check for special, hard-coded properties first
  954. fSystemProperty = FALSE;
  955. hr = propSetSystemProperty(
  956. pwszPropertyName,
  957. Flags,
  958. &fSystemProperty,
  959. pvarPropertyValue);
  960. _JumpIfError(hr, error, "propSetSystemProperty");
  961. if (!fSystemProperty)
  962. {
  963. hr = ComVerifyRequestContext(FALSE, Flags, Context, &RequestId);
  964. _JumpIfError(hr, error, "ComVerifyRequestContext");
  965. hr = myMarshalVariant(
  966. pvarPropertyValue,
  967. PROPMARSHAL_NULLBSTROK | PROPMARSHAL_LOCALSTRING | Flags,
  968. &cbprop,
  969. &pbprop);
  970. _JumpIfError(hr, error, "myMarshalVariant");
  971. hr = g_pCertDB->OpenRow(PROPTABLE_REQCERT, RequestId, NULL, &prow);
  972. _JumpIfError(hr, error, "OpenRow");
  973. if (PROPTYPE_DATE == (PROPTYPE_MASK & Flags))
  974. {
  975. hr = propVerifyDateRange(
  976. prow,
  977. Flags,
  978. pwszPropertyName,
  979. (FILETIME *) pbprop);
  980. _JumpIfError(hr, error, "propVerifyDateRange");
  981. }
  982. else
  983. if (PROPTYPE_STRING == (PROPTYPE_MASK & Flags) &&
  984. PROPTABLE_CERTIFICATE == (PROPTABLE_MASK & Flags))
  985. {
  986. hr = PKCSVerifySubjectRDN(
  987. prow,
  988. &pwszPropertyName,
  989. (WCHAR const *) pbprop,
  990. &fSubjectDot);
  991. _JumpIfError(hr, error, "PKCSVerifySubjectRDN");
  992. }
  993. if (NULL == pbprop && fSubjectDot)
  994. {
  995. hr = PKCSDeleteAllSubjectRDNs(prow, Flags);
  996. _JumpIfError(hr, error, "PKCSDeleteAllSubjectRDNs");
  997. }
  998. else
  999. {
  1000. hr = prow->SetProperty(pwszPropertyName, Flags, cbprop, pbprop);
  1001. _JumpIfError(hr, error, "SetProperty");
  1002. }
  1003. hr = prow->CommitTransaction(CDBROW_COMMIT_SOFTCOMMIT); // not critical to flush
  1004. _JumpIfError(hr, error, "CommitTransaction");
  1005. fCommitted = TRUE;
  1006. }
  1007. hr = S_OK;
  1008. error:
  1009. if (NULL != prow)
  1010. {
  1011. if (S_OK != hr && !fCommitted)
  1012. {
  1013. HRESULT hr2 = prow->CommitTransaction(CDBROW_COMMIT_ROLLBACK);
  1014. _PrintIfError(hr2, "CommitTransaction");
  1015. }
  1016. prow->Release();
  1017. }
  1018. if (NULL != pbprop)
  1019. {
  1020. LocalFree(pbprop);
  1021. }
  1022. return(myHError(hr));
  1023. }
  1024. HRESULT
  1025. PropGetExtension(
  1026. IN ICertDBRow *prow,
  1027. IN DWORD Flags,
  1028. IN WCHAR const *pwszExtensionName,
  1029. OUT DWORD *pdwExtFlags,
  1030. OUT DWORD *pcbValue,
  1031. OUT BYTE **ppbValue) // LocalAlloc
  1032. {
  1033. HRESULT hr;
  1034. DWORD cbprop;
  1035. BYTE *pbprop = NULL;
  1036. CSASSERT(
  1037. PROPCALLER_EXIT == (PROPCALLER_MASK & Flags) ||
  1038. PROPCALLER_POLICY == (PROPCALLER_MASK & Flags) ||
  1039. PROPCALLER_SERVER == (PROPCALLER_MASK & Flags));
  1040. CSASSERT(0 == (~(PROPMARSHAL_LOCALSTRING | PROPCALLER_MASK | PROPTYPE_MASK) & Flags));
  1041. hr = myVerifyObjId(pwszExtensionName);
  1042. _JumpIfError(hr, error, "myVerifyObjId");
  1043. cbprop = 0;
  1044. hr = prow->GetExtension(pwszExtensionName, pdwExtFlags, &cbprop, NULL);
  1045. _JumpIfError2(hr, error, "GetExtension(NULL)", CERTSRV_E_PROPERTY_EMPTY);
  1046. pbprop = (BYTE *) LocalAlloc(LMEM_FIXED, cbprop);
  1047. if (NULL == pbprop)
  1048. {
  1049. hr = E_OUTOFMEMORY;
  1050. _JumpError(hr, error, "LocalAlloc(ExtValue)");
  1051. }
  1052. hr = prow->GetExtension(pwszExtensionName, pdwExtFlags, &cbprop, pbprop);
  1053. _JumpIfError(hr, error, "GetExtension");
  1054. if (PROPTYPE_BINARY == (PROPTYPE_MASK & Flags))
  1055. {
  1056. *pcbValue = cbprop;
  1057. *ppbValue = pbprop;
  1058. pbprop = NULL;
  1059. }
  1060. else
  1061. {
  1062. hr = myDecodeExtension(Flags, pbprop, cbprop, ppbValue, pcbValue);
  1063. _JumpIfError(hr, error, "myDecodeExtension");
  1064. }
  1065. error:
  1066. if (NULL != pbprop)
  1067. {
  1068. LocalFree(pbprop);
  1069. }
  1070. return(myHError(hr));
  1071. }
  1072. HRESULT
  1073. PropSetExtension(
  1074. IN ICertDBRow *prow,
  1075. IN DWORD Flags,
  1076. IN WCHAR const *pwszExtensionName,
  1077. IN DWORD ExtFlags,
  1078. IN DWORD cbValue,
  1079. IN BYTE const *pbValue)
  1080. {
  1081. HRESULT hr;
  1082. DWORD cbprop;
  1083. BYTE *pbprop = NULL;
  1084. CSASSERT(
  1085. PROPCALLER_ADMIN == (PROPCALLER_MASK & Flags) ||
  1086. PROPCALLER_POLICY == (PROPCALLER_MASK & Flags) ||
  1087. PROPCALLER_SERVER == (PROPCALLER_MASK & Flags) ||
  1088. PROPCALLER_REQUEST == (PROPCALLER_MASK & Flags));
  1089. CSASSERT(0 == (~(PROPMARSHAL_LOCALSTRING | PROPCALLER_MASK | PROPTYPE_MASK) & Flags));
  1090. hr = myVerifyObjId(pwszExtensionName);
  1091. _JumpIfError(hr, error, "myVerifyObjId");
  1092. if (PROPTYPE_BINARY == (PROPTYPE_MASK & Flags))
  1093. {
  1094. cbprop = cbValue;
  1095. pbprop = (BYTE *) pbValue;
  1096. }
  1097. else
  1098. {
  1099. hr = myEncodeExtension(Flags, pbValue, cbValue, &pbprop, &cbprop);
  1100. _JumpIfError(hr, error, "myEncodeExtension");
  1101. }
  1102. hr = prow->SetExtension(pwszExtensionName, ExtFlags, cbprop, pbprop);
  1103. _JumpIfError(hr, error, "SetExtension");
  1104. error:
  1105. if (NULL != pbprop && pbprop != pbValue)
  1106. {
  1107. LocalFree(pbprop);
  1108. }
  1109. return(hr);
  1110. }
  1111. FNCIGETEXTENSION PropCIGetExtension;
  1112. HRESULT
  1113. PropCIGetExtension(
  1114. IN LONG Context,
  1115. IN DWORD Flags,
  1116. IN WCHAR const *pwszExtensionName,
  1117. OUT DWORD *pdwExtFlags,
  1118. OUT VARIANT *pvarValue)
  1119. {
  1120. HRESULT hr;
  1121. DWORD RequestId;
  1122. BYTE *pbValue = NULL;
  1123. DWORD cbValue;
  1124. ICertDBRow *prow = NULL;
  1125. if (NULL != pvarValue)
  1126. {
  1127. VariantInit(pvarValue);
  1128. }
  1129. if (NULL == pwszExtensionName || NULL == pdwExtFlags || NULL == pvarValue)
  1130. {
  1131. hr = E_POINTER;
  1132. _JumpError(hr, error, "NULL parm");
  1133. }
  1134. hr = ComVerifyRequestContext(FALSE, Flags, Context, &RequestId);
  1135. _JumpIfError(hr, error, "ComVerifyRequestContext");
  1136. hr = g_pCertDB->OpenRow(PROPOPEN_READONLY | PROPTABLE_REQCERT, RequestId, NULL, &prow);
  1137. _JumpIfError(hr, error, "OpenRow");
  1138. hr = PropGetExtension(
  1139. prow,
  1140. PROPMARSHAL_LOCALSTRING | Flags,
  1141. pwszExtensionName,
  1142. pdwExtFlags,
  1143. &cbValue,
  1144. &pbValue);
  1145. _JumpIfError2(hr, error, "PropGetExtension", CERTSRV_E_PROPERTY_EMPTY);
  1146. hr = myUnmarshalVariant(
  1147. PROPMARSHAL_LOCALSTRING | Flags,
  1148. cbValue,
  1149. pbValue,
  1150. pvarValue);
  1151. _JumpIfError(hr, error, "myUnmarshalVariant");
  1152. error:
  1153. if (NULL != prow)
  1154. {
  1155. prow->Release();
  1156. }
  1157. if (NULL != pbValue)
  1158. {
  1159. LocalFree(pbValue);
  1160. }
  1161. return(hr);
  1162. }
  1163. FNCISETPROPERTY PropCISetExtension;
  1164. HRESULT
  1165. PropCISetExtension(
  1166. IN LONG Context,
  1167. IN DWORD Flags,
  1168. IN WCHAR const *pwszExtensionName,
  1169. IN DWORD ExtFlags,
  1170. IN VARIANT const *pvarValue)
  1171. {
  1172. HRESULT hr;
  1173. DWORD RequestId;
  1174. DWORD cbprop;
  1175. BYTE *pbprop = NULL;
  1176. ICertDBRow *prow = NULL;
  1177. BOOL fCommitted = FALSE;
  1178. if (NULL == pwszExtensionName || NULL == pvarValue)
  1179. {
  1180. hr = E_POINTER;
  1181. _JumpError(hr, error, "NULL parm");
  1182. }
  1183. if ((PROPCALLER_MASK & Flags) != PROPCALLER_POLICY)
  1184. {
  1185. hr = E_INVALIDARG;
  1186. _JumpError(hr, error, "Flags: Invalid caller");
  1187. }
  1188. hr = ComVerifyRequestContext(FALSE, Flags, Context, &RequestId);
  1189. _JumpIfError(hr, error, "ComVerifyRequestContext");
  1190. hr = myMarshalVariant(
  1191. pvarValue,
  1192. PROPMARSHAL_LOCALSTRING | Flags,
  1193. &cbprop,
  1194. &pbprop);
  1195. _JumpIfError(hr, error, "myMarshalVariant");
  1196. hr = g_pCertDB->OpenRow(PROPTABLE_REQCERT, RequestId, NULL, &prow);
  1197. _JumpIfError(hr, error, "OpenRow");
  1198. hr = PropSetExtension(
  1199. prow,
  1200. PROPMARSHAL_LOCALSTRING | Flags,
  1201. pwszExtensionName,
  1202. ExtFlags,
  1203. cbprop,
  1204. pbprop);
  1205. _JumpIfError(hr, error, "PropSetExtension");
  1206. hr = prow->CommitTransaction(CDBROW_COMMIT_SOFTCOMMIT); // not critical to flush
  1207. _JumpIfError(hr, error, "CommitTransaction");
  1208. fCommitted = TRUE;
  1209. error:
  1210. if (NULL != prow)
  1211. {
  1212. if (S_OK != hr && !fCommitted)
  1213. {
  1214. HRESULT hr2 = prow->CommitTransaction(CDBROW_COMMIT_ROLLBACK);
  1215. _PrintIfError(hr2, "CommitTransaction");
  1216. }
  1217. prow->Release();
  1218. }
  1219. if (NULL != pbprop)
  1220. {
  1221. LocalFree(pbprop);
  1222. }
  1223. return(myHError(hr));
  1224. }
  1225. FNCIENUMSETUP PropCIEnumSetup;
  1226. HRESULT
  1227. PropCIEnumSetup(
  1228. IN LONG Context,
  1229. IN LONG Flags,
  1230. IN OUT CIENUM *pciEnum)
  1231. {
  1232. HRESULT hr;
  1233. DWORD RequestId;
  1234. CSASSERT(CSExpr(CIE_CALLER_POLICY == PROPCALLER_POLICY));
  1235. CSASSERT(CSExpr(CIE_CALLER_EXIT == PROPCALLER_EXIT));
  1236. CSASSERT(CSExpr(CIE_CALLER_MASK == PROPCALLER_MASK));
  1237. hr = ComVerifyRequestContext(FALSE, Flags, Context, &RequestId);
  1238. _JumpIfError(hr, error, "ComVerifyRequestContext");
  1239. hr = pciEnum->EnumSetup(RequestId, Context, Flags);
  1240. _JumpIfError(hr, error, "EnumSetup");
  1241. error:
  1242. return(hr);
  1243. }
  1244. FNCIENUMNEXT PropCIEnumNext;
  1245. HRESULT
  1246. PropCIEnumNext(
  1247. IN OUT CIENUM *pciEnum,
  1248. OUT BSTR *pstrPropertyName)
  1249. {
  1250. HRESULT hr;
  1251. DWORD RequestId;
  1252. CSASSERT(CSExpr(CIE_CALLER_POLICY == PROPCALLER_POLICY));
  1253. CSASSERT(CSExpr(CIE_CALLER_EXIT == PROPCALLER_EXIT));
  1254. CSASSERT(CSExpr(CIE_CALLER_MASK == PROPCALLER_MASK));
  1255. hr = ComVerifyRequestContext(
  1256. FALSE,
  1257. pciEnum->GetFlags(),
  1258. pciEnum->GetContext(),
  1259. &RequestId);
  1260. _JumpIfError(hr, error, "ComVerifyRequestContext");
  1261. hr = pciEnum->EnumNext(pstrPropertyName);
  1262. _JumpIfError2(hr, error, "EnumNext", S_FALSE);
  1263. error:
  1264. return(hr);
  1265. }
  1266. FNCIENUMCLOSE PropCIEnumClose;
  1267. HRESULT
  1268. PropCIEnumClose(
  1269. IN OUT CIENUM *pciEnum)
  1270. {
  1271. HRESULT hr;
  1272. hr = pciEnum->EnumClose();
  1273. _JumpIfError(hr, error, "EnumClose");
  1274. error:
  1275. return(hr);
  1276. }
  1277. HRESULT
  1278. PropSetAttributeProperty(
  1279. IN ICertDBRow *prow,
  1280. IN BOOL fConcatenateRDNs,
  1281. IN BOOL fPrependNewValue,
  1282. IN DWORD dwTable,
  1283. IN DWORD cwcNameMax,
  1284. OPTIONAL IN WCHAR const *pwszSuffix,
  1285. IN WCHAR const *pwszName,
  1286. IN WCHAR const *pwszValue)
  1287. {
  1288. HRESULT hr = S_OK;
  1289. WCHAR *pwszTemp = NULL;
  1290. WCHAR const *pwszValue2 = pwszValue;
  1291. DWORD cbProp;
  1292. DWORD dwFlags = dwTable | PROPTYPE_STRING | PROPCALLER_SERVER;
  1293. CSASSERT(
  1294. PROPTABLE_ATTRIBUTE == dwTable ||
  1295. PROPTABLE_REQUEST == dwTable ||
  1296. PROPTABLE_CERTIFICATE == dwTable);
  1297. // if the name and value are both non-empty ...
  1298. if (NULL != pwszName && L'\0' != *pwszName &&
  1299. NULL != pwszValue && L'\0' != *pwszValue)
  1300. {
  1301. if (PROPTABLE_ATTRIBUTE != dwTable)
  1302. {
  1303. if (g_fEnforceRDNNameLengths && wcslen(pwszValue) > cwcNameMax)
  1304. {
  1305. hr = CERTSRV_E_BAD_REQUESTSUBJECT;
  1306. DBGPRINT((
  1307. DBG_SS_CERTSRV,
  1308. "RDN component too long: %u/%u: %ws=\"%ws\"\n",
  1309. wcslen(pwszValue),
  1310. cwcNameMax,
  1311. pwszName,
  1312. pwszValue));
  1313. _JumpErrorStr(hr, error, "RDN component too long", pwszValue);
  1314. }
  1315. if (fConcatenateRDNs)
  1316. {
  1317. cbProp = 0;
  1318. hr = prow->GetProperty(pwszName, dwFlags, NULL, &cbProp, NULL);
  1319. if (CERTSRV_E_PROPERTY_EMPTY != hr)
  1320. {
  1321. DWORD cwcAdd;
  1322. _JumpIfError(hr, error, "GetProperty");
  1323. cwcAdd = 1 + wcslen(pwszValue);
  1324. // cbProp includes trailing L'\0' when out buffer is NULL
  1325. pwszTemp = (WCHAR *) LocalAlloc(
  1326. LMEM_FIXED,
  1327. cbProp + sizeof(WCHAR) * cwcAdd);
  1328. if (NULL == pwszTemp)
  1329. {
  1330. hr = E_OUTOFMEMORY;
  1331. _JumpError(hr, error, "LocalAlloc");
  1332. }
  1333. // If there are multiple RDN components for the same DB
  1334. // column, concatenate them.
  1335. if (fPrependNewValue)
  1336. {
  1337. wcscpy(pwszTemp, pwszValue);
  1338. wcscat(pwszTemp, wszNAMESEPARATORDEFAULT);
  1339. CSASSERT(wcslen(pwszTemp) == cwcAdd);
  1340. }
  1341. hr = prow->GetProperty(
  1342. pwszName,
  1343. dwFlags,
  1344. NULL,
  1345. &cbProp,
  1346. (BYTE *) &pwszTemp[fPrependNewValue? cwcAdd : 0]);
  1347. _JumpIfError(hr, error, "GetProperty");
  1348. // If there are multiple RDN components for the same DB
  1349. // column, concatenate them.
  1350. if (!fPrependNewValue)
  1351. {
  1352. wcscat(pwszTemp, wszNAMESEPARATORDEFAULT);
  1353. wcscat(pwszTemp, pwszValue);
  1354. }
  1355. pwszValue2 = pwszTemp;
  1356. // cbProp now does NOT include trailing L'\0'
  1357. CSASSERT(
  1358. sizeof(WCHAR) * wcslen(pwszTemp) ==
  1359. cbProp + sizeof(WCHAR) * cwcAdd);
  1360. }
  1361. }
  1362. else if (NULL != pwszSuffix)
  1363. {
  1364. hr = myAddNameSuffix(
  1365. pwszValue,
  1366. pwszSuffix,
  1367. cwcNameMax,
  1368. &pwszTemp);
  1369. _JumpIfError(hr, error, "myAddNameSuffix");
  1370. pwszValue2 = pwszTemp;
  1371. }
  1372. }
  1373. hr = prow->SetProperty(
  1374. pwszName,
  1375. dwFlags,
  1376. MAXDWORD,
  1377. (BYTE const *) pwszValue2);
  1378. _JumpIfError(hr, error, "SetProperty");
  1379. }
  1380. error:
  1381. if (NULL != pwszTemp)
  1382. {
  1383. LocalFree(pwszTemp);
  1384. }
  1385. return(hr);
  1386. }