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.

562 lines
15 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. //Security Review:This is fine. Buffer is correctly allocated.
  239. if (!::CopySid(dwLen, pNew, p))
  240. {
  241. ::LocalFree(pNew);
  242. return false;
  243. }
  244. m_bLocalAlloc = TRUE;
  245. m_pSID = pNew;
  246. ASSERT(dwLen == ::GetLengthSid(m_pSID));
  247. ASSERT(memcmp(p, m_pSID, dwLen) == 0);
  248. return true;
  249. }
  250. //+---------------------------------------------------------------------------
  251. //
  252. // Function: SetSecurityInfoMask
  253. //
  254. // Synopsis: Reads the security descriptor from the specied DS object
  255. //
  256. // Arguments: [IN punk] -- IUnknown from IDirectoryObject
  257. // [IN si] -- SecurityInformation
  258. //// History: 25-Dec-2000 -- Hiteshr Created
  259. //----------------------------------------------------------------------------
  260. HRESULT
  261. SetSecurityInfoMask(LPUNKNOWN punk, SECURITY_INFORMATION si)
  262. {
  263. HRESULT hr = E_INVALIDARG;
  264. if (punk)
  265. {
  266. IADsObjectOptions *pOptions;
  267. hr = punk->QueryInterface(IID_IADsObjectOptions, (void**)&pOptions);
  268. if (SUCCEEDED(hr))
  269. {
  270. VARIANT var;
  271. VariantInit(&var);
  272. V_VT(&var) = VT_I4;
  273. V_I4(&var) = si;
  274. hr = pOptions->SetOption(ADS_OPTION_SECURITY_MASK, var);
  275. pOptions->Release();
  276. }
  277. }
  278. return hr;
  279. }
  280. WCHAR const c_szSDProperty[] = L"nTSecurityDescriptor";
  281. //+---------------------------------------------------------------------------
  282. //
  283. // Function: DSReadObjectSecurity
  284. //
  285. // Synopsis: Reads the Dacl from the specied DS object
  286. //
  287. // Arguments: [in pDsObject] -- IDirettoryObject for dsobject
  288. // [psdControl] -- Control Setting for SD
  289. // They can be returned when calling
  290. // DSWriteObjectSecurity
  291. // [OUT ppDacl] -- DACL returned here
  292. //
  293. //
  294. // History 25-Oct-2000 -- hiteshr created
  295. //
  296. // Notes: If Object Doesn't have DACL, function will succeed but *ppDacl will
  297. // be NULL.
  298. // Caller must free *ppDacl, if not NULL, by calling LocalFree
  299. //
  300. //----------------------------------------------------------------------------
  301. HRESULT
  302. DSReadObjectSecurity(IN IDirectoryObject *pDsObject,
  303. OUT SECURITY_DESCRIPTOR_CONTROL * psdControl,
  304. OUT PACL *ppDacl)
  305. {
  306. ENTER_FUNCTION_HR(LEVEL5_LOGGING, DSReadObjectSecurity, hr);
  307. PADS_ATTR_INFO pSDAttributeInfo = NULL;
  308. do // false loop
  309. {
  310. LPWSTR pszSDProperty = (LPWSTR)c_szSDProperty;
  311. DWORD dwAttributesReturned;
  312. PSECURITY_DESCRIPTOR pSD = NULL;
  313. PACL pAcl = NULL;
  314. if(!pDsObject || !ppDacl)
  315. {
  316. ASSERT(FALSE);
  317. hr = E_INVALIDARG;
  318. break;
  319. }
  320. *ppDacl = NULL;
  321. // Set the SECURITY_INFORMATION mask
  322. hr = SetSecurityInfoMask(pDsObject, DACL_SECURITY_INFORMATION);
  323. if(FAILED(hr))
  324. {
  325. break;
  326. }
  327. //
  328. // Read the security descriptor
  329. //
  330. hr = pDsObject->GetObjectAttributes(&pszSDProperty,
  331. 1,
  332. &pSDAttributeInfo,
  333. &dwAttributesReturned);
  334. if (SUCCEEDED(hr) && !pSDAttributeInfo)
  335. hr = E_ACCESSDENIED; // This happens for SACL if no SecurityPrivilege
  336. if(FAILED(hr))
  337. {
  338. break;
  339. }
  340. ASSERT(ADSTYPE_NT_SECURITY_DESCRIPTOR == pSDAttributeInfo->dwADsType);
  341. ASSERT(ADSTYPE_NT_SECURITY_DESCRIPTOR == pSDAttributeInfo->pADsValues->dwType);
  342. pSD = (PSECURITY_DESCRIPTOR)pSDAttributeInfo->pADsValues->SecurityDescriptor.lpValue;
  343. ASSERT(IsValidSecurityDescriptor(pSD));
  344. //
  345. //Get the security descriptor control
  346. //
  347. if(psdControl)
  348. {
  349. DWORD dwRevision;
  350. if(!GetSecurityDescriptorControl(pSD, psdControl, &dwRevision))
  351. {
  352. DWORD _dwErr = GetLastError();
  353. hr = HRESULT_FROM_WIN32( _dwErr );
  354. break;
  355. }
  356. }
  357. //
  358. //Get pointer to DACL
  359. //
  360. BOOL bDaclPresent, bDaclDefaulted;
  361. if(!GetSecurityDescriptorDacl(pSD,
  362. &bDaclPresent,
  363. &pAcl,
  364. &bDaclDefaulted))
  365. {
  366. DWORD _dwErr = GetLastError();
  367. hr = HRESULT_FROM_WIN32( _dwErr );
  368. break;
  369. }
  370. if(!bDaclPresent ||
  371. !pAcl)
  372. {
  373. break;
  374. }
  375. ASSERT(IsValidAcl(pAcl));
  376. //
  377. //Make a copy of the DACL
  378. //
  379. *ppDacl = (PACL)LocalAlloc(LPTR,pAcl->AclSize);
  380. if(!*ppDacl)
  381. {
  382. hr = E_OUTOFMEMORY;
  383. break;
  384. }
  385. //Security Review:This is fine. Memory is correctly allocted above.
  386. CopyMemory(*ppDacl,pAcl,pAcl->AclSize);
  387. }while(0);
  388. if (pSDAttributeInfo)
  389. FreeADsMem(pSDAttributeInfo);
  390. return hr;
  391. }
  392. //+---------------------------------------------------------------------------
  393. //
  394. // Function: DSWriteObjectSecurity
  395. //
  396. // Synopsis: Writes the Dacl to the specied DS object
  397. //
  398. // Arguments: [in pDsObject] -- IDirettoryObject for dsobject
  399. // [sdControl] -- control for security descriptor
  400. // [IN pDacl] -- The DACL to be written
  401. //
  402. // History 25-Oct-2000 -- hiteshr created
  403. //----------------------------------------------------------------------------
  404. HRESULT
  405. DSWriteObjectSecurity(IN IDirectoryObject *pDsObject,
  406. IN SECURITY_DESCRIPTOR_CONTROL sdControl,
  407. PACL pDacl)
  408. {
  409. ENTER_FUNCTION_HR(LEVEL5_LOGGING, DSWriteObjectSecurity, hr);
  410. PISECURITY_DESCRIPTOR pSD = NULL;
  411. PSECURITY_DESCRIPTOR psd = NULL;
  412. do // false loop
  413. {
  414. ADSVALUE attributeValue;
  415. ADS_ATTR_INFO attributeInfo;
  416. DWORD dwAttributesModified;
  417. DWORD dwSDLength;
  418. if(!pDsObject || !pDacl)
  419. {
  420. ASSERT(FALSE);
  421. hr = E_INVALIDARG;
  422. break;
  423. }
  424. ASSERT(IsValidAcl(pDacl));
  425. // Set the SECURITY_INFORMATION mask
  426. hr = SetSecurityInfoMask(pDsObject, DACL_SECURITY_INFORMATION);
  427. if(FAILED(hr))
  428. {
  429. DEBUG_OUTPUT(MINIMAL_LOGGING,
  430. L"SetSecurityInfoMask failed: hr = 0x%x",
  431. hr);
  432. break;
  433. }
  434. //
  435. //Build the Security Descriptor
  436. //
  437. pSD = (PISECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
  438. if (pSD == NULL)
  439. {
  440. DEBUG_OUTPUT(MINIMAL_LOGGING,
  441. L"Failed to allocate memory for Security Descriptor");
  442. hr = E_OUTOFMEMORY;
  443. break;
  444. }
  445. //Security Review:This is fine.
  446. InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
  447. //
  448. // Finally, build the security descriptor
  449. //
  450. pSD->Control |= SE_DACL_PRESENT | SE_DACL_AUTO_INHERIT_REQ
  451. | (sdControl & (SE_DACL_PROTECTED | SE_DACL_AUTO_INHERITED));
  452. if(pDacl->AclSize)
  453. {
  454. pSD->Dacl = pDacl;
  455. }
  456. //
  457. // Need the total size
  458. //
  459. dwSDLength = GetSecurityDescriptorLength(pSD);
  460. //
  461. // If necessary, make a self-relative copy of the security descriptor
  462. //
  463. psd = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, dwSDLength);
  464. if (psd == NULL ||
  465. !MakeSelfRelativeSD(pSD, psd, &dwSDLength))
  466. {
  467. DWORD _dwErr = GetLastError();
  468. hr = HRESULT_FROM_WIN32( _dwErr );
  469. DEBUG_OUTPUT(MINIMAL_LOGGING,
  470. L"MakeSelfRelativeSD failed: hr = 0x%x",
  471. hr);
  472. break;
  473. }
  474. attributeValue.dwType = ADSTYPE_NT_SECURITY_DESCRIPTOR;
  475. attributeValue.SecurityDescriptor.dwLength = dwSDLength;
  476. attributeValue.SecurityDescriptor.lpValue = (LPBYTE)psd;
  477. attributeInfo.pszAttrName = (LPWSTR)c_szSDProperty;
  478. attributeInfo.dwControlCode = ADS_ATTR_UPDATE;
  479. attributeInfo.dwADsType = ADSTYPE_NT_SECURITY_DESCRIPTOR;
  480. attributeInfo.pADsValues = &attributeValue;
  481. attributeInfo.dwNumValues = 1;
  482. // Write the security descriptor
  483. hr = pDsObject->SetObjectAttributes(&attributeInfo,
  484. 1,
  485. &dwAttributesModified);
  486. } while (false);
  487. if (psd != NULL)
  488. {
  489. LocalFree(psd);
  490. }
  491. if(pSD != NULL)
  492. {
  493. LocalFree(pSD);
  494. }
  495. return hr;
  496. }