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.

1567 lines
39 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1999 - 2000
  5. //
  6. // File: event.cpp
  7. //
  8. // Contents: Cert CAuditEvent class implementation
  9. //
  10. //---------------------------------------------------------------------------
  11. #include <pch.cpp>
  12. #pragma hdrstop
  13. #include <sid.h>
  14. #include <tfc.h>
  15. #include <authzi.h>
  16. using namespace CertSrv;
  17. CAuditEvent::AUDIT_CATEGORIES cat[] =
  18. { // event ID // event category no of check role separation
  19. //args for this event
  20. {SE_AUDITID_CERTSRV_SHUTDOWN, AUDIT_FILTER_STARTSTOP, 0, TRUE},
  21. {SE_AUDITID_CERTSRV_SERVICESTART, AUDIT_FILTER_STARTSTOP, 2, TRUE},
  22. {SE_AUDITID_CERTSRV_SERVICESTOP, AUDIT_FILTER_STARTSTOP, 2, TRUE},
  23. {SE_AUDITID_CERTSRV_BACKUPSTART, AUDIT_FILTER_BACKUPRESTORE,1, TRUE},
  24. {SE_AUDITID_CERTSRV_BACKUPEND, AUDIT_FILTER_BACKUPRESTORE,0, TRUE},
  25. {SE_AUDITID_CERTSRV_RESTORESTART, AUDIT_FILTER_BACKUPRESTORE,0, FALSE},
  26. {SE_AUDITID_CERTSRV_RESTOREEND, AUDIT_FILTER_BACKUPRESTORE,0, FALSE},
  27. {SE_AUDITID_CERTSRV_DENYREQUEST, AUDIT_FILTER_CERTIFICATE, 1, TRUE},
  28. {SE_AUDITID_CERTSRV_RESUBMITREQUEST, AUDIT_FILTER_CERTIFICATE, 1, TRUE},
  29. {SE_AUDITID_CERTSRV_SETEXTENSION, AUDIT_FILTER_CERTIFICATE, 5, TRUE},
  30. {SE_AUDITID_CERTSRV_SETATTRIBUTES, AUDIT_FILTER_CERTIFICATE, 2, TRUE},
  31. {SE_AUDITID_CERTSRV_IMPORTCERT, AUDIT_FILTER_CERTIFICATE, 2, TRUE},
  32. {SE_AUDITID_CERTSRV_NEWREQUEST, AUDIT_FILTER_CERTIFICATE, 3, FALSE},
  33. {SE_AUDITID_CERTSRV_REQUESTAPPROVED, AUDIT_FILTER_CERTIFICATE, 6, FALSE},
  34. {SE_AUDITID_CERTSRV_REQUESTDENIED, AUDIT_FILTER_CERTIFICATE, 6, FALSE},
  35. {SE_AUDITID_CERTSRV_REQUESTPENDING, AUDIT_FILTER_CERTIFICATE, 6, FALSE},
  36. {SE_AUDITID_CERTSRV_DELETEROW, AUDIT_FILTER_CERTIFICATE, 3, TRUE},
  37. {SE_AUDITID_CERTSRV_PUBLISHCACERT, AUDIT_FILTER_CERTIFICATE, 3, FALSE},
  38. {SE_AUDITID_CERTSRV_REVOKECERT, AUDIT_FILTER_CERTREVOCATION, 2, TRUE},
  39. {SE_AUDITID_CERTSRV_PUBLISHCRL, AUDIT_FILTER_CERTREVOCATION, 3, TRUE},
  40. {SE_AUDITID_CERTSRV_AUTOPUBLISHCRL, AUDIT_FILTER_CERTREVOCATION, 5, FALSE},
  41. {SE_AUDITID_CERTSRV_SETSECURITY, AUDIT_FILTER_CASECURITY, 1, TRUE},
  42. {SE_AUDITID_CERTSRV_SETAUDITFILTER, AUDIT_FILTER_CASECURITY, 1, TRUE},
  43. {SE_AUDITID_CERTSRV_SETOFFICERRIGHTS, AUDIT_FILTER_CASECURITY, 2, TRUE},
  44. {SE_AUDITID_CERTSRV_ROLESEPARATIONSTATE,AUDIT_FILTER_CASECURITY, 1, FALSE},
  45. {SE_AUDITID_CERTSRV_GETARCHIVEDKEY, AUDIT_FILTER_KEYAARCHIVAL, 1, TRUE},
  46. {SE_AUDITID_CERTSRV_KEYARCHIVED, AUDIT_FILTER_KEYAARCHIVAL, 3, FALSE},
  47. {SE_AUDITID_CERTSRV_IMPORTKEY, AUDIT_FILTER_KEYAARCHIVAL, 1, TRUE},
  48. {SE_AUDITID_CERTSRV_SETCONFIGENTRY, AUDIT_FILTER_CACONFIG, 3, TRUE},
  49. {SE_AUDITID_CERTSRV_SETCAPROPERTY, AUDIT_FILTER_CACONFIG, 4, TRUE},
  50. };
  51. CAuditEvent::AUDIT_CATEGORIES *CAuditEvent::m_gAuditCategories = cat;
  52. DWORD CAuditEvent::m_gdwAuditCategoriesSize = sizeof(cat)/sizeof(cat[0]);
  53. bool CAuditEvent::m_gfRoleSeparationEnabled = false;
  54. CAuditEvent::CAuditEvent(ULONG ulEventID, DWORD dwFilter) :
  55. m_cEventData(0),
  56. m_cRequiredEventData(0),
  57. m_dwFilter(dwFilter),
  58. m_fRoleSeparationEnabled(false),
  59. m_pISS(NULL),
  60. m_hClientToken(NULL),
  61. m_pCASD(NULL),
  62. m_ClientContext(NULL),
  63. m_pSDPrivileges(NULL),
  64. m_pDaclPrivileges(NULL),
  65. m_hRpc(NULL),
  66. m_Error(0),
  67. m_MaskAllowed(0),
  68. m_crtGUID(0),
  69. m_pUserSid(NULL),
  70. m_hAuditEventType(NULL)
  71. {
  72. m_AuthzHandle = NULL;
  73. m_Request.ObjectTypeList = NULL;
  74. m_Request.PrincipalSelfSid = NULL;
  75. m_Request.ObjectTypeListLength = 0;
  76. m_Request.OptionalArguments = NULL;
  77. m_Reply.ResultListLength = 1;
  78. m_Reply.GrantedAccessMask = &m_MaskAllowed;
  79. m_Reply.Error = &m_Error;
  80. m_Reply.SaclEvaluationResults = &m_SaclEval;
  81. SetEventID(ulEventID);
  82. };
  83. // initializes internal data associated with a particular audit event
  84. void CAuditEvent::SetEventID(ULONG ulEventID)
  85. {
  86. m_ulEventID = ulEventID;
  87. for(DWORD c=0; c<m_gdwAuditCategoriesSize; c++)
  88. {
  89. if(((DWORD)m_ulEventID)==((DWORD)m_gAuditCategories[c].ulAuditID))
  90. {
  91. m_fRoleSeparationEnabled =
  92. m_gAuditCategories[c].fRoleSeparationEnabled;
  93. m_cRequiredEventData = m_gAuditCategories[c].dwParamCount;
  94. CSASSERT(m_EventDataMaxSize>=m_cRequiredEventData);
  95. if(!m_gAuditCategories[c].hAuditEventType)
  96. {
  97. AuthziInitializeAuditEventType(
  98. 0,
  99. SE_CATEGID_OBJECT_ACCESS,
  100. (USHORT)m_ulEventID,
  101. (USHORT)m_gAuditCategories[c].dwParamCount,
  102. &m_gAuditCategories[c].hAuditEventType);
  103. }
  104. m_hAuditEventType = m_gAuditCategories[c].hAuditEventType;
  105. break;
  106. }
  107. }
  108. }
  109. CAuditEvent::~CAuditEvent()
  110. {
  111. for(DWORD cData=0;cData<m_cEventData;cData++)
  112. delete m_pEventDataList[cData];
  113. FreeCachedHandles();
  114. }
  115. void CAuditEvent::CleanupAuditEventTypeHandles()
  116. {
  117. for(DWORD c=0; c<m_gdwAuditCategoriesSize; c++)
  118. {
  119. if(m_gAuditCategories[c].hAuditEventType)
  120. {
  121. AuthziFreeAuditEventType(m_gAuditCategories[c].hAuditEventType);
  122. }
  123. }
  124. }
  125. bool CAuditEvent::IsEventValid()
  126. {
  127. for(DWORD c=0; c<m_gdwAuditCategoriesSize; c++)
  128. {
  129. if(m_ulEventID==m_gAuditCategories[c].ulAuditID)
  130. return true;
  131. }
  132. return false;
  133. }
  134. bool CAuditEvent::IsEventEnabled()
  135. {
  136. if(0==m_ulEventID) // event is used for access check only
  137. return false;
  138. for(DWORD c=0; c<m_gdwAuditCategoriesSize; c++)
  139. {
  140. if(((DWORD)m_ulEventID)==((DWORD)m_gAuditCategories[c].ulAuditID))
  141. {
  142. return (m_dwFilter&m_gAuditCategories[c].dwFilter)?true:false;
  143. }
  144. }
  145. // if get here the event has an unknown ID
  146. CSASSERT(!L"Invalid event found");
  147. return false;
  148. }
  149. inline bool CAuditEvent::IsEventRoleSeparationEnabled()
  150. {
  151. return RoleSeparationIsEnabled() && m_fRoleSeparationEnabled;
  152. }
  153. HRESULT CAuditEvent::AddData(DWORD dwValue)
  154. {
  155. PROPVARIANT *pvtData = CreateNewEventData();
  156. if(!pvtData)
  157. {
  158. return E_OUTOFMEMORY;
  159. }
  160. V_VT(pvtData) = VT_UI4;
  161. V_UI4(pvtData) = dwValue;
  162. return S_OK;
  163. }
  164. HRESULT CAuditEvent::AddData(PBYTE pData, DWORD dwDataLen)
  165. {
  166. CSASSERT(pData && dwDataLen);
  167. PROPVARIANT *pvtData = CreateNewEventData();
  168. if(!pvtData)
  169. {
  170. return E_OUTOFMEMORY;
  171. }
  172. V_VT(pvtData) = VT_BLOB;
  173. pvtData->blob.cbSize = dwDataLen;
  174. pvtData->blob.pBlobData = (BYTE*)CoTaskMemAlloc(dwDataLen);
  175. if(!pvtData->blob.pBlobData)
  176. {
  177. return E_OUTOFMEMORY;
  178. }
  179. memcpy(pvtData->blob.pBlobData, pData, dwDataLen);
  180. return S_OK;
  181. }
  182. HRESULT CAuditEvent::AddData(bool fData)
  183. {
  184. PROPVARIANT *pvtData = CreateNewEventData();
  185. if(!pvtData)
  186. {
  187. return E_OUTOFMEMORY;
  188. }
  189. V_VT(pvtData) = VT_BOOL;
  190. V_BOOL(pvtData) = fData?VARIANT_TRUE:VARIANT_FALSE;
  191. return S_OK;
  192. }
  193. HRESULT CAuditEvent::AddData(LPCWSTR pcwszData)
  194. {
  195. if(!pcwszData)
  196. pcwszData = L"";
  197. PROPVARIANT *pvtData = CreateNewEventData();
  198. if(!pvtData)
  199. {
  200. return E_OUTOFMEMORY;
  201. }
  202. V_VT(pvtData) = VT_LPWSTR;
  203. pvtData->pwszVal =
  204. (LPWSTR)CoTaskMemAlloc((wcslen(pcwszData)+1)*sizeof(WCHAR));
  205. if(!pvtData->pwszVal)
  206. {
  207. return E_OUTOFMEMORY;
  208. }
  209. wcscpy(pvtData->pwszVal, pcwszData);
  210. return S_OK;
  211. }
  212. HRESULT CAuditEvent::AddData(LPCWSTR *ppcwszData)
  213. {
  214. CSASSERT(ppcwszData);
  215. PROPVARIANT *pvtData = CreateNewEventData();
  216. if(!pvtData)
  217. {
  218. return E_OUTOFMEMORY;
  219. }
  220. V_VT(pvtData) = VT_LPWSTR;
  221. DWORD dwTextLen = 1;
  222. for(LPCWSTR *ppcwszStr=ppcwszData; *ppcwszStr; ppcwszStr++)
  223. {
  224. dwTextLen += wcslen(*ppcwszStr)+2;
  225. }
  226. pvtData->pwszVal =
  227. (LPWSTR)CoTaskMemAlloc(dwTextLen*sizeof(WCHAR));
  228. if(!pvtData->pwszVal)
  229. {
  230. return E_OUTOFMEMORY;
  231. }
  232. wcscpy(pvtData->pwszVal, L"");
  233. for(ppcwszStr=ppcwszData; *ppcwszStr; ppcwszStr++)
  234. {
  235. wcscat(pvtData->pwszVal, *ppcwszStr);
  236. wcscat(pvtData->pwszVal, L"; ");
  237. }
  238. return S_OK;
  239. }
  240. HRESULT CAuditEvent::AddData(FILETIME time)
  241. {
  242. PROPVARIANT *pvtData = CreateNewEventData();
  243. if(!pvtData)
  244. {
  245. return E_OUTOFMEMORY;
  246. }
  247. V_VT(pvtData) = VT_FILETIME;
  248. pvtData->filetime = time;
  249. return S_OK;
  250. }
  251. HRESULT CAuditEvent::AddData(const VARIANT *pvar, bool fDoublePercentInStrings=false)
  252. {
  253. CSASSERT(pvar);
  254. EventData *pData = CreateNewEventData1();
  255. if(!pData)
  256. {
  257. return E_OUTOFMEMORY;
  258. }
  259. pData->m_fDoublePercentsInStrings = fDoublePercentInStrings;
  260. HRESULT hr = VariantCopy((VARIANT*)&pData->m_vtData, (VARIANT*)pvar);
  261. return hr;
  262. }
  263. PROPVARIANT *CAuditEvent::CreateNewEventData()
  264. {
  265. EventData *pData = CreateNewEventData1();
  266. return &pData->m_vtData;
  267. }
  268. CAuditEvent::EventData *CAuditEvent::CreateNewEventData1()
  269. {
  270. EventData *pData = new EventData;
  271. if(!pData)
  272. {
  273. return NULL;
  274. }
  275. m_pEventDataList[m_cEventData++] = pData;
  276. return pData;
  277. }
  278. HRESULT CAuditEvent::EventData::ConvertToStringI2I4(
  279. LONG lVal,
  280. LPWSTR *ppwszOut)
  281. {
  282. WCHAR wszVal[100]; // big enough to hold a LONG as string
  283. _itow(lVal, wszVal, 10);
  284. *ppwszOut = new WCHAR[wcslen(wszVal)+1];
  285. if(!*ppwszOut)
  286. {
  287. return E_OUTOFMEMORY;
  288. }
  289. wcscpy(*ppwszOut, wszVal);
  290. return S_OK;
  291. }
  292. HRESULT CAuditEvent::EventData::ConvertToStringUI2UI4(
  293. ULONG ulVal,
  294. LPWSTR *ppwszOut)
  295. {
  296. WCHAR wszVal[100]; // big enough to hold a LONG as string
  297. _itow(ulVal, wszVal, 10);
  298. *ppwszOut = new WCHAR[wcslen(wszVal)+1];
  299. if(!*ppwszOut)
  300. {
  301. return E_OUTOFMEMORY;
  302. }
  303. wcscpy(*ppwszOut, wszVal);
  304. return S_OK;
  305. }
  306. HRESULT CAuditEvent::EventData::DoublePercentsInString(
  307. LPCWSTR pcwszIn,
  308. LPWSTR *ppwszOut)
  309. {
  310. const WCHAR *pchSrc;
  311. WCHAR *pchDest;
  312. int cPercentChars = 0;
  313. wprintf(L"********Found %d percents\n", cPercentChars);
  314. *ppwszOut = new WCHAR[2*wcslen(pcwszIn)+1];
  315. if(!*ppwszOut)
  316. return E_OUTOFMEMORY;
  317. for(pchSrc = pcwszIn, pchDest = *ppwszOut;
  318. L'\0'!=*pchSrc;
  319. pchSrc++, pchDest++)
  320. {
  321. *pchDest = *pchSrc;
  322. if(L'%'==*pchSrc)
  323. *(++pchDest) = L'%';
  324. }
  325. *pchDest = L'\0';
  326. wprintf(L"****************************");
  327. wprintf(L"%s%", *ppwszOut);
  328. wprintf(L"****************************");
  329. return S_OK;
  330. }
  331. HRESULT CAuditEvent::EventData::ConvertToStringWSZ(
  332. LPCWSTR pcwszVal,
  333. LPWSTR *ppwszOut)
  334. {
  335. if(m_fDoublePercentsInStrings)
  336. {
  337. // replace each occurence of % with %%
  338. return DoublePercentsInString(
  339. pcwszVal,
  340. ppwszOut);
  341. }
  342. else
  343. {
  344. *ppwszOut = new WCHAR[(wcslen(pcwszVal)+1)];
  345. if(!*ppwszOut)
  346. {
  347. return E_OUTOFMEMORY;
  348. }
  349. wcscpy(*ppwszOut, pcwszVal);
  350. }
  351. return S_OK;
  352. }
  353. HRESULT CAuditEvent::EventData::ConvertToStringBOOL(
  354. BOOL fVal,
  355. LPWSTR *ppwszOut)
  356. {
  357. LPCWSTR pwszBoolVal =
  358. fVal==VARIANT_TRUE?
  359. g_pwszYes:
  360. g_pwszNo;
  361. *ppwszOut = new WCHAR[wcslen(pwszBoolVal)+1];
  362. if(!*ppwszOut)
  363. {
  364. return E_OUTOFMEMORY;
  365. }
  366. wcscpy(*ppwszOut, pwszBoolVal);
  367. return S_OK;
  368. }
  369. HRESULT CAuditEvent::EventData::ConvertToStringArrayUI1(
  370. LPSAFEARRAY psa,
  371. LPWSTR *ppwszOut)
  372. {
  373. SafeArrayEnum<BYTE> saenum(psa);
  374. if(!saenum.IsValid())
  375. {
  376. return E_INVALIDARG;
  377. }
  378. BYTE b;
  379. // byte array is formated as "0x00 0x00..." ie 5
  380. // chars per byte
  381. *ppwszOut = new WCHAR[saenum.GetCount()*5];
  382. if(!*ppwszOut)
  383. return E_OUTOFMEMORY;
  384. LPWSTR pwszCrt = *ppwszOut;
  385. while(S_OK==saenum.Next(b))
  386. {
  387. wsprintf(pwszCrt, L"0x%02X ", b); // eg "0x0f" or "0xa4"
  388. pwszCrt+=5;
  389. }
  390. return S_OK;
  391. }
  392. HRESULT CAuditEvent::EventData::ConvertToStringArrayBSTR(
  393. LPSAFEARRAY psa,
  394. LPWSTR *ppwszOut)
  395. {
  396. SafeArrayEnum<BSTR> saenum(psa);
  397. if(!saenum.IsValid())
  398. {
  399. return E_INVALIDARG;
  400. }
  401. DWORD dwLen = 1;
  402. BSTR bstr;
  403. while(S_OK==saenum.Next(bstr))
  404. {
  405. dwLen+=2*wcslen(bstr)+10;
  406. }
  407. *ppwszOut = new WCHAR[dwLen];
  408. if(!*ppwszOut)
  409. return E_OUTOFMEMORY;
  410. **ppwszOut = L'\0';
  411. saenum.Reset();
  412. while(S_OK==saenum.Next(bstr))
  413. {
  414. if(m_fDoublePercentsInStrings)
  415. {
  416. CAutoLPWSTR pwszTemp;
  417. if(S_OK != DoublePercentsInString(bstr,
  418. &pwszTemp))
  419. {
  420. delete[] *ppwszOut;
  421. *ppwszOut = NULL;
  422. return E_OUTOFMEMORY;
  423. }
  424. wcscat(*ppwszOut, pwszTemp);
  425. }
  426. else
  427. {
  428. wcscat(*ppwszOut, bstr);
  429. }
  430. wcscat(*ppwszOut, L"\n");
  431. }
  432. return S_OK;
  433. }
  434. HRESULT CAuditEvent::EventData::ConvertToString(LPWSTR *ppwszValue)
  435. {
  436. LPWSTR pwszVal = NULL;
  437. HRESULT hr = S_OK;
  438. switch(V_VT(&m_vtData))
  439. {
  440. case VT_I2:
  441. hr = ConvertToStringI2I4(V_I2(&m_vtData), ppwszValue);
  442. break;
  443. case VT_BYREF|VT_I2:
  444. hr = ConvertToStringI2I4(*V_I2REF(&m_vtData), ppwszValue);
  445. break;
  446. case VT_I4:
  447. hr = ConvertToStringI2I4(V_I4(&m_vtData), ppwszValue);
  448. break;
  449. case VT_BYREF|VT_I4:
  450. hr = ConvertToStringI2I4(*V_I4REF(&m_vtData), ppwszValue);
  451. break;
  452. case VT_UI2:
  453. hr = ConvertToStringUI2UI4(V_UI2(&m_vtData), ppwszValue);
  454. break;
  455. case VT_BYREF|VT_UI2:
  456. hr = ConvertToStringUI2UI4(*V_UI2REF(&m_vtData), ppwszValue);
  457. break;
  458. case VT_UI4:
  459. hr = ConvertToStringUI2UI4(V_UI4(&m_vtData), ppwszValue);
  460. break;
  461. case VT_BYREF|VT_UI4:
  462. hr = ConvertToStringUI2UI4(*V_UI4REF(&m_vtData), ppwszValue);
  463. break;
  464. case VT_BLOB:
  465. // We don't call CryptBinaryToString directly anywhere in the CA tree.
  466. // This avoids errors when linking in the CryptBinaryToString code
  467. // for NT 4 reskit builds.
  468. WCHAR *pwszLocalAlloc;
  469. hr = myCryptBinaryToString(
  470. m_vtData.blob.pBlobData,
  471. m_vtData.blob.cbSize,
  472. CRYPT_STRING_BASE64,
  473. &pwszLocalAlloc);
  474. if (S_OK != hr)
  475. {
  476. return(hr);
  477. }
  478. pwszVal = new WCHAR[(wcslen(pwszLocalAlloc) + 1)];
  479. if (NULL == pwszVal)
  480. {
  481. LocalFree(pwszLocalAlloc);
  482. return E_OUTOFMEMORY;
  483. }
  484. wcscpy(pwszVal, pwszLocalAlloc);
  485. LocalFree(pwszLocalAlloc);
  486. *ppwszValue = pwszVal;
  487. // pwszVal[cOut-2] = L'\0'; \\ Base64Encode adds a new line
  488. break;
  489. case VT_BOOL:
  490. hr = ConvertToStringBOOL(V_BOOL(&m_vtData), ppwszValue);
  491. break;
  492. case VT_BOOL|VT_BYREF:
  493. hr = ConvertToStringBOOL(*V_BOOLREF(&m_vtData), ppwszValue);
  494. break;
  495. case VT_LPWSTR:
  496. hr = ConvertToStringWSZ(m_vtData.pwszVal, ppwszValue);
  497. break;
  498. case VT_BSTR:
  499. hr = ConvertToStringWSZ(V_BSTR(&m_vtData), ppwszValue);
  500. break;
  501. case VT_BSTR|VT_BYREF:
  502. hr = ConvertToStringWSZ(*V_BSTRREF(&m_vtData), ppwszValue);
  503. break;
  504. case VT_FILETIME:
  505. {
  506. LPWSTR pwszTime = NULL;
  507. hr = myFileTimeToWszTime(
  508. &m_vtData.filetime,
  509. TRUE,
  510. &pwszTime);
  511. if(FAILED(hr))
  512. return hr;
  513. pwszVal = new WCHAR[wcslen(pwszTime)+1];
  514. if(!pwszVal)
  515. {
  516. return E_OUTOFMEMORY;
  517. }
  518. wcscpy(pwszVal, pwszTime);
  519. LocalFree(pwszTime);
  520. *ppwszValue = pwszVal;
  521. }
  522. break;
  523. case VT_ARRAY|VT_UI1:
  524. hr = ConvertToStringArrayUI1(V_ARRAY(&m_vtData), ppwszValue);
  525. break;
  526. case VT_ARRAY|VT_UI1|VT_BYREF:
  527. hr = ConvertToStringArrayUI1(*V_ARRAYREF(&m_vtData), ppwszValue);
  528. break;
  529. case VT_ARRAY|VT_BSTR:
  530. hr = ConvertToStringArrayBSTR(V_ARRAY(&m_vtData), ppwszValue);
  531. break;
  532. case VT_ARRAY|VT_BSTR|VT_BYREF:
  533. hr = ConvertToStringArrayBSTR(*V_ARRAYREF(&m_vtData), ppwszValue);
  534. break;
  535. default:
  536. {
  537. LPCWSTR pwszValOut = cAuditString_UnknownDataType;
  538. VARIANT varOut;
  539. VariantInit(&varOut);
  540. hr = VariantChangeType(&varOut, (VARIANT*)&m_vtData, 0, VT_BSTR);
  541. if(S_OK==hr)
  542. {
  543. pwszValOut = V_BSTR(&varOut);
  544. }
  545. pwszVal = new WCHAR[wcslen(pwszValOut)+1];
  546. if(!pwszVal)
  547. {
  548. return E_OUTOFMEMORY;
  549. }
  550. wcscpy(pwszVal, pwszValOut);
  551. VariantClear(&varOut);
  552. *ppwszValue = pwszVal;
  553. hr = S_OK;
  554. }
  555. break;
  556. }
  557. return hr;
  558. }
  559. HRESULT CAuditEvent::Report(bool fSuccess /* = true */)
  560. {
  561. HRESULT hr;
  562. AUTHZ_AUDIT_EVENT_HANDLE AuthzAIH = NULL;
  563. PAUDIT_PARAMS pAuditParams = NULL;
  564. PAUDIT_PARAM pParamArray = NULL;
  565. if(!IsEventEnabled())
  566. {
  567. return S_OK;
  568. }
  569. hr = BuildAuditParamArray(pParamArray);
  570. _JumpIfError(hr, error, "GetAuditText");
  571. if(!AuthziAllocateAuditParams(
  572. &pAuditParams,
  573. (USHORT)(m_cEventData+2))) // authz adds 2
  574. { // extra params
  575. hr = myHLastError(); // internally
  576. _JumpError(hr, error, "AuthziAllocateAuditParams");
  577. }
  578. #ifndef _DISABLE_AUTHZ_
  579. if(!AuthziInitializeAuditParamsFromArray(
  580. fSuccess?APF_AuditSuccess:APF_AuditFailure,
  581. g_AuthzCertSrvRM,
  582. (USHORT)m_cEventData,
  583. pParamArray,
  584. pAuditParams))
  585. #else
  586. SetLastError(E_INVALIDARG);
  587. #endif
  588. {
  589. hr = myHLastError();
  590. _JumpError(hr, error, "AuthziInitializeAuditParamsFromArray");
  591. }
  592. if (!AuthziInitializeAuditEvent(0,
  593. g_AuthzCertSrvRM,
  594. m_hAuditEventType,
  595. pAuditParams,
  596. NULL,
  597. INFINITE,
  598. L"",
  599. L"",
  600. L"",
  601. L"",
  602. &AuthzAIH))
  603. {
  604. hr = myHLastError();
  605. _JumpIfError(hr, error, "AuthzInitializeAuditInfo");
  606. }
  607. if(!AuthziLogAuditEvent( 0, AuthzAIH, NULL ))
  608. {
  609. hr = myHLastError();
  610. _JumpIfError(hr, error, "AuthzGenAuditEvent");
  611. }
  612. DBGPRINT((
  613. DBG_SS_AUDIT,
  614. "Audit event ID=%d\n",
  615. m_ulEventID));
  616. error:
  617. if(AuthzAIH)
  618. {
  619. AuthzFreeAuditEvent(AuthzAIH);
  620. }
  621. if(pAuditParams)
  622. {
  623. AuthziFreeAuditParams(pAuditParams);
  624. }
  625. FreeAuditParamArray(pParamArray);
  626. return hr;
  627. }
  628. HRESULT CAuditEvent::SaveFilter(LPCWSTR pcwszSanitizedName)
  629. {
  630. return mySetCertRegDWValue(
  631. pcwszSanitizedName,
  632. NULL,
  633. NULL,
  634. wszREGAUDITFILTER,
  635. m_dwFilter);
  636. }
  637. HRESULT CAuditEvent::LoadFilter(LPCWSTR pcwszSanitizedName)
  638. {
  639. return myGetCertRegDWValue(
  640. pcwszSanitizedName,
  641. NULL,
  642. NULL,
  643. wszREGAUDITFILTER,
  644. &m_dwFilter);
  645. }
  646. HRESULT CAuditEvent::Impersonate()
  647. {
  648. HRESULT hr;
  649. HANDLE hThread = NULL;
  650. CSASSERT(NULL==m_pISS);
  651. CSASSERT(NULL==m_hClientToken);
  652. if (NULL == m_hRpc)
  653. {
  654. // dcom impersonate
  655. hr = CoGetCallContext(IID_IServerSecurity, (void**)&m_pISS);
  656. _JumpIfError(hr, error, "CoGetCallContext");
  657. hr = m_pISS->ImpersonateClient();
  658. _JumpIfError(hr, error, "ImpersonateClient");
  659. }
  660. else
  661. {
  662. // rpc impersonate
  663. hr = RpcImpersonateClient((RPC_BINDING_HANDLE) m_hRpc);
  664. if (S_OK != hr)
  665. {
  666. hr = myHError(hr);
  667. _JumpError(hr, error, "RpcImpersonateClient");
  668. }
  669. }
  670. hThread = GetCurrentThread();
  671. if (NULL == hThread)
  672. {
  673. hr = myHLastError();
  674. _JumpIfError(hr, error, "GetCurrentThread");
  675. }
  676. if (!OpenThreadToken(hThread,
  677. TOKEN_QUERY | TOKEN_DUPLICATE,
  678. FALSE, // client impersonation
  679. &m_hClientToken))
  680. {
  681. hr = myHLastError();
  682. _JumpIfError(hr, error, "OpenThreadToken");
  683. }
  684. error:
  685. if(S_OK!=hr)
  686. {
  687. if(NULL!=m_pISS)
  688. {
  689. m_pISS->Release();
  690. m_pISS = NULL;
  691. }
  692. }
  693. if (NULL != hThread)
  694. {
  695. CloseHandle(hThread);
  696. }
  697. return hr;
  698. }
  699. HRESULT CAuditEvent::RevertToSelf()
  700. {
  701. HRESULT hr = S_OK;
  702. // CSASSERT(m_pISS||m_hRpc);
  703. if (NULL != m_hRpc) // rpc
  704. {
  705. hr = RpcRevertToSelf();
  706. if (S_OK != hr)
  707. {
  708. hr = myHError(hr);
  709. _JumpError(hr, error, "RpcRevertToSelf");
  710. }
  711. m_hRpc = NULL;
  712. }
  713. else if(m_pISS) // dcom
  714. {
  715. hr = m_pISS->RevertToSelf();
  716. _JumpIfError(hr, error, "IServerSecurity::RpcRevertToSelf");
  717. m_pISS->Release();
  718. m_pISS = NULL;
  719. }
  720. error:
  721. return hr;
  722. }
  723. HANDLE CAuditEvent::GetClientToken()
  724. {
  725. CSASSERT(m_hClientToken);
  726. HANDLE hSave = m_hClientToken;
  727. m_hClientToken = NULL;
  728. return hSave;
  729. }
  730. // dwAuditFlags - not asking for both success and failure implicitely
  731. // means the handles will be cached for future audit
  732. HRESULT
  733. CAuditEvent::AccessCheck(
  734. ACCESS_MASK Mask,
  735. DWORD dwAuditFlags,
  736. handle_t hRpc,
  737. HANDLE *phToken)
  738. {
  739. HRESULT hr = S_OK;
  740. LUID luid = {0,0};
  741. bool fAccessAllowed = false;
  742. DWORD dwRoles = 0;
  743. DWORD dwRolesChecked = 0;
  744. PACL pDacl = NULL;
  745. FreeCachedHandles();
  746. m_hRpc = hRpc;
  747. if (!g_CASD.IsInitialized())
  748. {
  749. hr = HRESULT_FROM_WIN32(ERROR_NOT_READY);
  750. _JumpError(hr, error, "Security not enabled");
  751. }
  752. hr = g_CASD.LockGet(&m_pCASD);
  753. _JumpIfError(hr, error, "CProtectedSecurityDescriptor::LockGet");
  754. hr = Impersonate();
  755. _JumpIfError(hr, error, "CAuditEvent::Impersonate");
  756. if(!AuthzInitializeContextFromToken(
  757. 0,
  758. m_hClientToken,
  759. g_AuthzCertSrvRM,
  760. NULL,
  761. luid,
  762. NULL,
  763. &m_ClientContext))
  764. {
  765. hr = myHLastError();
  766. _PrintError(hr, "AuthzInitializeContextFromToken");
  767. if (E_INVALIDARG == hr && !IsWhistler())
  768. {
  769. hr = S_OK;
  770. fAccessAllowed = TRUE;
  771. }
  772. goto error;
  773. }
  774. if(Mask & CA_ACCESS_LOCALADMIN)
  775. {
  776. bool fLocalAdmin;
  777. hr = IsCurrentUserBuiltinAdmin(&fLocalAdmin);
  778. _JumpIfError(hr, error, "IsCurrentUserBuiltinAdmin");
  779. if(fLocalAdmin)
  780. {
  781. dwRoles |= CA_ACCESS_LOCALADMIN;
  782. }
  783. }
  784. RevertToSelf();
  785. // Get privilege based roles if checking access on a privilege role
  786. // or if role separation is enabled when we have to know all roles
  787. if(IsEventRoleSeparationEnabled() ||
  788. Mask & (CA_ACCESS_OPERATOR|CA_ACCESS_AUDITOR|CA_ACCESS_LOCALADMIN))
  789. {
  790. hr = GetPrivilegeRoles(&dwRoles);
  791. _JumpIfError(hr, error, "CAuditEvent::GetPrivilegeRolesCount");
  792. hr = BuildPrivilegeSecurityDescriptor(dwRoles);
  793. _JumpIfError(hr, error, "CAuditEvent::BuildPrivilegeSecurityDescriptor");
  794. }
  795. // Get security descriptor based roles
  796. m_Request.DesiredAccess = MAXIMUM_ALLOWED;
  797. CSASSERT(!m_AuthzHandle);
  798. if(!AuthzAccessCheck(
  799. 0,
  800. m_ClientContext,
  801. &m_Request,
  802. NULL, //no audit
  803. m_pCASD,
  804. m_pSDPrivileges?(&m_pSDPrivileges):NULL,
  805. m_pSDPrivileges?1:0,
  806. &m_Reply,
  807. IsEventEnabled()?&m_AuthzHandle:NULL)) // no caching if no audit
  808. // event will be generated
  809. {
  810. hr = myHLastError();
  811. _JumpError(hr, error, "AuthzAccessCheck");
  812. }
  813. dwRoles |= m_Reply.GrantedAccessMask[0];
  814. if(m_Reply.Error[0]==ERROR_SUCCESS &&
  815. m_Reply.GrantedAccessMask[0]&Mask)
  816. {
  817. fAccessAllowed = true;
  818. }
  819. if(IsEventRoleSeparationEnabled() &&
  820. GetBitCount(dwRoles&CA_ACCESS_MASKROLES)>1)
  821. {
  822. hr = CERTSRV_E_ROLECONFLICT;
  823. fAccessAllowed = false;
  824. // don't return yet, we need to generate an audit
  825. }
  826. // Next is a fake access check to generate an audit.
  827. // Access is denied if:
  828. // - role separation is enabled and user has more than one role
  829. // - none of the roles requested is allowed
  830. // Generate audit if event is enabled and
  831. if(IsEventEnabled() &&
  832. (!fAccessAllowed && !(dwAuditFlags&m_gcNoAuditFailure) ||
  833. fAccessAllowed && !(dwAuditFlags&m_gcNoAuditSuccess)))
  834. {
  835. m_Request.DesiredAccess =
  836. fAccessAllowed?
  837. m_Reply.GrantedAccessMask[0]&Mask:
  838. Mask;
  839. if(CERTSRV_E_ROLECONFLICT==hr)
  840. m_Request.DesiredAccess = 0x0000ffff; //force a failure audit
  841. HRESULT hr2 = CachedGenerateAudit();
  842. if(S_OK != hr2)
  843. {
  844. hr = hr2;
  845. _JumpIfError(hr, error, "CAuditEvent::CachedGenerateAudit");
  846. }
  847. }
  848. if(phToken)
  849. {
  850. *phToken = GetClientToken();
  851. }
  852. error:
  853. #ifdef DBG_CERTSRV_DEBUG_PRINT
  854. if(IsEventRoleSeparationEnabled())
  855. {
  856. DBGPRINT((DBG_SS_AUDIT, "EVENT %d ROLES: 0x%x %s%s%s%s%s%s\n",
  857. m_ulEventID,
  858. dwRoles,
  859. (dwRoles&CA_ACCESS_ADMIN)?"CAADMIN ":"",
  860. (dwRoles&CA_ACCESS_OFFICER)?"OFFICER ":"",
  861. (dwRoles&CA_ACCESS_AUDITOR)?"AUDITOR ":"",
  862. (dwRoles&CA_ACCESS_OPERATOR)?"OPERATOR ":"",
  863. (dwRoles&CA_ACCESS_ENROLL)?"ENROLL ":"",
  864. (dwRoles&CA_ACCESS_READ)?"READ ":""));
  865. }
  866. #endif
  867. if(!IsEventEnabled())
  868. {
  869. FreeCachedHandles();
  870. }
  871. if(S_OK==hr)
  872. {
  873. hr = fAccessAllowed?S_OK:E_ACCESSDENIED;
  874. }
  875. return(hr);
  876. }
  877. HRESULT
  878. CAuditEvent::CachedGenerateAudit()
  879. {
  880. HRESULT hr = S_OK;
  881. AUTHZ_AUDIT_EVENT_HANDLE AuditInfo = NULL;
  882. PAUDIT_PARAMS pAuditParams = NULL;
  883. PAUDIT_PARAM pParamArray = NULL;
  884. if(!IsEventEnabled())
  885. {
  886. FreeCachedHandles();
  887. return S_OK;
  888. }
  889. CSASSERT(m_AuthzHandle);
  890. hr = BuildAuditParamArray(pParamArray);
  891. _JumpIfError(hr, error, "GetAuditText");
  892. if(!AuthziAllocateAuditParams(
  893. &pAuditParams,
  894. (USHORT)(m_cEventData+2))) // authz adds 2
  895. { // extra params
  896. hr = myHLastError(); // internally
  897. _JumpError(hr, error, "AuthziAllocateAuditParams");
  898. }
  899. #ifndef _DISABLE_AUTHZ_
  900. if(!AuthziInitializeAuditParamsFromArray(
  901. APF_AuditSuccess|APF_AuditFailure,
  902. g_AuthzCertSrvRM,
  903. (USHORT)m_cEventData,
  904. pParamArray,
  905. pAuditParams))
  906. #else
  907. SetLastError(E_INVALIDARG);
  908. #endif
  909. {
  910. hr = myHLastError();
  911. _JumpError(hr, error, "AuthzInitAuditParams");
  912. }
  913. if(!AuthziInitializeAuditEvent(
  914. 0,
  915. g_AuthzCertSrvRM,
  916. m_hAuditEventType,
  917. pAuditParams,
  918. NULL,
  919. INFINITE,
  920. L"",
  921. L"",
  922. L"",
  923. L"",
  924. &AuditInfo))
  925. {
  926. hr = myHLastError();
  927. _JumpError(hr, error, "AuthzInitAuditInfoHandle");
  928. }
  929. if(!AuthzCachedAccessCheck(
  930. 0,
  931. m_AuthzHandle,
  932. &m_Request,
  933. AuditInfo,
  934. &m_Reply))
  935. {
  936. hr = myHLastError();
  937. _JumpError(hr, error, "AuthzCachedAccessCheck");
  938. }
  939. error:
  940. if(AuditInfo)
  941. {
  942. AuthzFreeAuditEvent(AuditInfo);
  943. }
  944. if(pAuditParams)
  945. {
  946. AuthziFreeAuditParams(pAuditParams);
  947. }
  948. FreeCachedHandles();
  949. FreeAuditParamArray(pParamArray);
  950. return hr;
  951. }
  952. void CAuditEvent::FreeCachedHandles()
  953. {
  954. if(m_hClientToken)
  955. {
  956. CloseHandle(m_hClientToken);
  957. m_hClientToken = NULL;
  958. }
  959. if(m_AuthzHandle)
  960. {
  961. AuthzFreeHandle(m_AuthzHandle);
  962. m_AuthzHandle = NULL;
  963. }
  964. if(m_pCASD)
  965. {
  966. g_CASD.Unlock();
  967. m_pCASD = NULL;
  968. }
  969. if(m_ClientContext)
  970. {
  971. AuthzFreeContext(m_ClientContext);
  972. m_ClientContext = NULL;
  973. }
  974. if(m_pUserSid)
  975. {
  976. LocalFree(m_pUserSid);
  977. m_pUserSid = NULL;
  978. }
  979. if(m_pSDPrivileges)
  980. {
  981. LocalFree(m_pSDPrivileges);
  982. m_pSDPrivileges = NULL;
  983. }
  984. if(m_pDaclPrivileges)
  985. {
  986. LocalFree(m_pDaclPrivileges);
  987. m_pDaclPrivileges = NULL;
  988. }
  989. }
  990. HRESULT CAuditEvent::RoleSeparationFlagSave(LPCWSTR pcwszSanitizedName)
  991. {
  992. return mySetCertRegDWValue(
  993. pcwszSanitizedName,
  994. NULL,
  995. NULL,
  996. wszREGROLESEPARATIONENABLED,
  997. RoleSeparationIsEnabled()?1:0);
  998. }
  999. HRESULT CAuditEvent::RoleSeparationFlagLoad(LPCWSTR pcwszSanitizedName)
  1000. {
  1001. DWORD dwFlags = 0;
  1002. HRESULT hr = myGetCertRegDWValue(
  1003. pcwszSanitizedName,
  1004. NULL,
  1005. NULL,
  1006. wszREGROLESEPARATIONENABLED,
  1007. &dwFlags);
  1008. if(S_OK==hr)
  1009. {
  1010. RoleSeparationEnable(dwFlags?true:false);
  1011. }
  1012. return hr;
  1013. }
  1014. HRESULT CAuditEvent::GetPrivilegeRoles(PDWORD pdwRoles)
  1015. {
  1016. HRESULT hr = S_OK;
  1017. PTOKEN_USER pTokenUser = NULL;
  1018. DWORD cbTokenUser = 0;
  1019. PTOKEN_GROUPS pTokenGroups = NULL;
  1020. DWORD cbTokenGroups = 0;
  1021. DWORD dwRoles = 0;
  1022. LSA_HANDLE lsahPolicyHandle = NULL;
  1023. LSA_OBJECT_ATTRIBUTES ObjectAttributes;
  1024. NTSTATUS NTStatus;
  1025. // first get roles for the user itself
  1026. AuthzGetInformationFromContext(
  1027. m_ClientContext,
  1028. AuthzContextInfoUserSid,
  1029. 0,
  1030. &cbTokenUser,
  1031. NULL);
  1032. if(GetLastError()!=ERROR_INSUFFICIENT_BUFFER)
  1033. {
  1034. hr = myHLastError();
  1035. _JumpError(hr, error, "AuthzGetContextInformation");
  1036. }
  1037. pTokenUser = (PTOKEN_USER)LocalAlloc(LMEM_FIXED, cbTokenUser);
  1038. _JumpIfAllocFailed(pTokenUser, error);
  1039. if(!AuthzGetInformationFromContext(
  1040. m_ClientContext,
  1041. AuthzContextInfoUserSid,
  1042. cbTokenUser,
  1043. &cbTokenUser,
  1044. pTokenUser))
  1045. {
  1046. hr = myHLastError();
  1047. _JumpError(hr, error, "AuthzGetContextInformation");
  1048. }
  1049. // Object attributes are reserved, so initalize to zeroes.
  1050. ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
  1051. NTStatus = LsaOpenPolicy(
  1052. NULL,
  1053. &ObjectAttributes,
  1054. POLICY_LOOKUP_NAMES,
  1055. &lsahPolicyHandle);
  1056. if(STATUS_SUCCESS!=NTStatus)
  1057. {
  1058. hr = HRESULT_FROM_WIN32(LsaNtStatusToWinError(NTStatus));
  1059. _JumpError(hr, error, "LsaOpenPolicy");
  1060. }
  1061. CSASSERT(!m_pUserSid);
  1062. m_pUserSid = (PSID)LocalAlloc(LMEM_FIXED, GetLengthSid(pTokenUser->User.Sid));
  1063. _JumpIfAllocFailed(m_pUserSid, error);
  1064. CopySid(
  1065. GetLengthSid(pTokenUser->User.Sid),
  1066. m_pUserSid,
  1067. pTokenUser->User.Sid);
  1068. hr = GetUserPrivilegeRoles(lsahPolicyHandle, &pTokenUser->User, &dwRoles);
  1069. if(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)==hr)
  1070. {
  1071. hr =S_OK;
  1072. }
  1073. _JumpIfError(hr, error, "CAuditEvent::GetUserPrivilegeRoles");
  1074. *pdwRoles |= dwRoles;
  1075. // then find the roles assigned to the groups the user is member of
  1076. AuthzGetInformationFromContext(
  1077. m_ClientContext,
  1078. AuthzContextInfoGroupsSids,
  1079. 0,
  1080. &cbTokenGroups,
  1081. NULL);
  1082. if(GetLastError()!=ERROR_INSUFFICIENT_BUFFER)
  1083. {
  1084. hr = myHLastError();
  1085. _JumpError(hr, error, "AuthzGetContextInformation");
  1086. }
  1087. pTokenGroups = (PTOKEN_GROUPS)LocalAlloc(LMEM_FIXED, cbTokenGroups);
  1088. _JumpIfAllocFailed(pTokenGroups, error);
  1089. if(!AuthzGetInformationFromContext(
  1090. m_ClientContext,
  1091. AuthzContextInfoGroupsSids,
  1092. cbTokenGroups,
  1093. &cbTokenGroups,
  1094. pTokenGroups))
  1095. {
  1096. hr = myHLastError();
  1097. _JumpError(hr, error, "AuthzGetContextInformation");
  1098. }
  1099. for(DWORD cGroups = 0; cGroups<pTokenGroups->GroupCount; cGroups++)
  1100. {
  1101. dwRoles = 0;
  1102. hr = GetUserPrivilegeRoles(
  1103. lsahPolicyHandle,
  1104. &pTokenGroups->Groups[cGroups],
  1105. &dwRoles);
  1106. if(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)==hr)
  1107. {
  1108. hr =S_OK;
  1109. }
  1110. _JumpIfError(hr, error, "CAuditEvent::GetUserPrivilegeRoles");
  1111. *pdwRoles |= dwRoles;
  1112. }
  1113. error:
  1114. if(pTokenUser)
  1115. {
  1116. LocalFree(pTokenUser);
  1117. }
  1118. if(pTokenGroups)
  1119. {
  1120. LocalFree(pTokenGroups);
  1121. }
  1122. if(lsahPolicyHandle)
  1123. {
  1124. LsaClose(lsahPolicyHandle);
  1125. }
  1126. return hr;
  1127. }
  1128. HRESULT CAuditEvent::GetUserPrivilegeRoles(
  1129. LSA_HANDLE lsah,
  1130. PSID_AND_ATTRIBUTES pSA,
  1131. PDWORD pdwRoles)
  1132. {
  1133. NTSTATUS NTStatus;
  1134. PLSA_UNICODE_STRING pLSAString = NULL;
  1135. ULONG cRights, c;
  1136. NTStatus = LsaEnumerateAccountRights(
  1137. lsah,
  1138. pSA->Sid,
  1139. &pLSAString,
  1140. &cRights);
  1141. if(STATUS_SUCCESS!=NTStatus)
  1142. {
  1143. return HRESULT_FROM_WIN32(LsaNtStatusToWinError(NTStatus));
  1144. }
  1145. for(c=0; c<cRights; c++)
  1146. {
  1147. if(0==_wcsicmp(SE_SECURITY_NAME, pLSAString[c].Buffer))
  1148. {
  1149. *pdwRoles |= CA_ACCESS_AUDITOR;
  1150. }
  1151. else if(0==_wcsicmp(SE_BACKUP_NAME, pLSAString[c].Buffer))
  1152. {
  1153. *pdwRoles |= CA_ACCESS_OPERATOR;
  1154. }
  1155. }
  1156. if(pLSAString)
  1157. {
  1158. LsaFreeMemory(pLSAString);
  1159. }
  1160. return S_OK;
  1161. }
  1162. HRESULT
  1163. CAuditEvent::GetMyRoles(
  1164. DWORD *pdwRoles)
  1165. {
  1166. HRESULT hr = S_OK;
  1167. LUID luid = {0,0};
  1168. bool fAccessAllowed = true;
  1169. DWORD dwRoles = 0;
  1170. if (!g_CASD.IsInitialized())
  1171. {
  1172. hr = HRESULT_FROM_WIN32(ERROR_NOT_READY);
  1173. _JumpError(hr, error, "Security not enabled");
  1174. }
  1175. hr = g_CASD.LockGet(&m_pCASD);
  1176. _JumpIfError(hr, error, "CProtectedSecurityDescriptor::LockGet");
  1177. hr = Impersonate();
  1178. _JumpIfError(hr, error, "CAuditEvent::Impersonate");
  1179. if(!AuthzInitializeContextFromToken(
  1180. 0,
  1181. m_hClientToken,
  1182. g_AuthzCertSrvRM,
  1183. NULL,
  1184. luid,
  1185. NULL,
  1186. &m_ClientContext))
  1187. {
  1188. hr = myHLastError();
  1189. _JumpError(hr, error, "AuthzInitializeContextFromToken");
  1190. }
  1191. RevertToSelf();
  1192. hr = GetPrivilegeRoles(&dwRoles);
  1193. _JumpIfError(hr, error, "CAuditEvent::GetPrivilegeRoles");
  1194. m_Request.DesiredAccess = MAXIMUM_ALLOWED;
  1195. m_Reply.GrantedAccessMask[0] = 0;
  1196. if(!AuthzAccessCheck(
  1197. 0,
  1198. m_ClientContext,
  1199. &m_Request,
  1200. NULL, //no audit
  1201. m_pCASD,
  1202. NULL,
  1203. 0,
  1204. &m_Reply,
  1205. NULL))
  1206. {
  1207. hr = myHLastError();
  1208. _JumpError(hr, error, "AuthzAccessCheck");
  1209. }
  1210. dwRoles |= (m_Reply.GrantedAccessMask[0] &
  1211. (CA_ACCESS_MASKROLES | // returned mask could also
  1212. CA_ACCESS_READ | // include generic rights (like
  1213. CA_ACCESS_ENROLL)); // read and write DACL) which
  1214. // we are not interested in
  1215. *pdwRoles = dwRoles;
  1216. error:
  1217. FreeCachedHandles();
  1218. return(hr);
  1219. }
  1220. // Build a one ace DACL security descriptor with the roles
  1221. // passed in
  1222. HRESULT CAuditEvent::BuildPrivilegeSecurityDescriptor(DWORD dwRoles)
  1223. {
  1224. HRESULT hr = S_OK;
  1225. DWORD dwDaclSize;
  1226. PSID pOwnerSid = NULL; // no free
  1227. PSID pGroupSid = NULL; // no free
  1228. BOOL fDefaulted;
  1229. CSASSERT(NULL == m_pSDPrivileges);
  1230. CSASSERT(NULL == m_pDaclPrivileges);
  1231. m_pSDPrivileges = (PSECURITY_DESCRIPTOR)LocalAlloc(
  1232. LMEM_FIXED,
  1233. SECURITY_DESCRIPTOR_MIN_LENGTH);
  1234. _JumpIfAllocFailed(m_pSDPrivileges, error);
  1235. if (!InitializeSecurityDescriptor(
  1236. m_pSDPrivileges,
  1237. SECURITY_DESCRIPTOR_REVISION))
  1238. {
  1239. hr = myHLastError();
  1240. _JumpError(hr, error, "InitializeSecurityDescriptor");
  1241. }
  1242. CSASSERT(m_pUserSid && IsValidSid(m_pUserSid));
  1243. dwDaclSize = sizeof(ACL) +
  1244. sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD)+
  1245. GetLengthSid(m_pUserSid);
  1246. m_pDaclPrivileges = (PACL)LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT, dwDaclSize);
  1247. _JumpIfAllocFailed(m_pDaclPrivileges, error);
  1248. if(!InitializeAcl(m_pDaclPrivileges, dwDaclSize, ACL_REVISION))
  1249. {
  1250. hr = myHLastError();
  1251. _JumpError(hr, error, "InitializeAcl");
  1252. }
  1253. if(!AddAccessAllowedAce(
  1254. m_pDaclPrivileges,
  1255. ACL_REVISION,
  1256. dwRoles,
  1257. m_pUserSid))
  1258. {
  1259. hr = myHLastError();
  1260. _JumpError(hr, error, "AddAccessAllowedAce");
  1261. }
  1262. if(!GetSecurityDescriptorOwner(m_pCASD,
  1263. &pOwnerSid,
  1264. &fDefaulted))
  1265. {
  1266. hr = myHLastError();
  1267. _JumpError(hr, error, "GetSecurityDescriptorOwner");
  1268. }
  1269. if(!SetSecurityDescriptorOwner(m_pSDPrivileges,
  1270. pOwnerSid,
  1271. fDefaulted))
  1272. {
  1273. hr = myHLastError();
  1274. _JumpError(hr, error, "SetSecurityDescriptorOwner");
  1275. }
  1276. if(!GetSecurityDescriptorGroup(m_pCASD,
  1277. &pGroupSid,
  1278. &fDefaulted))
  1279. {
  1280. hr = myHLastError();
  1281. _JumpError(hr, error, "GetSecurityDescriptorGroup");
  1282. }
  1283. if(!SetSecurityDescriptorGroup(m_pSDPrivileges,
  1284. pGroupSid,
  1285. fDefaulted))
  1286. {
  1287. hr = myHLastError();
  1288. _JumpError(hr, error, "SetSecurityDescriptorGroup");
  1289. }
  1290. if(!SetSecurityDescriptorDacl(m_pSDPrivileges,
  1291. TRUE,
  1292. m_pDaclPrivileges,
  1293. FALSE))
  1294. {
  1295. hr = myHLastError();
  1296. _JumpError(hr, error, "SetSecurityDescriptorDacl");
  1297. }
  1298. CSASSERT(IsValidSecurityDescriptor(m_pSDPrivileges));
  1299. error:
  1300. if(S_OK != hr)
  1301. {
  1302. if(m_pDaclPrivileges)
  1303. {
  1304. LocalFree(m_pDaclPrivileges);
  1305. m_pDaclPrivileges = NULL;
  1306. }
  1307. if(m_pSDPrivileges)
  1308. {
  1309. LocalFree(m_pSDPrivileges);
  1310. m_pSDPrivileges = NULL;
  1311. }
  1312. }
  1313. return hr;
  1314. }
  1315. HRESULT CAuditEvent::BuildAuditParamArray(PAUDIT_PARAM& rpParamArray)
  1316. {
  1317. HRESULT hr = S_OK;
  1318. // number of parameters added should be the same as the number of
  1319. // params defined in the audit format string in msaudite.dll
  1320. CSASSERT(m_cEventData == m_cRequiredEventData);
  1321. rpParamArray = (PAUDIT_PARAM) LocalAlloc(
  1322. LMEM_FIXED | LMEM_ZEROINIT,
  1323. sizeof(AUDIT_PARAM)*m_cEventData);
  1324. _JumpIfAllocFailed(rpParamArray, error);
  1325. for(USHORT c=0;c<m_cEventData;c++)
  1326. {
  1327. rpParamArray[c].Type = APT_String;
  1328. hr = m_pEventDataList[c]->ConvertToString(
  1329. &rpParamArray[c].String);
  1330. _JumpIfError(hr, error, "ConvertToString");
  1331. }
  1332. error:
  1333. return hr;
  1334. }
  1335. void CAuditEvent::FreeAuditParamArray(PAUDIT_PARAM pParamArray)
  1336. {
  1337. if(pParamArray)
  1338. {
  1339. for(USHORT c=0;c<m_cEventData;c++)
  1340. {
  1341. if(pParamArray[c].String)
  1342. delete[] pParamArray[c].String;
  1343. }
  1344. LocalFree(pParamArray);
  1345. }
  1346. }