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.

555 lines
14 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000
  5. //
  6. // File: SecUtil.cpp
  7. //
  8. // Contents: Utility functions for working with security APIs
  9. //
  10. // History: 15-Sep-2000 JeffJon Created
  11. //
  12. //
  13. //--------------------------------------------------------------------------
  14. #include "pch.h"
  15. #include "secutil.h"
  16. extern const GUID GUID_CONTROL_UserChangePassword =
  17. { 0xab721a53, 0x1e2f, 0x11d0, { 0x98, 0x19, 0x00, 0xaa, 0x00, 0x40, 0x52, 0x9b}};
  18. //+--------------------------------------------------------------------------
  19. //
  20. // Member: CSimpleSecurityDescriptorHolder::CSimpleSecurityDescriptorHolder
  21. //
  22. // Synopsis: Constructor for the smart security descriptor
  23. //
  24. // Arguments:
  25. //
  26. // Returns:
  27. //
  28. // History: 15-Sep-2000 JeffJon Created
  29. //
  30. //---------------------------------------------------------------------------
  31. CSimpleSecurityDescriptorHolder::CSimpleSecurityDescriptorHolder()
  32. {
  33. m_pSD = NULL;
  34. }
  35. //+--------------------------------------------------------------------------
  36. //
  37. // Member: CSimpleSecurityDescriptorHolder::~CSimpleSecurityDescriptorHolder
  38. //
  39. // Synopsis: Destructor for the smart security descriptor
  40. //
  41. // Arguments:
  42. //
  43. // Returns:
  44. //
  45. // History: 15-Sep-2000 JeffJon Created
  46. //
  47. //---------------------------------------------------------------------------
  48. CSimpleSecurityDescriptorHolder::~CSimpleSecurityDescriptorHolder()
  49. {
  50. if (m_pSD != NULL)
  51. {
  52. ::LocalFree(m_pSD);
  53. m_pSD = NULL;
  54. }
  55. }
  56. ////////////////////////////////////////////////////////////////////////////////
  57. //+--------------------------------------------------------------------------
  58. //
  59. // Member: CSidHolder::CSidHolder
  60. //
  61. // Synopsis: Constructor : initializes the member data
  62. //
  63. // Arguments:
  64. //
  65. // Returns:
  66. //
  67. // History: 15-Sep-2000 JeffJon Created
  68. //
  69. //---------------------------------------------------------------------------
  70. CSidHolder::CSidHolder()
  71. {
  72. _Init();
  73. }
  74. //+--------------------------------------------------------------------------
  75. //
  76. // Member: CSidHolder::~CSidHolder
  77. //
  78. // Synopsis: Destructor : Frees all data associated with the wrapped SID
  79. //
  80. // Arguments:
  81. //
  82. // Returns:
  83. //
  84. // History: 15-Sep-2000 JeffJon Created
  85. //
  86. //---------------------------------------------------------------------------
  87. CSidHolder::~CSidHolder()
  88. {
  89. _Free();
  90. }
  91. //+--------------------------------------------------------------------------
  92. //
  93. // Member: CSidHolder::Get
  94. //
  95. // Synopsis: Public accessor to the SID being wrapped
  96. //
  97. // Arguments:
  98. //
  99. // Returns: PSID : pointer to the SID being wrapped. NULL if the class
  100. // is not currently wrapping a SID
  101. //
  102. // History: 15-Sep-2000 JeffJon Created
  103. //
  104. //---------------------------------------------------------------------------
  105. PSID CSidHolder::Get()
  106. {
  107. return m_pSID;
  108. }
  109. //+--------------------------------------------------------------------------
  110. //
  111. // Member: CSidHolder::Copy
  112. //
  113. // Synopsis: Frees the memory associated with the currently wrapped SID
  114. // and then copies the new SID
  115. //
  116. // Arguments: [p - IN] : SID to be copied
  117. //
  118. // Returns: bool : true if the copy was successful, false otherwise
  119. //
  120. // History: 15-Sep-2000 JeffJon Created
  121. //
  122. //---------------------------------------------------------------------------
  123. bool CSidHolder::Copy(PSID p)
  124. {
  125. _Free();
  126. return _Copy(p);
  127. }
  128. //+--------------------------------------------------------------------------
  129. //
  130. // Member: CSidHolder::Attach
  131. //
  132. // Synopsis: Attaches the SID to the wrapper
  133. //
  134. // Arguments: [p - IN] : SID to be wrapped by this class
  135. // [bLocalAlloc - OUT] : tells whether the SID should be freed
  136. // with LocalFree
  137. //
  138. // Returns:
  139. //
  140. // History: 15-Sep-2000 JeffJon Created
  141. //
  142. //---------------------------------------------------------------------------
  143. void CSidHolder::Attach(PSID p, bool bLocalAlloc)
  144. {
  145. _Free();
  146. m_pSID = p;
  147. m_bLocalAlloc = bLocalAlloc;
  148. }
  149. //+--------------------------------------------------------------------------
  150. //
  151. // Member: CSidHolder::Clear
  152. //
  153. // Synopsis: Frees the memory associated with the SID being wrapped
  154. //
  155. // Arguments:
  156. //
  157. // Returns:
  158. //
  159. // History: 15-Sep-2000 JeffJon Created
  160. //
  161. //---------------------------------------------------------------------------
  162. void CSidHolder::Clear()
  163. {
  164. _Free();
  165. }
  166. //+--------------------------------------------------------------------------
  167. //
  168. // Member: CSidHolder::_Init
  169. //
  170. // Synopsis: Initializes the member data to default values
  171. //
  172. // Arguments:
  173. //
  174. // Returns:
  175. //
  176. // History: 15-Sep-2000 JeffJon Created
  177. //
  178. //---------------------------------------------------------------------------
  179. void CSidHolder::_Init()
  180. {
  181. m_pSID = NULL;
  182. m_bLocalAlloc = TRUE;
  183. }
  184. //+--------------------------------------------------------------------------
  185. //
  186. // Member: CSidHolder::_Free
  187. //
  188. // Synopsis: Frees the memory associated with the SID being wrapped
  189. //
  190. // Arguments:
  191. //
  192. // Returns:
  193. //
  194. // History: 15-Sep-2000 JeffJon Created
  195. //
  196. //---------------------------------------------------------------------------
  197. void CSidHolder::_Free()
  198. {
  199. if (m_pSID != NULL)
  200. {
  201. if (m_bLocalAlloc)
  202. {
  203. ::LocalFree(m_pSID);
  204. }
  205. else
  206. {
  207. ::FreeSid(m_pSID);
  208. _Init();
  209. }
  210. }
  211. }
  212. //+--------------------------------------------------------------------------
  213. //
  214. // Member: CSidHolder::_Copy
  215. //
  216. // Synopsis: Makes a copy of the SID being wrapped
  217. //
  218. // Arguments: [p - OUT] : destination of the SID being copied
  219. //
  220. // Returns: bool : true if SID was copied successfully
  221. // false if there was a failure
  222. //
  223. // History: 15-Sep-2000 JeffJon Created
  224. //
  225. //---------------------------------------------------------------------------
  226. bool CSidHolder::_Copy(PSID p)
  227. {
  228. if ( (p == NULL) || !::IsValidSid(p) )
  229. {
  230. return false;
  231. }
  232. DWORD dwLen = ::GetLengthSid(p);
  233. PSID pNew = ::LocalAlloc(LPTR, dwLen);
  234. if (pNew == NULL)
  235. {
  236. return false;
  237. }
  238. if (!::CopySid(dwLen, pNew, p))
  239. {
  240. ::LocalFree(pNew);
  241. return false;
  242. }
  243. m_bLocalAlloc = TRUE;
  244. m_pSID = pNew;
  245. ASSERT(dwLen == ::GetLengthSid(m_pSID));
  246. ASSERT(memcmp(p, m_pSID, dwLen) == 0);
  247. return true;
  248. }
  249. //+---------------------------------------------------------------------------
  250. //
  251. // Function: SetSecurityInfoMask
  252. //
  253. // Synopsis: Reads the security descriptor from the specied DS object
  254. //
  255. // Arguments: [IN punk] -- IUnknown from IDirectoryObject
  256. // [IN si] -- SecurityInformation
  257. //// History: 25-Dec-2000 -- Hiteshr Created
  258. //----------------------------------------------------------------------------
  259. HRESULT
  260. SetSecurityInfoMask(LPUNKNOWN punk, SECURITY_INFORMATION si)
  261. {
  262. HRESULT hr = E_INVALIDARG;
  263. if (punk)
  264. {
  265. IADsObjectOptions *pOptions;
  266. hr = punk->QueryInterface(IID_IADsObjectOptions, (void**)&pOptions);
  267. if (SUCCEEDED(hr))
  268. {
  269. VARIANT var;
  270. VariantInit(&var);
  271. V_VT(&var) = VT_I4;
  272. V_I4(&var) = si;
  273. hr = pOptions->SetOption(ADS_OPTION_SECURITY_MASK, var);
  274. pOptions->Release();
  275. }
  276. }
  277. return hr;
  278. }
  279. WCHAR const c_szSDProperty[] = L"nTSecurityDescriptor";
  280. //+---------------------------------------------------------------------------
  281. //
  282. // Function: DSReadObjectSecurity
  283. //
  284. // Synopsis: Reads the Dacl from the specied DS object
  285. //
  286. // Arguments: [in pDsObject] -- IDirettoryObject for dsobject
  287. // [psdControl] -- Control Setting for SD
  288. // They can be returned when calling
  289. // DSWriteObjectSecurity
  290. // [OUT ppDacl] -- DACL returned here
  291. //
  292. //
  293. // History 25-Oct-2000 -- hiteshr created
  294. //
  295. // Notes: If Object Doesn't have DACL, function will succeed but *ppDacl will
  296. // be NULL.
  297. // Caller must free *ppDacl, if not NULL, by calling LocalFree
  298. //
  299. //----------------------------------------------------------------------------
  300. HRESULT
  301. DSReadObjectSecurity(IN IDirectoryObject *pDsObject,
  302. OUT SECURITY_DESCRIPTOR_CONTROL * psdControl,
  303. OUT PACL *ppDacl)
  304. {
  305. ENTER_FUNCTION_HR(LEVEL5_LOGGING, DSReadObjectSecurity, hr);
  306. PADS_ATTR_INFO pSDAttributeInfo = NULL;
  307. do // false loop
  308. {
  309. LPWSTR pszSDProperty = (LPWSTR)c_szSDProperty;
  310. DWORD dwAttributesReturned;
  311. PSECURITY_DESCRIPTOR pSD = NULL;
  312. PACL pAcl = NULL;
  313. if(!pDsObject || !ppDacl)
  314. {
  315. ASSERT(FALSE);
  316. hr = E_INVALIDARG;
  317. break;
  318. }
  319. *ppDacl = NULL;
  320. // Set the SECURITY_INFORMATION mask
  321. hr = SetSecurityInfoMask(pDsObject, DACL_SECURITY_INFORMATION);
  322. if(FAILED(hr))
  323. {
  324. break;
  325. }
  326. //
  327. // Read the security descriptor
  328. //
  329. hr = pDsObject->GetObjectAttributes(&pszSDProperty,
  330. 1,
  331. &pSDAttributeInfo,
  332. &dwAttributesReturned);
  333. if (SUCCEEDED(hr) && !pSDAttributeInfo)
  334. hr = E_ACCESSDENIED; // This happens for SACL if no SecurityPrivilege
  335. if(FAILED(hr))
  336. {
  337. break;
  338. }
  339. ASSERT(ADSTYPE_NT_SECURITY_DESCRIPTOR == pSDAttributeInfo->dwADsType);
  340. ASSERT(ADSTYPE_NT_SECURITY_DESCRIPTOR == pSDAttributeInfo->pADsValues->dwType);
  341. pSD = (PSECURITY_DESCRIPTOR)pSDAttributeInfo->pADsValues->SecurityDescriptor.lpValue;
  342. ASSERT(IsValidSecurityDescriptor(pSD));
  343. //
  344. //Get the security descriptor control
  345. //
  346. if(psdControl)
  347. {
  348. DWORD dwRevision;
  349. if(!GetSecurityDescriptorControl(pSD, psdControl, &dwRevision))
  350. {
  351. hr = HRESULT_FROM_WIN32(GetLastError());
  352. break;
  353. }
  354. }
  355. //
  356. //Get pointer to DACL
  357. //
  358. BOOL bDaclPresent, bDaclDefaulted;
  359. if(!GetSecurityDescriptorDacl(pSD,
  360. &bDaclPresent,
  361. &pAcl,
  362. &bDaclDefaulted))
  363. {
  364. hr = HRESULT_FROM_WIN32(GetLastError());
  365. break;
  366. }
  367. if(!bDaclPresent ||
  368. !pAcl)
  369. {
  370. break;
  371. }
  372. ASSERT(IsValidAcl(pAcl));
  373. //
  374. //Make a copy of the DACL
  375. //
  376. *ppDacl = (PACL)LocalAlloc(LPTR,pAcl->AclSize);
  377. if(!*ppDacl)
  378. {
  379. hr = E_OUTOFMEMORY;
  380. break;
  381. }
  382. CopyMemory(*ppDacl,pAcl,pAcl->AclSize);
  383. }while(0);
  384. if (pSDAttributeInfo)
  385. FreeADsMem(pSDAttributeInfo);
  386. return hr;
  387. }
  388. //+---------------------------------------------------------------------------
  389. //
  390. // Function: DSWriteObjectSecurity
  391. //
  392. // Synopsis: Writes the Dacl to the specied DS object
  393. //
  394. // Arguments: [in pDsObject] -- IDirettoryObject for dsobject
  395. // [sdControl] -- control for security descriptor
  396. // [IN pDacl] -- The DACL to be written
  397. //
  398. // History 25-Oct-2000 -- hiteshr created
  399. //----------------------------------------------------------------------------
  400. HRESULT
  401. DSWriteObjectSecurity(IN IDirectoryObject *pDsObject,
  402. IN SECURITY_DESCRIPTOR_CONTROL sdControl,
  403. PACL pDacl)
  404. {
  405. ENTER_FUNCTION_HR(LEVEL5_LOGGING, DSWriteObjectSecurity, hr);
  406. PISECURITY_DESCRIPTOR pSD = NULL;
  407. PSECURITY_DESCRIPTOR psd = NULL;
  408. do // false loop
  409. {
  410. ADSVALUE attributeValue;
  411. ADS_ATTR_INFO attributeInfo;
  412. DWORD dwAttributesModified;
  413. DWORD dwSDLength;
  414. if(!pDsObject || !pDacl)
  415. {
  416. ASSERT(FALSE);
  417. hr = E_INVALIDARG;
  418. break;
  419. }
  420. ASSERT(IsValidAcl(pDacl));
  421. // Set the SECURITY_INFORMATION mask
  422. hr = SetSecurityInfoMask(pDsObject, DACL_SECURITY_INFORMATION);
  423. if(FAILED(hr))
  424. {
  425. DEBUG_OUTPUT(MINIMAL_LOGGING,
  426. L"SetSecurityInfoMask failed: hr = 0x%x",
  427. hr);
  428. break;
  429. }
  430. //
  431. //Build the Security Descriptor
  432. //
  433. pSD = (PISECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
  434. if (pSD == NULL)
  435. {
  436. DEBUG_OUTPUT(MINIMAL_LOGGING,
  437. L"Failed to allocate memory for Security Descriptor");
  438. hr = E_OUTOFMEMORY;
  439. break;
  440. }
  441. InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
  442. //
  443. // Finally, build the security descriptor
  444. //
  445. pSD->Control |= SE_DACL_PRESENT | SE_DACL_AUTO_INHERIT_REQ
  446. | (sdControl & (SE_DACL_PROTECTED | SE_DACL_AUTO_INHERITED));
  447. if(pDacl->AclSize)
  448. {
  449. pSD->Dacl = pDacl;
  450. }
  451. //
  452. // Need the total size
  453. //
  454. dwSDLength = GetSecurityDescriptorLength(pSD);
  455. //
  456. // If necessary, make a self-relative copy of the security descriptor
  457. //
  458. psd = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, dwSDLength);
  459. if (psd == NULL ||
  460. !MakeSelfRelativeSD(pSD, psd, &dwSDLength))
  461. {
  462. hr = HRESULT_FROM_WIN32(GetLastError());
  463. DEBUG_OUTPUT(MINIMAL_LOGGING,
  464. L"MakeSelfRelativeSD failed: hr = 0x%x",
  465. hr);
  466. break;
  467. }
  468. attributeValue.dwType = ADSTYPE_NT_SECURITY_DESCRIPTOR;
  469. attributeValue.SecurityDescriptor.dwLength = dwSDLength;
  470. attributeValue.SecurityDescriptor.lpValue = (LPBYTE)psd;
  471. attributeInfo.pszAttrName = (LPWSTR)c_szSDProperty;
  472. attributeInfo.dwControlCode = ADS_ATTR_UPDATE;
  473. attributeInfo.dwADsType = ADSTYPE_NT_SECURITY_DESCRIPTOR;
  474. attributeInfo.pADsValues = &attributeValue;
  475. attributeInfo.dwNumValues = 1;
  476. // Write the security descriptor
  477. hr = pDsObject->SetObjectAttributes(&attributeInfo,
  478. 1,
  479. &dwAttributesModified);
  480. } while (false);
  481. if (psd != NULL)
  482. {
  483. LocalFree(psd);
  484. }
  485. if(pSD != NULL)
  486. {
  487. LocalFree(pSD);
  488. }
  489. return hr;
  490. }