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.

2985 lines
73 KiB

  1. /*++
  2. Copyright (C) 1997-2001 Microsoft Corporation
  3. Module Name:
  4. WINNTSEC.CPP
  5. Abstract:
  6. Generic wrapper classes for NT security objects.
  7. Documention on class members is in WINNTSEC.CPP. Inline members
  8. are commented in this file.
  9. History:
  10. raymcc 08-Jul-97 Created.
  11. --*/
  12. #include "precomp.h"
  13. #include <stdio.h>
  14. #include <io.h>
  15. #include <errno.h>
  16. #include <winntsec.h>
  17. #include <genutils.h>
  18. #include "arena.h"
  19. #include "reg.h"
  20. #include "wbemutil.h"
  21. #include "arrtempl.h"
  22. #include <cominit.h>
  23. #include <Sddl.h>
  24. extern "C"
  25. {
  26. #include <lmaccess.h>
  27. #include <lmapibuf.h>
  28. #include <lmerr.h>
  29. };
  30. #include <helper.h>
  31. //***************************************************************************
  32. //
  33. // CNtSid::GetSize
  34. //
  35. // Returns the size of the SID in bytes.
  36. //
  37. //***************************************************************************
  38. // ok
  39. DWORD CNtSid::GetSize()
  40. {
  41. if (m_pSid == 0 || !IsValidSid(m_pSid))
  42. return 0;
  43. return GetLengthSid(m_pSid);
  44. }
  45. //***************************************************************************
  46. //
  47. // CNtSid Copy Constructor
  48. //
  49. //***************************************************************************
  50. // ok
  51. CNtSid::CNtSid( const CNtSid &Src)
  52. {
  53. m_pSid = 0;
  54. m_pMachine = 0;
  55. if (Src.m_dwStatus != CNtSid::NoError)
  56. {
  57. m_dwStatus = Src.m_dwStatus;
  58. return;
  59. }
  60. m_dwStatus = InternalError;
  61. if (NULL == Src.m_pSid) return;
  62. DWORD dwLen = GetLengthSid(Src.m_pSid);
  63. wmilib::auto_buffer<BYTE> pTmpSid( new BYTE [dwLen]);
  64. if (NULL == pTmpSid.get()) return;
  65. ZeroMemory(pTmpSid.get(),dwLen);
  66. if (!CopySid(dwLen, pTmpSid.get(), Src.m_pSid)) return;
  67. wmilib::auto_buffer<WCHAR> pTmpMachine;
  68. if (Src.m_pMachine)
  69. {
  70. size_t cchTmp = wcslen(Src.m_pMachine) + 1;
  71. pTmpMachine.reset(new WCHAR[cchTmp]);
  72. if (NULL == pTmpMachine.get()) return;
  73. memcpy(pTmpMachine.get(),Src.m_pMachine,cchTmp*sizeof(WCHAR));
  74. }
  75. m_pSid = pTmpSid.release();
  76. m_pMachine = pTmpMachine.release();
  77. m_dwStatus = NoError;
  78. }
  79. //***************************************************************************
  80. //
  81. // CNtSid Copy Constructor
  82. //
  83. //***************************************************************************
  84. // ok
  85. CNtSid::CNtSid(SidType st)
  86. {
  87. m_pSid = 0;
  88. m_dwStatus = InternalError;
  89. m_pMachine = 0;
  90. if(st == CURRENT_USER ||st == CURRENT_THREAD)
  91. {
  92. HANDLE hToken;
  93. if(st == CURRENT_USER)
  94. {
  95. if(!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &hToken))
  96. return;
  97. }
  98. else
  99. {
  100. if(!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken))
  101. return;
  102. }
  103. OnDelete< HANDLE , BOOL(*)(HANDLE) , CloseHandle > cm(hToken);
  104. // Get the user sid
  105. // ================
  106. TOKEN_USER tu;
  107. DWORD dwLen = 0;
  108. GetTokenInformation(hToken, TokenUser, &tu, sizeof(tu), &dwLen);
  109. if(dwLen == 0) return;
  110. wmilib::auto_buffer<BYTE> pTemp( new BYTE[dwLen]);
  111. if (NULL == pTemp.get()) return;
  112. DWORD dwRealLen = dwLen;
  113. if(!GetTokenInformation(hToken, TokenUser, pTemp.get(), dwRealLen, &dwLen)) return;
  114. // Make a copy of the SID
  115. // ======================
  116. PSID pSid = ((TOKEN_USER*)pTemp.get())->User.Sid;
  117. DWORD dwSidLen = GetLengthSid(pSid);
  118. m_pSid = new BYTE[dwSidLen];
  119. if (m_pSid)
  120. {
  121. CopySid(dwSidLen, m_pSid, pSid);
  122. m_dwStatus = NoError;
  123. }
  124. }
  125. return;
  126. }
  127. //***************************************************************************
  128. //
  129. // CNtSid::CopyTo
  130. //
  131. // An unchecked copy of the internal SID to the destination pointer.
  132. //
  133. // Parameters:
  134. // <pDestination> points to the buffer to which to copy the SID. The
  135. // buffer must be large enough to hold the SID.
  136. //
  137. // Return value:
  138. // TRUE on success, FALSE on failure.
  139. //
  140. //***************************************************************************
  141. // ok
  142. BOOL CNtSid::CopyTo(PSID pDestination)
  143. {
  144. if (m_pSid == 0 || m_dwStatus != NoError)
  145. return FALSE;
  146. DWORD dwLen = GetLengthSid(m_pSid);
  147. memcpy(pDestination, m_pSid, dwLen);
  148. return TRUE;
  149. }
  150. //***************************************************************************
  151. //
  152. // CNtSid assignment operator
  153. //
  154. //***************************************************************************
  155. // ok
  156. CNtSid & CNtSid::operator =( const CNtSid &Src)
  157. {
  158. CNtSid tmp(Src);
  159. std::swap(this->m_dwStatus,tmp.m_dwStatus);
  160. std::swap(this->m_pMachine,tmp.m_pMachine);
  161. std::swap(this->m_pSid,tmp.m_pSid);
  162. std::swap(this->m_snu,tmp.m_snu);
  163. return *this;
  164. }
  165. //***************************************************************************
  166. //
  167. // CNtSid comparison operator
  168. //
  169. //***************************************************************************
  170. int CNtSid::operator ==(CNtSid &Comparand)
  171. {
  172. if (m_pSid == 0 && Comparand.m_pSid == 0 &&
  173. m_dwStatus == Comparand.m_dwStatus)
  174. return 1;
  175. if (m_dwStatus != Comparand.m_dwStatus)
  176. return 0;
  177. if (m_pSid && Comparand.m_pSid)
  178. return EqualSid(m_pSid, Comparand.m_pSid);
  179. else
  180. return 0;
  181. }
  182. //***************************************************************************
  183. //
  184. // CNtSid::CNtSid
  185. //
  186. // Constructor which builds a SID directly from a user or group name.
  187. // If the machine is available, then its name can be used to help
  188. // distinguish the same name in different SAM databases (domains, etc).
  189. //
  190. // Parameters:
  191. //
  192. // <pUser> The desired user or group.
  193. //
  194. // <pMachine> Points to a machine name with or without backslashes,
  195. // or else is NULL, in which case the current machine, domain,
  196. // and trusted domains are searched for a match.
  197. //
  198. // After construction, call GetStatus() to determine if the constructor
  199. // succeeded. NoError is expected.
  200. //
  201. //***************************************************************************
  202. // ok
  203. CNtSid::CNtSid(
  204. LPWSTR pUser,
  205. LPWSTR pMachine
  206. )
  207. {
  208. DWORD dwRequired = 0;
  209. DWORD dwDomRequired = 0;
  210. LPWSTR pszDomain = NULL;
  211. m_pSid = 0;
  212. m_pMachine = 0;
  213. if (pMachine)
  214. {
  215. size_t stringLength = wcslen(pMachine) + 1;
  216. m_pMachine = new wchar_t[stringLength];
  217. if (!m_pMachine)
  218. {
  219. m_dwStatus = Failed;
  220. return;
  221. }
  222. StringCchCopyW(m_pMachine, stringLength, pMachine);
  223. }
  224. BOOL bRes = LookupAccountNameW(
  225. m_pMachine,
  226. pUser,
  227. m_pSid,
  228. &dwRequired,
  229. pszDomain,
  230. &dwDomRequired,
  231. &m_snu
  232. );
  233. DWORD dwLastErr = GetLastError();
  234. if (dwLastErr != ERROR_INSUFFICIENT_BUFFER)
  235. {
  236. m_pSid = 0;
  237. if (dwLastErr == ERROR_ACCESS_DENIED)
  238. m_dwStatus = AccessDenied;
  239. else
  240. m_dwStatus = InvalidSid;
  241. return;
  242. }
  243. m_pSid = (PSID) new BYTE [dwRequired];
  244. if (!m_pSid)
  245. {
  246. m_dwStatus = Failed;
  247. return;
  248. }
  249. ZeroMemory(m_pSid, dwRequired);
  250. pszDomain = new wchar_t[dwDomRequired + 1];
  251. if (!pszDomain)
  252. {
  253. delete [] m_pSid;
  254. m_pSid = 0;
  255. m_dwStatus = Failed;
  256. return;
  257. }
  258. bRes = LookupAccountNameW(
  259. pMachine,
  260. pUser,
  261. m_pSid,
  262. &dwRequired,
  263. pszDomain,
  264. &dwDomRequired,
  265. &m_snu
  266. );
  267. if (!bRes || !IsValidSid(m_pSid))
  268. {
  269. delete [] m_pSid;
  270. delete [] pszDomain;
  271. m_pSid = 0;
  272. m_dwStatus = InvalidSid;
  273. return;
  274. }
  275. delete [] pszDomain; // We never really needed this
  276. m_dwStatus = NoError;
  277. }
  278. //***************************************************************************
  279. //
  280. // CNtSid::CNtSid
  281. //
  282. // Constructs a CNtSid object directly from an NT SID. The SID is copied,
  283. // so the caller retains ownership.
  284. //
  285. // Parameters:
  286. // <pSrc> The source SID upon which to base the object.
  287. //
  288. // Call GetStatus() after construction to ensure the object was
  289. // constructed correctly. NoError is expected.
  290. //
  291. //***************************************************************************
  292. // ok
  293. CNtSid::CNtSid(PSID pSrc)
  294. {
  295. m_pMachine = 0;
  296. m_pSid = 0;
  297. m_dwStatus = NoError;
  298. if (!IsValidSid(pSrc))
  299. {
  300. m_dwStatus = InvalidSid;
  301. return;
  302. }
  303. DWORD dwLen = GetLengthSid(pSrc);
  304. m_pSid = (PSID) new BYTE [dwLen];
  305. if ( m_pSid == NULL )
  306. {
  307. m_dwStatus = Failed;
  308. return;
  309. }
  310. ZeroMemory(m_pSid, dwLen);
  311. if (!CopySid(dwLen, m_pSid, pSrc))
  312. {
  313. delete [] m_pSid;
  314. m_dwStatus = InternalError;
  315. return;
  316. }
  317. }
  318. //***************************************************************************
  319. //
  320. // CNtSid::GetInfo
  321. //
  322. // Returns information about the SID.
  323. //
  324. // Parameters:
  325. // <pRetAccount> Receives a UNICODE string containing the account
  326. // name (user or group). The caller must use operator
  327. // delete to free the memory. This can be NULL if
  328. // this information is not required.
  329. // <pRetDomain> Returns a UNICODE string containing the domain
  330. // name in which the account resides. The caller must
  331. // use operator delete to free the memory. This can be
  332. // NULL if this information is not required.
  333. // <pdwUse> Points to a DWORD to receive information about the name.
  334. // Possible return values are defined under SID_NAME_USE
  335. // in NT SDK documentation. Examples are
  336. // SidTypeUser, SidTypeGroup, etc.
  337. // for an example.
  338. //
  339. // Return values:
  340. // NoError, InvalidSid, Failed
  341. //
  342. //***************************************************************************
  343. // ok
  344. int CNtSid::GetInfo(
  345. LPWSTR *pRetAccount, // Account, use operator delete
  346. LPWSTR *pRetDomain, // Domain, use operator delete
  347. DWORD *pdwUse // See SID_NAME_USE for values
  348. )
  349. {
  350. if (pRetAccount)
  351. *pRetAccount = 0;
  352. if (pRetDomain)
  353. *pRetDomain = 0;
  354. if (pdwUse)
  355. *pdwUse = 0;
  356. if (!m_pSid || !IsValidSid(m_pSid))
  357. return InvalidSid;
  358. DWORD dwNameLen = 0;
  359. DWORD dwDomainLen = 0;
  360. LPWSTR pUser = 0;
  361. LPWSTR pDomain = 0;
  362. SID_NAME_USE Use;
  363. // Do the first lookup to get the buffer sizes required.
  364. // =====================================================
  365. BOOL bRes = LookupAccountSidW(
  366. m_pMachine,
  367. m_pSid,
  368. pUser,
  369. &dwNameLen,
  370. pDomain,
  371. &dwDomainLen,
  372. &Use
  373. );
  374. DWORD dwLastErr = GetLastError();
  375. if (dwLastErr != ERROR_INSUFFICIENT_BUFFER)
  376. {
  377. return Failed;
  378. }
  379. // Allocate the required buffers and look them up again.
  380. // =====================================================
  381. pUser = new wchar_t[dwNameLen + 1];
  382. if (!pUser)
  383. return Failed;
  384. pDomain = new wchar_t[dwDomainLen + 1];
  385. if (!pDomain)
  386. {
  387. delete pUser;
  388. return Failed;
  389. }
  390. bRes = LookupAccountSidW(
  391. m_pMachine,
  392. m_pSid,
  393. pUser,
  394. &dwNameLen,
  395. pDomain,
  396. &dwDomainLen,
  397. &Use
  398. );
  399. if (!bRes)
  400. {
  401. delete [] pUser;
  402. delete [] pDomain;
  403. return Failed;
  404. }
  405. if (pRetAccount)
  406. *pRetAccount = pUser;
  407. else
  408. delete [] pUser;
  409. if (pRetDomain)
  410. *pRetDomain = pDomain;
  411. else
  412. delete [] pDomain;
  413. if (pdwUse)
  414. *pdwUse = Use;
  415. return NoError;
  416. }
  417. //***************************************************************************
  418. //
  419. // CNtSid destructor
  420. //
  421. //***************************************************************************
  422. CNtSid::~CNtSid()
  423. {
  424. delete [] m_pSid;
  425. delete [] m_pMachine;
  426. }
  427. //***************************************************************************
  428. //
  429. // CNtSid::GetTextSid
  430. //
  431. // Converts the sid to text form. The caller should passin a 130 character
  432. // buffer.
  433. //
  434. //***************************************************************************
  435. BOOL CNtSid::GetTextSid(LPTSTR pszSidText, LPDWORD dwBufferLen)
  436. {
  437. // test if Sid is valid
  438. if(m_pSid == 0 || !IsValidSid(m_pSid))
  439. return FALSE;
  440. LPTSTR textualSid = 0;
  441. if (ConvertSidToStringSid(m_pSid, &textualSid))
  442. {
  443. HRESULT fit = StringCchCopy(pszSidText, *dwBufferLen, textualSid);
  444. LocalFree(textualSid);
  445. return SUCCEEDED(fit);
  446. };
  447. return FALSE;
  448. }
  449. //***************************************************************************
  450. //
  451. // CNtAce::CNtAce
  452. //
  453. // Constructor which directly builds the ACE based on a user, access mask
  454. // and flags without a need to build an explicit SID.
  455. //
  456. //
  457. // Parameters:
  458. // <AccessMask> A WINNT ACCESS_MASK which specifies the permissions
  459. // the user should have to the object being secured.
  460. // See ACCESS_MASK in NT SDK documentation.
  461. // <dwAceType> One of the following:
  462. // ACCESS_ALLOWED_ACE_TYPE
  463. // ACCESS_DENIED_ACE_TYPE
  464. // ACCESS_AUDIT_ACE_TYPE
  465. // See ACE_HEADER in NT SDK documentation.
  466. // <dwAceFlags> Of of the ACE propation flags. See ACE_HEADER
  467. // in NT SDK documentation for legal values.
  468. // <sid> CNtSid specifying the user or group for which the ACE is being
  469. // created.
  470. //
  471. // After construction, call GetStatus() to verify that the ACE
  472. // is valid. NoError is expected.
  473. //
  474. //***************************************************************************
  475. // ok
  476. CNtAce::CNtAce(
  477. ACCESS_MASK AccessMask,
  478. DWORD dwAceType,
  479. DWORD dwAceFlags,
  480. CNtSid & Sid
  481. )
  482. {
  483. m_pAce = 0;
  484. m_dwStatus = NoError;
  485. // If the SID is invalid, the ACE will be as well.
  486. // ===============================================
  487. if (Sid.GetStatus() != CNtSid::NoError)
  488. {
  489. m_dwStatus = InvalidAce;
  490. return;
  491. }
  492. // Compute the size of the ACE.
  493. // ============================
  494. DWORD dwSidLength = Sid.GetSize();
  495. DWORD dwTotal = dwSidLength + sizeof(GENERIC_ACE) - 4;
  496. m_pAce = (PGENERIC_ACE) new BYTE[dwTotal];
  497. if (m_pAce)
  498. {
  499. ZeroMemory(m_pAce, dwTotal);
  500. // Build up the ACE info.
  501. // ======================
  502. m_pAce->Header.AceType = BYTE(dwAceType);
  503. m_pAce->Header.AceFlags = BYTE(dwAceFlags);
  504. m_pAce->Header.AceSize = WORD(dwTotal);
  505. m_pAce->Mask = AccessMask;
  506. BOOL bRes = Sid.CopyTo(PSID(&m_pAce->SidStart));
  507. if (!bRes)
  508. {
  509. delete m_pAce;
  510. m_pAce = 0;
  511. m_dwStatus = InvalidAce;
  512. return;
  513. }
  514. m_dwStatus = NoError;
  515. }
  516. else
  517. m_dwStatus = InternalError;
  518. }
  519. //***************************************************************************
  520. //
  521. // CNtAce::CNtAce
  522. //
  523. // Constructor which directly builds the ACE based on a user, access mask
  524. // and flags without a need to build an explicit SID.
  525. //
  526. //
  527. // Parameters:
  528. // <AccessMask> A WINNT ACCESS_MASK which specifies the permissions
  529. // the user should have to the object being secured.
  530. // See ACCESS_MASK in NT SDK documentation.
  531. // <dwAceType> One of the following:
  532. // ACCESS_ALLOWED_ACE_TYPE
  533. // ACCESS_DENIED_ACE_TYPE
  534. // ACCESS_AUDIT_ACE_TYPE
  535. // See ACE_HEADER in NT SDK documentation.
  536. // <dwAceFlags> Of of the ACE propation flags. See ACE_HEADER
  537. // in NT SDK documentation for legal values.
  538. // <pUser> The user or group for which the ACE is being
  539. // created.
  540. // <pMachine> If NULL, the current machine, domain, and trusted
  541. // domains are searched for a match. If not NULL,
  542. // can point to a UNICODE machine name (with or without
  543. // leading backslashes) which contains the account.
  544. //
  545. // After construction, call GetStatus() to verify that the ACE
  546. // is valid. NoError is expected.
  547. //
  548. //***************************************************************************
  549. // ok
  550. CNtAce::CNtAce(
  551. ACCESS_MASK AccessMask,
  552. DWORD dwAceType,
  553. DWORD dwAceFlags,
  554. LPWSTR pUser,
  555. LPWSTR pMachine
  556. )
  557. {
  558. m_pAce = 0;
  559. m_dwStatus = NoError;
  560. // Create the SID of the user.
  561. // ===========================
  562. CNtSid Sid(pUser, pMachine);
  563. // If the SID is invalid, the ACE will be as well.
  564. // ===============================================
  565. if (Sid.GetStatus() != CNtSid::NoError)
  566. {
  567. m_dwStatus = InvalidAce;
  568. return;
  569. }
  570. // Compute the size of the ACE.
  571. // ============================
  572. DWORD dwSidLength = Sid.GetSize();
  573. DWORD dwTotal = dwSidLength + sizeof(GENERIC_ACE) - 4;
  574. m_pAce = (PGENERIC_ACE) new BYTE[dwTotal];
  575. if ( m_pAce == NULL )
  576. {
  577. m_dwStatus = InternalError;
  578. return;
  579. }
  580. ZeroMemory(m_pAce, dwTotal);
  581. // Build up the ACE info.
  582. // ======================
  583. m_pAce->Header.AceType = BYTE(dwAceType);
  584. m_pAce->Header.AceFlags = BYTE(dwAceFlags);
  585. m_pAce->Header.AceSize = WORD(dwTotal);
  586. m_pAce->Mask = AccessMask;
  587. BOOL bRes = Sid.CopyTo(PSID(&m_pAce->SidStart));
  588. if (!bRes)
  589. {
  590. delete m_pAce;
  591. m_pAce = 0;
  592. m_dwStatus = InvalidAce;
  593. return;
  594. }
  595. m_dwStatus = NoError;
  596. }
  597. //***************************************************************************
  598. //
  599. // CNtAce::GetAccessMask
  600. //
  601. // Returns the ACCESS_MASK of the ACe.
  602. //
  603. //***************************************************************************
  604. ACCESS_MASK CNtAce::GetAccessMask()
  605. {
  606. if (m_pAce == 0)
  607. return 0;
  608. return m_pAce->Mask;
  609. }
  610. //***************************************************************************
  611. //
  612. // CNtAce::GetSerializedSize
  613. //
  614. // Returns the number of bytes needed to store this
  615. //
  616. //***************************************************************************
  617. DWORD CNtAce::GetSerializedSize()
  618. {
  619. if (m_pAce == 0)
  620. return 0;
  621. return m_pAce->Header.AceSize;
  622. }
  623. //***************************************************************************
  624. //
  625. // CNtAce::GetSid
  626. //
  627. // Returns a copy of the CNtSid object which makes up the ACE.
  628. //
  629. // Return value:
  630. // A newly allocated CNtSid which represents the user or group
  631. // referenced in the ACE. The caller must use operator delete to free
  632. // the memory.
  633. //
  634. //***************************************************************************
  635. // ok
  636. CNtSid* CNtAce::GetSid()
  637. {
  638. if (m_pAce == 0)
  639. return 0;
  640. PSID pSid = 0;
  641. pSid = &m_pAce->SidStart;
  642. if (!IsValidSid(pSid))
  643. return 0;
  644. return new CNtSid(pSid);
  645. }
  646. //***************************************************************************
  647. //
  648. // CNtAce::GetSid
  649. //
  650. // Gets the SID in an alternate manner, by assigning to an existing
  651. // object instead of returning a dynamically allocated one.
  652. //
  653. // Parameters:
  654. // <Dest> A reference to a CNtSid to receive the SID.
  655. //
  656. // Return value:
  657. // TRUE on successful assignment, FALSE on failure.
  658. //
  659. //***************************************************************************
  660. BOOL CNtAce::GetSid(CNtSid &Dest)
  661. {
  662. CNtSid *pSid = GetSid();
  663. if (pSid == 0)
  664. return FALSE;
  665. Dest = *pSid;
  666. delete pSid;
  667. return TRUE;
  668. }
  669. //***************************************************************************
  670. //
  671. // CNtAce::CNtAce
  672. //
  673. // Alternate constructor which uses a normal NT ACE as a basis for
  674. // object construction.
  675. //
  676. // Parameters:
  677. // <pAceSrc> A read-only pointer to the source ACE upon which to
  678. // base object construction.
  679. //
  680. // After construction, GetStatus() can be used to determine if the
  681. // object constructed properly. NoError is expected.
  682. //
  683. //***************************************************************************
  684. // ok
  685. CNtAce::CNtAce(PGENERIC_ACE pAceSrc)
  686. {
  687. m_dwStatus = NoError;
  688. if (pAceSrc == 0)
  689. {
  690. m_dwStatus = NullAce;
  691. m_pAce = 0;
  692. return;
  693. }
  694. m_pAce = (PGENERIC_ACE) new BYTE[pAceSrc->Header.AceSize];
  695. if ( m_pAce == NULL )
  696. {
  697. m_dwStatus = InternalError;
  698. return;
  699. }
  700. ZeroMemory(m_pAce, pAceSrc->Header.AceSize);
  701. memcpy(m_pAce, pAceSrc, pAceSrc->Header.AceSize);
  702. }
  703. //***************************************************************************
  704. //
  705. // CNtAce copy constructor.
  706. //
  707. //***************************************************************************
  708. // ok
  709. CNtAce::CNtAce(const CNtAce &Src)
  710. {
  711. if (NoError == Src.m_dwStatus)
  712. {
  713. m_pAce = (PGENERIC_ACE)new BYTE[Src.m_pAce->Header.AceSize];
  714. if (NULL == m_pAce)
  715. {
  716. m_dwStatus = InternalError;
  717. return;
  718. }
  719. memcpy(m_pAce,Src.m_pAce,Src.m_pAce->Header.AceSize);
  720. }
  721. else
  722. {
  723. m_pAce = Src.m_pAce;
  724. }
  725. m_dwStatus = Src.m_dwStatus;
  726. }
  727. //***************************************************************************
  728. //
  729. // CNtAce assignment operator.
  730. //
  731. //***************************************************************************
  732. // ok
  733. CNtAce &CNtAce::operator =(const CNtAce &Src)
  734. {
  735. CNtAce tmp(Src);
  736. std::swap(m_pAce,tmp.m_pAce);
  737. std::swap(m_dwStatus,tmp.m_dwStatus);
  738. return *this;
  739. }
  740. //***************************************************************************
  741. //
  742. // CNtAce destructor
  743. //
  744. //***************************************************************************
  745. // ok
  746. CNtAce::~CNtAce()
  747. {
  748. delete m_pAce;
  749. }
  750. //***************************************************************************
  751. //
  752. // CNtAce::GetType
  753. //
  754. // Gets the Ace Type as defined under the NT SDK documentation for
  755. // ACE_HEADER.
  756. //
  757. // Return value:
  758. // Returns ACCESS_ALLOWED_ACE_TYPE, ACCESS_DENIED_ACE_TYPE, or
  759. // SYSTEM_AUDIT_ACE_TYPE. Returns -1 on error, such as a null ACE.
  760. //
  761. // Returning -1 (or an analog) is required as an error code because
  762. // ACCESS_ALLOWED_ACE_TYPE is defined to be zero.
  763. //
  764. //***************************************************************************
  765. // ok
  766. int CNtAce::GetType()
  767. {
  768. if (m_pAce == 0 || m_dwStatus != NoError)
  769. return -1;
  770. return m_pAce->Header.AceType;
  771. }
  772. //***************************************************************************
  773. //
  774. // CNtAce::GetFlags
  775. //
  776. // Gets the Ace Flag as defined under the NT SDK documentation for
  777. // ACE_HEADER.
  778. //
  779. // Return value:
  780. // Returning -1 if error, other wise the flags.
  781. //
  782. //***************************************************************************
  783. int CNtAce::GetFlags()
  784. {
  785. if (m_pAce == 0 || m_dwStatus != NoError)
  786. return -1;
  787. return m_pAce->Header.AceFlags;
  788. }
  789. HRESULT CNtAce::GetFullUserName2(WCHAR ** pBuff)
  790. {
  791. CNtSid *pSid = GetSid();
  792. CDeleteMe<CNtSid> d0(pSid);
  793. if(NULL == pSid || CNtSid::NoError != pSid->GetStatus())
  794. return WBEM_E_OUT_OF_MEMORY;
  795. DWORD dwJunk;
  796. LPWSTR pRetAccount = NULL, pRetDomain = NULL;
  797. if(0 != pSid->GetInfo(&pRetAccount, &pRetDomain,&dwJunk))
  798. return WBEM_E_FAILED;
  799. CDeleteMe<WCHAR> d1(pRetAccount);
  800. CDeleteMe<WCHAR> d2(pRetDomain);
  801. int iLen = 3;
  802. if(pRetAccount)
  803. iLen += wcslen(pRetAccount);
  804. if(pRetDomain)
  805. iLen += wcslen(pRetDomain);
  806. (*pBuff) = new WCHAR[iLen];
  807. if((*pBuff) == NULL)
  808. return WBEM_E_OUT_OF_MEMORY;
  809. (*pBuff)[0] = 0;
  810. if(pRetDomain && wcslen(pRetDomain) > 0)
  811. StringCchCopyW(*pBuff, iLen, pRetDomain);
  812. else
  813. StringCchCopyW(*pBuff, iLen, L".");
  814. StringCchCatW(*pBuff, iLen, L"|");
  815. StringCchCatW(*pBuff, iLen, pRetAccount);
  816. return S_OK;
  817. }
  818. //***************************************************************************
  819. //
  820. // CNtAce::Serialize
  821. //
  822. // Serializes the ace.
  823. //
  824. //***************************************************************************
  825. bool CNtAce::Serialize(BYTE * pData, size_t bufferSize)
  826. {
  827. if(m_pAce == NULL)
  828. return false;
  829. DWORD dwSize = m_pAce->Header.AceSize;
  830. if (bufferSize < dwSize) return false;
  831. memcpy((void *)pData, (void *)m_pAce, dwSize);
  832. return true;
  833. }
  834. //***************************************************************************
  835. //
  836. // CNtAce::Deserialize
  837. //
  838. // Deserializes the ace. Normally this isnt called since the
  839. // CNtAce(PGENERIC_ACE pAceSrc) constructor is fine. However, this is
  840. // used for the case where the db was created on win9x and we are now
  841. // running on nt. In that case, the format is the same as outlined in
  842. // C9XAce::Serialize
  843. //
  844. //***************************************************************************
  845. bool CNtAce::Deserialize(BYTE * pData)
  846. {
  847. BYTE * pNext;
  848. pNext = pData + 2*(wcslen((LPWSTR)pData) + 1);
  849. DWORD * pdwData = (DWORD *)pNext;
  850. DWORD dwFlags, dwType, dwAccess;
  851. dwFlags = *pdwData;
  852. pdwData++;
  853. dwType = *pdwData;
  854. pdwData++;
  855. dwAccess = *pdwData;
  856. pdwData++;
  857. CNtAce temp(dwAccess, dwType, dwFlags, (LPWSTR)pData);
  858. *this = temp;
  859. return true;
  860. }
  861. //***************************************************************************
  862. //
  863. // CNtAcl::CNtAcl
  864. //
  865. // Constructs an empty ACL with a user-specified size.
  866. //
  867. // Parameters:
  868. // <dwInitialSize> Defaults to 128. Recommended values are 128 or
  869. // higher in powers of two.
  870. //
  871. // After construction, GetStatus() should be called to verify
  872. // the ACL initialized properly. Expected value is NoError.
  873. //
  874. //***************************************************************************
  875. // ok
  876. CNtAcl::CNtAcl(DWORD dwInitialSize)
  877. {
  878. m_pAcl = (PACL) new BYTE[dwInitialSize];
  879. if ( m_pAcl == NULL )
  880. {
  881. m_dwStatus = InternalError;
  882. return;
  883. }
  884. ZeroMemory(m_pAcl, dwInitialSize);
  885. BOOL bRes = InitializeAcl(m_pAcl, dwInitialSize, ACL_REVISION);
  886. if (!bRes)
  887. {
  888. delete m_pAcl;
  889. m_pAcl = 0;
  890. m_dwStatus = NullAcl;
  891. return;
  892. }
  893. m_dwStatus = NoError;
  894. }
  895. //***************************************************************************
  896. //
  897. // CNtAcl copy constructor.
  898. //
  899. //***************************************************************************
  900. // ok
  901. CNtAcl::CNtAcl(const CNtAcl &Src)
  902. {
  903. if (Src.m_pAcl)
  904. {
  905. if (!IsValidAcl(Src.m_pAcl))
  906. {
  907. m_pAcl = 0;
  908. m_dwStatus = InvalidAcl;
  909. return;
  910. }
  911. m_pAcl = (PACL)new BYTE[Src.m_pAcl->AclSize];
  912. if (NULL == m_pAcl)
  913. {
  914. m_dwStatus = InternalError;
  915. return;
  916. }
  917. memcpy(m_pAcl, Src.m_pAcl,Src.m_pAcl->AclSize);
  918. }
  919. else
  920. {
  921. m_pAcl = Src.m_pAcl;
  922. }
  923. m_dwStatus = Src.m_dwStatus;
  924. }
  925. //***************************************************************************
  926. //
  927. // CNtAcl assignment operator
  928. //
  929. //***************************************************************************
  930. // ok
  931. CNtAcl &CNtAcl::operator = (const CNtAcl &Src)
  932. {
  933. CNtAcl tmp(Src);
  934. std::swap(m_pAcl,tmp.m_pAcl);
  935. std::swap(m_dwStatus,tmp.m_dwStatus);
  936. return *this;
  937. }
  938. //***************************************************************************
  939. //
  940. // CNtAcl::GetAce
  941. //
  942. // Returns an ACE at the specified index. To enumerate ACEs, the caller
  943. // should determine the number of ACEs using GetNumAces() and then call
  944. // this function with each index starting from 0 to number of ACEs - 1.
  945. //
  946. // Parameters:
  947. // <nIndex> The index of the desired ACE.
  948. //
  949. // Return value:
  950. // A newly allocated CNtAce object which must be deallocated using
  951. // operator delete. This is only a copy. Modifications to the returned
  952. // CNtAce do not affect the ACL from which it came.
  953. //
  954. // Returns NULL on error.
  955. //
  956. //***************************************************************************
  957. // ok
  958. CNtAce *CNtAcl::GetAce(int nIndex)
  959. {
  960. if (m_pAcl == 0)
  961. return 0;
  962. LPVOID pAce = 0;
  963. BOOL bRes = ::GetAce(m_pAcl, (DWORD) nIndex, &pAce);
  964. if (!bRes)
  965. return 0;
  966. return new CNtAce(PGENERIC_ACE(pAce));
  967. }
  968. //***************************************************************************
  969. //
  970. // CNtAcl::GetAce
  971. //
  972. // Alternate method to get ACEs to avoid dynamic allocation & cleanup,
  973. // since an auto object can be used as the parameter.
  974. //
  975. // Parameters:
  976. // <Dest> A reference to a CNtAce to receive the ACE value.
  977. //
  978. // Return value:
  979. // TRUE if assigned, FALSE if not.
  980. //
  981. //***************************************************************************
  982. BOOL CNtAcl::GetAce(int nIndex, CNtAce &Dest)
  983. {
  984. CNtAce *pNew = GetAce(nIndex);
  985. if (pNew == 0)
  986. return FALSE;
  987. Dest = *pNew;
  988. delete pNew;
  989. return TRUE;
  990. }
  991. //***************************************************************************
  992. //
  993. // CNtAcl::DeleteAce
  994. //
  995. // Removes the specified ACE from the ACL.
  996. //
  997. // Parameters:
  998. // <nIndex> The 0-based index of the ACE which should be removed.
  999. //
  1000. // Return value:
  1001. // TRUE if the ACE was deleted, FALSE if not.
  1002. //
  1003. //***************************************************************************
  1004. // ok
  1005. BOOL CNtAcl::DeleteAce(int nIndex)
  1006. {
  1007. if (m_pAcl == 0)
  1008. return FALSE;
  1009. BOOL bRes = ::DeleteAce(m_pAcl, DWORD(nIndex));
  1010. return bRes;
  1011. }
  1012. //***************************************************************************
  1013. //
  1014. // CNtAcl::GetSize()
  1015. //
  1016. // Return value:
  1017. // Returns the size in bytes of the ACL
  1018. //
  1019. //***************************************************************************
  1020. // ok
  1021. DWORD CNtAcl::GetSize()
  1022. {
  1023. if (m_pAcl == 0 || !IsValidAcl(m_pAcl))
  1024. return 0;
  1025. return DWORD(m_pAcl->AclSize);
  1026. }
  1027. //***************************************************************************
  1028. //
  1029. // CNtAcl::GetAclSizeInfo
  1030. //
  1031. // Gets information about used/unused space in the ACL. This function
  1032. // is primarily for internal use.
  1033. //
  1034. // Parameters:
  1035. // <pdwBytesInUse> Points to a DWORD to receive the number of
  1036. // bytes in use in the ACL. Can be NULL.
  1037. // <pdwBytesFree> Points to a DWORD to receive the number of
  1038. // bytes free in the ACL. Can be NULL.
  1039. //
  1040. // Return value:
  1041. // Returns TRUE if the information was retrieved, FALSE if not.
  1042. //
  1043. //***************************************************************************
  1044. // ok
  1045. BOOL CNtAcl::GetAclSizeInfo(
  1046. PDWORD pdwBytesInUse,
  1047. PDWORD pdwBytesFree
  1048. )
  1049. {
  1050. if (m_pAcl == 0)
  1051. return 0;
  1052. if (!IsValidAcl(m_pAcl))
  1053. return 0;
  1054. if (pdwBytesInUse)
  1055. *pdwBytesInUse = 0;
  1056. if (pdwBytesFree)
  1057. *pdwBytesFree = 0;
  1058. ACL_SIZE_INFORMATION inf;
  1059. BOOL bRes = GetAclInformation(
  1060. m_pAcl,
  1061. &inf,
  1062. sizeof(ACL_SIZE_INFORMATION),
  1063. AclSizeInformation
  1064. );
  1065. if (!bRes)
  1066. return FALSE;
  1067. if (pdwBytesInUse)
  1068. *pdwBytesInUse = inf.AclBytesInUse;
  1069. if (pdwBytesFree)
  1070. *pdwBytesFree = inf.AclBytesFree;
  1071. return bRes;
  1072. }
  1073. /* --------------------------------------------------------------------------
  1074. | BOOL CNtAcl::OrderAces ( )
  1075. |
  1076. | Orders the ACEs in an ACL according to following
  1077. |
  1078. | { ACEni1, ACEni2, ACEni3.ACEnix | ACEin1, ACEin2, ACEin3.ACEinx }
  1079. | (non-inherited) (inherited)
  1080. |
  1081. | Non-inherited ACEs are inserted at the beginning of the ACL followed by
  1082. | inherited ACEs. Each group is also ordered according to recommended NT
  1083. | ACE grouping policy (DENY followed by ALLOW).
  1084. |
  1085. | Returns: [BOOL] TRUE if ACL is valid and grouping succeeded
  1086. | FALSE if ACL is invalid and grouping failed.
  1087. |
  1088. --------------------------------------------------------------------------
  1089. */
  1090. CNtAcl* CNtAcl::OrderAces ( )
  1091. {
  1092. //
  1093. // Verify valid ACL
  1094. //
  1095. if (m_pAcl == 0 || m_dwStatus != NoError)
  1096. {
  1097. return NULL ;
  1098. }
  1099. //
  1100. // Create a new CNtAcl and use the AddAce (which performs ordering).
  1101. //
  1102. int numAces = GetNumAces();
  1103. wmilib::auto_ptr<CNtAcl> pAcl(new CNtAcl(sizeof(ACL)));
  1104. if ( NULL == pAcl.get() ) return NULL;
  1105. if ( pAcl->GetStatus ( ) != CNtAcl::NoError ) return NULL;
  1106. //
  1107. // Loop through all ACEs and add to new ACL via AddAce
  1108. //
  1109. for ( int i = 0; i < numAces; i++ )
  1110. {
  1111. CNtAce* pAce = GetAce(i);
  1112. if ( pAce )
  1113. {
  1114. CDeleteMe<CNtAce> delme (pAce);
  1115. if ( pAcl->AddAce ( pAce ) == FALSE )
  1116. {
  1117. return NULL;
  1118. }
  1119. }
  1120. else
  1121. return NULL;
  1122. }
  1123. return pAcl.release();
  1124. }
  1125. //***************************************************************************
  1126. //
  1127. // CNtAcl::AddAce
  1128. //
  1129. // Adds an ACE to the ACL.
  1130. // Ordering semantics for denial ACEs are handled automatically.
  1131. //
  1132. // Parameters:
  1133. // <pAce> A read-only pointer to the CNtAce to be added.
  1134. //
  1135. // Return value:
  1136. // TRUE on success, FALSE on failure.
  1137. //
  1138. //***************************************************************************
  1139. // ok
  1140. BOOL CNtAcl::AddAce(CNtAce *pAce)
  1141. {
  1142. // Verify we have an ACL and a valid ACE.
  1143. // ======================================
  1144. if (m_pAcl == 0 || m_dwStatus != NoError)
  1145. return FALSE;
  1146. if (pAce->GetStatus() != CNtAce::NoError)
  1147. return FALSE;
  1148. // Inherited aces go after non inherited aces
  1149. bool bInherited = (pAce->GetFlags() & INHERITED_ACE) != 0;
  1150. int iFirstInherited = 0;
  1151. // inherited aces must go after non inherited. Find out
  1152. // the position of the first inherited ace
  1153. int iCnt;
  1154. for(iCnt = 0; iCnt < m_pAcl->AceCount; iCnt++)
  1155. {
  1156. CNtAce *pAce2 = GetAce(iCnt);
  1157. CDeleteMe<CNtAce> dm(pAce2);
  1158. if (pAce2)
  1159. if((pAce2->GetFlags() & INHERITED_ACE) != 0)
  1160. break;
  1161. }
  1162. iFirstInherited = iCnt;
  1163. // Since we want to add access denial ACEs to the front of the ACL,
  1164. // we have to determine the type of ACE.
  1165. // ================================================================
  1166. DWORD dwIndex;
  1167. if (pAce->GetType() == ACCESS_DENIED_ACE_TYPE)
  1168. dwIndex = (bInherited) ? iFirstInherited : 0;
  1169. else
  1170. dwIndex = (bInherited) ? MAXULONG : iFirstInherited;
  1171. // Verify that there is enough room in the ACL.
  1172. // ============================================
  1173. DWORD dwRequiredFree = pAce->GetSize();
  1174. DWORD dwFree = 0;
  1175. DWORD dwUsed = 0;
  1176. GetAclSizeInfo(&dwUsed, &dwFree);
  1177. // If we don't have enough room, resize the ACL.
  1178. // =============================================
  1179. if (dwFree < dwRequiredFree)
  1180. {
  1181. BOOL bRes = Resize(dwUsed + dwRequiredFree);
  1182. if (!bRes)
  1183. return FALSE;
  1184. }
  1185. // Now actually add the ACE.
  1186. // =========================
  1187. BOOL bRes = ::AddAce(
  1188. m_pAcl,
  1189. ACL_REVISION,
  1190. dwIndex, // Either beginning or end.
  1191. pAce->GetPtr(), // Get ptr to ACE.
  1192. pAce->GetSize() // One ACE only.
  1193. );
  1194. return bRes;
  1195. }
  1196. //***************************************************************************
  1197. //
  1198. // CNtAcl::Resize()
  1199. //
  1200. // Expands the size of the ACL to hold more info or reduces the size
  1201. // of the ACL for maximum efficiency after ACL editing is completed.
  1202. //
  1203. // Normally, the user should not attempt to resize the ACL to a larger
  1204. // size, as this is automatically handled by AddAce. However, shrinking
  1205. // the ACL to its minimum size is recommended.
  1206. //
  1207. // Parameters:
  1208. // <dwNewSize> The required new size of the ACL in bytes. If set to
  1209. // the class constant MinimumSize (1), then the ACL
  1210. // is reduced to its minimum size.
  1211. //
  1212. // Return value:
  1213. // TRUE on success, FALSE on failure.
  1214. //
  1215. //***************************************************************************
  1216. // ok
  1217. BOOL CNtAcl::Resize(DWORD dwNewSize)
  1218. {
  1219. if (m_pAcl == 0 || m_dwStatus != NoError)
  1220. return FALSE;
  1221. if (!IsValidAcl(m_pAcl))
  1222. return FALSE;
  1223. // If the ACL cannot be reduced to the requested size,
  1224. // return FALSE.
  1225. // ===================================================
  1226. DWORD dwInUse, dwFree;
  1227. if (!GetAclSizeInfo(&dwInUse, &dwFree))
  1228. return FALSE;
  1229. if (dwNewSize == MinimumSize) // If user is requesting a 'minimize'
  1230. dwNewSize = dwInUse;
  1231. if (dwNewSize < dwInUse)
  1232. return FALSE;
  1233. // Allocate a new ACL.
  1234. // ===================
  1235. CNtAcl *pNewAcl = new CNtAcl(dwNewSize);
  1236. if (!pNewAcl || pNewAcl->GetStatus() != NoError)
  1237. {
  1238. delete pNewAcl;
  1239. return FALSE;
  1240. }
  1241. // Loop through ACEs and transfer them.
  1242. // ====================================
  1243. for (int i = 0; i < GetNumAces(); i++)
  1244. {
  1245. CNtAce *pAce = GetAce(i);
  1246. if (pAce == NULL)
  1247. {
  1248. delete pNewAcl;
  1249. return FALSE;
  1250. }
  1251. BOOL bRes = pNewAcl->AddAce(pAce);
  1252. if (!bRes)
  1253. {
  1254. DWORD dwLast = GetLastError();
  1255. delete pAce;
  1256. delete pNewAcl;
  1257. return FALSE;
  1258. }
  1259. delete pAce;
  1260. }
  1261. if (!IsValid())
  1262. {
  1263. delete pNewAcl;
  1264. return FALSE;
  1265. }
  1266. // Now transfer the ACL.
  1267. // =====================
  1268. *this = *pNewAcl;
  1269. delete pNewAcl;
  1270. return TRUE;
  1271. }
  1272. //***************************************************************************
  1273. //
  1274. // CNtAcl::CNtAcl
  1275. //
  1276. // Alternate constructor which builds the object based on a plain
  1277. // NT ACL.
  1278. //
  1279. // Parameters:
  1280. // <pAcl> Pointer to a read-only ACL.
  1281. //
  1282. //***************************************************************************
  1283. // ok
  1284. CNtAcl::CNtAcl(PACL pAcl)
  1285. {
  1286. m_pAcl = 0;
  1287. m_dwStatus = NoError;
  1288. if (pAcl == 0)
  1289. {
  1290. m_dwStatus = NullAcl;
  1291. return;
  1292. }
  1293. if (!IsValidAcl(pAcl))
  1294. {
  1295. m_dwStatus = InvalidAcl;
  1296. return;
  1297. }
  1298. m_pAcl = (PACL) new BYTE[pAcl->AclSize];
  1299. if(m_pAcl == NULL)
  1300. {
  1301. m_dwStatus = InternalError;
  1302. return;
  1303. }
  1304. ZeroMemory(m_pAcl, pAcl->AclSize);
  1305. memcpy(m_pAcl, pAcl, pAcl->AclSize);
  1306. }
  1307. /*
  1308. --------------------------------------------------------------------------
  1309. |
  1310. | Checks to see if the Acl contains an ACE with the specified SID.
  1311. | The characteristics of the ACE is irrelevant. Only SID comparison applies.
  1312. |
  1313. --------------------------------------------------------------------------
  1314. */
  1315. BOOL CNtAcl::ContainsSid ( CNtSid& sid, BYTE& flags )
  1316. {
  1317. BOOL bContainsSid = FALSE ;
  1318. int iNumAces = GetNumAces ( ) ;
  1319. if ( iNumAces < 0 )
  1320. {
  1321. return FALSE ;
  1322. }
  1323. for ( int i = 0 ; i < iNumAces; i++ )
  1324. {
  1325. CNtAce* pAce = GetAce ( i ) ;
  1326. if (pAce)
  1327. {
  1328. CDeleteMe<CNtAce> AceDelete ( pAce ) ;
  1329. CNtSid* pSid = pAce->GetSid ( ) ;
  1330. CDeleteMe<CNtSid> SidDelete ( pSid ) ;
  1331. if (pSid && pSid->IsValid())
  1332. {
  1333. if ( EqualSid ( sid.GetPtr ( ), pSid->GetPtr ( ) ) == TRUE )
  1334. {
  1335. flags = ( BYTE ) pAce->GetFlags ( ) ;
  1336. bContainsSid = TRUE ;
  1337. break ;
  1338. }
  1339. }
  1340. }
  1341. }
  1342. return bContainsSid ;
  1343. }
  1344. //***************************************************************************
  1345. //
  1346. // CNtAcl::GetNumAces
  1347. //
  1348. // Return value:
  1349. // Returns the number of ACEs available in the ACL. Zero is a legal return
  1350. // value. Returns -1 on error
  1351. //
  1352. // Aces can be retrieved using GetAce using index values from 0...n-1 where
  1353. // n is the value returned from this function.
  1354. //
  1355. //***************************************************************************
  1356. // ok
  1357. int CNtAcl::GetNumAces()
  1358. {
  1359. if (m_pAcl == 0)
  1360. return -1;
  1361. ACL_SIZE_INFORMATION inf;
  1362. BOOL bRes = GetAclInformation(
  1363. m_pAcl,
  1364. &inf,
  1365. sizeof(ACL_SIZE_INFORMATION),
  1366. AclSizeInformation
  1367. );
  1368. if (!bRes)
  1369. {
  1370. return -1;
  1371. }
  1372. return (int) inf.AceCount;
  1373. }
  1374. //***************************************************************************
  1375. //
  1376. // CNtAcl destructor
  1377. //
  1378. //***************************************************************************
  1379. // ok
  1380. CNtAcl::~CNtAcl()
  1381. {
  1382. if (m_pAcl)
  1383. delete m_pAcl;
  1384. }
  1385. //***************************************************************************
  1386. //
  1387. // CNtSecurityDescriptor::GetDacl
  1388. //
  1389. // Returns the DACL of the security descriptor.
  1390. //
  1391. // Return value:
  1392. // A newly allocated CNtAcl which contains the DACL. This object
  1393. // is a copy of the DACL and modifications made to it do not affect
  1394. // the security descriptor. The caller must use operator delete
  1395. // to deallocate the CNtAcl.
  1396. //
  1397. // Returns NULL on error or if no DACL is available.
  1398. //
  1399. //***************************************************************************
  1400. // ok
  1401. CNtAcl *CNtSecurityDescriptor::GetDacl()
  1402. {
  1403. BOOL bDaclPresent = FALSE;
  1404. BOOL bDefaulted;
  1405. PACL pDacl;
  1406. BOOL bRes = GetSecurityDescriptorDacl(
  1407. m_pSD,
  1408. &bDaclPresent,
  1409. &pDacl,
  1410. &bDefaulted
  1411. );
  1412. if (!bRes)
  1413. {
  1414. return 0;
  1415. }
  1416. if (!bDaclPresent) // No DACL present
  1417. return 0;
  1418. CNtAcl *pNewDacl = new CNtAcl(pDacl);
  1419. return pNewDacl;
  1420. }
  1421. //***************************************************************************
  1422. //
  1423. // CNtSecurityDescriptor::GetDacl
  1424. //
  1425. // An alternate method to returns the DACL of the security descriptor.
  1426. // This version uses an existing object instead of returning a
  1427. // dynamically allocated object.
  1428. //
  1429. // Parameters:
  1430. // <DestAcl> A object which will receive the DACL.
  1431. //
  1432. // Return value:
  1433. // TRUE on success, FALSE on failure
  1434. //
  1435. //***************************************************************************
  1436. BOOL CNtSecurityDescriptor::GetDacl(CNtAcl &DestAcl)
  1437. {
  1438. CNtAcl *pNew = GetDacl();
  1439. if (pNew == 0)
  1440. return FALSE;
  1441. DestAcl = *pNew;
  1442. delete pNew;
  1443. return TRUE;
  1444. }
  1445. //***************************************************************************
  1446. //
  1447. // SNtAbsoluteSD
  1448. //
  1449. // SD Helpers
  1450. //
  1451. //***************************************************************************
  1452. SNtAbsoluteSD::SNtAbsoluteSD()
  1453. {
  1454. m_pSD = 0;
  1455. m_pDacl = 0;
  1456. m_pSacl = 0;
  1457. m_pOwner = 0;
  1458. m_pPrimaryGroup = 0;
  1459. }
  1460. SNtAbsoluteSD::~SNtAbsoluteSD()
  1461. {
  1462. if (m_pSD)
  1463. delete m_pSD;
  1464. if (m_pDacl)
  1465. delete m_pDacl;
  1466. if (m_pSacl)
  1467. delete m_pSacl;
  1468. if (m_pOwner)
  1469. delete m_pOwner;
  1470. if (m_pPrimaryGroup)
  1471. delete m_pPrimaryGroup;
  1472. }
  1473. //***************************************************************************
  1474. //
  1475. // CNtSecurityDescriptor::GetAbsoluteCopy
  1476. //
  1477. // Returns a copy of the current object's internal SD in absolute format.
  1478. // Returns NULL on error. The memory must be freed with LocalFree().
  1479. //
  1480. //***************************************************************************
  1481. // ok
  1482. SNtAbsoluteSD* CNtSecurityDescriptor::GetAbsoluteCopy()
  1483. {
  1484. if (m_dwStatus != NoError || m_pSD == 0 || !IsValid())
  1485. return 0;
  1486. // Prepare for conversion.
  1487. // =======================
  1488. DWORD dwSDSize = 0, dwDaclSize = 0, dwSaclSize = 0,
  1489. dwOwnerSize = 0, dwPrimaryGroupSize = 0;
  1490. SNtAbsoluteSD *pNewSD = new SNtAbsoluteSD;
  1491. if (!pNewSD)
  1492. return NULL;
  1493. BOOL bRes = MakeAbsoluteSD(
  1494. m_pSD,
  1495. pNewSD->m_pSD,
  1496. &dwSDSize,
  1497. pNewSD->m_pDacl,
  1498. &dwDaclSize,
  1499. pNewSD->m_pSacl,
  1500. &dwSaclSize,
  1501. pNewSD->m_pOwner,
  1502. &dwOwnerSize,
  1503. pNewSD->m_pPrimaryGroup,
  1504. &dwPrimaryGroupSize
  1505. );
  1506. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  1507. {
  1508. delete pNewSD;
  1509. return 0;
  1510. }
  1511. // Allocate the required buffers and convert.
  1512. // ==========================================
  1513. pNewSD->m_pSD = (PSECURITY_DESCRIPTOR) new BYTE[dwSDSize];
  1514. if(pNewSD->m_pSD == NULL)
  1515. {
  1516. delete pNewSD;
  1517. return NULL;
  1518. }
  1519. ZeroMemory(pNewSD->m_pSD, dwSDSize);
  1520. pNewSD->m_pDacl = (PACL) new BYTE[dwDaclSize];
  1521. if(pNewSD->m_pDacl == NULL)
  1522. {
  1523. delete pNewSD;
  1524. return NULL;
  1525. }
  1526. ZeroMemory(pNewSD->m_pDacl, dwDaclSize);
  1527. pNewSD->m_pSacl = (PACL) new BYTE[dwSaclSize];
  1528. if(pNewSD->m_pSacl == NULL)
  1529. {
  1530. delete pNewSD;
  1531. return NULL;
  1532. }
  1533. ZeroMemory(pNewSD->m_pSacl, dwSaclSize);
  1534. pNewSD->m_pOwner = (PSID) new BYTE[dwOwnerSize];
  1535. if(pNewSD->m_pOwner == NULL)
  1536. {
  1537. delete pNewSD;
  1538. return NULL;
  1539. }
  1540. ZeroMemory(pNewSD->m_pOwner, dwOwnerSize);
  1541. pNewSD->m_pPrimaryGroup = (PSID) new BYTE[dwPrimaryGroupSize];
  1542. if(pNewSD->m_pPrimaryGroup == NULL)
  1543. {
  1544. delete pNewSD;
  1545. return NULL;
  1546. }
  1547. ZeroMemory(pNewSD->m_pPrimaryGroup, dwPrimaryGroupSize);
  1548. bRes = MakeAbsoluteSD(
  1549. m_pSD,
  1550. pNewSD->m_pSD,
  1551. &dwSDSize,
  1552. pNewSD->m_pDacl,
  1553. &dwDaclSize,
  1554. pNewSD->m_pSacl,
  1555. &dwSaclSize,
  1556. pNewSD->m_pOwner,
  1557. &dwOwnerSize,
  1558. pNewSD->m_pPrimaryGroup,
  1559. &dwPrimaryGroupSize
  1560. );
  1561. if (!bRes)
  1562. {
  1563. delete pNewSD;
  1564. return 0;
  1565. }
  1566. return pNewSD;
  1567. }
  1568. //***************************************************************************
  1569. //
  1570. // CNtSecurityDescriptor::SetFromAbsoluteCopy
  1571. //
  1572. // Replaces the current SD from an absolute copy.
  1573. //
  1574. // Parameters:
  1575. // <pSrcSD> A read-only pointer to the absolute SD used as a source.
  1576. //
  1577. // Return value:
  1578. // TRUE on success, FALSE on failure.
  1579. //
  1580. //***************************************************************************
  1581. // ok
  1582. BOOL CNtSecurityDescriptor::SetFromAbsoluteCopy(
  1583. SNtAbsoluteSD *pSrcSD
  1584. )
  1585. {
  1586. if (pSrcSD == 0 || !IsValidSecurityDescriptor(pSrcSD->m_pSD))
  1587. return FALSE;
  1588. // Ensure that SD is self-relative
  1589. // ===============================
  1590. SECURITY_DESCRIPTOR_CONTROL ctrl;
  1591. DWORD dwRev;
  1592. BOOL bRes = GetSecurityDescriptorControl(
  1593. pSrcSD->m_pSD,
  1594. &ctrl,
  1595. &dwRev
  1596. );
  1597. if (!bRes)
  1598. return FALSE;
  1599. if (ctrl & SE_SELF_RELATIVE) // Source is not absolute!!
  1600. return FALSE;
  1601. // If here, we are committed to change.
  1602. // ====================================
  1603. if (m_pSD)
  1604. {
  1605. delete m_pSD;
  1606. }
  1607. m_pSD = 0;
  1608. m_dwStatus = NullSD;
  1609. DWORD dwRequired = 0;
  1610. bRes = MakeSelfRelativeSD(
  1611. pSrcSD->m_pSD,
  1612. m_pSD,
  1613. &dwRequired
  1614. );
  1615. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  1616. {
  1617. m_dwStatus = InvalidSD;
  1618. return FALSE;
  1619. }
  1620. m_pSD = new BYTE[dwRequired];
  1621. if (!m_pSD)
  1622. {
  1623. m_dwStatus = InvalidSD;
  1624. return FALSE;
  1625. }
  1626. ZeroMemory(m_pSD, dwRequired);
  1627. bRes = MakeSelfRelativeSD(
  1628. pSrcSD->m_pSD,
  1629. m_pSD,
  1630. &dwRequired
  1631. );
  1632. if (!bRes)
  1633. {
  1634. m_dwStatus = InvalidSD;
  1635. delete m_pSD;
  1636. m_pSD = 0;
  1637. return FALSE;
  1638. }
  1639. m_dwStatus = NoError;
  1640. return TRUE;
  1641. }
  1642. //***************************************************************************
  1643. //
  1644. // CNtSecurityDescriptor::SetDacl
  1645. //
  1646. // Sets the DACL of the Security descriptor.
  1647. //
  1648. // Parameters:
  1649. // <pSrc> A read-only pointer to the new DACL to replace the current one.
  1650. //
  1651. // Return value:
  1652. // TRUE on success, FALSE on failure.
  1653. //
  1654. //***************************************************************************
  1655. BOOL CNtSecurityDescriptor::SetDacl(CNtAcl *pSrc)
  1656. {
  1657. if (m_dwStatus != NoError || m_pSD == 0)
  1658. return FALSE;
  1659. // Since we cannot alter a self-relative SD, we have to make
  1660. // an absolute one, alter it, and then set the current
  1661. // SD based on the absolute one (we keep the self-relative form
  1662. // internally in the m_pSD variable.
  1663. // ============================================================
  1664. SNtAbsoluteSD *pTmp = GetAbsoluteCopy();
  1665. if (pTmp == 0)
  1666. return FALSE;
  1667. BOOL bRes = ::SetSecurityDescriptorDacl(
  1668. pTmp->m_pSD,
  1669. TRUE,
  1670. pSrc->GetPtr(),
  1671. FALSE
  1672. );
  1673. if (!bRes)
  1674. {
  1675. delete pTmp;
  1676. return FALSE;
  1677. }
  1678. bRes = SetFromAbsoluteCopy(pTmp);
  1679. delete pTmp;
  1680. return TRUE;
  1681. }
  1682. //***************************************************************************
  1683. //
  1684. // CNtSecurityDescriptor constructor
  1685. //
  1686. // A default constructor creates a no-access security descriptor.
  1687. //
  1688. //***************************************************************************
  1689. // ok
  1690. CNtSecurityDescriptor::CNtSecurityDescriptor()
  1691. {
  1692. m_pSD = 0;
  1693. m_dwStatus = NoError;
  1694. PSECURITY_DESCRIPTOR pTmp = new BYTE[SECURITY_DESCRIPTOR_MIN_LENGTH];
  1695. if (!pTmp)
  1696. {
  1697. delete pTmp;
  1698. m_dwStatus = InvalidSD;
  1699. return;
  1700. }
  1701. ZeroMemory(pTmp, SECURITY_DESCRIPTOR_MIN_LENGTH);
  1702. if (!InitializeSecurityDescriptor(pTmp, SECURITY_DESCRIPTOR_REVISION))
  1703. {
  1704. delete pTmp;
  1705. m_dwStatus = InvalidSD;
  1706. return;
  1707. }
  1708. DWORD dwRequired = 0;
  1709. BOOL bRes = MakeSelfRelativeSD(
  1710. pTmp,
  1711. m_pSD,
  1712. &dwRequired
  1713. );
  1714. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  1715. {
  1716. m_dwStatus = InvalidSD;
  1717. delete pTmp;
  1718. return;
  1719. }
  1720. m_pSD = new BYTE[dwRequired];
  1721. if (!m_pSD)
  1722. {
  1723. m_dwStatus = InvalidSD;
  1724. delete pTmp;
  1725. return;
  1726. }
  1727. ZeroMemory(m_pSD, dwRequired);
  1728. bRes = MakeSelfRelativeSD(
  1729. pTmp,
  1730. m_pSD,
  1731. &dwRequired
  1732. );
  1733. if (!bRes)
  1734. {
  1735. m_dwStatus = InvalidSD;
  1736. delete m_pSD;
  1737. m_pSD = 0;
  1738. delete pTmp;
  1739. return;
  1740. }
  1741. delete pTmp;
  1742. m_dwStatus = NoError;
  1743. }
  1744. //***************************************************************************
  1745. //
  1746. // CNtSecurityDescriptor::GetSize
  1747. //
  1748. // Returns the size in bytes of the internal SD.
  1749. //
  1750. //***************************************************************************
  1751. // ok
  1752. DWORD CNtSecurityDescriptor::GetSize()
  1753. {
  1754. if (m_pSD == 0 || m_dwStatus != NoError)
  1755. return 0;
  1756. return GetSecurityDescriptorLength(m_pSD);
  1757. }
  1758. //***************************************************************************
  1759. //
  1760. // CNtSecurityDescriptor copy constructor
  1761. //
  1762. //***************************************************************************
  1763. // ok
  1764. CNtSecurityDescriptor::CNtSecurityDescriptor(CNtSecurityDescriptor &Src)
  1765. {
  1766. m_pSD = 0;
  1767. m_dwStatus = NoError;
  1768. *this = Src;
  1769. }
  1770. //***************************************************************************
  1771. //
  1772. // CNtSecurityDescriptor assignment operator
  1773. //
  1774. //***************************************************************************
  1775. // ok
  1776. CNtSecurityDescriptor & CNtSecurityDescriptor::operator=(
  1777. CNtSecurityDescriptor &Src
  1778. )
  1779. {
  1780. if (m_pSD)
  1781. delete m_pSD;
  1782. m_dwStatus = Src.m_dwStatus;
  1783. m_pSD = 0;
  1784. if (Src.m_pSD == 0)
  1785. return *this;
  1786. //SIZE_T dwSize = 2*GetSecurityDescriptorLength(Src.m_pSD);
  1787. SIZE_T dwSize = GetSecurityDescriptorLength(Src.m_pSD);
  1788. m_pSD = (PSECURITY_DESCRIPTOR) new BYTE[dwSize];
  1789. if(m_pSD == NULL)
  1790. {
  1791. m_dwStatus = Failed;
  1792. }
  1793. else
  1794. {
  1795. ZeroMemory(m_pSD, dwSize);
  1796. CopyMemory(m_pSD, Src.m_pSD, dwSize);
  1797. }
  1798. return *this;
  1799. }
  1800. //***************************************************************************
  1801. //
  1802. // CNtSecurityDescriptor destructor.
  1803. //
  1804. //***************************************************************************
  1805. // ok
  1806. CNtSecurityDescriptor::~CNtSecurityDescriptor()
  1807. {
  1808. if (m_pSD)
  1809. delete m_pSD;
  1810. }
  1811. //***************************************************************************
  1812. //
  1813. // CNtSecurityDescriptor::GetSacl
  1814. //
  1815. // Returns the SACL of the security descriptor.
  1816. //
  1817. // Return value:
  1818. // A newly allocated CNtAcl which contains the SACL. This object
  1819. // is a copy of the SACL and modifications made to it do not affect
  1820. // the security descriptor. The caller must use operator delete
  1821. // to deallocate the CNtAcl.
  1822. //
  1823. // Returns NULL on error or if no SACL is available.
  1824. //
  1825. //***************************************************************************
  1826. // ok
  1827. CNtAcl *CNtSecurityDescriptor::GetSacl()
  1828. {
  1829. BOOL bSaclPresent = FALSE;
  1830. BOOL bDefaulted;
  1831. PACL pSacl;
  1832. BOOL bRes = GetSecurityDescriptorSacl(
  1833. m_pSD,
  1834. &bSaclPresent,
  1835. &pSacl,
  1836. &bDefaulted
  1837. );
  1838. if (!bRes)
  1839. {
  1840. return 0;
  1841. }
  1842. if (!bSaclPresent) // No Sacl present
  1843. return 0;
  1844. CNtAcl *pNewSacl = new CNtAcl(pSacl);
  1845. return pNewSacl;
  1846. }
  1847. //***************************************************************************
  1848. //
  1849. // CNtSecurityDescriptor::SetSacl
  1850. //
  1851. // Sets the SACL of the Security descriptor.
  1852. //
  1853. // Parameters:
  1854. // <pSrc> A read-only pointer to the new DACL to replace the current one.
  1855. //
  1856. // Return value:
  1857. // TRUE on success, FALSE on failure.
  1858. //
  1859. //***************************************************************************
  1860. // ok
  1861. BOOL CNtSecurityDescriptor::SetSacl(CNtAcl *pSrc)
  1862. {
  1863. if (m_dwStatus != NoError || m_pSD == 0)
  1864. return FALSE;
  1865. // Since we cannot alter a self-relative SD, we have to make
  1866. // an absolute one, alter it, and then set the current
  1867. // SD based on the absolute one (we keep the self-relative form
  1868. // internally in the m_pSD variable.
  1869. // ============================================================
  1870. SNtAbsoluteSD *pTmp = GetAbsoluteCopy();
  1871. if (pTmp == 0)
  1872. return FALSE;
  1873. BOOL bRes = ::SetSecurityDescriptorSacl(
  1874. pTmp->m_pSD,
  1875. TRUE,
  1876. pSrc->GetPtr(),
  1877. FALSE
  1878. );
  1879. if (!bRes)
  1880. {
  1881. delete pTmp;
  1882. return FALSE;
  1883. }
  1884. bRes = SetFromAbsoluteCopy(pTmp);
  1885. delete pTmp;
  1886. return TRUE;
  1887. }
  1888. //***************************************************************************
  1889. //
  1890. // CNtSecurityDescriptor::GetGroup
  1891. //
  1892. //***************************************************************************
  1893. // ok
  1894. CNtSid *CNtSecurityDescriptor::GetGroup()
  1895. {
  1896. if (m_pSD == 0 || m_dwStatus != NoError)
  1897. return 0;
  1898. PSID pSid = 0;
  1899. BOOL bDefaulted;
  1900. BOOL bRes = GetSecurityDescriptorGroup(m_pSD, &pSid, &bDefaulted);
  1901. if ( NULL == pSid )
  1902. {
  1903. ERRORTRACE((LOG_WBEMCORE, "ERROR: Security descriptor has no group\n"));
  1904. return 0;
  1905. }
  1906. if (!bRes || !IsValidSid(pSid))
  1907. return 0;
  1908. return new CNtSid(pSid);
  1909. }
  1910. //***************************************************************************
  1911. //
  1912. // CNtSecurityDescriptor::SetGroup
  1913. //
  1914. //***************************************************************************
  1915. // ok
  1916. BOOL CNtSecurityDescriptor::SetGroup(CNtSid *pSid)
  1917. {
  1918. if (m_dwStatus != NoError || m_pSD == 0 || NULL == pSid)
  1919. return FALSE;
  1920. if ( pSid->GetPtr() == NULL )
  1921. {
  1922. ERRORTRACE((LOG_WBEMCORE, "ERROR: Security descriptor is trying to bland out the group!\n"));
  1923. return FALSE;
  1924. }
  1925. // Since we cannot alter a self-relative SD, we have to make
  1926. // an absolute one, alter it, and then set the current
  1927. // SD based on the absolute one (we keep the self-relative form
  1928. // internally in the m_pSD variable.
  1929. // ============================================================
  1930. SNtAbsoluteSD *pTmp = GetAbsoluteCopy();
  1931. if (pTmp == 0)
  1932. return FALSE;
  1933. BOOL bRes = ::SetSecurityDescriptorGroup(
  1934. pTmp->m_pSD,
  1935. pSid->GetPtr(),
  1936. FALSE
  1937. );
  1938. if (!bRes)
  1939. {
  1940. delete pTmp;
  1941. return FALSE;
  1942. }
  1943. bRes = SetFromAbsoluteCopy(pTmp);
  1944. delete pTmp;
  1945. return TRUE;
  1946. }
  1947. //***************************************************************************
  1948. //
  1949. // CNtSecurityDescriptor::HasOwner
  1950. //
  1951. // Determines if a security descriptor has an owner.
  1952. //
  1953. // Return values:
  1954. // SDNotOwned, SDOwned, Failed
  1955. //
  1956. //***************************************************************************
  1957. // ok
  1958. int CNtSecurityDescriptor::HasOwner()
  1959. {
  1960. if (m_pSD == 0 || m_dwStatus != NoError)
  1961. return Failed;
  1962. PSID pSid = 0;
  1963. BOOL bDefaulted;
  1964. BOOL bRes = GetSecurityDescriptorOwner(m_pSD, &pSid, &bDefaulted);
  1965. if (!bRes || !IsValidSid(pSid))
  1966. return Failed;
  1967. if (pSid == 0)
  1968. return SDNotOwned;
  1969. return SDOwned;
  1970. }
  1971. //***************************************************************************
  1972. //
  1973. // CNtSecurityDescriptor::GetOwner
  1974. //
  1975. // Returns the SID of the owner of the Security Descriptor or NULL
  1976. // if an error occurred or there is no owner. Use HasOwner() to
  1977. // determine this.
  1978. //
  1979. //***************************************************************************
  1980. // ok
  1981. CNtSid *CNtSecurityDescriptor::GetOwner()
  1982. {
  1983. if (m_pSD == 0 || m_dwStatus != NoError)
  1984. return 0;
  1985. PSID pSid = 0;
  1986. BOOL bDefaulted;
  1987. BOOL bRes = GetSecurityDescriptorOwner(m_pSD, &pSid, &bDefaulted);
  1988. // bad for a SD not to have an Owner, but it can be that way
  1989. if ( NULL == pSid) return 0;
  1990. if (!bRes || !IsValidSid(pSid))
  1991. return 0;
  1992. return new CNtSid(pSid);
  1993. }
  1994. //***************************************************************************
  1995. //
  1996. // CNtSecurityDescriptor::SetOwner
  1997. //
  1998. // Sets the owner of a security descriptor.
  1999. //
  2000. // Parameters:
  2001. // <pSid> The SID of the new owner.
  2002. //
  2003. // Return Value:
  2004. // TRUE if owner was changed, FALSE if not.
  2005. //
  2006. //***************************************************************************
  2007. // ok
  2008. BOOL CNtSecurityDescriptor::SetOwner(CNtSid *pSid)
  2009. {
  2010. if (m_pSD == 0 || m_dwStatus != NoError || NULL == pSid)
  2011. return FALSE;
  2012. if (!pSid->IsValid())
  2013. return FALSE;
  2014. // bad practice to remove owner, but this might be the usage
  2015. //_DBG_ASSERT(NULL != pSid->GetPtr());
  2016. // We must convert to absolute format to make the change.
  2017. // =======================================================
  2018. SNtAbsoluteSD *pTmp = GetAbsoluteCopy();
  2019. if (pTmp == 0)
  2020. return FALSE;
  2021. BOOL bRes = SetSecurityDescriptorOwner(pTmp->m_pSD, pSid->GetPtr(), FALSE);
  2022. if (!bRes)
  2023. {
  2024. delete pTmp;
  2025. return FALSE;
  2026. }
  2027. // If here, we have managed the change, so we have to
  2028. // convert *this back from the temporary absolute SD.
  2029. // ===================================================
  2030. bRes = SetFromAbsoluteCopy(pTmp);
  2031. delete pTmp;
  2032. return bRes;
  2033. }
  2034. //***************************************************************************
  2035. //
  2036. // CNtSecurityDescriptor::CNtSecurityDescriptor
  2037. //
  2038. //***************************************************************************
  2039. // ok
  2040. CNtSecurityDescriptor::CNtSecurityDescriptor(
  2041. PSECURITY_DESCRIPTOR pSD,
  2042. BOOL bAcquire
  2043. )
  2044. {
  2045. m_pSD = 0;
  2046. m_dwStatus = NullSD;
  2047. // Ensure that SD is not NULL.
  2048. // ===========================
  2049. if (pSD == 0)
  2050. {
  2051. if (bAcquire)
  2052. delete pSD;
  2053. return;
  2054. }
  2055. if (!IsValidSecurityDescriptor(pSD))
  2056. {
  2057. m_dwStatus = InvalidSD;
  2058. if (bAcquire)
  2059. delete pSD;
  2060. return;
  2061. }
  2062. // Ensure that SD is self-relative
  2063. // ===============================
  2064. SECURITY_DESCRIPTOR_CONTROL ctrl;
  2065. DWORD dwRev;
  2066. BOOL bRes = GetSecurityDescriptorControl(
  2067. pSD,
  2068. &ctrl,
  2069. &dwRev
  2070. );
  2071. if (!bRes)
  2072. {
  2073. m_dwStatus = InvalidSD;
  2074. if (bAcquire)
  2075. delete pSD;
  2076. return;
  2077. }
  2078. if ((ctrl & SE_SELF_RELATIVE) == 0)
  2079. {
  2080. // If here, we have to conver the SD to self-relative form.
  2081. // ========================================================
  2082. DWORD dwRequired = 0;
  2083. bRes = MakeSelfRelativeSD(
  2084. pSD,
  2085. m_pSD,
  2086. &dwRequired
  2087. );
  2088. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  2089. {
  2090. m_dwStatus = InvalidSD;
  2091. if (bAcquire)
  2092. delete pSD;
  2093. return;
  2094. }
  2095. m_pSD = new BYTE[dwRequired];
  2096. if (!m_pSD)
  2097. {
  2098. m_dwStatus = InvalidSD;
  2099. if (bAcquire)
  2100. delete pSD;
  2101. return;
  2102. }
  2103. ZeroMemory(m_pSD, dwRequired);
  2104. bRes = MakeSelfRelativeSD(
  2105. pSD,
  2106. m_pSD,
  2107. &dwRequired
  2108. );
  2109. if (!bRes)
  2110. {
  2111. m_dwStatus = InvalidSD;
  2112. if (bAcquire)
  2113. delete pSD;
  2114. return;
  2115. }
  2116. m_dwStatus = NoError;
  2117. return;
  2118. }
  2119. // If here, the SD was already self-relative.
  2120. // ==========================================
  2121. if (bAcquire)
  2122. m_pSD = pSD;
  2123. else
  2124. {
  2125. DWORD dwRes = GetSecurityDescriptorLength(pSD);
  2126. m_pSD = new BYTE[dwRes];
  2127. if (!m_pSD)
  2128. {
  2129. m_dwStatus = InvalidSD;
  2130. return;
  2131. }
  2132. ZeroMemory(m_pSD, dwRes);
  2133. memcpy(m_pSD, pSD, dwRes);
  2134. }
  2135. m_dwStatus = NoError;
  2136. }
  2137. //***************************************************************************
  2138. //
  2139. // CNtSecurity::IsUserInGroup
  2140. //
  2141. // Determines if the use belongs to a particular NTLM group.
  2142. //
  2143. // Parameters:
  2144. // <hToken> The user's access token.
  2145. // <Sid> Object containing the sid of the group being tested.
  2146. //
  2147. // Return value:
  2148. // TRUE if the user belongs to the group.
  2149. //
  2150. //***************************************************************************
  2151. BOOL CNtSecurity::IsUserInGroup(
  2152. HANDLE hAccessToken,
  2153. CNtSid & Sid)
  2154. {
  2155. if(NULL == hAccessToken ) return FALSE;
  2156. BOOL bRetMember;
  2157. if (CheckTokenMembership(hAccessToken,Sid.GetPtr(),&bRetMember))
  2158. {
  2159. return bRetMember;
  2160. }
  2161. return FALSE;
  2162. }
  2163. C9XAce::C9XAce(
  2164. ACCESS_MASK Mask,
  2165. DWORD AceType,
  2166. DWORD dwAceFlags,
  2167. LPWSTR pUser
  2168. )
  2169. {
  2170. m_wszFullName = NULL;
  2171. if(pUser)
  2172. m_wszFullName = Macro_CloneLPWSTR(pUser);
  2173. m_dwAccess = Mask;
  2174. m_iFlags = dwAceFlags;
  2175. m_iType = AceType;
  2176. }
  2177. C9XAce::~C9XAce()
  2178. {
  2179. if(m_wszFullName)
  2180. delete [] m_wszFullName;
  2181. }
  2182. HRESULT C9XAce::GetFullUserName2(WCHAR ** pBuff)
  2183. {
  2184. if(wcslen(m_wszFullName) < 1)
  2185. return WBEM_E_FAILED;
  2186. int iLen = wcslen(m_wszFullName)+4;
  2187. *pBuff = new WCHAR[iLen];
  2188. if(*pBuff == NULL)
  2189. return WBEM_E_OUT_OF_MEMORY;
  2190. // there are two possible formats, the first is "UserName", and the
  2191. // second is "domain\username".
  2192. WCHAR * pSlash;
  2193. for(pSlash = m_wszFullName; *pSlash && *pSlash != L'\\'; pSlash++); // intentional
  2194. if(*pSlash && pSlash > m_wszFullName)
  2195. {
  2196. // got a domain\user, convert to domain|user
  2197. StringCchCopyW(*pBuff, iLen, m_wszFullName);
  2198. for(pSlash = *pBuff; *pSlash; pSlash++)
  2199. if(*pSlash == L'\\')
  2200. {
  2201. *pSlash = L'|';
  2202. break;
  2203. }
  2204. }
  2205. else
  2206. {
  2207. // got a "user", convert to ".|user"
  2208. StringCchCopyW(*pBuff, iLen, L".|");
  2209. StringCchCatW(*pBuff, iLen, m_wszFullName);
  2210. }
  2211. return S_OK;
  2212. }
  2213. //***************************************************************************
  2214. //
  2215. // C9XAce::GetSerializedSize
  2216. //
  2217. // Returns the number of bytes needed to store this
  2218. //
  2219. //***************************************************************************
  2220. DWORD C9XAce::GetSerializedSize()
  2221. {
  2222. if (m_wszFullName == 0 || wcslen(m_wszFullName) == 0)
  2223. return 0;
  2224. return 2 * (wcslen(m_wszFullName) + 1) + 12;
  2225. }
  2226. //***************************************************************************
  2227. //
  2228. // C9XAce::Serialize
  2229. //
  2230. // Serializes the ace. The serialized version will consist of
  2231. // <DOMAIN\USERNAME LPWSTR><FLAGS><TYPE><MASK>
  2232. //
  2233. // Note that the fields are dwords except for the name.
  2234. //
  2235. //***************************************************************************
  2236. bool C9XAce::Serialize(BYTE * pData, size_t bufferSize)
  2237. {
  2238. if (FAILED(StringCbCopyW((LPWSTR)pData, bufferSize, m_wszFullName))) return false;
  2239. pData += 2*(wcslen(m_wszFullName) + 1);
  2240. DWORD * pdwData = (DWORD *)pData;
  2241. *pdwData = m_iFlags;
  2242. pdwData++;
  2243. *pdwData = m_iType;
  2244. pdwData++;
  2245. *pdwData = m_dwAccess;
  2246. pdwData++;
  2247. return true;
  2248. }
  2249. //***************************************************************************
  2250. //
  2251. // C9XAce::Deserialize
  2252. //
  2253. // Deserializes the ace. See the comments for Serialize for comments.
  2254. //
  2255. //***************************************************************************
  2256. bool C9XAce::Deserialize(BYTE * pData)
  2257. {
  2258. size_t stringSize = wcslen((LPWSTR)pData) + 1;
  2259. m_wszFullName = new WCHAR[stringSize];
  2260. if (!m_wszFullName)
  2261. return false;
  2262. StringCchCopyW(m_wszFullName, stringSize, (LPWSTR)pData);
  2263. pData += 2*(wcslen(m_wszFullName) + 1);
  2264. DWORD * pdwData = (DWORD *)pData;
  2265. m_iFlags = *pdwData;
  2266. pdwData++;
  2267. m_iType = *pdwData;
  2268. pdwData++;
  2269. m_dwAccess = *pdwData;
  2270. pdwData++;
  2271. return true;
  2272. }
  2273. //***************************************************************************
  2274. //
  2275. // BOOL SetObjectAccess2
  2276. //
  2277. // DESCRIPTION:
  2278. //
  2279. // Adds read/open and set access for the everyone group to an object.
  2280. //
  2281. // PARAMETERS:
  2282. //
  2283. // hObj Object to set access on.
  2284. //
  2285. // RETURN VALUE:
  2286. //
  2287. // Returns TRUE if OK.
  2288. //
  2289. //***************************************************************************
  2290. BOOL SetObjectAccess2(IN HANDLE hObj)
  2291. {
  2292. PSECURITY_DESCRIPTOR pSD = NULL;
  2293. DWORD dwLastErr = 0;
  2294. BOOL bRet = FALSE;
  2295. // no point if we arnt on nt
  2296. if(!IsNT())
  2297. {
  2298. return TRUE;
  2299. }
  2300. // figure out how much space to allocate
  2301. DWORD dwSizeNeeded;
  2302. bRet = GetKernelObjectSecurity(
  2303. hObj, // handle of object to query
  2304. DACL_SECURITY_INFORMATION, // requested information
  2305. pSD, // address of security descriptor
  2306. 0, // size of buffer for security descriptor
  2307. &dwSizeNeeded); // address of required size of buffer
  2308. if(bRet == TRUE || (ERROR_INSUFFICIENT_BUFFER != GetLastError()))
  2309. return FALSE;
  2310. pSD = new BYTE[dwSizeNeeded];
  2311. if(pSD == NULL)
  2312. return FALSE;
  2313. // Get the data
  2314. bRet = GetKernelObjectSecurity(
  2315. hObj, // handle of object to query
  2316. DACL_SECURITY_INFORMATION, // requested information
  2317. pSD, // address of security descriptor
  2318. dwSizeNeeded, // size of buffer for security descriptor
  2319. &dwSizeNeeded ); // address of required size of buffer
  2320. if(bRet == FALSE)
  2321. {
  2322. delete pSD;
  2323. return FALSE;
  2324. }
  2325. // move it into object for
  2326. CNtSecurityDescriptor sd(pSD,TRUE); // Acquires ownership of the memory
  2327. if(sd.GetStatus() != 0)
  2328. return FALSE;
  2329. CNtAcl acl;
  2330. if(!sd.GetDacl(acl))
  2331. return FALSE;
  2332. // Create an everyone ace
  2333. PSID pRawSid;
  2334. SID_IDENTIFIER_AUTHORITY id2 = SECURITY_WORLD_SID_AUTHORITY;;
  2335. if(AllocateAndInitializeSid( &id2, 1,
  2336. 0,0,0,0,0,0,0,0,&pRawSid))
  2337. {
  2338. CNtSid SidUsers(pRawSid);
  2339. FreeSid(pRawSid);
  2340. CNtAce * pace = new CNtAce(EVENT_MODIFY_STATE | SYNCHRONIZE, ACCESS_ALLOWED_ACE_TYPE, 0
  2341. , SidUsers);
  2342. if(pace == NULL)
  2343. return FALSE;
  2344. if( pace->GetStatus() == 0)
  2345. acl.AddAce(pace);
  2346. delete pace;
  2347. }
  2348. if(acl.GetStatus() != 0)
  2349. return FALSE;
  2350. sd.SetDacl(&acl);
  2351. bRet = SetKernelObjectSecurity(hObj, DACL_SECURITY_INFORMATION, sd.GetPtr());
  2352. return bRet;
  2353. }
  2354. //***************************************************************************
  2355. //
  2356. // IsAdmin
  2357. //
  2358. // returns TRUE if we are a member of the admin group or running as
  2359. // NETWORK_SERVICE or running as LOCAL_SERVICE
  2360. //
  2361. //***************************************************************************
  2362. BOOL IsAdmin(HANDLE hAccess)
  2363. {
  2364. BOOL bRet = FALSE;
  2365. PSID pRawSid;
  2366. SID_IDENTIFIER_AUTHORITY id = SECURITY_NT_AUTHORITY;
  2367. if(AllocateAndInitializeSid( &id, 2,
  2368. SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
  2369. 0,0,0,0,0,0,&pRawSid))
  2370. {
  2371. CNtSid Sid(pRawSid);
  2372. FreeSid( pRawSid );
  2373. if (CNtSid::NoError != Sid.GetStatus()) return FALSE;
  2374. bRet = CNtSecurity::IsUserInGroup(hAccess, Sid);
  2375. }
  2376. return bRet;
  2377. }
  2378. //***************************************************************************
  2379. //
  2380. // IsNetworkService
  2381. //
  2382. // returns TRUE if we are running as NETWORK_SERVICE
  2383. //
  2384. //***************************************************************************
  2385. BOOL IsNetworkService ( HANDLE hAccess )
  2386. {
  2387. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2388. // Construct the NETWORK_SERVICE SID
  2389. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2390. SID_IDENTIFIER_AUTHORITY id = SECURITY_NT_AUTHORITY;
  2391. PSID pSidSystem;
  2392. BOOL bRes = FALSE;
  2393. if ( AllocateAndInitializeSid(&id, 1, SECURITY_NETWORK_SERVICE_RID, 0, 0,0,0,0,0,0,&pSidSystem) )
  2394. {
  2395. if ( !CheckTokenMembership ( hAccess, pSidSystem, &bRes ) )
  2396. {
  2397. bRes = FALSE;
  2398. }
  2399. FreeSid ( pSidSystem );
  2400. }
  2401. return bRes;
  2402. }
  2403. //***************************************************************************
  2404. //
  2405. // IsLocalService
  2406. //
  2407. // returns TRUE if we are running as LOCAL_SERVICE
  2408. //
  2409. //***************************************************************************
  2410. BOOL IsLocalService ( HANDLE hAccess )
  2411. {
  2412. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2413. // Construct the NETWORK_SERVICE SID
  2414. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2415. SID_IDENTIFIER_AUTHORITY id = SECURITY_NT_AUTHORITY;
  2416. PSID pSidSystem;
  2417. BOOL bRes = FALSE;
  2418. if ( AllocateAndInitializeSid(&id, 1, SECURITY_LOCAL_SERVICE_RID, 0, 0,0,0,0,0,0,&pSidSystem) )
  2419. {
  2420. if ( !CheckTokenMembership ( hAccess, pSidSystem, &bRes ) )
  2421. {
  2422. bRes = FALSE;
  2423. }
  2424. FreeSid ( pSidSystem );
  2425. }
  2426. return bRes;
  2427. }
  2428. //***************************************************************************
  2429. //
  2430. // IsInAdminGroup
  2431. //
  2432. // returns TRUE if we are a member of the admin group.
  2433. //
  2434. //***************************************************************************
  2435. BOOL IsInAdminGroup()
  2436. {
  2437. HANDLE hAccessToken = INVALID_HANDLE_VALUE;
  2438. if(S_OK != GetAccessToken(hAccessToken))
  2439. return TRUE; // Not having a token indicates an internal thread
  2440. CCloseHandle cm(hAccessToken);
  2441. DWORD dwMask = 0;
  2442. if(IsAdmin(hAccessToken))
  2443. return TRUE;
  2444. else
  2445. return FALSE;
  2446. }
  2447. //***************************************************************************
  2448. //
  2449. // HRESULT GetAccessToken
  2450. //
  2451. // Gets the access token and sets it the the reference argument.
  2452. //
  2453. //***************************************************************************
  2454. HRESULT GetAccessToken(HANDLE &hAccessToken)
  2455. {
  2456. bool bIsImpersonating = WbemIsImpersonating();
  2457. HRESULT hRes = S_OK;
  2458. if(bIsImpersonating == false)
  2459. hRes = WbemCoImpersonateClient();
  2460. if(hRes == S_OK)
  2461. {
  2462. BOOL bOK = OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &hAccessToken);
  2463. if(bOK == FALSE)
  2464. {
  2465. hRes = WBEM_E_INVALID_CONTEXT;
  2466. }
  2467. else
  2468. hRes = S_OK;
  2469. }
  2470. if(bIsImpersonating == false)
  2471. WbemCoRevertToSelf();
  2472. return hRes;
  2473. }