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.

480 lines
12 KiB

  1. //+--------------------------------------------------------------------------
  2. // File: officer.cpp
  3. // Contents: officer rights implementation
  4. //---------------------------------------------------------------------------
  5. #include <stdafx.h>
  6. #include "officer.h"
  7. #include "certsd.h"
  8. #define __dwFILE__ __dwFILE_CERTMMC_OFFICER_CPP__
  9. using namespace CertSrv;
  10. static const DEFAULT_USERNAME_SIZE = 256;
  11. CClientPermission::CClientPermission(BOOL fAllow, PSID pSid) :
  12. m_fAllow(fAllow),
  13. m_Sid(pSid)
  14. {}
  15. HRESULT COfficerRights::Add(PSID pSid, BOOL fAllow)
  16. {
  17. HRESULT hr = S_OK;
  18. CClientPermission* pClient = new CClientPermission(fAllow, pSid);
  19. if(!CClientPermission::IsInitialized(pClient) ||
  20. !m_List.AddTail(pClient))
  21. {
  22. hr = E_OUTOFMEMORY;
  23. _JumpError(hr, error, "");
  24. }
  25. error:
  26. if(S_OK!=hr)
  27. delete pClient;
  28. return hr;
  29. }
  30. HRESULT COfficerRights::Init(PACCESS_ALLOWED_CALLBACK_ACE pAce)
  31. {
  32. HRESULT hr = S_OK;
  33. // no object reuse
  34. CSASSERT(!m_pSid);
  35. CSASSERT(m_List.IsEmpty());
  36. CSASSERT(IsValidSid((PSID)(&pAce->SidStart)));
  37. m_pSid = new CSid((PSID)(&pAce->SidStart));
  38. if(!m_pSid)
  39. {
  40. hr = E_OUTOFMEMORY;
  41. _JumpError(hr, error, "new CSid");
  42. }
  43. hr = AddSidList(pAce);
  44. _JumpIfError(hr, error, "COfficerRights::AddSidList");
  45. error:
  46. if(S_OK!=hr)
  47. {
  48. Cleanup();
  49. }
  50. return hr;
  51. }
  52. HRESULT COfficerRights::AddSidList(PACCESS_ALLOWED_CALLBACK_ACE pAce)
  53. {
  54. HRESULT hr = S_OK;
  55. PSID pSid;
  56. DWORD cSids;
  57. PSID_LIST pSidList = (PSID_LIST) (((BYTE*)&pAce->SidStart)+
  58. GetLengthSid(&pAce->SidStart));
  59. CSASSERT(EqualSid((PSID)&pAce->SidStart, GetSid()));
  60. for(pSid=(PSID)&pSidList->SidListStart, cSids=0;
  61. cSids<pSidList->dwSidCount;
  62. cSids++, pSid = (PSID)(((BYTE*)pSid)+GetLengthSid(pSid)))
  63. {
  64. hr = Add(pSid, ACCESS_ALLOWED_CALLBACK_ACE_TYPE==pAce->Header.AceType);
  65. _JumpIfError(hr, error, "COfficerRights::Add");
  66. }
  67. error:
  68. return hr;
  69. }
  70. COfficerRightsList::~COfficerRightsList()
  71. {
  72. Cleanup();
  73. }
  74. HRESULT COfficerRightsList::Load(PSECURITY_DESCRIPTOR pSD)
  75. {
  76. HRESULT hr = S_OK;
  77. PACL pAcl; // no free
  78. ACL_SIZE_INFORMATION AclInfo;
  79. PACCESS_ALLOWED_CALLBACK_ACE pAce;
  80. DWORD cAce;
  81. COfficerRights *pOfficerRights = NULL;
  82. DWORD cList;
  83. COfficerRights* pExistingOfficer;
  84. CSASSERT(IsValidSecurityDescriptor(pSD));
  85. hr = myGetSecurityDescriptorDacl(pSD, &pAcl);
  86. _JumpIfError(hr, error, "myGetSecurityDescriptorDacl");
  87. if(!GetAclInformation(pAcl,
  88. &AclInfo,
  89. sizeof(AclInfo),
  90. AclSizeInformation))
  91. {
  92. hr = myHLastError();
  93. _JumpError(hr, error, "GetAclInformation");
  94. }
  95. m_dwCountList = 0;
  96. m_List = (COfficerRights **)LocalAlloc(LMEM_FIXED,
  97. sizeof(COfficerRights*)*AclInfo.AceCount);
  98. if(!m_List)
  99. {
  100. hr = E_OUTOFMEMORY;
  101. _JumpError(hr, error, "LocalAlloc");
  102. }
  103. ZeroMemory(m_List, sizeof(COfficerRights*)*AclInfo.AceCount);
  104. for(cAce=0; cAce<AclInfo.AceCount; cAce++)
  105. {
  106. pExistingOfficer = NULL;
  107. if(!GetAce(pAcl, cAce, (PVOID*)&pAce))
  108. {
  109. hr = myHLastError();
  110. _JumpError(hr, error, "GetAce");
  111. }
  112. CSASSERT(
  113. ACCESS_ALLOWED_CALLBACK_ACE_TYPE == pAce->Header.AceType ||
  114. ACCESS_DENIED_CALLBACK_ACE_TYPE == pAce->Header.AceType);
  115. // Detect if another object already exists for this officer; if so, we
  116. // will add the client list to it instead of creating a new object
  117. // Assuming denied aces always come before allow aces, we can limit
  118. // the search to allow type
  119. if(ACCESS_ALLOWED_CALLBACK_ACE_TYPE==pAce->Header.AceType)
  120. {
  121. for(cList=0; cList<m_dwCountList; cList++)
  122. {
  123. if(EqualSid(m_List[cList]->GetSid(),
  124. (PSID)&pAce->SidStart))
  125. {
  126. pExistingOfficer = m_List[cList];
  127. break;
  128. }
  129. }
  130. }
  131. if(pExistingOfficer)
  132. {
  133. // add SID list stored in this ace to existing officer object
  134. hr = pExistingOfficer->AddSidList(pAce);
  135. _JumpIfError(hr, error, "COfficerRights::AddSidList");
  136. }
  137. else
  138. {
  139. // create new officer object
  140. pOfficerRights = new COfficerRights;
  141. if(!pOfficerRights)
  142. {
  143. hr = E_OUTOFMEMORY;
  144. _JumpError(hr, error, "new COfficerRights");
  145. }
  146. hr = pOfficerRights->Init(pAce);
  147. _JumpIfError(hr, error, "COfficerRights::Init");
  148. m_List[m_dwCountList] = pOfficerRights;
  149. pOfficerRights = NULL;
  150. m_dwCountList++;
  151. }
  152. }
  153. error:
  154. if(S_OK!=hr && m_List)
  155. {
  156. if(m_List)
  157. {
  158. LocalFree(m_List);
  159. m_List = NULL;
  160. }
  161. if(pOfficerRights)
  162. {
  163. delete pOfficerRights;
  164. }
  165. }
  166. return hr;
  167. }
  168. HRESULT COfficerRightsList::Save(PSECURITY_DESCRIPTOR &rpSD)
  169. {
  170. HRESULT hr = S_OK;
  171. PSECURITY_DESCRIPTOR pSD = NULL, pSDSelfRelative = NULL;
  172. DWORD dwSelfRelativeSize = 0;
  173. PSID pSidBuiltinAdministrators = NULL;
  174. PACL pAcl = NULL;
  175. rpSD = NULL;
  176. pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LMEM_FIXED,
  177. SECURITY_DESCRIPTOR_MIN_LENGTH);
  178. if (!pSD)
  179. {
  180. hr = E_OUTOFMEMORY;
  181. _JumpError(hr, error, "LocalAlloc");
  182. }
  183. #ifdef _DEBUG
  184. ZeroMemory(pSD, SECURITY_DESCRIPTOR_MIN_LENGTH);
  185. #endif
  186. if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION))
  187. {
  188. hr = myHLastError();
  189. _JumpError(hr, error, "InitializeSecurityDescriptor");
  190. }
  191. hr = GetBuiltinAdministratorsSID(&pSidBuiltinAdministrators);
  192. _JumpIfError(hr, error, "GetBuiltinAdministratorsSID");
  193. if(!SetSecurityDescriptorOwner(
  194. pSD,
  195. pSidBuiltinAdministrators,
  196. FALSE))
  197. {
  198. hr = myHLastError();
  199. _JumpError(hr, error, "SetSecurityDescriptorControl");
  200. }
  201. hr = BuildAcl(pAcl);
  202. _JumpIfError(hr, error, "BuildAcl");
  203. if(!SetSecurityDescriptorDacl(
  204. pSD,
  205. TRUE, // DACL present
  206. pAcl,
  207. FALSE)) // DACL defaulted
  208. {
  209. hr = myHLastError();
  210. _JumpError(hr, error, "SetSecurityDescriptorDacl");
  211. }
  212. CSASSERT(IsValidSecurityDescriptor(pSD));
  213. MakeSelfRelativeSD(pSD, NULL, &dwSelfRelativeSize);
  214. if(ERROR_INSUFFICIENT_BUFFER!=GetLastError())
  215. {
  216. hr = myHLastError();
  217. _JumpError(hr, error, "SetSecurityDescriptorDacl");
  218. }
  219. pSDSelfRelative = (PSECURITY_DESCRIPTOR)LocalAlloc(LMEM_FIXED, dwSelfRelativeSize);
  220. if(!pSDSelfRelative)
  221. {
  222. hr = E_OUTOFMEMORY;
  223. _JumpError(hr, error, "LocalAlloc");
  224. }
  225. if(!MakeSelfRelativeSD(pSD, pSDSelfRelative, &dwSelfRelativeSize))
  226. {
  227. hr = myHLastError();
  228. _JumpError(hr, error, "MakeSelfRelativeSD");
  229. }
  230. rpSD = pSDSelfRelative;
  231. error:
  232. if(pAcl)
  233. {
  234. LocalFree(pAcl);
  235. }
  236. if(pSD)
  237. {
  238. LocalFree(pSD);
  239. }
  240. if(pSidBuiltinAdministrators)
  241. {
  242. LocalFree(pSidBuiltinAdministrators);
  243. }
  244. return hr;
  245. }
  246. HRESULT COfficerRightsList::BuildAcl(PACL &rpAcl)
  247. {
  248. HRESULT hr = S_OK;
  249. DWORD dwAclSize = sizeof(ACL);
  250. DWORD cRights;
  251. PACL pAcl = NULL;
  252. rpAcl = NULL;
  253. // calculate total acl size by adding the space required
  254. // for the ACEs resulting from each COfficerRights
  255. for(cRights=0;cRights<m_dwCountList;cRights++)
  256. {
  257. dwAclSize += m_List[cRights]->GetAceSize(FALSE);
  258. dwAclSize += m_List[cRights]->GetAceSize(TRUE);
  259. }
  260. pAcl = (PACL)LocalAlloc(LMEM_FIXED, dwAclSize);
  261. if(!pAcl)
  262. {
  263. hr = E_OUTOFMEMORY;
  264. _JumpError(hr, error, "LocalAlloc");
  265. }
  266. #ifdef _DEBUG
  267. ZeroMemory(pAcl, dwAclSize);
  268. #endif
  269. if(!InitializeAcl(pAcl, dwAclSize, ACL_REVISION))
  270. {
  271. hr = myHLastError();
  272. _JumpError(hr, error, "InitializeAcl");
  273. }
  274. // add deny aces first
  275. for(cRights=0;cRights<m_dwCountList;cRights++)
  276. {
  277. hr = m_List[cRights]->AddAce(pAcl, FALSE);
  278. _JumpIfError(hr, error, "COfficerRights::AddAce");
  279. }
  280. // then add allow aces
  281. for(cRights=0;cRights<m_dwCountList;cRights++)
  282. {
  283. hr = m_List[cRights]->AddAce(pAcl, TRUE);
  284. _JumpIfError(hr, error, "COfficerRights::AddAce");
  285. }
  286. CSASSERT(IsValidAcl(pAcl));
  287. rpAcl = pAcl;
  288. error:
  289. if(S_OK!=hr)
  290. {
  291. if(pAcl)
  292. {
  293. LocalFree(pAcl);
  294. }
  295. }
  296. return hr;
  297. }
  298. DWORD COfficerRights::GetAceSize(BOOL fAllow)
  299. {
  300. DWORD dwAceSize = sizeof(ACCESS_ALLOWED_CALLBACK_ACE);
  301. dwAceSize += GetLengthSid(m_pSid->GetSid());
  302. BOOL fFound = FALSE;
  303. TPtrListEnum<CClientPermission> CPEnum(m_List);
  304. CClientPermission *pCP;
  305. for(pCP=CPEnum.Next();pCP;pCP=CPEnum.Next())
  306. {
  307. if(pCP->GetPermission()==fAllow)
  308. {
  309. dwAceSize += GetLengthSid(pCP->GetSid());
  310. fFound = TRUE;
  311. }
  312. }
  313. return fFound?dwAceSize:0;
  314. }
  315. HRESULT COfficerRights::AddAce(PACL pAcl, BOOL fAllow)
  316. {
  317. HRESULT hr = S_OK;
  318. PACCESS_ALLOWED_CALLBACK_ACE pAce = NULL;
  319. DWORD dwAceSize = GetAceSize(fAllow);
  320. DWORD dwSidSize = GetLengthSid(m_pSid->GetSid());
  321. DWORD dwClientSidSize;
  322. PSID_LIST pSidList;
  323. PSID pClientSid;
  324. TPtrListEnum<CClientPermission> CPEnum(m_List);
  325. CClientPermission *pCP;
  326. BOOL fFound = FALSE;
  327. DWORD dwSidCount = 0;
  328. if(dwAceSize)
  329. {
  330. pAce = (PACCESS_ALLOWED_CALLBACK_ACE) LocalAlloc(LMEM_FIXED, dwAceSize);
  331. if(!pAce)
  332. {
  333. hr = E_OUTOFMEMORY;
  334. _JumpError(hr, error, "LocalAlloc");
  335. }
  336. #ifdef _DEBUG
  337. ZeroMemory(pAce, dwAceSize);
  338. #endif
  339. pAce->Header.AceType = (BYTE) (fAllow?
  340. ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
  341. ACCESS_DENIED_CALLBACK_ACE_TYPE);
  342. pAce->Header.AceFlags= 0;
  343. pAce->Header.AceSize = (USHORT)dwAceSize;
  344. pAce->Mask = DELETE;
  345. CopySid(dwSidSize,
  346. (PSID)&pAce->SidStart,
  347. m_pSid->GetSid());
  348. pSidList = (PSID_LIST)(((BYTE*)&pAce->SidStart)+dwSidSize);
  349. pSidList->dwSidCount = m_List.GetCount();
  350. pClientSid = (PSID)&pSidList->SidListStart;
  351. for(pCP=CPEnum.Next(); pCP; pCP=CPEnum.Next())
  352. {
  353. if(pCP->GetPermission()==fAllow)
  354. {
  355. dwClientSidSize = GetLengthSid(pCP->GetSid());
  356. CopySid(dwClientSidSize,
  357. pClientSid,
  358. pCP->GetSid());
  359. pClientSid = (((BYTE*)pClientSid)+dwClientSidSize);
  360. fFound = TRUE;
  361. dwSidCount++;
  362. }
  363. }
  364. pSidList->dwSidCount = dwSidCount;
  365. CSASSERT(pClientSid==((BYTE*)pAce)+dwAceSize);
  366. if(fFound)
  367. {
  368. if(!::AddAce(
  369. pAcl,
  370. ACL_REVISION,
  371. MAXDWORD,
  372. pAce,
  373. dwAceSize))
  374. {
  375. hr = myHLastError();
  376. _JumpError(hr, error, "AddAce");
  377. }
  378. }
  379. }
  380. error:
  381. if(pAce)
  382. {
  383. LocalFree(pAce);
  384. }
  385. return hr;
  386. }
  387. void COfficerRightsList::Dump()
  388. {
  389. DBGPRINT((DBG_SS_INFO, "Officers: %d\n", m_dwCountList));
  390. wprintf(L"Officers: %d\n", m_dwCountList);
  391. for(DWORD dwCount=0;dwCount<m_dwCountList;dwCount++)
  392. {
  393. COfficerRights *pOR = GetAt(dwCount);
  394. wprintf(L"Officer %ws, %d clients\n", pOR->GetName(), pOR->GetCount());
  395. for(DWORD c=0;c<pOR->GetCount();c++)
  396. {
  397. CClientPermission *pCli = pOR->GetAt(c);
  398. wprintf(L"\tClient %ws, %ws\n", pCli->GetName(), pCli->GetPermission()?L"allow":L"deny");
  399. }
  400. }
  401. }
  402. // Searches the list for an object with this SID; if found returns
  403. // object index, if not found, returns DWORD_MAX
  404. DWORD COfficerRights::Find(PSID pSid)
  405. {
  406. CClientPermission perm(TRUE, pSid);
  407. return m_List.FindIndex(perm);
  408. }