Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4392 lines
102 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 <tchar.h>
  18. #include <genutils.h>
  19. #include "arena.h"
  20. #include "reg.h"
  21. #include "wbemutil.h"
  22. #include "arrtempl.h"
  23. #include <cominit.h>
  24. extern "C"
  25. {
  26. #include <lmaccess.h>
  27. #include <lmapibuf.h>
  28. #include <lmerr.h>
  29. };
  30. //***************************************************************************
  31. //
  32. // CNtSid::GetSize
  33. //
  34. // Returns the size of the SID in bytes.
  35. //
  36. //***************************************************************************
  37. // ok
  38. DWORD CNtSid::GetSize()
  39. {
  40. if (m_pSid == 0 || !IsValidSid(m_pSid))
  41. return 0;
  42. return GetLengthSid(m_pSid);
  43. }
  44. //***************************************************************************
  45. //
  46. // CNtSid Copy Constructor
  47. //
  48. //***************************************************************************
  49. // ok
  50. CNtSid::CNtSid(CNtSid &Src)
  51. {
  52. m_pSid = 0;
  53. m_dwStatus = 0;
  54. m_pMachine = 0;
  55. *this = Src;
  56. }
  57. //***************************************************************************
  58. //
  59. // CNtSid Copy Constructor
  60. //
  61. //***************************************************************************
  62. // ok
  63. CNtSid::CNtSid(SidType st)
  64. {
  65. m_pSid = 0;
  66. m_dwStatus = InternalError;
  67. m_pMachine = 0;
  68. if(st == CURRENT_USER ||st == CURRENT_THREAD)
  69. {
  70. HANDLE hToken;
  71. if(st == CURRENT_USER)
  72. {
  73. if(!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &hToken))
  74. return;
  75. }
  76. else
  77. {
  78. if(!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken))
  79. return;
  80. }
  81. // Get the user sid
  82. // ================
  83. TOKEN_USER tu;
  84. DWORD dwLen = 0;
  85. GetTokenInformation(hToken, TokenUser, &tu, sizeof(tu), &dwLen);
  86. if(dwLen == 0)
  87. {
  88. CloseHandle(hToken);
  89. return;
  90. }
  91. BYTE* pTemp = new BYTE[dwLen];
  92. if (!pTemp)
  93. {
  94. CloseHandle(hToken);
  95. return;
  96. }
  97. DWORD dwRealLen = dwLen;
  98. if(!GetTokenInformation(hToken, TokenUser, pTemp, dwRealLen, &dwLen))
  99. {
  100. CloseHandle(hToken);
  101. delete [] pTemp;
  102. return;
  103. }
  104. CloseHandle(hToken);
  105. // Make a copy of the SID
  106. // ======================
  107. PSID pSid = ((TOKEN_USER*)pTemp)->User.Sid;
  108. DWORD dwSidLen = GetLengthSid(pSid);
  109. m_pSid = new BYTE[dwSidLen];
  110. if (m_pSid)
  111. CopySid(dwSidLen, m_pSid, pSid);
  112. delete [] pTemp;
  113. m_dwStatus = 0;
  114. }
  115. return;
  116. }
  117. //***************************************************************************
  118. //
  119. // CNtSid::CopyTo
  120. //
  121. // An unchecked copy of the internal SID to the destination pointer.
  122. //
  123. // Parameters:
  124. // <pDestination> points to the buffer to which to copy the SID. The
  125. // buffer must be large enough to hold the SID.
  126. //
  127. // Return value:
  128. // TRUE on success, FALSE on failure.
  129. //
  130. //***************************************************************************
  131. // ok
  132. BOOL CNtSid::CopyTo(PSID pDestination)
  133. {
  134. if (m_pSid == 0 || m_dwStatus != NoError)
  135. return FALSE;
  136. DWORD dwLen = GetLengthSid(m_pSid);
  137. memcpy(pDestination, m_pSid, dwLen);
  138. return TRUE;
  139. }
  140. //***************************************************************************
  141. //
  142. // CNtSid assignment operator
  143. //
  144. //***************************************************************************
  145. // ok
  146. CNtSid & CNtSid::operator =(CNtSid &Src)
  147. {
  148. if (m_pMachine != 0)
  149. {
  150. delete [] m_pMachine;
  151. m_pMachine = 0;
  152. }
  153. if (m_pSid != 0)
  154. {
  155. delete [] m_pSid;
  156. m_pSid = 0;
  157. }
  158. if (Src.m_pSid == 0)
  159. {
  160. m_pSid = 0;
  161. m_dwStatus = NullSid;
  162. return *this;
  163. }
  164. if (!IsValidSid(Src.m_pSid))
  165. {
  166. m_pSid = 0;
  167. m_dwStatus = InvalidSid;
  168. return *this;
  169. }
  170. // If here, the source has a real SID.
  171. // ===================================
  172. DWORD dwLen = GetLengthSid(Src.m_pSid);
  173. m_pSid = (PSID) new BYTE [dwLen];
  174. if (!m_pSid)
  175. {
  176. m_dwStatus = InternalError;
  177. return *this;
  178. }
  179. ZeroMemory(m_pSid, dwLen);
  180. if (!CopySid(dwLen, m_pSid, Src.m_pSid))
  181. {
  182. delete [] m_pSid;
  183. m_pSid = NULL;
  184. m_dwStatus = InternalError;
  185. return *this;
  186. }
  187. if (Src.m_pMachine)
  188. {
  189. m_pMachine = new wchar_t[wcslen(Src.m_pMachine) + 1];
  190. if (!m_pMachine)
  191. {
  192. delete [] m_pSid;
  193. m_pSid = NULL;
  194. m_dwStatus = InternalError;
  195. return *this;
  196. }
  197. wcscpy(m_pMachine, Src.m_pMachine);
  198. }
  199. m_dwStatus = NoError;
  200. return *this;
  201. }
  202. //***************************************************************************
  203. //
  204. // CNtSid comparison operator
  205. //
  206. //***************************************************************************
  207. int CNtSid::operator ==(CNtSid &Comparand)
  208. {
  209. if (m_pSid == 0 && Comparand.m_pSid == 0)
  210. return 1;
  211. if (m_pSid == 0 || Comparand.m_pSid == 0)
  212. return 0;
  213. return EqualSid(m_pSid, Comparand.m_pSid);
  214. }
  215. //***************************************************************************
  216. //
  217. // CNtSid::CNtSid
  218. //
  219. // Constructor which builds a SID directly from a user or group name.
  220. // If the machine is available, then its name can be used to help
  221. // distinguish the same name in different SAM databases (domains, etc).
  222. //
  223. // Parameters:
  224. //
  225. // <pUser> The desired user or group.
  226. //
  227. // <pMachine> Points to a machine name with or without backslashes,
  228. // or else is NULL, in which case the current machine, domain,
  229. // and trusted domains are searched for a match.
  230. //
  231. // After construction, call GetStatus() to determine if the constructor
  232. // succeeded. NoError is expected.
  233. //
  234. //***************************************************************************
  235. // ok
  236. CNtSid::CNtSid(
  237. LPWSTR pUser,
  238. LPWSTR pMachine
  239. )
  240. {
  241. DWORD dwRequired = 0;
  242. DWORD dwDomRequired = 0;
  243. LPWSTR pszDomain = NULL;
  244. m_pSid = 0;
  245. m_pMachine = 0;
  246. if (pMachine)
  247. {
  248. m_pMachine = new wchar_t[wcslen(pMachine) + 1];
  249. if (!m_pMachine)
  250. {
  251. m_dwStatus = Failed;
  252. return;
  253. }
  254. wcscpy(m_pMachine, pMachine);
  255. }
  256. BOOL bRes = LookupAccountNameW(
  257. m_pMachine,
  258. pUser,
  259. m_pSid,
  260. &dwRequired,
  261. pszDomain,
  262. &dwDomRequired,
  263. &m_snu
  264. );
  265. DWORD dwLastErr = GetLastError();
  266. if (dwLastErr != ERROR_INSUFFICIENT_BUFFER)
  267. {
  268. m_pSid = 0;
  269. if (dwLastErr == ERROR_ACCESS_DENIED)
  270. m_dwStatus = AccessDenied;
  271. else
  272. m_dwStatus = InvalidSid;
  273. return;
  274. }
  275. m_pSid = (PSID) new BYTE [dwRequired];
  276. if (!m_pSid)
  277. {
  278. m_dwStatus = Failed;
  279. return;
  280. }
  281. ZeroMemory(m_pSid, dwRequired);
  282. pszDomain = new wchar_t[dwDomRequired + 1];
  283. if (!pszDomain)
  284. {
  285. delete [] m_pSid;
  286. m_pSid = 0;
  287. m_dwStatus = Failed;
  288. return;
  289. }
  290. bRes = LookupAccountNameW(
  291. pMachine,
  292. pUser,
  293. m_pSid,
  294. &dwRequired,
  295. pszDomain,
  296. &dwDomRequired,
  297. &m_snu
  298. );
  299. if (!bRes || !IsValidSid(m_pSid))
  300. {
  301. delete [] m_pSid;
  302. delete [] pszDomain;
  303. m_pSid = 0;
  304. m_dwStatus = InvalidSid;
  305. return;
  306. }
  307. delete [] pszDomain; // We never really needed this
  308. m_dwStatus = NoError;
  309. }
  310. //***************************************************************************
  311. //
  312. // CNtSid::CNtSid
  313. //
  314. // Constructs a CNtSid object directly from an NT SID. The SID is copied,
  315. // so the caller retains ownership.
  316. //
  317. // Parameters:
  318. // <pSrc> The source SID upon which to base the object.
  319. //
  320. // Call GetStatus() after construction to ensure the object was
  321. // constructed correctly. NoError is expected.
  322. //
  323. //***************************************************************************
  324. // ok
  325. CNtSid::CNtSid(PSID pSrc)
  326. {
  327. m_pMachine = 0;
  328. m_pSid = 0;
  329. m_dwStatus = NoError;
  330. if (!IsValidSid(pSrc))
  331. {
  332. m_dwStatus = InvalidSid;
  333. return;
  334. }
  335. DWORD dwLen = GetLengthSid(pSrc);
  336. m_pSid = (PSID) new BYTE [dwLen];
  337. // Check for mem. alloc. failure
  338. // NT RAID#: 158600 [marioh]
  339. if ( m_pSid == NULL )
  340. {
  341. m_dwStatus = Failed;
  342. return;
  343. }
  344. ZeroMemory(m_pSid, dwLen);
  345. if (!CopySid(dwLen, m_pSid, pSrc))
  346. {
  347. delete [] m_pSid;
  348. m_dwStatus = InternalError;
  349. return;
  350. }
  351. }
  352. //***************************************************************************
  353. //
  354. // CNtSid::GetInfo
  355. //
  356. // Returns information about the SID.
  357. //
  358. // Parameters:
  359. // <pRetAccount> Receives a UNICODE string containing the account
  360. // name (user or group). The caller must use operator
  361. // delete to free the memory. This can be NULL if
  362. // this information is not required.
  363. // <pRetDomain> Returns a UNICODE string containing the domain
  364. // name in which the account resides. The caller must
  365. // use operator delete to free the memory. This can be
  366. // NULL if this information is not required.
  367. // <pdwUse> Points to a DWORD to receive information about the name.
  368. // Possible return values are defined under SID_NAME_USE
  369. // in NT SDK documentation. Examples are
  370. // SidTypeUser, SidTypeGroup, etc. See CNtSid::Dump()
  371. // for an example.
  372. //
  373. // Return values:
  374. // NoError, InvalidSid, Failed
  375. //
  376. //***************************************************************************
  377. // ok
  378. int CNtSid::GetInfo(
  379. LPWSTR *pRetAccount, // Account, use operator delete
  380. LPWSTR *pRetDomain, // Domain, use operator delete
  381. DWORD *pdwUse // See SID_NAME_USE for values
  382. )
  383. {
  384. if (pRetAccount)
  385. *pRetAccount = 0;
  386. if (pRetDomain)
  387. *pRetDomain = 0;
  388. if (pdwUse)
  389. *pdwUse = 0;
  390. if (!m_pSid || !IsValidSid(m_pSid))
  391. return InvalidSid;
  392. DWORD dwNameLen = 0;
  393. DWORD dwDomainLen = 0;
  394. LPWSTR pUser = 0;
  395. LPWSTR pDomain = 0;
  396. SID_NAME_USE Use;
  397. // Do the first lookup to get the buffer sizes required.
  398. // =====================================================
  399. BOOL bRes = LookupAccountSidW(
  400. m_pMachine,
  401. m_pSid,
  402. pUser,
  403. &dwNameLen,
  404. pDomain,
  405. &dwDomainLen,
  406. &Use
  407. );
  408. DWORD dwLastErr = GetLastError();
  409. if (dwLastErr != ERROR_INSUFFICIENT_BUFFER)
  410. {
  411. return Failed;
  412. }
  413. // Allocate the required buffers and look them up again.
  414. // =====================================================
  415. pUser = new wchar_t[dwNameLen + 1];
  416. if (!pUser)
  417. return Failed;
  418. pDomain = new wchar_t[dwDomainLen + 1];
  419. if (!pDomain)
  420. {
  421. delete pUser;
  422. return Failed;
  423. }
  424. bRes = LookupAccountSidW(
  425. m_pMachine,
  426. m_pSid,
  427. pUser,
  428. &dwNameLen,
  429. pDomain,
  430. &dwDomainLen,
  431. &Use
  432. );
  433. if (!bRes)
  434. {
  435. delete [] pUser;
  436. delete [] pDomain;
  437. return Failed;
  438. }
  439. if (pRetAccount)
  440. *pRetAccount = pUser;
  441. else
  442. delete [] pUser;
  443. if (pRetDomain)
  444. *pRetDomain = pDomain;
  445. else
  446. delete [] pDomain;
  447. if (pdwUse)
  448. *pdwUse = Use;
  449. return NoError;
  450. }
  451. //***************************************************************************
  452. //
  453. // CNtSid::Dump
  454. //
  455. // Dumps the SID to the console outuput for debugging.
  456. //
  457. //***************************************************************************
  458. // ok
  459. void CNtSid::Dump()
  460. {
  461. LPWSTR pUser, pDomain;
  462. DWORD dwUse;
  463. printf("---SID DUMP---\n");
  464. if (m_pSid == 0)
  465. {
  466. printf("<NULL>\n");
  467. return;
  468. }
  469. if (!IsValidSid(m_pSid))
  470. {
  471. printf("<Invalid Sid>\n");
  472. return;
  473. }
  474. int nRes = GetInfo(&pUser, &pDomain, &dwUse);
  475. if (nRes != NoError)
  476. return;
  477. // Print out SID in SID-style notation.
  478. // ====================================
  479. // Print out human-readable info.
  480. // ===============================
  481. printf("User = %S Domain = %S Type = ", pUser, pDomain);
  482. delete [] pUser;
  483. delete [] pDomain;
  484. switch (dwUse)
  485. {
  486. case SidTypeUser:
  487. printf("SidTypeUser\n");
  488. break;
  489. case SidTypeGroup:
  490. printf("SidTypeGroup\n");
  491. break;
  492. case SidTypeDomain:
  493. printf("SidTypeDomain\n");
  494. break;
  495. case SidTypeAlias:
  496. printf("SidTypeAlias\n");
  497. break;
  498. case SidTypeWellKnownGroup:
  499. printf("SidTypeWellKnownGroup\n");
  500. break;
  501. case SidTypeDeletedAccount:
  502. printf("SidTypeDeletedAccount\n");
  503. break;
  504. case SidTypeUnknown:
  505. printf("SidTypeUnknown\n");
  506. break;
  507. case SidTypeInvalid:
  508. default:
  509. printf("SidTypeInvalid\n");
  510. }
  511. }
  512. //***************************************************************************
  513. //
  514. // CNtSid destructor
  515. //
  516. //***************************************************************************
  517. CNtSid::~CNtSid()
  518. {
  519. if (m_pSid)
  520. delete [] m_pSid;
  521. if (m_pMachine)
  522. delete [] m_pMachine;
  523. }
  524. //***************************************************************************
  525. //
  526. // CNtSid::GetTextSid
  527. //
  528. // Converts the sid to text form. The caller should passin a 130 character
  529. // buffer.
  530. //
  531. //***************************************************************************
  532. BOOL CNtSid::GetTextSid(LPTSTR pszSidText, LPDWORD dwBufferLen)
  533. {
  534. PSID_IDENTIFIER_AUTHORITY psia;
  535. DWORD dwSubAuthorities = 0;
  536. DWORD dwSidRev=SID_REVISION;
  537. DWORD dwCounter = 0;
  538. DWORD dwSidSize = 0;
  539. // test if Sid is valid
  540. if(m_pSid == 0 || !IsValidSid(m_pSid))
  541. return FALSE;
  542. // obtain SidIdentifierAuthority
  543. psia=GetSidIdentifierAuthority(m_pSid);
  544. // obtain sidsubauthority count
  545. PUCHAR p = GetSidSubAuthorityCount(m_pSid);
  546. dwSubAuthorities = *p;
  547. // compute buffer length
  548. // S-SID_REVISION- + identifierauthority- + subauthorities- + NULL
  549. dwSidSize=(15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR);
  550. // check provided buffer length. If not large enough, indicate proper size.
  551. if (*dwBufferLen < dwSidSize)
  552. {
  553. *dwBufferLen = dwSidSize;
  554. return FALSE;
  555. }
  556. // prepare S-SID_REVISION-
  557. dwSidSize=wsprintf(pszSidText, TEXT("S-%lu-"), dwSidRev );
  558. // prepare SidIdentifierAuthority
  559. if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) )
  560. {
  561. dwSidSize+=wsprintf(pszSidText + lstrlen(pszSidText),
  562. TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
  563. (USHORT)psia->Value[0],
  564. (USHORT)psia->Value[1],
  565. (USHORT)psia->Value[2],
  566. (USHORT)psia->Value[3],
  567. (USHORT)psia->Value[4],
  568. (USHORT)psia->Value[5]);
  569. }
  570. else
  571. {
  572. dwSidSize+=wsprintf(pszSidText + lstrlen(pszSidText),
  573. TEXT("%lu"),
  574. (ULONG)(psia->Value[5] ) +
  575. (ULONG)(psia->Value[4] << 8) +
  576. (ULONG)(psia->Value[3] << 16) +
  577. (ULONG)(psia->Value[2] << 24) );
  578. }
  579. // loop through SidSubAuthorities
  580. for (dwCounter=0 ; dwCounter < dwSubAuthorities ; dwCounter++)
  581. {
  582. dwSidSize+=wsprintf(pszSidText + dwSidSize, TEXT("-%lu"),
  583. *GetSidSubAuthority(m_pSid, dwCounter) );
  584. }
  585. return TRUE;
  586. }
  587. //***************************************************************************
  588. //
  589. // CNtAce::CNtAce
  590. //
  591. // Constructor which directly builds the ACE based on a user, access mask
  592. // and flags without a need to build an explicit SID.
  593. //
  594. //
  595. // Parameters:
  596. // <AccessMask> A WINNT ACCESS_MASK which specifies the permissions
  597. // the user should have to the object being secured.
  598. // See ACCESS_MASK in NT SDK documentation.
  599. // <dwAceType> One of the following:
  600. // ACCESS_ALLOWED_ACE_TYPE
  601. // ACCESS_DENIED_ACE_TYPE
  602. // ACCESS_AUDIT_ACE_TYPE
  603. // See ACE_HEADER in NT SDK documentation.
  604. // <dwAceFlags> Of of the ACE propation flags. See ACE_HEADER
  605. // in NT SDK documentation for legal values.
  606. // <sid> CNtSid specifying the user or group for which the ACE is being
  607. // created.
  608. //
  609. // After construction, call GetStatus() to verify that the ACE
  610. // is valid. NoError is expected.
  611. //
  612. //***************************************************************************
  613. // ok
  614. CNtAce::CNtAce(
  615. ACCESS_MASK AccessMask,
  616. DWORD dwAceType,
  617. DWORD dwAceFlags,
  618. CNtSid & Sid
  619. )
  620. {
  621. m_pAce = 0;
  622. m_dwStatus = 0;
  623. // If the SID is invalid, the ACE will be as well.
  624. // ===============================================
  625. if (Sid.GetStatus() != CNtSid::NoError)
  626. {
  627. m_dwStatus = InvalidAce;
  628. return;
  629. }
  630. // Compute the size of the ACE.
  631. // ============================
  632. DWORD dwSidLength = Sid.GetSize();
  633. DWORD dwTotal = dwSidLength + sizeof(GENERIC_ACE) - 4;
  634. m_pAce = (PGENERIC_ACE) new BYTE[dwTotal];
  635. if (m_pAce)
  636. {
  637. ZeroMemory(m_pAce, dwTotal);
  638. // Build up the ACE info.
  639. // ======================
  640. m_pAce->Header.AceType = BYTE(dwAceType);
  641. m_pAce->Header.AceFlags = BYTE(dwAceFlags);
  642. m_pAce->Header.AceSize = WORD(dwTotal);
  643. m_pAce->Mask = AccessMask;
  644. BOOL bRes = Sid.CopyTo(PSID(&m_pAce->SidStart));
  645. if (!bRes)
  646. {
  647. delete m_pAce;
  648. m_pAce = 0;
  649. m_dwStatus = InvalidAce;
  650. return;
  651. }
  652. m_dwStatus = NoError;
  653. }
  654. else
  655. m_dwStatus = InternalError;
  656. }
  657. //***************************************************************************
  658. //
  659. // CNtAce::CNtAce
  660. //
  661. // Constructor which directly builds the ACE based on a user, access mask
  662. // and flags without a need to build an explicit SID.
  663. //
  664. //
  665. // Parameters:
  666. // <AccessMask> A WINNT ACCESS_MASK which specifies the permissions
  667. // the user should have to the object being secured.
  668. // See ACCESS_MASK in NT SDK documentation.
  669. // <dwAceType> One of the following:
  670. // ACCESS_ALLOWED_ACE_TYPE
  671. // ACCESS_DENIED_ACE_TYPE
  672. // ACCESS_AUDIT_ACE_TYPE
  673. // See ACE_HEADER in NT SDK documentation.
  674. // <dwAceFlags> Of of the ACE propation flags. See ACE_HEADER
  675. // in NT SDK documentation for legal values.
  676. // <pUser> The user or group for which the ACE is being
  677. // created.
  678. // <pMachine> If NULL, the current machine, domain, and trusted
  679. // domains are searched for a match. If not NULL,
  680. // can point to a UNICODE machine name (with or without
  681. // leading backslashes) which contains the account.
  682. //
  683. // After construction, call GetStatus() to verify that the ACE
  684. // is valid. NoError is expected.
  685. //
  686. //***************************************************************************
  687. // ok
  688. CNtAce::CNtAce(
  689. ACCESS_MASK AccessMask,
  690. DWORD dwAceType,
  691. DWORD dwAceFlags,
  692. LPWSTR pUser,
  693. LPWSTR pMachine
  694. )
  695. {
  696. m_pAce = 0;
  697. m_dwStatus = 0;
  698. // Create the SID of the user.
  699. // ===========================
  700. CNtSid Sid(pUser, pMachine);
  701. // If the SID is invalid, the ACE will be as well.
  702. // ===============================================
  703. if (Sid.GetStatus() != CNtSid::NoError)
  704. {
  705. m_dwStatus = InvalidAce;
  706. return;
  707. }
  708. // Compute the size of the ACE.
  709. // ============================
  710. DWORD dwSidLength = Sid.GetSize();
  711. DWORD dwTotal = dwSidLength + sizeof(GENERIC_ACE) - 4;
  712. m_pAce = (PGENERIC_ACE) new BYTE[dwTotal];
  713. if ( m_pAce == NULL )
  714. {
  715. m_dwStatus = InternalError;
  716. return;
  717. }
  718. ZeroMemory(m_pAce, dwTotal);
  719. // Build up the ACE info.
  720. // ======================
  721. m_pAce->Header.AceType = BYTE(dwAceType);
  722. m_pAce->Header.AceFlags = BYTE(dwAceFlags);
  723. m_pAce->Header.AceSize = WORD(dwTotal);
  724. m_pAce->Mask = AccessMask;
  725. BOOL bRes = Sid.CopyTo(PSID(&m_pAce->SidStart));
  726. if (!bRes)
  727. {
  728. delete m_pAce;
  729. m_pAce = 0;
  730. m_dwStatus = InvalidAce;
  731. return;
  732. }
  733. m_dwStatus = NoError;
  734. }
  735. //***************************************************************************
  736. //
  737. // CNtAce::GetAccessMask
  738. //
  739. // Returns the ACCESS_MASK of the ACe.
  740. //
  741. //***************************************************************************
  742. ACCESS_MASK CNtAce::GetAccessMask()
  743. {
  744. if (m_pAce == 0)
  745. return 0;
  746. return m_pAce->Mask;
  747. }
  748. //***************************************************************************
  749. //
  750. // CNtAce::GetSerializedSize
  751. //
  752. // Returns the number of bytes needed to store this
  753. //
  754. //***************************************************************************
  755. DWORD CNtAce::GetSerializedSize()
  756. {
  757. if (m_pAce == 0)
  758. return 0;
  759. return m_pAce->Header.AceSize;
  760. }
  761. //***************************************************************************
  762. //
  763. // CNtAce::DumpAccessMask
  764. //
  765. // A helper function for CNtAce::Dump(). Illustrates the values
  766. // that the ACCESS_MASK for the ACE can take on.
  767. //
  768. //***************************************************************************
  769. // ok
  770. void CNtAce::DumpAccessMask()
  771. {
  772. if (m_pAce == 0)
  773. return;
  774. ACCESS_MASK AccessMask = m_pAce->Mask;
  775. printf("Access Mask = 0x%X\n", AccessMask);
  776. printf(" User Portion = 0x%X\n", AccessMask & 0xFFFF);
  777. if (AccessMask & DELETE)
  778. printf(" DELETE\n");
  779. if (AccessMask & READ_CONTROL)
  780. printf(" READ_CONTROL\n");
  781. if (AccessMask & WRITE_DAC)
  782. printf(" WRITE_DAC\n");
  783. if (AccessMask & WRITE_OWNER)
  784. printf(" WRITE_OWNER\n");
  785. if (AccessMask & SYNCHRONIZE)
  786. printf(" SYNCHRONIZE\n");
  787. if (AccessMask & ACCESS_SYSTEM_SECURITY)
  788. printf(" ACCESS_SYSTEM_SECURITY\n");
  789. if (AccessMask & MAXIMUM_ALLOWED)
  790. printf(" MAXIMUM_ALLOWED\n");
  791. if (AccessMask & GENERIC_ALL)
  792. printf(" GENERIC_ALL\n");
  793. if (AccessMask & GENERIC_EXECUTE)
  794. printf(" GENERIC_EXECUTE\n");
  795. if (AccessMask & GENERIC_READ)
  796. printf(" GENERIC_READ\n");
  797. if (AccessMask & GENERIC_WRITE)
  798. printf(" GENERIC_WRITE\n");
  799. }
  800. //***************************************************************************
  801. //
  802. // CNtAce::GetSid
  803. //
  804. // Returns a copy of the CNtSid object which makes up the ACE.
  805. //
  806. // Return value:
  807. // A newly allocated CNtSid which represents the user or group
  808. // referenced in the ACE. The caller must use operator delete to free
  809. // the memory.
  810. //
  811. //***************************************************************************
  812. // ok
  813. CNtSid* CNtAce::GetSid()
  814. {
  815. if (m_pAce == 0)
  816. return 0;
  817. PSID pSid = 0;
  818. pSid = &m_pAce->SidStart;
  819. if (!IsValidSid(pSid))
  820. return 0;
  821. return new CNtSid(pSid);
  822. }
  823. //***************************************************************************
  824. //
  825. // CNtAce::GetSid
  826. //
  827. // Gets the SID in an alternate manner, by assigning to an existing
  828. // object instead of returning a dynamically allocated one.
  829. //
  830. // Parameters:
  831. // <Dest> A reference to a CNtSid to receive the SID.
  832. //
  833. // Return value:
  834. // TRUE on successful assignment, FALSE on failure.
  835. //
  836. //***************************************************************************
  837. BOOL CNtAce::GetSid(CNtSid &Dest)
  838. {
  839. CNtSid *pSid = GetSid();
  840. if (pSid == 0)
  841. return FALSE;
  842. Dest = *pSid;
  843. delete pSid;
  844. return TRUE;
  845. }
  846. //***************************************************************************
  847. //
  848. // CNtAce::Dump
  849. //
  850. // Dumps the current ACE to the console for debugging purposes.
  851. // Illustrates the structure of the ACE and the values the different
  852. // fields can take on.
  853. //
  854. //***************************************************************************
  855. // ok
  856. void CNtAce::Dump(int iAceNum)
  857. {
  858. if(iAceNum != -1)
  859. printf("\n---ACE DUMP FOR ACE #%d---\n", iAceNum);
  860. else
  861. printf("\n---ACE DUMP---\n");
  862. printf("Ace Type = ");
  863. if (m_pAce == 0)
  864. {
  865. printf("NULL ACE\n");
  866. return;
  867. }
  868. switch (m_pAce->Header.AceType)
  869. {
  870. case ACCESS_ALLOWED_ACE_TYPE:
  871. printf("ACCESS_ALLOWED_ACE_TYPE\n");
  872. break;
  873. case ACCESS_DENIED_ACE_TYPE:
  874. printf("ACCESS_DENIED_ACE_TYPE\n");
  875. break;
  876. case SYSTEM_AUDIT_ACE_TYPE:
  877. printf("SYSTEM_AUDIT_ACE_TYPE\n");
  878. break;
  879. default:
  880. printf("INVALID ACE\n");
  881. break;
  882. }
  883. // Dump ACE flags.
  884. // ===============
  885. printf("ACE FLAGS = ");
  886. if (m_pAce->Header.AceFlags & INHERITED_ACE)
  887. printf("INHERITED_ACE ");
  888. if (m_pAce->Header.AceFlags & CONTAINER_INHERIT_ACE)
  889. printf("CONTAINER_INHERIT_ACE ");
  890. if (m_pAce->Header.AceFlags & INHERIT_ONLY_ACE)
  891. printf("INHERIT_ONLY_ACE ");
  892. if (m_pAce->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE)
  893. printf("NO_PROPAGATE_INHERIT_ACE ");
  894. if (m_pAce->Header.AceFlags & OBJECT_INHERIT_ACE)
  895. printf("OBJECT_INHERIT_ACE ");
  896. if (m_pAce->Header.AceFlags & FAILED_ACCESS_ACE_FLAG)
  897. printf(" FAILED_ACCESS_ACE_FLAG");
  898. if (m_pAce->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
  899. printf(" SUCCESSFUL_ACCESS_ACE_FLAG");
  900. printf("\n");
  901. // Dump the SID.
  902. // =============
  903. CNtSid *pSid = GetSid();
  904. if (pSid)
  905. {
  906. pSid->Dump();
  907. delete pSid;
  908. }
  909. DumpAccessMask();
  910. }
  911. //***************************************************************************
  912. //
  913. // CNtAce::CNtAce
  914. //
  915. // Alternate constructor which uses a normal NT ACE as a basis for
  916. // object construction.
  917. //
  918. // Parameters:
  919. // <pAceSrc> A read-only pointer to the source ACE upon which to
  920. // base object construction.
  921. //
  922. // After construction, GetStatus() can be used to determine if the
  923. // object constructed properly. NoError is expected.
  924. //
  925. //***************************************************************************
  926. // ok
  927. CNtAce::CNtAce(PGENERIC_ACE pAceSrc)
  928. {
  929. m_dwStatus = NoError;
  930. if (pAceSrc == 0)
  931. {
  932. m_dwStatus = NullAce;
  933. m_pAce = 0;
  934. }
  935. m_pAce = (PGENERIC_ACE) new BYTE[pAceSrc->Header.AceSize];
  936. if ( m_pAce == NULL )
  937. {
  938. m_dwStatus = InternalError;
  939. return;
  940. }
  941. ZeroMemory(m_pAce, pAceSrc->Header.AceSize);
  942. memcpy(m_pAce, pAceSrc, pAceSrc->Header.AceSize);
  943. }
  944. //***************************************************************************
  945. //
  946. // CNtAce copy constructor.
  947. //
  948. //***************************************************************************
  949. // ok
  950. CNtAce::CNtAce(CNtAce &Src)
  951. {
  952. m_dwStatus = NoError;
  953. m_pAce = 0;
  954. *this = Src;
  955. }
  956. //***************************************************************************
  957. //
  958. // CNtAce assignment operator.
  959. //
  960. //***************************************************************************
  961. // ok
  962. CNtAce &CNtAce::operator =(CNtAce &Src)
  963. {
  964. if (m_pAce != 0)
  965. delete m_pAce;
  966. if (Src.m_pAce == 0)
  967. {
  968. m_pAce = 0;
  969. m_dwStatus = NullAce;
  970. return *this;
  971. }
  972. m_pAce = (PGENERIC_ACE) new BYTE[Src.m_pAce->Header.AceSize];
  973. if(m_pAce == NULL)
  974. {
  975. m_dwStatus = InternalError;
  976. }
  977. else
  978. {
  979. ZeroMemory(m_pAce, Src.m_pAce->Header.AceSize);
  980. memcpy(m_pAce, Src.m_pAce, Src.m_pAce->Header.AceSize);
  981. m_dwStatus = Src.m_dwStatus;
  982. }
  983. return *this;
  984. }
  985. //***************************************************************************
  986. //
  987. // CNtAce destructor
  988. //
  989. //***************************************************************************
  990. // ok
  991. CNtAce::~CNtAce()
  992. {
  993. if (m_pAce)
  994. delete m_pAce;
  995. }
  996. //***************************************************************************
  997. //
  998. // CNtAce::GetType
  999. //
  1000. // Gets the Ace Type as defined under the NT SDK documentation for
  1001. // ACE_HEADER.
  1002. //
  1003. // Return value:
  1004. // Returns ACCESS_ALLOWED_ACE_TYPE, ACCESS_DENIED_ACE_TYPE, or
  1005. // SYSTEM_AUDIT_ACE_TYPE. Returns -1 on error, such as a null ACE.
  1006. //
  1007. // Returning -1 (or an analog) is required as an error code because
  1008. // ACCESS_ALLOWED_ACE_TYPE is defined to be zero.
  1009. //
  1010. //***************************************************************************
  1011. // ok
  1012. int CNtAce::GetType()
  1013. {
  1014. if (m_pAce == 0 || m_dwStatus != NoError)
  1015. return -1;
  1016. return m_pAce->Header.AceType;
  1017. }
  1018. //***************************************************************************
  1019. //
  1020. // CNtAce::GetFlags
  1021. //
  1022. // Gets the Ace Flag as defined under the NT SDK documentation for
  1023. // ACE_HEADER.
  1024. //
  1025. // Return value:
  1026. // Returning -1 if error, other wise the flags.
  1027. //
  1028. //***************************************************************************
  1029. int CNtAce::GetFlags()
  1030. {
  1031. if (m_pAce == 0 || m_dwStatus != NoError)
  1032. return -1;
  1033. return m_pAce->Header.AceFlags;
  1034. }
  1035. //***************************************************************************
  1036. //
  1037. // CNtAce::GetFullUserName
  1038. //
  1039. // Gets the domain\user name.
  1040. //
  1041. //***************************************************************************
  1042. HRESULT CNtAce::GetFullUserName(WCHAR * pBuff, DWORD dwSize)
  1043. {
  1044. CNtSid *pSid = GetSid();
  1045. if(pSid == NULL)
  1046. return WBEM_E_OUT_OF_MEMORY;
  1047. CDeleteMe<CNtSid> d0(pSid);
  1048. DWORD dwJunk;
  1049. LPWSTR pRetAccount = NULL, pRetDomain = NULL;
  1050. pSid->GetInfo(&pRetAccount, &pRetDomain,&dwJunk);
  1051. CDeleteMe<WCHAR> d1(pRetAccount);
  1052. CDeleteMe<WCHAR> d2(pRetDomain);
  1053. WCHAR wTemp[256];
  1054. wTemp[0] = 0;
  1055. if(pRetDomain && wcslen(pRetDomain) > 0)
  1056. {
  1057. wcscpy(wTemp, pRetDomain);
  1058. wcscat(wTemp, L"|");
  1059. }
  1060. wcscat(wTemp, pRetAccount);
  1061. wcsncpy(pBuff, wTemp, dwSize-1);
  1062. return S_OK;
  1063. }
  1064. HRESULT CNtAce::GetFullUserName2(WCHAR ** pBuff)
  1065. {
  1066. CNtSid *pSid = GetSid();
  1067. if(pSid == NULL)
  1068. return WBEM_E_OUT_OF_MEMORY;
  1069. CDeleteMe<CNtSid> d0(pSid);
  1070. DWORD dwJunk;
  1071. LPWSTR pRetAccount = NULL, pRetDomain = NULL;
  1072. if(0 != pSid->GetInfo(&pRetAccount, &pRetDomain,&dwJunk))
  1073. return WBEM_E_FAILED;
  1074. CDeleteMe<WCHAR> d1(pRetAccount);
  1075. CDeleteMe<WCHAR> d2(pRetDomain);
  1076. int iLen = 3;
  1077. if(pRetAccount)
  1078. iLen += wcslen(pRetAccount);
  1079. if(pRetDomain)
  1080. iLen += wcslen(pRetDomain);
  1081. (*pBuff) = new WCHAR[iLen];
  1082. if((*pBuff) == NULL)
  1083. return WBEM_E_OUT_OF_MEMORY;
  1084. (*pBuff)[0] = 0;
  1085. if(pRetDomain && wcslen(pRetDomain) > 0)
  1086. wcscpy(*pBuff, pRetDomain);
  1087. else
  1088. wcscpy(*pBuff, L".");
  1089. wcscat(*pBuff, L"|");
  1090. wcscat(*pBuff, pRetAccount);
  1091. return S_OK;
  1092. }
  1093. //***************************************************************************
  1094. //
  1095. // CNtAce::Serialize
  1096. //
  1097. // Serializes the ace.
  1098. //
  1099. //***************************************************************************
  1100. bool CNtAce::Serialize(BYTE * pData)
  1101. {
  1102. if(m_pAce == NULL)
  1103. return false;
  1104. DWORD dwSize = m_pAce->Header.AceSize;
  1105. memcpy((void *)pData, (void *)m_pAce, dwSize);
  1106. return true;
  1107. }
  1108. //***************************************************************************
  1109. //
  1110. // CNtAce::Deserialize
  1111. //
  1112. // Deserializes the ace. Normally this isnt called since the
  1113. // CNtAce(PGENERIC_ACE pAceSrc) constructor is fine. However, this is
  1114. // used for the case where the db was created on win9x and we are now
  1115. // running on nt. In that case, the format is the same as outlined in
  1116. // C9XAce::Serialize
  1117. //
  1118. //***************************************************************************
  1119. bool CNtAce::Deserialize(BYTE * pData)
  1120. {
  1121. BYTE * pNext;
  1122. pNext = pData + 2*(wcslen((LPWSTR)pData) + 1);
  1123. DWORD * pdwData = (DWORD *)pNext;
  1124. DWORD dwFlags, dwType, dwAccess;
  1125. dwFlags = *pdwData;
  1126. pdwData++;
  1127. dwType = *pdwData;
  1128. pdwData++;
  1129. dwAccess = *pdwData;
  1130. pdwData++;
  1131. CNtAce temp(dwAccess, dwType, dwFlags, (LPWSTR)pData);
  1132. *this = temp;
  1133. return true;
  1134. }
  1135. //***************************************************************************
  1136. //
  1137. // CNtAcl::CNtAcl
  1138. //
  1139. // Constructs an empty ACL with a user-specified size.
  1140. //
  1141. // Parameters:
  1142. // <dwInitialSize> Defaults to 128. Recommended values are 128 or
  1143. // higher in powers of two.
  1144. //
  1145. // After construction, GetStatus() should be called to verify
  1146. // the ACL initialized properly. Expected value is NoError.
  1147. //
  1148. //***************************************************************************
  1149. // ok
  1150. CNtAcl::CNtAcl(DWORD dwInitialSize)
  1151. {
  1152. m_pAcl = (PACL) new BYTE[dwInitialSize];
  1153. if ( m_pAcl == NULL )
  1154. {
  1155. m_dwStatus = InternalError;
  1156. return;
  1157. }
  1158. ZeroMemory(m_pAcl, dwInitialSize);
  1159. BOOL bRes = InitializeAcl(m_pAcl, dwInitialSize, ACL_REVISION);
  1160. if (!bRes)
  1161. {
  1162. delete m_pAcl;
  1163. m_pAcl = 0;
  1164. m_dwStatus = NullAcl;
  1165. return;
  1166. }
  1167. m_dwStatus = NoError;
  1168. }
  1169. //***************************************************************************
  1170. //
  1171. // CNtAcl copy constructor.
  1172. //
  1173. //***************************************************************************
  1174. // ok
  1175. CNtAcl::CNtAcl(CNtAcl &Src)
  1176. {
  1177. m_pAcl = 0;
  1178. m_dwStatus = NoError;
  1179. *this = Src;
  1180. }
  1181. //***************************************************************************
  1182. //
  1183. // CNtAcl assignment operator
  1184. //
  1185. //***************************************************************************
  1186. // ok
  1187. CNtAcl &CNtAcl::operator = (CNtAcl &Src)
  1188. {
  1189. if (m_pAcl != 0)
  1190. delete m_pAcl;
  1191. // Default to a NULL ACL.
  1192. // ======================
  1193. m_pAcl = 0;
  1194. m_dwStatus = NullAcl;
  1195. if (Src.m_pAcl == 0)
  1196. return *this;
  1197. // Now copy the source ACL.
  1198. // ========================
  1199. DWORD dwSize = Src.m_pAcl->AclSize;
  1200. m_pAcl = (PACL) new BYTE[dwSize];
  1201. if(m_pAcl == NULL)
  1202. {
  1203. m_dwStatus = InternalError;
  1204. return *this;
  1205. }
  1206. ZeroMemory(m_pAcl, dwSize);
  1207. memcpy(m_pAcl, Src.m_pAcl, dwSize);
  1208. // Verify it.
  1209. // ==========
  1210. if (!IsValidAcl(m_pAcl))
  1211. {
  1212. delete m_pAcl;
  1213. m_pAcl = 0;
  1214. m_dwStatus = InvalidAcl;
  1215. return *this;
  1216. }
  1217. m_dwStatus = Src.m_dwStatus;
  1218. return *this;
  1219. }
  1220. //***************************************************************************
  1221. //
  1222. // CNtAcl::GetAce
  1223. //
  1224. // Returns an ACE at the specified index. To enumerate ACEs, the caller
  1225. // should determine the number of ACEs using GetNumAces() and then call
  1226. // this function with each index starting from 0 to number of ACEs - 1.
  1227. //
  1228. // Parameters:
  1229. // <nIndex> The index of the desired ACE.
  1230. //
  1231. // Return value:
  1232. // A newly allocated CNtAce object which must be deallocated using
  1233. // operator delete. This is only a copy. Modifications to the returned
  1234. // CNtAce do not affect the ACL from which it came.
  1235. //
  1236. // Returns NULL on error.
  1237. //
  1238. //***************************************************************************
  1239. // ok
  1240. CNtAce *CNtAcl::GetAce(int nIndex)
  1241. {
  1242. if (m_pAcl == 0)
  1243. return 0;
  1244. LPVOID pAce = 0;
  1245. BOOL bRes = ::GetAce(m_pAcl, (DWORD) nIndex, &pAce);
  1246. if (!bRes)
  1247. return 0;
  1248. return new CNtAce(PGENERIC_ACE(pAce));
  1249. }
  1250. //***************************************************************************
  1251. //
  1252. // CNtAcl::GetAce
  1253. //
  1254. // Alternate method to get ACEs to avoid dynamic allocation & cleanup,
  1255. // since an auto object can be used as the parameter.
  1256. //
  1257. // Parameters:
  1258. // <Dest> A reference to a CNtAce to receive the ACE value.
  1259. //
  1260. // Return value:
  1261. // TRUE if assigned, FALSE if not.
  1262. //
  1263. //***************************************************************************
  1264. BOOL CNtAcl::GetAce(int nIndex, CNtAce &Dest)
  1265. {
  1266. CNtAce *pNew = GetAce(nIndex);
  1267. if (pNew == 0)
  1268. return FALSE;
  1269. Dest = *pNew;
  1270. delete pNew;
  1271. return TRUE;
  1272. }
  1273. //***************************************************************************
  1274. //
  1275. // CNtAcl::DeleteAce
  1276. //
  1277. // Removes the specified ACE from the ACL.
  1278. //
  1279. // Parameters:
  1280. // <nIndex> The 0-based index of the ACE which should be removed.
  1281. //
  1282. // Return value:
  1283. // TRUE if the ACE was deleted, FALSE if not.
  1284. //
  1285. //***************************************************************************
  1286. // ok
  1287. BOOL CNtAcl::DeleteAce(int nIndex)
  1288. {
  1289. if (m_pAcl == 0)
  1290. return FALSE;
  1291. BOOL bRes = ::DeleteAce(m_pAcl, DWORD(nIndex));
  1292. return bRes;
  1293. }
  1294. //***************************************************************************
  1295. //
  1296. // CNtAcl::GetSize()
  1297. //
  1298. // Return value:
  1299. // Returns the size in bytes of the ACL
  1300. //
  1301. //***************************************************************************
  1302. // ok
  1303. DWORD CNtAcl::GetSize()
  1304. {
  1305. if (m_pAcl == 0 || !IsValidAcl(m_pAcl))
  1306. return 0;
  1307. return DWORD(m_pAcl->AclSize);
  1308. }
  1309. //***************************************************************************
  1310. //
  1311. // CNtAcl::GetAclSizeInfo
  1312. //
  1313. // Gets information about used/unused space in the ACL. This function
  1314. // is primarily for internal use.
  1315. //
  1316. // Parameters:
  1317. // <pdwBytesInUse> Points to a DWORD to receive the number of
  1318. // bytes in use in the ACL. Can be NULL.
  1319. // <pdwBytesFree> Points to a DWORD to receive the number of
  1320. // bytes free in the ACL. Can be NULL.
  1321. //
  1322. // Return value:
  1323. // Returns TRUE if the information was retrieved, FALSE if not.
  1324. //
  1325. //***************************************************************************
  1326. // ok
  1327. BOOL CNtAcl::GetAclSizeInfo(
  1328. PDWORD pdwBytesInUse,
  1329. PDWORD pdwBytesFree
  1330. )
  1331. {
  1332. if (m_pAcl == 0)
  1333. return 0;
  1334. if (!IsValidAcl(m_pAcl))
  1335. return 0;
  1336. if (pdwBytesInUse)
  1337. *pdwBytesInUse = 0;
  1338. if (pdwBytesFree)
  1339. *pdwBytesFree = 0;
  1340. ACL_SIZE_INFORMATION inf;
  1341. BOOL bRes = GetAclInformation(
  1342. m_pAcl,
  1343. &inf,
  1344. sizeof(ACL_SIZE_INFORMATION),
  1345. AclSizeInformation
  1346. );
  1347. if (!bRes)
  1348. return FALSE;
  1349. if (pdwBytesInUse)
  1350. *pdwBytesInUse = inf.AclBytesInUse;
  1351. if (pdwBytesFree)
  1352. *pdwBytesFree = inf.AclBytesFree;
  1353. return bRes;
  1354. }
  1355. //***************************************************************************
  1356. //
  1357. // CNtAcl::AddAce
  1358. //
  1359. // Adds an ACE to the ACL.
  1360. // Ordering semantics for denial ACEs are handled automatically.
  1361. //
  1362. // Parameters:
  1363. // <pAce> A read-only pointer to the CNtAce to be added.
  1364. //
  1365. // Return value:
  1366. // TRUE on success, FALSE on failure.
  1367. //
  1368. //***************************************************************************
  1369. // ok
  1370. BOOL CNtAcl::AddAce(CNtAce *pAce)
  1371. {
  1372. // Verify we have an ACL and a valid ACE.
  1373. // ======================================
  1374. if (m_pAcl == 0 || m_dwStatus != NoError)
  1375. return FALSE;
  1376. if (pAce->GetStatus() != CNtAce::NoError)
  1377. return FALSE;
  1378. // Inherited aces go after non inherited aces
  1379. bool bInherited = (pAce->GetFlags() & INHERITED_ACE) != 0;
  1380. int iFirstInherited = 0;
  1381. // inherited aces must go after non inherited. Find out
  1382. // the position of the first inherited ace
  1383. int iCnt;
  1384. for(iCnt = 0; iCnt < m_pAcl->AceCount; iCnt++)
  1385. {
  1386. CNtAce *pAce2 = GetAce(iCnt);
  1387. CDeleteMe<CNtAce> dm(pAce2);
  1388. if (pAce2)
  1389. if((pAce2->GetFlags() & INHERITED_ACE) != 0)
  1390. break;
  1391. }
  1392. iFirstInherited = iCnt;
  1393. // Since we want to add access denial ACEs to the front of the ACL,
  1394. // we have to determine the type of ACE.
  1395. // ================================================================
  1396. DWORD dwIndex;
  1397. if (pAce->GetType() == ACCESS_DENIED_ACE_TYPE)
  1398. dwIndex = (bInherited) ? iFirstInherited : 0;
  1399. else
  1400. dwIndex = (bInherited) ? MAXULONG : iFirstInherited;
  1401. // Verify that there is enough room in the ACL.
  1402. // ============================================
  1403. DWORD dwRequiredFree = pAce->GetSize();
  1404. DWORD dwFree = 0;
  1405. DWORD dwUsed = 0;
  1406. GetAclSizeInfo(&dwUsed, &dwFree);
  1407. // If we don't have enough room, resize the ACL.
  1408. // =============================================
  1409. if (dwFree < dwRequiredFree)
  1410. {
  1411. BOOL bRes = Resize(dwUsed + dwRequiredFree);
  1412. if (!bRes)
  1413. return FALSE;
  1414. }
  1415. // Now actually add the ACE.
  1416. // =========================
  1417. BOOL bRes = ::AddAce(
  1418. m_pAcl,
  1419. ACL_REVISION,
  1420. dwIndex, // Either beginning or end.
  1421. pAce->GetPtr(), // Get ptr to ACE.
  1422. pAce->GetSize() // One ACE only.
  1423. );
  1424. return bRes;
  1425. }
  1426. //***************************************************************************
  1427. //
  1428. // CNtAcl::Resize()
  1429. //
  1430. // Expands the size of the ACL to hold more info or reduces the size
  1431. // of the ACL for maximum efficiency after ACL editing is completed.
  1432. //
  1433. // Normally, the user should not attempt to resize the ACL to a larger
  1434. // size, as this is automatically handled by AddAce. However, shrinking
  1435. // the ACL to its minimum size is recommended.
  1436. //
  1437. // Parameters:
  1438. // <dwNewSize> The required new size of the ACL in bytes. If set to
  1439. // the class constant MinimumSize (1), then the ACL
  1440. // is reduced to its minimum size.
  1441. //
  1442. // Return value:
  1443. // TRUE on success, FALSE on failure.
  1444. //
  1445. //***************************************************************************
  1446. // ok
  1447. BOOL CNtAcl::Resize(DWORD dwNewSize)
  1448. {
  1449. if (m_pAcl == 0 || m_dwStatus != NoError)
  1450. return FALSE;
  1451. if (!IsValidAcl(m_pAcl))
  1452. return FALSE;
  1453. // If the ACL cannot be reduced to the requested size,
  1454. // return FALSE.
  1455. // ===================================================
  1456. DWORD dwInUse, dwFree;
  1457. if (!GetAclSizeInfo(&dwInUse, &dwFree))
  1458. return FALSE;
  1459. if (dwNewSize == MinimumSize) // If user is requesting a 'minimize'
  1460. dwNewSize = dwInUse;
  1461. if (dwNewSize < dwInUse)
  1462. return FALSE;
  1463. // Allocate a new ACL.
  1464. // ===================
  1465. CNtAcl *pNewAcl = new CNtAcl(dwNewSize);
  1466. if (!pNewAcl || pNewAcl->GetStatus() != NoError)
  1467. {
  1468. delete pNewAcl;
  1469. return FALSE;
  1470. }
  1471. // Loop through ACEs and transfer them.
  1472. // ====================================
  1473. for (int i = 0; i < GetNumAces(); i++)
  1474. {
  1475. CNtAce *pAce = GetAce(i);
  1476. if (pAce == NULL)
  1477. {
  1478. delete pNewAcl;
  1479. return FALSE;
  1480. }
  1481. BOOL bRes = pNewAcl->AddAce(pAce);
  1482. if (!bRes)
  1483. {
  1484. DWORD dwLast = GetLastError();
  1485. delete pAce;
  1486. delete pNewAcl;
  1487. return FALSE;
  1488. }
  1489. delete pAce;
  1490. }
  1491. if (!IsValid())
  1492. {
  1493. delete pNewAcl;
  1494. return FALSE;
  1495. }
  1496. // Now transfer the ACL.
  1497. // =====================
  1498. *this = *pNewAcl;
  1499. delete pNewAcl;
  1500. return TRUE;
  1501. }
  1502. //***************************************************************************
  1503. //
  1504. // CNtAcl::CNtAcl
  1505. //
  1506. // Alternate constructor which builds the object based on a plain
  1507. // NT ACL.
  1508. //
  1509. // Parameters:
  1510. // <pAcl> Pointer to a read-only ACL.
  1511. //
  1512. //***************************************************************************
  1513. // ok
  1514. CNtAcl::CNtAcl(PACL pAcl)
  1515. {
  1516. m_pAcl = 0;
  1517. m_dwStatus = NoError;
  1518. if (pAcl == 0)
  1519. {
  1520. m_dwStatus = NullAcl;
  1521. return;
  1522. }
  1523. if (!IsValidAcl(pAcl))
  1524. {
  1525. m_dwStatus = InvalidAcl;
  1526. return;
  1527. }
  1528. m_pAcl = (PACL) new BYTE[pAcl->AclSize];
  1529. if(m_pAcl == NULL)
  1530. {
  1531. m_dwStatus = InternalError;
  1532. return;
  1533. }
  1534. ZeroMemory(m_pAcl, pAcl->AclSize);
  1535. memcpy(m_pAcl, pAcl, pAcl->AclSize);
  1536. }
  1537. /*
  1538. --------------------------------------------------------------------------
  1539. |
  1540. | Checks to see if the Acl contains an ACE with the specified SID.
  1541. | The characteristics of the ACE is irrelevant. Only SID comparison applies.
  1542. |
  1543. --------------------------------------------------------------------------
  1544. */
  1545. BOOL CNtAcl::ContainsSid ( CNtSid& sid, BYTE& flags )
  1546. {
  1547. BOOL bContainsSid = FALSE ;
  1548. int iNumAces = GetNumAces ( ) ;
  1549. if ( iNumAces < 0 )
  1550. {
  1551. return FALSE ;
  1552. }
  1553. for ( int i = 0 ; i < iNumAces; i++ )
  1554. {
  1555. CNtAce* pAce = GetAce ( i ) ;
  1556. CNtSid* pSid = pAce->GetSid ( ) ;
  1557. CDeleteMe<CNtAce> AceDelete ( pAce ) ;
  1558. CDeleteMe<CNtSid> SidDelete ( pSid ) ;
  1559. if ( pAce && pSid )
  1560. {
  1561. if ( EqualSid ( sid.GetPtr ( ), pSid->GetPtr ( ) ) == TRUE )
  1562. {
  1563. flags = ( BYTE ) pAce->GetFlags ( ) ;
  1564. bContainsSid = TRUE ;
  1565. break ;
  1566. }
  1567. }
  1568. }
  1569. return bContainsSid ;
  1570. }
  1571. //***************************************************************************
  1572. //
  1573. // CNtAcl::GetNumAces
  1574. //
  1575. // Return value:
  1576. // Returns the number of ACEs available in the ACL. Zero is a legal return
  1577. // value. Returns -1 on error
  1578. //
  1579. // Aces can be retrieved using GetAce using index values from 0...n-1 where
  1580. // n is the value returned from this function.
  1581. //
  1582. //***************************************************************************
  1583. // ok
  1584. int CNtAcl::GetNumAces()
  1585. {
  1586. if (m_pAcl == 0)
  1587. return -1;
  1588. ACL_SIZE_INFORMATION inf;
  1589. BOOL bRes = GetAclInformation(
  1590. m_pAcl,
  1591. &inf,
  1592. sizeof(ACL_SIZE_INFORMATION),
  1593. AclSizeInformation
  1594. );
  1595. if (!bRes)
  1596. {
  1597. return -1;
  1598. }
  1599. return (int) inf.AceCount;
  1600. }
  1601. //***************************************************************************
  1602. //
  1603. // CNtAcl destructor
  1604. //
  1605. //***************************************************************************
  1606. // ok
  1607. CNtAcl::~CNtAcl()
  1608. {
  1609. if (m_pAcl)
  1610. delete m_pAcl;
  1611. }
  1612. //***************************************************************************
  1613. //
  1614. // CNtAcl::Dump
  1615. //
  1616. // Dumps the ACL to the console for debugging purposes. Illustrates
  1617. // how to traverse the ACL and extract the ACEs.
  1618. //
  1619. //***************************************************************************
  1620. // ok
  1621. void CNtAcl::Dump()
  1622. {
  1623. printf("---ACL DUMP---\n");
  1624. if (m_pAcl == 0)
  1625. {
  1626. switch (m_dwStatus)
  1627. {
  1628. case NullAcl:
  1629. printf("NullAcl\n");
  1630. break;
  1631. case InvalidAcl:
  1632. printf("InvalidAcl\n");
  1633. break;
  1634. default:
  1635. printf("<internal error; unknown status>\n");
  1636. }
  1637. return;
  1638. }
  1639. DWORD InUse, Free;
  1640. GetAclSizeInfo(&InUse, &Free);
  1641. printf("%d bytes in use, %d bytes free\n",
  1642. InUse, Free
  1643. );
  1644. printf("Number of ACEs = %d\n", GetNumAces());
  1645. for (int i = 0; i < GetNumAces(); i++)
  1646. {
  1647. CNtAce *pAce = GetAce(i);
  1648. if (pAce)
  1649. {
  1650. pAce->Dump(i+1);
  1651. delete pAce;
  1652. }
  1653. }
  1654. printf("---END ACL DUMP---\n");
  1655. }
  1656. //***************************************************************************
  1657. //
  1658. // CNtSecurityDescriptor::GetDacl
  1659. //
  1660. // Returns the DACL of the security descriptor.
  1661. //
  1662. // Return value:
  1663. // A newly allocated CNtAcl which contains the DACL. This object
  1664. // is a copy of the DACL and modifications made to it do not affect
  1665. // the security descriptor. The caller must use operator delete
  1666. // to deallocate the CNtAcl.
  1667. //
  1668. // Returns NULL on error or if no DACL is available.
  1669. //
  1670. //***************************************************************************
  1671. // ok
  1672. CNtAcl *CNtSecurityDescriptor::GetDacl()
  1673. {
  1674. BOOL bDaclPresent = FALSE;
  1675. BOOL bDefaulted;
  1676. PACL pDacl;
  1677. BOOL bRes = GetSecurityDescriptorDacl(
  1678. m_pSD,
  1679. &bDaclPresent,
  1680. &pDacl,
  1681. &bDefaulted
  1682. );
  1683. if (!bRes)
  1684. {
  1685. return 0;
  1686. }
  1687. if (!bDaclPresent) // No DACL present
  1688. return 0;
  1689. CNtAcl *pNewDacl = new CNtAcl(pDacl);
  1690. return pNewDacl;
  1691. }
  1692. //***************************************************************************
  1693. //
  1694. // CNtSecurityDescriptor::GetDacl
  1695. //
  1696. // An alternate method to returns the DACL of the security descriptor.
  1697. // This version uses an existing object instead of returning a
  1698. // dynamically allocated object.
  1699. //
  1700. // Parameters:
  1701. // <DestAcl> A object which will receive the DACL.
  1702. //
  1703. // Return value:
  1704. // TRUE on success, FALSE on failure
  1705. //
  1706. //***************************************************************************
  1707. BOOL CNtSecurityDescriptor::GetDacl(CNtAcl &DestAcl)
  1708. {
  1709. CNtAcl *pNew = GetDacl();
  1710. if (pNew == 0)
  1711. return FALSE;
  1712. DestAcl = *pNew;
  1713. delete pNew;
  1714. return TRUE;
  1715. }
  1716. //***************************************************************************
  1717. //
  1718. // SNtAbsoluteSD
  1719. //
  1720. // SD Helpers
  1721. //
  1722. //***************************************************************************
  1723. SNtAbsoluteSD::SNtAbsoluteSD()
  1724. {
  1725. m_pSD = 0;
  1726. m_pDacl = 0;
  1727. m_pSacl = 0;
  1728. m_pOwner = 0;
  1729. m_pPrimaryGroup = 0;
  1730. }
  1731. SNtAbsoluteSD::~SNtAbsoluteSD()
  1732. {
  1733. if (m_pSD)
  1734. delete m_pSD;
  1735. if (m_pDacl)
  1736. delete m_pDacl;
  1737. if (m_pSacl)
  1738. delete m_pSacl;
  1739. if (m_pOwner)
  1740. delete m_pOwner;
  1741. if (m_pPrimaryGroup)
  1742. delete m_pPrimaryGroup;
  1743. }
  1744. //***************************************************************************
  1745. //
  1746. // CNtSecurityDescriptor::GetAbsoluteCopy
  1747. //
  1748. // Returns a copy of the current object's internal SD in absolute format.
  1749. // Returns NULL on error. The memory must be freed with LocalFree().
  1750. //
  1751. //***************************************************************************
  1752. // ok
  1753. SNtAbsoluteSD* CNtSecurityDescriptor::GetAbsoluteCopy()
  1754. {
  1755. if (m_dwStatus != NoError || m_pSD == 0 || !IsValid())
  1756. return 0;
  1757. // Prepare for conversion.
  1758. // =======================
  1759. DWORD dwSDSize = 0, dwDaclSize = 0, dwSaclSize = 0,
  1760. dwOwnerSize = 0, dwPrimaryGroupSize = 0;
  1761. SNtAbsoluteSD *pNewSD = new SNtAbsoluteSD;
  1762. if (!pNewSD)
  1763. return NULL;
  1764. BOOL bRes = MakeAbsoluteSD(
  1765. m_pSD,
  1766. pNewSD->m_pSD,
  1767. &dwSDSize,
  1768. pNewSD->m_pDacl,
  1769. &dwDaclSize,
  1770. pNewSD->m_pSacl,
  1771. &dwSaclSize,
  1772. pNewSD->m_pOwner,
  1773. &dwOwnerSize,
  1774. pNewSD->m_pPrimaryGroup,
  1775. &dwPrimaryGroupSize
  1776. );
  1777. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  1778. {
  1779. delete pNewSD;
  1780. return 0;
  1781. }
  1782. // Allocate the required buffers and convert.
  1783. // ==========================================
  1784. pNewSD->m_pSD = (PSECURITY_DESCRIPTOR) new BYTE[dwSDSize];
  1785. if(pNewSD->m_pSD == NULL)
  1786. {
  1787. delete pNewSD;
  1788. return NULL;
  1789. }
  1790. ZeroMemory(pNewSD->m_pSD, dwSDSize);
  1791. pNewSD->m_pDacl = (PACL) new BYTE[dwDaclSize];
  1792. if(pNewSD->m_pDacl == NULL)
  1793. {
  1794. delete pNewSD;
  1795. return NULL;
  1796. }
  1797. ZeroMemory(pNewSD->m_pDacl, dwDaclSize);
  1798. pNewSD->m_pSacl = (PACL) new BYTE[dwSaclSize];
  1799. if(pNewSD->m_pSacl == NULL)
  1800. {
  1801. delete pNewSD;
  1802. return NULL;
  1803. }
  1804. ZeroMemory(pNewSD->m_pSacl, dwSaclSize);
  1805. pNewSD->m_pOwner = (PSID) new BYTE[dwOwnerSize];
  1806. if(pNewSD->m_pOwner == NULL)
  1807. {
  1808. delete pNewSD;
  1809. return NULL;
  1810. }
  1811. ZeroMemory(pNewSD->m_pOwner, dwOwnerSize);
  1812. pNewSD->m_pPrimaryGroup = (PSID) new BYTE[dwPrimaryGroupSize];
  1813. if(pNewSD->m_pPrimaryGroup == NULL)
  1814. {
  1815. delete pNewSD;
  1816. return NULL;
  1817. }
  1818. ZeroMemory(pNewSD->m_pPrimaryGroup, dwPrimaryGroupSize);
  1819. bRes = MakeAbsoluteSD(
  1820. m_pSD,
  1821. pNewSD->m_pSD,
  1822. &dwSDSize,
  1823. pNewSD->m_pDacl,
  1824. &dwDaclSize,
  1825. pNewSD->m_pSacl,
  1826. &dwSaclSize,
  1827. pNewSD->m_pOwner,
  1828. &dwOwnerSize,
  1829. pNewSD->m_pPrimaryGroup,
  1830. &dwPrimaryGroupSize
  1831. );
  1832. if (!bRes)
  1833. {
  1834. delete pNewSD;
  1835. return 0;
  1836. }
  1837. return pNewSD;
  1838. }
  1839. //***************************************************************************
  1840. //
  1841. // CNtSecurityDescriptor::SetFromAbsoluteCopy
  1842. //
  1843. // Replaces the current SD from an absolute copy.
  1844. //
  1845. // Parameters:
  1846. // <pSrcSD> A read-only pointer to the absolute SD used as a source.
  1847. //
  1848. // Return value:
  1849. // TRUE on success, FALSE on failure.
  1850. //
  1851. //***************************************************************************
  1852. // ok
  1853. BOOL CNtSecurityDescriptor::SetFromAbsoluteCopy(
  1854. SNtAbsoluteSD *pSrcSD
  1855. )
  1856. {
  1857. if (pSrcSD == 0 || !IsValidSecurityDescriptor(pSrcSD->m_pSD))
  1858. return FALSE;
  1859. // Ensure that SD is self-relative
  1860. // ===============================
  1861. SECURITY_DESCRIPTOR_CONTROL ctrl;
  1862. DWORD dwRev;
  1863. BOOL bRes = GetSecurityDescriptorControl(
  1864. pSrcSD->m_pSD,
  1865. &ctrl,
  1866. &dwRev
  1867. );
  1868. if (!bRes)
  1869. return FALSE;
  1870. if (ctrl & SE_SELF_RELATIVE) // Source is not absolute!!
  1871. return FALSE;
  1872. // If here, we are committed to change.
  1873. // ====================================
  1874. if (m_pSD)
  1875. {
  1876. delete m_pSD;
  1877. }
  1878. m_pSD = 0;
  1879. m_dwStatus = NullSD;
  1880. DWORD dwRequired = 0;
  1881. bRes = MakeSelfRelativeSD(
  1882. pSrcSD->m_pSD,
  1883. m_pSD,
  1884. &dwRequired
  1885. );
  1886. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  1887. {
  1888. m_dwStatus = InvalidSD;
  1889. return FALSE;
  1890. }
  1891. m_pSD = new BYTE[dwRequired];
  1892. if (!m_pSD)
  1893. {
  1894. m_dwStatus = InvalidSD;
  1895. return FALSE;
  1896. }
  1897. ZeroMemory(m_pSD, dwRequired);
  1898. bRes = MakeSelfRelativeSD(
  1899. pSrcSD->m_pSD,
  1900. m_pSD,
  1901. &dwRequired
  1902. );
  1903. if (!bRes)
  1904. {
  1905. m_dwStatus = InvalidSD;
  1906. delete m_pSD;
  1907. m_pSD = 0;
  1908. return FALSE;
  1909. }
  1910. m_dwStatus = NoError;
  1911. return TRUE;
  1912. }
  1913. //***************************************************************************
  1914. //
  1915. // CNtSecurityDescriptor::SetDacl
  1916. //
  1917. // Sets the DACL of the Security descriptor.
  1918. //
  1919. // Parameters:
  1920. // <pSrc> A read-only pointer to the new DACL to replace the current one.
  1921. //
  1922. // Return value:
  1923. // TRUE on success, FALSE on failure.
  1924. //
  1925. //***************************************************************************
  1926. BOOL CNtSecurityDescriptor::SetDacl(CNtAcl *pSrc)
  1927. {
  1928. if (m_dwStatus != NoError || m_pSD == 0)
  1929. return FALSE;
  1930. // Since we cannot alter a self-relative SD, we have to make
  1931. // an absolute one, alter it, and then set the current
  1932. // SD based on the absolute one (we keep the self-relative form
  1933. // internally in the m_pSD variable.
  1934. // ============================================================
  1935. SNtAbsoluteSD *pTmp = GetAbsoluteCopy();
  1936. if (pTmp == 0)
  1937. return FALSE;
  1938. BOOL bRes = ::SetSecurityDescriptorDacl(
  1939. pTmp->m_pSD,
  1940. TRUE,
  1941. pSrc->GetPtr(),
  1942. FALSE
  1943. );
  1944. if (!bRes)
  1945. {
  1946. delete pTmp;
  1947. return FALSE;
  1948. }
  1949. bRes = SetFromAbsoluteCopy(pTmp);
  1950. delete pTmp;
  1951. return TRUE;
  1952. }
  1953. //***************************************************************************
  1954. //
  1955. // CNtSecurityDescriptor::Dump
  1956. //
  1957. // Dumps the contents of the security descriptor to the console
  1958. // for debugging purposes.
  1959. //
  1960. //***************************************************************************
  1961. // ?
  1962. void CNtSecurityDescriptor::Dump()
  1963. {
  1964. SECURITY_DESCRIPTOR_CONTROL Control;
  1965. DWORD dwRev;
  1966. BOOL bRes;
  1967. printf("--- SECURITY DESCRIPTOR DUMP ---\n");
  1968. bRes = GetSecurityDescriptorControl(m_pSD, &Control, &dwRev);
  1969. if (!bRes)
  1970. {
  1971. printf("SD Dump: Failed to get control info\n");
  1972. return;
  1973. }
  1974. printf("Revision : 0x%X\n", dwRev);
  1975. printf("Control Info :\n");
  1976. if (Control & SE_SELF_RELATIVE)
  1977. printf(" SE_SELF_RELATIVE\n");
  1978. if (Control & SE_OWNER_DEFAULTED)
  1979. printf(" SE_OWNER_DEFAULTED\n");
  1980. if (Control & SE_GROUP_DEFAULTED)
  1981. printf(" SE_GROUP_DEFAULTED\n");
  1982. if (Control & SE_DACL_PRESENT)
  1983. printf(" SE_DACL_PRESENT\n");
  1984. if (Control & SE_DACL_DEFAULTED)
  1985. printf(" SE_DACL_DEFAULTED\n");
  1986. if (Control & SE_SACL_PRESENT)
  1987. printf(" SE_SACL_PRESENT\n");
  1988. if (Control & SE_SACL_DEFAULTED)
  1989. printf(" SE_SACL_DEFAULTED\n");
  1990. if (Control & SE_DACL_PROTECTED)
  1991. printf(" SE_DACL_PROTECTED\n");
  1992. // Get owner.
  1993. // =========
  1994. CNtSid *pSid = GetOwner();
  1995. if (pSid)
  1996. {
  1997. printf("Owner : ");
  1998. pSid->Dump();
  1999. delete pSid;
  2000. }
  2001. CNtAcl *pDacl = GetDacl();
  2002. if (pDacl == 0)
  2003. {
  2004. printf("Unable to locate DACL\n");
  2005. return;
  2006. }
  2007. printf("DACL retrieved\n");
  2008. pDacl->Dump();
  2009. delete pDacl;
  2010. }
  2011. //***************************************************************************
  2012. //
  2013. // CNtSecurityDescriptor constructor
  2014. //
  2015. // A default constructor creates a no-access security descriptor.
  2016. //
  2017. //***************************************************************************
  2018. // ok
  2019. CNtSecurityDescriptor::CNtSecurityDescriptor()
  2020. {
  2021. m_pSD = 0;
  2022. m_dwStatus = NoError;
  2023. PSECURITY_DESCRIPTOR pTmp = new BYTE[SECURITY_DESCRIPTOR_MIN_LENGTH];
  2024. if (!pTmp)
  2025. {
  2026. delete pTmp;
  2027. m_dwStatus = InvalidSD;
  2028. return;
  2029. }
  2030. ZeroMemory(pTmp, SECURITY_DESCRIPTOR_MIN_LENGTH);
  2031. if (!InitializeSecurityDescriptor(pTmp, SECURITY_DESCRIPTOR_REVISION))
  2032. {
  2033. delete pTmp;
  2034. m_dwStatus = InvalidSD;
  2035. return;
  2036. }
  2037. DWORD dwRequired = 0;
  2038. BOOL bRes = MakeSelfRelativeSD(
  2039. pTmp,
  2040. m_pSD,
  2041. &dwRequired
  2042. );
  2043. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  2044. {
  2045. m_dwStatus = InvalidSD;
  2046. delete pTmp;
  2047. return;
  2048. }
  2049. m_pSD = new BYTE[dwRequired];
  2050. if (!m_pSD)
  2051. {
  2052. m_dwStatus = InvalidSD;
  2053. delete pTmp;
  2054. return;
  2055. }
  2056. ZeroMemory(m_pSD, dwRequired);
  2057. bRes = MakeSelfRelativeSD(
  2058. pTmp,
  2059. m_pSD,
  2060. &dwRequired
  2061. );
  2062. if (!bRes)
  2063. {
  2064. m_dwStatus = InvalidSD;
  2065. delete m_pSD;
  2066. m_pSD = 0;
  2067. delete pTmp;
  2068. return;
  2069. }
  2070. delete pTmp;
  2071. m_dwStatus = NoError;
  2072. }
  2073. //***************************************************************************
  2074. //
  2075. // CNtSecurityDescriptor::GetSize
  2076. //
  2077. // Returns the size in bytes of the internal SD.
  2078. //
  2079. //***************************************************************************
  2080. // ok
  2081. DWORD CNtSecurityDescriptor::GetSize()
  2082. {
  2083. if (m_pSD == 0 || m_dwStatus != NoError)
  2084. return 0;
  2085. return GetSecurityDescriptorLength(m_pSD);
  2086. }
  2087. //***************************************************************************
  2088. //
  2089. // CNtSecurityDescriptor copy constructor
  2090. //
  2091. //***************************************************************************
  2092. // ok
  2093. CNtSecurityDescriptor::CNtSecurityDescriptor(CNtSecurityDescriptor &Src)
  2094. {
  2095. m_pSD = 0;
  2096. m_dwStatus = NoError;
  2097. *this = Src;
  2098. }
  2099. //***************************************************************************
  2100. //
  2101. // CNtSecurityDescriptor assignment operator
  2102. //
  2103. //***************************************************************************
  2104. // ok
  2105. CNtSecurityDescriptor & CNtSecurityDescriptor::operator=(
  2106. CNtSecurityDescriptor &Src
  2107. )
  2108. {
  2109. if (m_pSD)
  2110. delete m_pSD;
  2111. m_dwStatus = Src.m_dwStatus;
  2112. m_pSD = 0;
  2113. if (Src.m_pSD == 0)
  2114. return *this;
  2115. //SIZE_T dwSize = 2*GetSecurityDescriptorLength(Src.m_pSD);
  2116. SIZE_T dwSize = GetSecurityDescriptorLength(Src.m_pSD);
  2117. m_pSD = (PSECURITY_DESCRIPTOR) new BYTE[dwSize];
  2118. if(m_pSD == NULL)
  2119. {
  2120. m_dwStatus = Failed;
  2121. }
  2122. else
  2123. {
  2124. ZeroMemory(m_pSD, dwSize);
  2125. CopyMemory(m_pSD, Src.m_pSD, dwSize);
  2126. }
  2127. return *this;
  2128. }
  2129. //***************************************************************************
  2130. //
  2131. // CNtSecurityDescriptor destructor.
  2132. //
  2133. //***************************************************************************
  2134. // ok
  2135. CNtSecurityDescriptor::~CNtSecurityDescriptor()
  2136. {
  2137. if (m_pSD)
  2138. delete m_pSD;
  2139. }
  2140. //***************************************************************************
  2141. //
  2142. // CNtSecurityDescriptor::GetSacl
  2143. //
  2144. // Returns the SACL of the security descriptor.
  2145. //
  2146. // Return value:
  2147. // A newly allocated CNtAcl which contains the SACL. This object
  2148. // is a copy of the SACL and modifications made to it do not affect
  2149. // the security descriptor. The caller must use operator delete
  2150. // to deallocate the CNtAcl.
  2151. //
  2152. // Returns NULL on error or if no SACL is available.
  2153. //
  2154. //***************************************************************************
  2155. // ok
  2156. CNtAcl *CNtSecurityDescriptor::GetSacl()
  2157. {
  2158. BOOL bSaclPresent = FALSE;
  2159. BOOL bDefaulted;
  2160. PACL pSacl;
  2161. BOOL bRes = GetSecurityDescriptorSacl(
  2162. m_pSD,
  2163. &bSaclPresent,
  2164. &pSacl,
  2165. &bDefaulted
  2166. );
  2167. if (!bRes)
  2168. {
  2169. return 0;
  2170. }
  2171. if (!bSaclPresent) // No Sacl present
  2172. return 0;
  2173. CNtAcl *pNewSacl = new CNtAcl(pSacl);
  2174. return pNewSacl;
  2175. }
  2176. //***************************************************************************
  2177. //
  2178. // CNtSecurityDescriptor::SetSacl
  2179. //
  2180. // Sets the SACL of the Security descriptor.
  2181. //
  2182. // Parameters:
  2183. // <pSrc> A read-only pointer to the new DACL to replace the current one.
  2184. //
  2185. // Return value:
  2186. // TRUE on success, FALSE on failure.
  2187. //
  2188. //***************************************************************************
  2189. // ok
  2190. BOOL CNtSecurityDescriptor::SetSacl(CNtAcl *pSrc)
  2191. {
  2192. if (m_dwStatus != NoError || m_pSD == 0)
  2193. return FALSE;
  2194. // Since we cannot alter a self-relative SD, we have to make
  2195. // an absolute one, alter it, and then set the current
  2196. // SD based on the absolute one (we keep the self-relative form
  2197. // internally in the m_pSD variable.
  2198. // ============================================================
  2199. SNtAbsoluteSD *pTmp = GetAbsoluteCopy();
  2200. if (pTmp == 0)
  2201. return FALSE;
  2202. BOOL bRes = ::SetSecurityDescriptorSacl(
  2203. pTmp->m_pSD,
  2204. TRUE,
  2205. pSrc->GetPtr(),
  2206. FALSE
  2207. );
  2208. if (!bRes)
  2209. {
  2210. delete pTmp;
  2211. return FALSE;
  2212. }
  2213. bRes = SetFromAbsoluteCopy(pTmp);
  2214. delete pTmp;
  2215. return TRUE;
  2216. }
  2217. //***************************************************************************
  2218. //
  2219. // CNtSecurityDescriptor::GetGroup
  2220. //
  2221. //***************************************************************************
  2222. // ok
  2223. CNtSid *CNtSecurityDescriptor::GetGroup()
  2224. {
  2225. if (m_pSD == 0 || m_dwStatus != NoError)
  2226. return 0;
  2227. PSID pSid = 0;
  2228. BOOL bDefaulted;
  2229. BOOL bRes = GetSecurityDescriptorGroup(m_pSD, &pSid, &bDefaulted);
  2230. // TMP: Check to make sure the group is not NULL!!!!
  2231. if ( pSid == NULL )
  2232. {
  2233. // DebugBreak();
  2234. ERRORTRACE((LOG_WBEMCORE, "ERROR: Security descriptor has no group\n"));
  2235. }
  2236. if (!bRes || !IsValidSid(pSid))
  2237. return 0;
  2238. return new CNtSid(pSid);
  2239. }
  2240. //***************************************************************************
  2241. //
  2242. // CNtSecurityDescriptor::SetGroup
  2243. //
  2244. //***************************************************************************
  2245. // ok
  2246. BOOL CNtSecurityDescriptor::SetGroup(CNtSid *pSid)
  2247. {
  2248. if (m_dwStatus != NoError || m_pSD == 0)
  2249. return FALSE;
  2250. // TMP: Check to make sure the group is not NULL!!!!
  2251. if ( pSid->GetPtr() == NULL )
  2252. {
  2253. // DebugBreak();
  2254. ERRORTRACE((LOG_WBEMCORE, "ERROR: Security descriptor is trying to bland out the group!\n"));
  2255. }
  2256. // Since we cannot alter a self-relative SD, we have to make
  2257. // an absolute one, alter it, and then set the current
  2258. // SD based on the absolute one (we keep the self-relative form
  2259. // internally in the m_pSD variable.
  2260. // ============================================================
  2261. SNtAbsoluteSD *pTmp = GetAbsoluteCopy();
  2262. if (pTmp == 0)
  2263. return FALSE;
  2264. BOOL bRes = ::SetSecurityDescriptorGroup(
  2265. pTmp->m_pSD,
  2266. pSid->GetPtr(),
  2267. FALSE
  2268. );
  2269. if (!bRes)
  2270. {
  2271. delete pTmp;
  2272. return FALSE;
  2273. }
  2274. bRes = SetFromAbsoluteCopy(pTmp);
  2275. delete pTmp;
  2276. return TRUE;
  2277. }
  2278. //***************************************************************************
  2279. //
  2280. // CNtSecurityDescriptor::HasOwner
  2281. //
  2282. // Determines if a security descriptor has an owner.
  2283. //
  2284. // Return values:
  2285. // SDNotOwned, SDOwned, Failed
  2286. //
  2287. //***************************************************************************
  2288. // ok
  2289. int CNtSecurityDescriptor::HasOwner()
  2290. {
  2291. if (m_pSD == 0 || m_dwStatus != NoError)
  2292. return Failed;
  2293. PSID pSid = 0;
  2294. BOOL bRes = GetSecurityDescriptorOwner(m_pSD, &pSid, 0);
  2295. if (!bRes || !IsValidSid(pSid))
  2296. return Failed;
  2297. if (pSid == 0)
  2298. return SDNotOwned;
  2299. return SDOwned;
  2300. }
  2301. //***************************************************************************
  2302. //
  2303. // CNtSecurityDescriptor::GetOwner
  2304. //
  2305. // Returns the SID of the owner of the Security Descriptor or NULL
  2306. // if an error occurred or there is no owner. Use HasOwner() to
  2307. // determine this.
  2308. //
  2309. //***************************************************************************
  2310. // ok
  2311. CNtSid *CNtSecurityDescriptor::GetOwner()
  2312. {
  2313. if (m_pSD == 0 || m_dwStatus != NoError)
  2314. return 0;
  2315. PSID pSid = 0;
  2316. BOOL bDefaulted;
  2317. BOOL bRes = GetSecurityDescriptorOwner(m_pSD, &pSid, &bDefaulted);
  2318. // TMP: Check to make sure the owner is not NULL!!!!
  2319. if ( pSid == NULL )
  2320. {
  2321. // DebugBreak();
  2322. ERRORTRACE((LOG_WBEMCORE, "ERROR: Security descriptor has no owner\n"));
  2323. }
  2324. if (!bRes || !IsValidSid(pSid))
  2325. return 0;
  2326. return new CNtSid(pSid);
  2327. }
  2328. //***************************************************************************
  2329. //
  2330. // CNtSecurityDescriptor::SetOwner
  2331. //
  2332. // Sets the owner of a security descriptor.
  2333. //
  2334. // Parameters:
  2335. // <pSid> The SID of the new owner.
  2336. //
  2337. // Return Value:
  2338. // TRUE if owner was changed, FALSE if not.
  2339. //
  2340. //***************************************************************************
  2341. // ok
  2342. BOOL CNtSecurityDescriptor::SetOwner(CNtSid *pSid)
  2343. {
  2344. if (m_pSD == 0 || m_dwStatus != NoError)
  2345. return FALSE;
  2346. if (!pSid->IsValid())
  2347. return FALSE;
  2348. // TMP: Check to make sure the owner is not NULL!!!!
  2349. if ( pSid->GetPtr() == NULL )
  2350. {
  2351. ERRORTRACE((LOG_WBEMCORE, "ERROR: Security descriptor is trying to zap the owner!\n"));
  2352. // DebugBreak();
  2353. }
  2354. // We must convert to absolute format to make the change.
  2355. // =======================================================
  2356. SNtAbsoluteSD *pTmp = GetAbsoluteCopy();
  2357. if (pTmp == 0)
  2358. return FALSE;
  2359. BOOL bRes = SetSecurityDescriptorOwner(pTmp->m_pSD, pSid->GetPtr(), FALSE);
  2360. if (!bRes)
  2361. {
  2362. delete pTmp;
  2363. return FALSE;
  2364. }
  2365. // If here, we have managed the change, so we have to
  2366. // convert *this back from the temporary absolute SD.
  2367. // ===================================================
  2368. bRes = SetFromAbsoluteCopy(pTmp);
  2369. delete pTmp;
  2370. return bRes;
  2371. }
  2372. //***************************************************************************
  2373. //
  2374. // CNtSecurityDescriptor::CNtSecurityDescriptor
  2375. //
  2376. //***************************************************************************
  2377. // ok
  2378. CNtSecurityDescriptor::CNtSecurityDescriptor(
  2379. PSECURITY_DESCRIPTOR pSD,
  2380. BOOL bAcquire
  2381. )
  2382. {
  2383. m_pSD = 0;
  2384. m_dwStatus = NullSD;
  2385. // Ensure that SD is not NULL.
  2386. // ===========================
  2387. if (pSD == 0)
  2388. {
  2389. if (bAcquire)
  2390. delete pSD;
  2391. return;
  2392. }
  2393. if (!IsValidSecurityDescriptor(pSD))
  2394. {
  2395. m_dwStatus = InvalidSD;
  2396. if (bAcquire)
  2397. delete pSD;
  2398. return;
  2399. }
  2400. // Ensure that SD is self-relative
  2401. // ===============================
  2402. SECURITY_DESCRIPTOR_CONTROL ctrl;
  2403. DWORD dwRev;
  2404. BOOL bRes = GetSecurityDescriptorControl(
  2405. pSD,
  2406. &ctrl,
  2407. &dwRev
  2408. );
  2409. if (!bRes)
  2410. {
  2411. m_dwStatus = InvalidSD;
  2412. if (bAcquire)
  2413. delete pSD;
  2414. return;
  2415. }
  2416. if ((ctrl & SE_SELF_RELATIVE) == 0)
  2417. {
  2418. // If here, we have to conver the SD to self-relative form.
  2419. // ========================================================
  2420. DWORD dwRequired = 0;
  2421. bRes = MakeSelfRelativeSD(
  2422. pSD,
  2423. m_pSD,
  2424. &dwRequired
  2425. );
  2426. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  2427. {
  2428. m_dwStatus = InvalidSD;
  2429. if (bAcquire)
  2430. delete pSD;
  2431. return;
  2432. }
  2433. m_pSD = new BYTE[dwRequired];
  2434. if (!m_pSD)
  2435. {
  2436. m_dwStatus = InvalidSD;
  2437. if (bAcquire)
  2438. delete pSD;
  2439. return;
  2440. }
  2441. ZeroMemory(m_pSD, dwRequired);
  2442. bRes = MakeSelfRelativeSD(
  2443. pSD,
  2444. m_pSD,
  2445. &dwRequired
  2446. );
  2447. if (!bRes)
  2448. {
  2449. m_dwStatus = InvalidSD;
  2450. if (bAcquire)
  2451. delete pSD;
  2452. return;
  2453. }
  2454. m_dwStatus = NoError;
  2455. return;
  2456. }
  2457. // If here, the SD was already self-relative.
  2458. // ==========================================
  2459. if (bAcquire)
  2460. m_pSD = pSD;
  2461. else
  2462. {
  2463. DWORD dwRes = GetSecurityDescriptorLength(pSD);
  2464. m_pSD = new BYTE[dwRes];
  2465. if (!m_pSD)
  2466. {
  2467. m_dwStatus = InvalidSD;
  2468. return;
  2469. }
  2470. ZeroMemory(m_pSD, dwRes);
  2471. memcpy(m_pSD, pSD, dwRes);
  2472. }
  2473. m_dwStatus = NoError;
  2474. }
  2475. //***************************************************************************
  2476. //
  2477. // CNtSecurity::DumpPrivileges
  2478. //
  2479. // Dumps current process token privileges to the console.
  2480. //
  2481. //***************************************************************************
  2482. BOOL CNtSecurity::DumpPrivileges()
  2483. {
  2484. HANDLE hToken = 0;
  2485. TOKEN_INFORMATION_CLASS tki;
  2486. BOOL bRes;
  2487. LPVOID pTokenInfo = 0;
  2488. DWORD dwRequiredBytes;
  2489. BOOL bRetVal = FALSE;
  2490. TOKEN_PRIVILEGES *pPriv = 0;
  2491. TCHAR *pName = 0;
  2492. DWORD dwIndex;
  2493. DWORD dwLastError;
  2494. _tprintf(__TEXT("--- Current Token Privilege Dump ---\n"));
  2495. // Starting point: open the process token.
  2496. // =======================================
  2497. bRes = OpenProcessToken(
  2498. GetCurrentProcess(),
  2499. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  2500. &hToken
  2501. );
  2502. if (!bRes)
  2503. {
  2504. _tprintf(__TEXT("Unable to open process token\n"));
  2505. goto Exit;
  2506. }
  2507. // Query for privileges.
  2508. // =====================
  2509. tki = TokenPrivileges;
  2510. bRes = GetTokenInformation(
  2511. hToken,
  2512. tki,
  2513. pTokenInfo,
  2514. 0,
  2515. &dwRequiredBytes
  2516. );
  2517. dwLastError = GetLastError();
  2518. if (dwLastError != ERROR_INSUFFICIENT_BUFFER)
  2519. {
  2520. printf("Unable to get buffer size for token information\n");
  2521. goto Exit;
  2522. }
  2523. pTokenInfo = new BYTE[dwRequiredBytes];
  2524. if (!pTokenInfo)
  2525. goto Exit;
  2526. ZeroMemory(pTokenInfo, dwRequiredBytes);
  2527. bRes = GetTokenInformation(
  2528. hToken,
  2529. tki,
  2530. pTokenInfo,
  2531. dwRequiredBytes,
  2532. &dwRequiredBytes
  2533. );
  2534. if (!bRes)
  2535. {
  2536. printf("Unable to query token\n");
  2537. goto Exit;
  2538. }
  2539. // Loop through the privileges.
  2540. // ============================
  2541. pPriv = (TOKEN_PRIVILEGES *) pTokenInfo;
  2542. for (dwIndex = 0; dwIndex < pPriv->PrivilegeCount; dwIndex++)
  2543. {
  2544. pName = 0;
  2545. dwRequiredBytes = 0;
  2546. // Find the buffer size required for the name.
  2547. // ===========================================
  2548. bRes = LookupPrivilegeName(
  2549. 0, // System name
  2550. &pPriv->Privileges[dwIndex].Luid,
  2551. pName,
  2552. &dwRequiredBytes
  2553. );
  2554. dwLastError = GetLastError();
  2555. if (dwLastError != ERROR_INSUFFICIENT_BUFFER)
  2556. {
  2557. printf("Failed to find privilege name\n");
  2558. goto Exit;
  2559. }
  2560. // Allocate enough space to hold the privilege name.
  2561. // =================================================
  2562. pName = (TCHAR *) new BYTE[dwRequiredBytes];
  2563. if(pName == NULL)
  2564. goto Exit;
  2565. ZeroMemory(pName, dwRequiredBytes);
  2566. bRes = LookupPrivilegeName(
  2567. 0, // System name
  2568. &pPriv->Privileges[dwIndex].Luid,
  2569. pName,
  2570. &dwRequiredBytes
  2571. );
  2572. printf("%s ", pName);
  2573. delete pName;
  2574. // Determine the privilege 'status'.
  2575. // =================================
  2576. if (pPriv->Privileges[dwIndex].Attributes & SE_PRIVILEGE_ENABLED)
  2577. printf("<ENABLED> ");
  2578. if (pPriv->Privileges[dwIndex].Attributes & SE_PRIVILEGE_ENABLED_BY_DEFAULT)
  2579. printf("<ENABLED BY DEFAULT> ");
  2580. if (pPriv->Privileges[dwIndex].Attributes & SE_PRIVILEGE_USED_FOR_ACCESS)
  2581. printf("<USED FOR ACCESS> ");
  2582. printf("\n");
  2583. pName = 0;
  2584. }
  2585. printf("--- End Privilege Dump ---\n");
  2586. bRetVal = TRUE;
  2587. Exit:
  2588. if (pTokenInfo)
  2589. delete pTokenInfo;
  2590. if (hToken)
  2591. CloseHandle(hToken);
  2592. return bRetVal;
  2593. }
  2594. //***************************************************************************
  2595. //
  2596. // CNtSecurity::SetPrivilege
  2597. //
  2598. // Ensures a given privilege is enabled.
  2599. //
  2600. // Parameters:
  2601. //
  2602. // <pszPrivilegeName> One of the SE_ constants defined in WINNT.H for
  2603. // privilege names. Example: SE_SECURITY_NAME
  2604. // <bEnable> If TRUE, the privilege will be enabled. If FALSE,
  2605. // the privilege will be disabled.
  2606. //
  2607. // Return value:
  2608. // TRUE if the privilege was enabled, FALSE if not.
  2609. //
  2610. //***************************************************************************
  2611. // ok
  2612. BOOL CNtSecurity::SetPrivilege(
  2613. TCHAR *pszPrivilegeName, // An SE_ value.
  2614. BOOL bEnable // TRUE=enable, FALSE=disable
  2615. )
  2616. {
  2617. HANDLE hToken = 0;
  2618. TOKEN_PRIVILEGES tkp;
  2619. LUID priv;
  2620. BOOL bRes;
  2621. BOOL bRetVal = FALSE;
  2622. bRes = OpenProcessToken(
  2623. GetCurrentProcess(),
  2624. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  2625. &hToken
  2626. );
  2627. if (!bRes)
  2628. goto Exit;
  2629. // Locate the privilege LUID based on the requested name.
  2630. // ======================================================
  2631. bRes = LookupPrivilegeValue(
  2632. 0, // system name, 0=local
  2633. pszPrivilegeName,
  2634. &priv
  2635. );
  2636. if (!bRes)
  2637. goto Exit;
  2638. // We now have the LUID. Next, we build up the privilege
  2639. // setting based on the user-specified <bEnable>.
  2640. // ======================================================
  2641. tkp.PrivilegeCount = 1;
  2642. tkp.Privileges[0].Luid = priv;
  2643. if (bEnable)
  2644. tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  2645. else
  2646. tkp.Privileges[0].Attributes = 0;
  2647. // Do it.
  2648. // ======
  2649. bRes = AdjustTokenPrivileges(
  2650. hToken,
  2651. FALSE,
  2652. &tkp,
  2653. sizeof(TOKEN_PRIVILEGES),
  2654. 0,
  2655. 0
  2656. );
  2657. if (!bRes)
  2658. goto Exit;
  2659. bRetVal = TRUE;
  2660. Exit:
  2661. if (hToken)
  2662. CloseHandle(hToken);
  2663. return bRetVal;
  2664. }
  2665. //***************************************************************************
  2666. //
  2667. // CNtSecurity::GetFileSD
  2668. //
  2669. // Gets the complete security descriptor for file or directory on NT systems.
  2670. //
  2671. // Parameters:
  2672. // <pszFile> The path to the file or directory.
  2673. //
  2674. // <SecInfo> The information which will be manipulated. See
  2675. // SECURITY_INFORMATION in NT SDK documentation.
  2676. //
  2677. // <pReturnedSD> Receives a pointer to the CNtSecurityDecriptor object
  2678. // which represents security on the file. The caller
  2679. // becomes onwer of the object, which must be deallocated
  2680. // with operator delete.
  2681. //
  2682. // The returned object which is a copy of the
  2683. // underlying security descriptor. Changes to the returned
  2684. // object are not propagated to the file. SetFileSD must
  2685. // be used to do this.
  2686. //
  2687. // This will be set to point to NULL on error.
  2688. //
  2689. // Return value:
  2690. // NoError, NotFound, AccessDenied, Failed
  2691. //
  2692. //***************************************************************************
  2693. // ok
  2694. int CNtSecurity::GetFileSD(
  2695. IN TCHAR *pszFile,
  2696. IN SECURITY_INFORMATION SecInfo,
  2697. OUT CNtSecurityDescriptor **pReturnedSD
  2698. )
  2699. {
  2700. // First, verify that the file/dir exists.
  2701. // =======================================
  2702. #ifdef _UNICODE
  2703. int nRes = _waccess(pszFile, 0);
  2704. #else
  2705. int nRes = _access(pszFile, 0);
  2706. #endif
  2707. if (nRes != 0)
  2708. {
  2709. if (errno == ENOENT)
  2710. return NotFound;
  2711. if (errno == EACCES)
  2712. return AccessDenied;
  2713. if (nRes == -1) // Other errors
  2714. return Failed;
  2715. }
  2716. // If here, we think we can play with it.
  2717. // ======================================
  2718. PSECURITY_DESCRIPTOR pSD = 0;
  2719. DWORD dwRequiredBytes;
  2720. BOOL bRes;
  2721. DWORD dwLastError;
  2722. *pReturnedSD = 0;
  2723. // Call once first to get the required buffer sizes.
  2724. // =================================================
  2725. bRes = GetFileSecurity(
  2726. pszFile,
  2727. SecInfo,
  2728. pSD,
  2729. 0,
  2730. &dwRequiredBytes
  2731. );
  2732. dwLastError = GetLastError();
  2733. if (dwLastError != ERROR_INSUFFICIENT_BUFFER)
  2734. {
  2735. // Analyze the error
  2736. return Failed;
  2737. }
  2738. // Now call again with a buffer large enough to hold the SD.
  2739. // =========================================================
  2740. pSD = (PSECURITY_DESCRIPTOR) new BYTE[dwRequiredBytes];
  2741. if(pSD == NULL)
  2742. return Failed;
  2743. ZeroMemory(pSD, dwRequiredBytes);
  2744. bRes = GetFileSecurity(
  2745. pszFile,
  2746. SecInfo,
  2747. pSD,
  2748. dwRequiredBytes,
  2749. &dwRequiredBytes
  2750. );
  2751. if (!bRes)
  2752. {
  2753. delete pSD;
  2754. return Failed;
  2755. }
  2756. // If here, we have a security descriptor.
  2757. // =======================================
  2758. CNtSecurityDescriptor *pNewSD = new CNtSecurityDescriptor(pSD, TRUE);
  2759. if(pNewSD == NULL)
  2760. {
  2761. delete pSD;
  2762. return Failed;
  2763. }
  2764. *pReturnedSD = pNewSD;
  2765. return NoError;
  2766. }
  2767. //***************************************************************************
  2768. //
  2769. // CNtSecurity::GetRegSD
  2770. //
  2771. // Retrieves the security descriptor for a registry key.
  2772. //
  2773. // Parameters:
  2774. // <hRoot> The root key (HKEY_LOCAL_MACHINE, etc.)
  2775. // <pszSubKey> The subkey under the root key.
  2776. // <SecInfo> The information which will be manipulated. See
  2777. // SECURITY_INFORMATION in NT SDK documentation.
  2778. // <pSD> Receives the pointer to the security descriptor if
  2779. // no error occurs. Caller must use operator delete.
  2780. //
  2781. // Return value:
  2782. // NoError, NotFound, AccessDenied, Failed
  2783. //
  2784. //***************************************************************************
  2785. int CNtSecurity::GetRegSD(
  2786. IN HKEY hRoot,
  2787. IN TCHAR *pszSubKey,
  2788. IN SECURITY_INFORMATION SecInfo,
  2789. OUT CNtSecurityDescriptor **pSD
  2790. )
  2791. {
  2792. HKEY hKey;
  2793. *pSD = 0;
  2794. ACCESS_MASK amAccess = KEY_ALL_ACCESS;
  2795. if (SecInfo & SACL_SECURITY_INFORMATION)
  2796. amAccess |= ACCESS_SYSTEM_SECURITY;
  2797. LONG lRes = RegOpenKeyEx(hRoot, pszSubKey, 0, amAccess, &hKey);
  2798. if (lRes == ERROR_ACCESS_DENIED)
  2799. return AccessDenied;
  2800. if (lRes != ERROR_SUCCESS)
  2801. return Failed;
  2802. // If here, the key is open. Now we try to get the security descriptor.
  2803. // =====================================================================
  2804. PSECURITY_DESCRIPTOR pTmpSD = 0;
  2805. DWORD dwRequired = 0;
  2806. // Determine the buffer size required.
  2807. // ===================================
  2808. lRes = RegGetKeySecurity(hKey, SecInfo, pTmpSD, &dwRequired);
  2809. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  2810. {
  2811. RegCloseKey(hKey);
  2812. return Failed;
  2813. }
  2814. // Allocate room for the SD and get it.
  2815. // ====================================
  2816. pTmpSD = new BYTE[dwRequired];
  2817. if (!pTmpSD)
  2818. {
  2819. RegCloseKey(hKey);
  2820. return Failed;
  2821. }
  2822. ZeroMemory(pTmpSD, dwRequired);
  2823. lRes = RegGetKeySecurity(hKey, SecInfo, pTmpSD, &dwRequired);
  2824. if (lRes != 0 || !IsValidSecurityDescriptor(pTmpSD))
  2825. {
  2826. delete pTmpSD;
  2827. RegCloseKey(hKey);
  2828. return Failed;
  2829. }
  2830. RegCloseKey(hKey);
  2831. CNtSecurityDescriptor *pNewSD = new CNtSecurityDescriptor(pTmpSD, TRUE);
  2832. if(pNewSD == NULL)
  2833. {
  2834. delete pTmpSD;
  2835. return Failed;
  2836. }
  2837. *pSD = pNewSD;
  2838. return NoError;
  2839. }
  2840. //***************************************************************************
  2841. //
  2842. // CNtSecurity::SetRegSD
  2843. //
  2844. // Sets the security descriptor for a registry key.
  2845. //
  2846. // Parameters:
  2847. // <hRoot> The root key (HKEY_LOCAL_MACHINE, etc.)
  2848. // <pszSubKey> The subkey under the root key.
  2849. // <SecInfo> The information which will be manipulated. See
  2850. // SECURITY_INFORMATION in NT SDK documentation.
  2851. // <pSD> The read-only pointer to the new security descriptor.
  2852. //
  2853. // Return value:
  2854. // NoError, NotFound, AccessDenied, Failed
  2855. //
  2856. //***************************************************************************
  2857. int CNtSecurity::SetRegSD(
  2858. IN HKEY hRoot,
  2859. IN TCHAR *pszSubKey,
  2860. IN SECURITY_INFORMATION SecInfo,
  2861. IN CNtSecurityDescriptor *pSD
  2862. )
  2863. {
  2864. HKEY hKey;
  2865. if (!pSD->IsValid())
  2866. return Failed;
  2867. ACCESS_MASK amAccess = KEY_ALL_ACCESS;
  2868. if (SecInfo & SACL_SECURITY_INFORMATION)
  2869. amAccess |= ACCESS_SYSTEM_SECURITY;
  2870. LONG lRes = RegOpenKeyEx(hRoot, pszSubKey, 0, amAccess, &hKey);
  2871. if (lRes == ERROR_ACCESS_DENIED)
  2872. return AccessDenied;
  2873. if (lRes != ERROR_SUCCESS)
  2874. return Failed;
  2875. // If here, the key is open. Now we try to get the security descriptor.
  2876. // =====================================================================
  2877. PSECURITY_DESCRIPTOR pTmpSD = 0;
  2878. DWORD dwRequired = 0;
  2879. // Determine the buffer size required.
  2880. // ===================================
  2881. lRes = RegSetKeySecurity(hKey, SecInfo, pSD->GetPtr());
  2882. if (lRes != 0)
  2883. {
  2884. RegCloseKey(hKey);
  2885. return Failed;
  2886. }
  2887. RegCloseKey(hKey);
  2888. return NoError;
  2889. }
  2890. //***************************************************************************
  2891. //
  2892. // CNtSecurity::SetFileSD
  2893. //
  2894. // Sets the security descriptor for a file or directory.
  2895. //
  2896. // Parameters:
  2897. // <pszFile> The file/dir for which to set security.
  2898. // <SecInfo> The information which will be manipulated. See
  2899. // SECURITY_INFORMATION in NT SDK documentation.
  2900. // <pSD> Pointer to a valid CNtSecurityDescriptor
  2901. //
  2902. //***************************************************************************
  2903. // ok
  2904. BOOL CNtSecurity::SetFileSD(
  2905. IN TCHAR *pszFile,
  2906. IN SECURITY_INFORMATION SecInfo,
  2907. IN CNtSecurityDescriptor *pSD
  2908. )
  2909. {
  2910. // First, verify that the file/dir exists.
  2911. // =======================================
  2912. #ifdef _UNICODE
  2913. int nRes = _waccess(pszFile, 0);
  2914. #else
  2915. int nRes = _access(pszFile, 0);
  2916. #endif
  2917. if (nRes != 0)
  2918. return FALSE;
  2919. // Verify the SD is good.
  2920. // ======================
  2921. if (pSD->GetStatus() != NoError)
  2922. return FALSE;
  2923. BOOL bRes = ::SetFileSecurity(
  2924. pszFile,
  2925. SecInfo,
  2926. pSD->GetPtr()
  2927. );
  2928. return bRes;
  2929. }
  2930. //***************************************************************************
  2931. //
  2932. // CNtSecurity::GetDCName
  2933. //
  2934. // Determines the domain controller for a given domain name.
  2935. //
  2936. // Parameters:
  2937. // <pszDomain> The domain name for which to find the controller.
  2938. // <pszDC> Receives a pointer to the DC name. Deallocate with
  2939. // operator delete.
  2940. // <pszServer> Optional remote helper server on which to execute
  2941. // the query. Defaults to NULL, which typically
  2942. // succeeds.
  2943. //
  2944. // Return value:
  2945. // NoError, NotFound, InvalidName
  2946. //
  2947. //***************************************************************************
  2948. /*
  2949. int CNtSecurity::GetDCName(
  2950. IN LPWSTR pszDomain,
  2951. OUT LPWSTR *pszDC,
  2952. IN LPWSTR pszServer
  2953. )
  2954. {
  2955. LPBYTE pBuf;
  2956. NET_API_STATUS Status;
  2957. Status = NetGetDCName(pszServer, pszDomain, &pBuf);
  2958. if (Status == NERR_DCNotFound)
  2959. return NotFound;
  2960. if (Status == ERROR_INVALID_NAME)
  2961. return InvalidName;
  2962. LPWSTR pRetStr = new wchar_t[wcslen(LPWSTR(pBuf)) + 1];
  2963. wcscpy(pRetStr, LPWSTR(pBuf));
  2964. NetApiBufferFree(pBuf);
  2965. *pszDC = pRetStr;
  2966. return NoError;
  2967. }
  2968. */
  2969. //***************************************************************************
  2970. //
  2971. // CNtSecurity::IsUserInGroup2
  2972. //
  2973. // Determines if the use belongs to a particular NTLM group by checking the
  2974. // group list in the access token. This may be a better way than the
  2975. // current implementation.
  2976. //
  2977. // Parameters:
  2978. // <hToken> The user's access token.
  2979. // <Sid> Object containing the sid of the group being tested.
  2980. //
  2981. // Return value:
  2982. // TRUE if the user belongs to the group.
  2983. //
  2984. //***************************************************************************
  2985. /*
  2986. BOOL CNtSecurity::IsUserInGroup2(
  2987. HANDLE hAccessToken,
  2988. CNtSid & Sid)
  2989. {
  2990. if(!IsNT() || hAccessToken == NULL)
  2991. return FALSE; // No point in further testing
  2992. DWORD dwErr;
  2993. // Obtain and the groups from token. Start off by determining how much
  2994. // memory is required.
  2995. TOKEN_GROUPS Groups;
  2996. DWORD dwLen = 0;
  2997. GetTokenInformation(hAccessToken, TokenGroups, &Groups, sizeof(Groups), &dwLen);
  2998. if(dwLen == 0)
  2999. return FALSE;
  3000. // Load up the group list
  3001. int BUFFER_SIZE = dwLen;
  3002. BYTE * byteBuffer = new BYTE[BUFFER_SIZE];
  3003. if(byteBuffer == NULL)
  3004. return FALSE;
  3005. DWORD dwSizeRequired = 0;
  3006. BOOL bResult = GetTokenInformation( hAccessToken,
  3007. TokenGroups,
  3008. (void *) byteBuffer,
  3009. BUFFER_SIZE,
  3010. &dwSizeRequired );
  3011. if ( !bResult ) {
  3012. delete [] byteBuffer;
  3013. dwErr = GetLastError();
  3014. return ( FALSE );
  3015. }
  3016. // Loop through the group list looking for a match
  3017. BOOL bFound = FALSE;
  3018. PTOKEN_GROUPS pGroups = (PTOKEN_GROUPS) byteBuffer;
  3019. for ( unsigned i = 0; i < pGroups->GroupCount; i++ )
  3020. {
  3021. CNtSid test(pGroups->Groups[i].Sid);
  3022. if(test == Sid)
  3023. {
  3024. bFound = TRUE;
  3025. break;
  3026. }
  3027. }
  3028. delete [] byteBuffer;
  3029. return bFound;
  3030. }*/
  3031. //***************************************************************************
  3032. //
  3033. // CNtSecurity::IsUserInGroup
  3034. //
  3035. // Determines if the use belongs to a particular NTLM group.
  3036. //
  3037. // Parameters:
  3038. // <hToken> The user's access token.
  3039. // <Sid> Object containing the sid of the group being tested.
  3040. //
  3041. // Return value:
  3042. // TRUE if the user belongs to the group.
  3043. //
  3044. //***************************************************************************
  3045. BOOL CNtSecurity::IsUserInGroup(
  3046. HANDLE hAccessToken,
  3047. CNtSid & Sid)
  3048. {
  3049. if(!IsNT() || hAccessToken == NULL)
  3050. return FALSE; // No point in further testing
  3051. // create a security descriptor with a single entry which
  3052. // is the group in question.
  3053. CNtAce ace(1,ACCESS_ALLOWED_ACE_TYPE,0,Sid);
  3054. if(ace.GetStatus() != 0)
  3055. return FALSE;
  3056. CNtAcl acl;
  3057. acl.AddAce(&ace);
  3058. CNtSecurityDescriptor sd;
  3059. sd.SetDacl(&acl);
  3060. sd.SetGroup(&Sid); // Access check doesnt really care what you put, so long as you
  3061. // put something for the owner
  3062. sd.SetOwner(&Sid);
  3063. GENERIC_MAPPING map;
  3064. map.GenericRead = 1;
  3065. map.GenericWrite = 0;
  3066. map.GenericExecute = 0;
  3067. map.GenericAll = 0;
  3068. PRIVILEGE_SET ps[10];
  3069. DWORD dwSize = 10 * sizeof(PRIVILEGE_SET);
  3070. DWORD dwGranted;
  3071. BOOL bResult;
  3072. BOOL bOK = ::AccessCheck(sd.GetPtr(), hAccessToken, 1, &map, ps, &dwSize, &dwGranted, &bResult);
  3073. DWORD dwErr = GetLastError();
  3074. if(bOK && bResult)
  3075. return TRUE;
  3076. else
  3077. return FALSE;
  3078. }
  3079. //***************************************************************************
  3080. //
  3081. // CNtSecurity::DoesGroupExist
  3082. //
  3083. // Determines if a group exists.
  3084. //
  3085. // Return value:
  3086. // TRUE if the group exists
  3087. //
  3088. //***************************************************************************
  3089. bool CNtSecurity::DoesLocalGroupExist(
  3090. LPWSTR pwszGroup,
  3091. LPWSTR pwszMachine)
  3092. {
  3093. bool bRet = false;
  3094. HINSTANCE hAPI = LoadLibraryEx(__TEXT("netapi32"), NULL, 0);
  3095. if(hAPI)
  3096. {
  3097. NET_API_STATUS (NET_API_FUNCTION *pfnGetInfo)(LPWSTR , LPWSTR ,DWORD , LPBYTE *);
  3098. (FARPROC&)pfnGetInfo = GetProcAddress(hAPI, "NetLocalGroupGetInfo");
  3099. long lRes;
  3100. if(pfnGetInfo)
  3101. {
  3102. LOCALGROUP_INFO_1 * info;
  3103. lRes = pfnGetInfo(pwszMachine, pwszGroup, 1, (LPBYTE *)&info);
  3104. if(lRes == NERR_Success)
  3105. {
  3106. NET_API_STATUS (NET_API_FUNCTION *pfnBufferFree)(LPVOID);
  3107. (FARPROC&)pfnBufferFree = GetProcAddress(hAPI, "NetApiBufferFree");
  3108. if(pfnBufferFree)
  3109. pfnBufferFree(info);
  3110. bRet = true;
  3111. }
  3112. }
  3113. FreeLibrary(hAPI);
  3114. }
  3115. return bRet;
  3116. }
  3117. //***************************************************************************
  3118. //
  3119. // CNtSecurity::AddLocalGroup
  3120. //
  3121. // Determines if a group exists.
  3122. //
  3123. // Return value:
  3124. // TRUE if the group exists
  3125. //
  3126. //***************************************************************************
  3127. bool CNtSecurity::AddLocalGroup(LPWSTR pwszGroupName, LPWSTR pwszGroupDescription)
  3128. {
  3129. bool bRet = false;
  3130. HINSTANCE hAPI = LoadLibraryEx(__TEXT("netapi32"), NULL, 0);
  3131. if(hAPI)
  3132. {
  3133. LOCALGROUP_INFO_1 info;
  3134. info.lgrpi1_name = pwszGroupName;
  3135. info.lgrpi1_comment = pwszGroupDescription;
  3136. NET_API_STATUS (*pfnLocalAdd)(LPWSTR ,DWORD , LPBYTE ,LPDWORD);
  3137. (FARPROC&)pfnLocalAdd = GetProcAddress(hAPI, "NetLocalGroupAdd");
  3138. if(pfnLocalAdd)
  3139. bRet = (pfnLocalAdd(NULL, 1, (LPBYTE)&info, NULL) == NERR_Success);
  3140. FreeLibrary(hAPI);
  3141. }
  3142. return bRet;
  3143. }
  3144. //***************************************************************************
  3145. //
  3146. //***************************************************************************
  3147. void ChangeSecurity(CNtSecurityDescriptor *pSD)
  3148. {
  3149. CNtAcl Acl;
  3150. ACCESS_MASK Mask = FULL_CONTROL;
  3151. CNtSid Sid(L"Everyone", 0);
  3152. CNtAce Ace(
  3153. Mask,
  3154. ACCESS_ALLOWED_ACE_TYPE,
  3155. CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE,
  3156. Sid);
  3157. if (Ace.GetStatus() != CNtAce::NoError)
  3158. {
  3159. printf("Bad ACE\n");
  3160. return;
  3161. }
  3162. CNtAce Ace2(Ace);
  3163. CNtAce Ace3;
  3164. Ace3 = Ace2;
  3165. Acl.AddAce(&Ace3);
  3166. CNtAcl Acl2(Acl);
  3167. CNtAcl Acl3;
  3168. Acl3 = Acl2;
  3169. pSD->SetDacl(&Acl);
  3170. CNtSecurityDescriptor SD2(*pSD);
  3171. CNtSecurityDescriptor SD3;
  3172. SD3.SetDacl(&Acl3);
  3173. SD3 = SD2;
  3174. *pSD = SD3;
  3175. CNtSid *pOwner = pSD->GetOwner();
  3176. if (pOwner)
  3177. pSD->SetOwner(pOwner);
  3178. }
  3179. //***************************************************************************
  3180. //
  3181. //***************************************************************************
  3182. void SidTest(char *pUser, char *pMachine)
  3183. {
  3184. wchar_t User[128], Mach[128];
  3185. MultiByteToWideChar(CP_ACP, 0, pUser, -1, User, 128);
  3186. MultiByteToWideChar(CP_ACP, 0, pMachine, -1, Mach, 128);
  3187. printf("------SID TEST----------\n");
  3188. LPWSTR pMach2 = 0;
  3189. if (pMachine)
  3190. pMach2 = Mach;
  3191. CNtSid TseSid(User, pMach2);
  3192. printf("TseSid status = %d\n", TseSid.GetStatus());
  3193. TseSid.Dump();
  3194. }
  3195. void TestRegSec()
  3196. {
  3197. CNtSecurityDescriptor *pSD = 0;
  3198. int nRes = CNtSecurity::GetRegSD(HKEY_LOCAL_MACHINE,WBEM_REG_WBEM,
  3199. DACL_SECURITY_INFORMATION, &pSD);
  3200. printf("----------------BEGIN SECURITY KEY DUMP-------------\n");
  3201. pSD->Dump();
  3202. printf("----------------END SECURITY KEY DUMP-------------\n");
  3203. if (pSD->IsValid())
  3204. nRes = CNtSecurity::SetRegSD(HKEY_LOCAL_MACHINE, WBEM_REG_WBEM,
  3205. DACL_SECURITY_INFORMATION, pSD);
  3206. }
  3207. /*
  3208. void main(int argc, char **argv)
  3209. {
  3210. BOOL bRes;
  3211. printf("Test\n");
  3212. if (argc < 2)
  3213. return;
  3214. bRes = CNtSecurity::SetPrivilege(SE_SECURITY_NAME, TRUE);
  3215. CNtSecurity::DumpPrivileges();
  3216. CNtSecurityDescriptor *pSD = 0;
  3217. int nRes = CNtSecurity::GetFileSD(argv[1], DACL_SECURITY_INFORMATION, &pSD);
  3218. if (nRes == CNtSecurity::NotFound)
  3219. {
  3220. printf("No such file/dir\n");
  3221. return;
  3222. }
  3223. if (nRes != 0)
  3224. {
  3225. printf("Cannot get security descriptor. Last=%d\n", GetLastError());
  3226. }
  3227. pSD->Dump();
  3228. delete pSD;
  3229. }
  3230. */
  3231. //***************************************************************************
  3232. //
  3233. // FIsRunningAsService
  3234. //
  3235. // Purpose:
  3236. // Determines if the current process is running as a service.
  3237. //
  3238. // Returns:
  3239. // FALSE if running interactively
  3240. // TRUE if running as a service.
  3241. //
  3242. //***************************************************************************
  3243. /*BOOL FIsRunningAsService(VOID)
  3244. {
  3245. HWINSTA hws = GetProcessWindowStation();
  3246. if(hws == NULL)
  3247. return TRUE;
  3248. DWORD LengthNeeded;
  3249. BOOL bService = FALSE;
  3250. USEROBJECTFLAGS fl;
  3251. if(GetUserObjectInformation(hws, UOI_FLAGS, &fl, sizeof(USEROBJECTFLAGS), &LengthNeeded))
  3252. if(fl.dwFlags & WSF_VISIBLE)
  3253. bService = FALSE;
  3254. else
  3255. bService = TRUE;
  3256. CloseWindowStation(hws);
  3257. return bService;
  3258. }*/
  3259. C9XAce::C9XAce(
  3260. ACCESS_MASK Mask,
  3261. DWORD AceType,
  3262. DWORD dwAceFlags,
  3263. LPWSTR pUser
  3264. )
  3265. {
  3266. m_wszFullName = NULL;
  3267. if(pUser)
  3268. m_wszFullName = Macro_CloneLPWSTR(pUser);
  3269. m_dwAccess = Mask;
  3270. m_iFlags = dwAceFlags;
  3271. m_iType = AceType;
  3272. }
  3273. C9XAce::~C9XAce()
  3274. {
  3275. if(m_wszFullName)
  3276. delete [] m_wszFullName;
  3277. }
  3278. HRESULT C9XAce::GetFullUserName(WCHAR * pBuff, DWORD dwSize)
  3279. {
  3280. if(pBuff && m_wszFullName)
  3281. {
  3282. wcsncpy(pBuff, m_wszFullName, dwSize-1);
  3283. pBuff[dwSize-1] = 0;
  3284. return S_OK;
  3285. }
  3286. return WBEM_E_FAILED;
  3287. }
  3288. HRESULT C9XAce::GetFullUserName2(WCHAR ** pBuff)
  3289. {
  3290. if(wcslen(m_wszFullName) < 1)
  3291. return WBEM_E_FAILED;
  3292. int iLen = wcslen(m_wszFullName)+4;
  3293. *pBuff = new WCHAR[iLen];
  3294. if(*pBuff == NULL)
  3295. return WBEM_E_OUT_OF_MEMORY;
  3296. // there are two possible formats, the first is "UserName", and the
  3297. // second is "domain\username".
  3298. WCHAR * pSlash;
  3299. for(pSlash = m_wszFullName; *pSlash && *pSlash != L'\\'; pSlash++); // intentional
  3300. if(*pSlash && pSlash > m_wszFullName)
  3301. {
  3302. // got a domain\user, convert to domain|user
  3303. wcscpy(*pBuff, m_wszFullName);
  3304. for(pSlash = *pBuff; *pSlash; pSlash++)
  3305. if(*pSlash == L'\\')
  3306. {
  3307. *pSlash = L'|';
  3308. break;
  3309. }
  3310. }
  3311. else
  3312. {
  3313. // got a "user", convert to ".|user"
  3314. wcscpy(*pBuff, L".|");
  3315. wcscat(*pBuff, m_wszFullName);
  3316. }
  3317. return S_OK;
  3318. }
  3319. //***************************************************************************
  3320. //
  3321. // C9XAce::GetSerializedSize
  3322. //
  3323. // Returns the number of bytes needed to store this
  3324. //
  3325. //***************************************************************************
  3326. DWORD C9XAce::GetSerializedSize()
  3327. {
  3328. if (m_wszFullName == 0 || wcslen(m_wszFullName) == 0)
  3329. return 0;
  3330. return 2 * (wcslen(m_wszFullName) + 1) + 12;
  3331. }
  3332. //***************************************************************************
  3333. //
  3334. // C9XAce::Serialize
  3335. //
  3336. // Serializes the ace. The serialized version will consist of
  3337. // <DOMAIN\USERNAME LPWSTR><FLAGS><TYPE><MASK>
  3338. //
  3339. // Note that the fields are dwords except for the name.
  3340. //
  3341. //***************************************************************************
  3342. bool C9XAce::Serialize(BYTE * pData)
  3343. {
  3344. wcscpy((LPWSTR)pData, m_wszFullName);
  3345. pData += 2*(wcslen(m_wszFullName) + 1);
  3346. DWORD * pdwData = (DWORD *)pData;
  3347. *pdwData = m_iFlags;
  3348. pdwData++;
  3349. *pdwData = m_iType;
  3350. pdwData++;
  3351. *pdwData = m_dwAccess;
  3352. pdwData++;
  3353. return true;
  3354. }
  3355. //***************************************************************************
  3356. //
  3357. // C9XAce::Deserialize
  3358. //
  3359. // Deserializes the ace. See the comments for Serialize for comments.
  3360. //
  3361. //***************************************************************************
  3362. bool C9XAce::Deserialize(BYTE * pData)
  3363. {
  3364. m_wszFullName = new WCHAR[wcslen((LPWSTR)pData) + 1];
  3365. if (!m_wszFullName)
  3366. return false;
  3367. wcscpy(m_wszFullName, (LPWSTR)pData);
  3368. pData += 2*(wcslen(m_wszFullName) + 1);
  3369. DWORD * pdwData = (DWORD *)pData;
  3370. m_iFlags = *pdwData;
  3371. pdwData++;
  3372. m_iType = *pdwData;
  3373. pdwData++;
  3374. m_dwAccess = *pdwData;
  3375. pdwData++;
  3376. return true;
  3377. }
  3378. //***************************************************************************
  3379. //
  3380. // BOOL SetObjectAccess2
  3381. //
  3382. // DESCRIPTION:
  3383. //
  3384. // Adds read/open and set access for the everyone group to an object.
  3385. //
  3386. // PARAMETERS:
  3387. //
  3388. // hObj Object to set access on.
  3389. //
  3390. // RETURN VALUE:
  3391. //
  3392. // Returns TRUE if OK.
  3393. //
  3394. //***************************************************************************
  3395. BOOL SetObjectAccess2(IN HANDLE hObj)
  3396. {
  3397. PSECURITY_DESCRIPTOR pSD = NULL;
  3398. DWORD dwLastErr = 0;
  3399. BOOL bRet = FALSE;
  3400. // no point if we arnt on nt
  3401. if(!IsNT())
  3402. {
  3403. return TRUE;
  3404. }
  3405. // figure out how much space to allocate
  3406. DWORD dwSizeNeeded;
  3407. bRet = GetKernelObjectSecurity(
  3408. hObj, // handle of object to query
  3409. DACL_SECURITY_INFORMATION, // requested information
  3410. pSD, // address of security descriptor
  3411. 0, // size of buffer for security descriptor
  3412. &dwSizeNeeded); // address of required size of buffer
  3413. if(bRet == TRUE || (ERROR_INSUFFICIENT_BUFFER != GetLastError()))
  3414. return FALSE;
  3415. pSD = new BYTE[dwSizeNeeded];
  3416. if(pSD == NULL)
  3417. return FALSE;
  3418. // Get the data
  3419. bRet = GetKernelObjectSecurity(
  3420. hObj, // handle of object to query
  3421. DACL_SECURITY_INFORMATION, // requested information
  3422. pSD, // address of security descriptor
  3423. dwSizeNeeded, // size of buffer for security descriptor
  3424. &dwSizeNeeded ); // address of required size of buffer
  3425. if(bRet == FALSE)
  3426. {
  3427. delete pSD;
  3428. return FALSE;
  3429. }
  3430. // move it into object for
  3431. CNtSecurityDescriptor sd(pSD,TRUE); // Acquires ownership of the memory
  3432. if(sd.GetStatus() != 0)
  3433. return FALSE;
  3434. CNtAcl acl;
  3435. if(!sd.GetDacl(acl))
  3436. return FALSE;
  3437. // Create an everyone ace
  3438. PSID pRawSid;
  3439. SID_IDENTIFIER_AUTHORITY id2 = SECURITY_WORLD_SID_AUTHORITY;;
  3440. if(AllocateAndInitializeSid( &id2, 1,
  3441. 0,0,0,0,0,0,0,0,&pRawSid))
  3442. {
  3443. CNtSid SidUsers(pRawSid);
  3444. FreeSid(pRawSid);
  3445. CNtAce * pace = new CNtAce(EVENT_MODIFY_STATE | SYNCHRONIZE, ACCESS_ALLOWED_ACE_TYPE, 0
  3446. , SidUsers);
  3447. if(pace == NULL)
  3448. return FALSE;
  3449. if( pace->GetStatus() == 0)
  3450. acl.AddAce(pace);
  3451. delete pace;
  3452. }
  3453. if(acl.GetStatus() != 0)
  3454. return FALSE;
  3455. sd.SetDacl(&acl);
  3456. bRet = SetKernelObjectSecurity(hObj, DACL_SECURITY_INFORMATION, sd.GetPtr());
  3457. return TRUE;
  3458. }
  3459. //***************************************************************************
  3460. //
  3461. // IsAdmin
  3462. //
  3463. // returns TRUE if we are a member of the admin group or running as
  3464. // NETWORK_SERVICE or running as LOCAL_SERVICE
  3465. //
  3466. //***************************************************************************
  3467. BOOL IsAdmin(HANDLE hAccess)
  3468. {
  3469. BOOL bRet = FALSE;
  3470. PSID pRawSid;
  3471. SID_IDENTIFIER_AUTHORITY id = SECURITY_NT_AUTHORITY;
  3472. if(AllocateAndInitializeSid( &id, 2,
  3473. SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
  3474. 0,0,0,0,0,0,&pRawSid))
  3475. {
  3476. CNtSid Sid(pRawSid);
  3477. bRet = CNtSecurity::IsUserInGroup(hAccess, Sid);
  3478. // We're done with this
  3479. FreeSid( pRawSid );
  3480. }
  3481. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3482. // Lets check for NETWORK_SERVICE and LOCAL_SERVICE since
  3483. // they also want full admin rights
  3484. // COMMENTED OUT DUE TO: 504554
  3485. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3486. //if ( !bRet )
  3487. //{
  3488. // bRet = IsNetworkService ( hAccess );
  3489. // if ( !bRet )
  3490. // {
  3491. // bRet = IsLocalService ( hAccess );
  3492. // }
  3493. //}
  3494. return bRet;
  3495. }
  3496. //***************************************************************************
  3497. //
  3498. // IsNetworkService
  3499. //
  3500. // returns TRUE if we are running as NETWORK_SERVICE
  3501. //
  3502. //***************************************************************************
  3503. BOOL IsNetworkService ( HANDLE hAccess )
  3504. {
  3505. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3506. // Construct the NETWORK_SERVICE SID
  3507. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3508. SID_IDENTIFIER_AUTHORITY id = SECURITY_NT_AUTHORITY;
  3509. PSID pSidSystem;
  3510. BOOL bRes = FALSE;
  3511. if ( AllocateAndInitializeSid(&id, 1, SECURITY_NETWORK_SERVICE_RID, 0, 0,0,0,0,0,0,&pSidSystem) )
  3512. {
  3513. if ( !CheckTokenMembership ( hAccess, pSidSystem, &bRes ) )
  3514. {
  3515. bRes = FALSE;
  3516. }
  3517. FreeSid ( pSidSystem );
  3518. }
  3519. return bRes;
  3520. }
  3521. //***************************************************************************
  3522. //
  3523. // IsLocalService
  3524. //
  3525. // returns TRUE if we are running as LOCAL_SERVICE
  3526. //
  3527. //***************************************************************************
  3528. BOOL IsLocalService ( HANDLE hAccess )
  3529. {
  3530. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3531. // Construct the NETWORK_SERVICE SID
  3532. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3533. SID_IDENTIFIER_AUTHORITY id = SECURITY_NT_AUTHORITY;
  3534. PSID pSidSystem;
  3535. BOOL bRes = FALSE;
  3536. if ( AllocateAndInitializeSid(&id, 1, SECURITY_LOCAL_SERVICE_RID, 0, 0,0,0,0,0,0,&pSidSystem) )
  3537. {
  3538. if ( !CheckTokenMembership ( hAccess, pSidSystem, &bRes ) )
  3539. {
  3540. bRes = FALSE;
  3541. }
  3542. FreeSid ( pSidSystem );
  3543. }
  3544. return bRes;
  3545. }
  3546. //***************************************************************************
  3547. //
  3548. // IsInAdminGroup
  3549. //
  3550. // returns TRUE if we are a member of the admin group.
  3551. //
  3552. //***************************************************************************
  3553. BOOL IsInAdminGroup()
  3554. {
  3555. HANDLE hAccessToken = INVALID_HANDLE_VALUE;
  3556. if(S_OK != GetAccessToken(hAccessToken))
  3557. return TRUE; // Not having a token indicates an internal thread
  3558. CCloseHandle cm(hAccessToken);
  3559. DWORD dwMask = 0;
  3560. if(IsAdmin(hAccessToken))
  3561. return TRUE;
  3562. else
  3563. return FALSE;
  3564. }
  3565. //***************************************************************************
  3566. //
  3567. // HRESULT GetAccessToken
  3568. //
  3569. // Gets the access token and sets it the the reference argument.
  3570. //
  3571. //***************************************************************************
  3572. HRESULT GetAccessToken(HANDLE &hAccessToken)
  3573. {
  3574. // Ensures auto release of the mutex if we crash
  3575. CAutoSecurityMutex autosm;
  3576. bool bIsImpersonating = WbemIsImpersonating();
  3577. HRESULT hRes = S_OK;
  3578. if(bIsImpersonating == false)
  3579. hRes = WbemCoImpersonateClient();
  3580. if(hRes == S_OK)
  3581. {
  3582. BOOL bOK = OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &hAccessToken);
  3583. if(bOK == FALSE)
  3584. {
  3585. hRes = WBEM_E_INVALID_CONTEXT;
  3586. }
  3587. else
  3588. hRes = S_OK;
  3589. }
  3590. if(bIsImpersonating == false)
  3591. WbemCoRevertToSelf();
  3592. // The security mutex will auto release
  3593. return hRes;
  3594. }