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.

2774 lines
86 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1993 - 1995.
  5. //
  6. // File: aclutil.cxx
  7. //
  8. // Contents: utility function(s) for ACL api
  9. //
  10. // History: 8/94 davemont Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #include <aclpch.hxx>
  14. #pragma hdrstop
  15. extern "C"
  16. {
  17. #include <stdio.h>
  18. #include <permit.h>
  19. #include <dsgetdc.h>
  20. #include <lmapibuf.h>
  21. #include <wmistr.h>
  22. #include <ntprov.hxx>
  23. #include <strings.h>
  24. }
  25. DLLFuncsTable DLLFuncs;
  26. typedef struct _NAME_RID_INFO {
  27. PWSTR pwszName;
  28. ULONG Rid;
  29. } NAME_RID_INFO, *PNAME_RID_INFO;
  30. BOOL NameSidLookupInfoLoaded = FALSE;
  31. NAME_RID_INFO NameSidLookup[] = {
  32. { NULL, DOMAIN_ALIAS_RID_ACCOUNT_OPS },
  33. { NULL, DOMAIN_ALIAS_RID_PRINT_OPS },
  34. { NULL, DOMAIN_ALIAS_RID_SYSTEM_OPS },
  35. { NULL, DOMAIN_ALIAS_RID_POWER_USERS }
  36. };
  37. //
  38. // Private functions
  39. //
  40. DWORD AccpLoadLocalizedNameTranslations()
  41. {
  42. DWORD dwErr = ERROR_SUCCESS;
  43. ULONG Value = 0,i;
  44. WCHAR wszStringBuffer[ 256];
  45. RtlAcquireResourceExclusive(&gLocalSidCacheLock, TRUE);
  46. if ( !NameSidLookupInfoLoaded ) {
  47. for (i = 0; i < sizeof( NameSidLookup ) / sizeof( NAME_RID_INFO ); i++ )
  48. {
  49. switch ( NameSidLookup[ i ].Rid )
  50. {
  51. case DOMAIN_ALIAS_RID_ACCOUNT_OPS:
  52. Value = ACCPROV_ACCOUNT_OPS;
  53. break;
  54. case DOMAIN_ALIAS_RID_PRINT_OPS:
  55. Value = ACCPROV_PRINTER_OPS;
  56. break;
  57. case DOMAIN_ALIAS_RID_SYSTEM_OPS:
  58. Value = ACCPROV_SYSTEM_OPS;
  59. break;
  60. case DOMAIN_ALIAS_RID_POWER_USERS:
  61. Value = ACCPROV_POWER_USERS;
  62. break;
  63. }
  64. if (LoadString(ghDll,
  65. Value,
  66. wszStringBuffer,
  67. sizeof( wszStringBuffer ) / sizeof( WCHAR )) != 0)
  68. {
  69. ACC_ALLOC_AND_COPY_STRINGW(wszStringBuffer,
  70. NameSidLookup[ i ].pwszName,
  71. dwErr );
  72. }
  73. else
  74. {
  75. dwErr = GetLastError();
  76. }
  77. if(dwErr != ERROR_SUCCESS)
  78. {
  79. break;
  80. }
  81. }
  82. if(dwErr != ERROR_SUCCESS)
  83. {
  84. for(i = 0; i< sizeof( NameSidLookup ) / sizeof( NAME_RID_INFO ); i++ )
  85. {
  86. LocalFree( NameSidLookup[ i ].pwszName );
  87. NameSidLookup[ i ].pwszName = NULL;
  88. }
  89. }
  90. else
  91. {
  92. NameSidLookupInfoLoaded = TRUE;
  93. }
  94. }
  95. RtlReleaseResource( &gLocalSidCacheLock );
  96. return( dwErr );
  97. }
  98. DWORD AccpDoSidLookup(IN PWSTR pwszServer,
  99. IN PWSTR pwszName,
  100. OUT PSID *ppSid,
  101. OUT SID_NAME_USE *pSidType)
  102. {
  103. #define BASE_DOMAIN_NAME_SIZE 64
  104. #define BASE_SID_SIZE 64
  105. DWORD dwErr = ERROR_SUCCESS;
  106. DWORD cusid = BASE_SID_SIZE;
  107. DWORD crd = BASE_DOMAIN_NAME_SIZE;
  108. SID_NAME_USE esidtype = SidTypeUnknown;
  109. WCHAR domainbuf[BASE_DOMAIN_NAME_SIZE];
  110. LPWSTR domain = (LPWSTR)domainbuf;
  111. domainbuf[0] = L'\0';
  112. if (LoadString(ghDll,
  113. ACCPROV_NTAUTHORITY,
  114. domainbuf,
  115. sizeof( domainbuf ) / sizeof( WCHAR )) != 0)
  116. {
  117. if(_wcsicmp(pwszServer, domainbuf) == 0)
  118. {
  119. pwszServer = NULL;
  120. }
  121. } else if(_wcsicmp(pwszServer, L"NT AUTHORITY") == 0)
  122. {
  123. pwszServer = NULL;
  124. }
  125. *ppSid = (PSID)AccAlloc(cusid);
  126. if(*ppSid == NULL)
  127. {
  128. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  129. }
  130. else
  131. {
  132. if(!LookupAccountName(pwszServer,
  133. pwszName,
  134. *ppSid,
  135. &cusid,
  136. domain,
  137. &crd,
  138. &esidtype))
  139. {
  140. dwErr = GetLastError();
  141. if(dwErr == ERROR_INSUFFICIENT_BUFFER)
  142. {
  143. dwErr = ERROR_SUCCESS;
  144. //
  145. // if the rooom for the sid was not big enough,
  146. // grow it.
  147. //
  148. if(cusid > BASE_SID_SIZE)
  149. {
  150. AccFree(*ppSid);
  151. *ppSid = (PSID)AccAlloc(cusid);
  152. if (*ppSid == NULL)
  153. {
  154. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  155. }
  156. }
  157. if(dwErr == ERROR_SUCCESS)
  158. {
  159. if(crd > BASE_DOMAIN_NAME_SIZE)
  160. {
  161. domain = (LPWSTR)AccAlloc(crd * sizeof(WCHAR));
  162. if (NULL == domain)
  163. {
  164. AccFree(*ppSid);
  165. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  166. }
  167. }
  168. if(dwErr == ERROR_SUCCESS)
  169. {
  170. if(!LookupAccountName(pwszServer,
  171. pwszName,
  172. *ppSid,
  173. &cusid,
  174. domain,
  175. &crd,
  176. &esidtype))
  177. {
  178. dwErr = GetLastError();
  179. AccFree(*ppSid);
  180. }
  181. if(domain != (LPWSTR)domainbuf)
  182. {
  183. AccFree(domain);
  184. }
  185. }
  186. }
  187. }
  188. else if(dwErr != ERROR_SUCCESS)
  189. {
  190. AccFree(*ppSid);
  191. *ppSid = NULL;
  192. }
  193. }
  194. else if(dwErr != ERROR_SUCCESS)
  195. {
  196. AccFree(*ppSid);
  197. *ppSid = NULL;
  198. }
  199. }
  200. return(dwErr);
  201. }
  202. //+---------------------------------------------------------------------------
  203. //
  204. // Function : AccLookupAccountSid
  205. //
  206. // Synopsis : returns the SID for the specified trustee
  207. //
  208. // Arguments: [IN pwszServer] -- Name of the server to remote the
  209. // call to
  210. // [IN pName] -- the name to lookup the SID for
  211. // [OUT ppwszName] -- Where the name is returned
  212. // [OUT pSidType] -- Where the SID type is returned
  213. //
  214. // Returns: ERROR_SUCCESS -- Success
  215. // ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed.
  216. // ERROR_INVALID_PARAMETER -- The trustee form was bad
  217. //
  218. //----------------------------------------------------------------------------
  219. DWORD AccLookupAccountSid(IN PWSTR pwszServer,
  220. IN PTRUSTEE pName,
  221. OUT PSID *ppsid,
  222. OUT SID_NAME_USE *pSidType)
  223. {
  224. #define BASE_DOMAIN_NAME_SIZE 64
  225. #define BASE_SID_SIZE 64
  226. DWORD dwErr = ERROR_SUCCESS;
  227. DWORD cusid = BASE_SID_SIZE;
  228. DWORD crd = BASE_DOMAIN_NAME_SIZE;
  229. SID_NAME_USE esidtype = SidTypeUnknown;
  230. WCHAR domainbuf[BASE_DOMAIN_NAME_SIZE];
  231. LPWSTR domain = (LPWSTR)domainbuf;
  232. PWSTR pwszSep;
  233. PWSTR pwszTempName;
  234. if(pName->TrusteeForm == TRUSTEE_IS_SID)
  235. {
  236. //
  237. // Trustee is of form TRUSTEE_IS_SID
  238. //
  239. *ppsid = (PSID) AccAlloc( GetLengthSid((PSID)pName->ptstrName) );
  240. if (*ppsid != NULL)
  241. {
  242. if (!CopySid( GetLengthSid((PSID)pName->ptstrName),
  243. *ppsid,
  244. (PSID)pName->ptstrName))
  245. {
  246. dwErr = GetLastError();
  247. AccFree(*ppsid);
  248. *ppsid = NULL;
  249. }
  250. }
  251. else
  252. {
  253. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  254. }
  255. }
  256. else if(pName->TrusteeForm == TRUSTEE_IS_NAME)
  257. {
  258. //
  259. // Trustee is of form TRUSTEE_IS_NAME.
  260. //
  261. //
  262. // Check for CURRENT_USER (in which case we get the name from
  263. // the token)
  264. //
  265. if(_wcsicmp(pName->ptstrName, L"CURRENT_USER") == 0)
  266. {
  267. HANDLE token_handle;
  268. dwErr = GetCurrentToken( &token_handle );
  269. //
  270. // if we have a token, get the user SID from it
  271. //
  272. if(dwErr == ERROR_SUCCESS)
  273. {
  274. dwErr = AccGetSidFromToken(pwszServer,
  275. token_handle,
  276. TokenUser,
  277. ppsid);
  278. CloseHandle(token_handle);
  279. }
  280. }
  281. else
  282. {
  283. //
  284. // if not current user, we have to do a name lookup
  285. // first allocate a default sid (so the name lookup is not
  286. // always performed twice.)
  287. //
  288. *ppsid = (PSID)AccAlloc(cusid);
  289. if(*ppsid != NULL)
  290. {
  291. if(!LookupAccountName(pwszServer,
  292. pName->ptstrName,
  293. *ppsid,
  294. &cusid,
  295. domain,
  296. &crd,
  297. &esidtype))
  298. {
  299. dwErr = GetLastError();
  300. if(dwErr == ERROR_INSUFFICIENT_BUFFER)
  301. {
  302. dwErr = ERROR_SUCCESS;
  303. //
  304. // if the rooom for the sid was not big enough,
  305. // grow it.
  306. //
  307. if(cusid > BASE_SID_SIZE)
  308. {
  309. AccFree(*ppsid);
  310. *ppsid = (PSID)AccAlloc(cusid);
  311. if (*ppsid == NULL)
  312. {
  313. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  314. }
  315. }
  316. if(dwErr == ERROR_SUCCESS)
  317. {
  318. if(crd > BASE_DOMAIN_NAME_SIZE)
  319. {
  320. domain = (LPWSTR)AccAlloc(crd * sizeof(WCHAR));
  321. if (NULL == domain)
  322. {
  323. AccFree(*ppsid);
  324. *ppsid = NULL;
  325. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  326. }
  327. }
  328. if(dwErr == ERROR_SUCCESS)
  329. {
  330. if(!LookupAccountName(pwszServer,
  331. pName->ptstrName,
  332. *ppsid,
  333. &cusid,
  334. domain,
  335. &crd,
  336. &esidtype))
  337. {
  338. dwErr = GetLastError();
  339. AccFree(*ppsid);
  340. *ppsid = NULL;
  341. }
  342. if(crd > BASE_DOMAIN_NAME_SIZE)
  343. {
  344. AccFree(domain);
  345. }
  346. }
  347. }
  348. }
  349. else
  350. {
  351. //
  352. // See if is a translation of a known name
  353. //
  354. dwErr = AccpLoadLocalizedNameTranslations();
  355. *ppsid = NULL;
  356. if(dwErr == ERROR_SUCCESS)
  357. {
  358. //
  359. // Check our well known sids
  360. //
  361. static SID_IDENTIFIER_AUTHORITY UaspBuiltinAuthority =
  362. SECURITY_NT_AUTHORITY;
  363. DWORD BuiltSid[sizeof(SID)/sizeof(DWORD) + 2 ];
  364. PSID pSid = (PSID)BuiltSid;
  365. RtlInitializeSid( pSid,
  366. &UaspBuiltinAuthority,
  367. 1 );
  368. *(RtlSubAuthoritySid(pSid, 0)) = SECURITY_BUILTIN_DOMAIN_RID;
  369. for( ULONG i = 0;
  370. i < sizeof( NameSidLookup ) / sizeof( NAME_RID_INFO );
  371. i++ )
  372. {
  373. if ( _wcsicmp( pName->ptstrName, NameSidLookup[ i ].pwszName ) == 0)
  374. {
  375. *(RtlSubAuthoritySid(pSid, 1)) = NameSidLookup[ i ].Rid;
  376. break;
  377. }
  378. }
  379. if ( i == sizeof( NameSidLookup ) / sizeof( NAME_RID_INFO ) )
  380. {
  381. pSid = NULL;
  382. }
  383. else
  384. {
  385. dwErr = ERROR_SUCCESS;
  386. ACC_ALLOC_AND_COPY_SID(pSid,
  387. *ppsid,
  388. dwErr);
  389. }
  390. }
  391. //
  392. // See if we have a server name specified in the user name
  393. // when we didn't have one provided.
  394. //
  395. if(pwszServer == NULL)
  396. {
  397. ACC_ALLOC_AND_COPY_STRINGW(pName->ptstrName,
  398. pwszTempName,
  399. dwErr );
  400. if(dwErr == ERROR_SUCCESS)
  401. {
  402. pwszSep = wcschr(pwszTempName, L'\\');
  403. if(pwszSep != NULL)
  404. {
  405. *pwszSep = L'\0';
  406. dwErr = AccpDoSidLookup(pwszTempName,
  407. pwszSep + 1,
  408. ppsid,
  409. pSidType);
  410. if(dwErr != ERROR_SUCCESS)
  411. {
  412. //
  413. // Ok, may that was a domain name instead of a
  414. // server name
  415. //
  416. PDOMAIN_CONTROLLER_INFOW pDCI = NULL;
  417. dwErr = DsGetDcNameW(NULL,
  418. pwszTempName,
  419. NULL,
  420. NULL,
  421. 0,
  422. &pDCI);
  423. if(dwErr == ERROR_SUCCESS)
  424. {
  425. dwErr = AccpDoSidLookup(
  426. pDCI[0].DomainControllerAddress,
  427. pwszSep + 1,
  428. ppsid,
  429. pSidType );
  430. NetApiBufferFree(pDCI);
  431. }
  432. }
  433. }
  434. LocalFree(pwszTempName);
  435. }
  436. }
  437. //
  438. // If for any reason we haven't converted it, go ahead and
  439. // dump it as a string.
  440. //
  441. if(*ppsid == NULL)
  442. {
  443. dwErr = ConvertStringToSid(pName->ptstrName,
  444. ppsid);
  445. }
  446. }
  447. }
  448. }
  449. else
  450. {
  451. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  452. }
  453. }
  454. }
  455. else
  456. {
  457. //
  458. // Trustee is not of known form
  459. //
  460. dwErr = ERROR_INVALID_PARAMETER;
  461. }
  462. if(dwErr == ERROR_SUCCESS)
  463. {
  464. *pSidType = esidtype;
  465. }
  466. return(dwErr);
  467. }
  468. //+---------------------------------------------------------------------------
  469. //
  470. // Function : AccGetSidFromToken
  471. //
  472. // Synopsis : Gets the SID from the given token handle
  473. //
  474. // Arguments: IN pwszServer -- Name of server to remote the
  475. // call to
  476. // IN [hToken] -- Token handle
  477. // IN [TIC] -- Token information class
  478. // OUT [ppSidFromToken]-- Where the SID is returned
  479. //
  480. // Returns: ERROR_SUCCESS -- Everything worked
  481. // ERROR_NOT_ENOUGH_MEMORY A memory allocation failed
  482. //
  483. //----------------------------------------------------------------------------
  484. DWORD AccGetSidFromToken(IN PWSTR pwszServer,
  485. IN HANDLE hToken,
  486. IN TOKEN_INFORMATION_CLASS TIC,
  487. IN PSID *ppSidFromToken)
  488. {
  489. DWORD dwErr = ERROR_SUCCESS;
  490. ULONG cSize;
  491. BYTE bBuf[64];
  492. PTOKEN_USER pTknUsr = (TOKEN_USER *)bBuf;
  493. if(GetTokenInformation(hToken,
  494. TIC,
  495. pTknUsr,
  496. sizeof(bBuf),
  497. &cSize) == FALSE)
  498. {
  499. dwErr = GetLastError();
  500. if(dwErr == ERROR_INSUFFICIENT_BUFFER)
  501. {
  502. dwErr = ERROR_SUCCESS;
  503. pTknUsr = (PTOKEN_USER)AccAlloc(cSize);
  504. if(pTknUsr == NULL)
  505. {
  506. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  507. }
  508. else
  509. {
  510. //
  511. // Now, call it again...
  512. //
  513. if(GetTokenInformation(hToken,
  514. TIC,
  515. pTknUsr,
  516. sizeof(bBuf),
  517. &cSize) == FALSE)
  518. {
  519. dwErr = GetLastError();
  520. //
  521. // deallocate our buffer here, since noone else
  522. // will
  523. //
  524. AccFree(pTknUsr);
  525. }
  526. }
  527. }
  528. }
  529. //
  530. // One way or another, we got the token info, so we'll grab the
  531. // sid
  532. //
  533. if(dwErr == ERROR_SUCCESS)
  534. {
  535. //
  536. // allocate room for the returned sid
  537. //
  538. ULONG cSidSize = RtlLengthSid(pTknUsr->User.Sid);
  539. *ppSidFromToken = (PSID)AccAlloc(cSidSize);
  540. if(*ppSidFromToken == NULL)
  541. {
  542. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  543. }
  544. else
  545. {
  546. //
  547. // and copy the new sid
  548. //
  549. NTSTATUS Status = RtlCopySid(cSidSize,
  550. *ppSidFromToken,
  551. pTknUsr->User.Sid);
  552. if(!NT_SUCCESS(Status))
  553. {
  554. dwErr = RtlNtStatusToDosError(Status);
  555. AccFree(*ppSidFromToken);
  556. *ppSidFromToken = NULL;
  557. }
  558. }
  559. //
  560. // See if we had to allocate
  561. //
  562. if(pTknUsr != (PTOKEN_USER)bBuf)
  563. {
  564. AccFree(pTknUsr);
  565. }
  566. }
  567. return(dwErr);
  568. }
  569. //+---------------------------------------------------------------------------
  570. //
  571. // Function : AccLookupAccountTrustee
  572. //
  573. // Synopsis : returns the TRUSTEE for the specified sid
  574. //
  575. // Arguments: [IN pwszServer] -- The server to remote the call to
  576. // OUT [pTrustee] -- the returned trustee
  577. // IN [pSid] -- the SID
  578. //
  579. // Returns: ERROR_SUCCESS -- Everything worked
  580. // ERROR_NOT_ENOUGH_MEMORY A memory allocation failed
  581. //
  582. //----------------------------------------------------------------------------
  583. DWORD AccLookupAccountTrustee(IN PWSTR pwszServer,
  584. IN PSID pSid,
  585. OUT PTRUSTEE *ppTrustee)
  586. {
  587. #define BASE_TRUSTEE_NAME_SIZE 256
  588. acDebugOut((DEB_TRACE_ACC, "in AccLookupAccountTrustee \n"));
  589. PWSTR pwszName;
  590. PWSTR pwszDomain;
  591. SID_NAME_USE SidType;
  592. DWORD dwErr = AccLookupAccountName(pwszServer,
  593. pSid,
  594. &pwszName,
  595. &pwszDomain,
  596. &SidType);
  597. if(dwErr == ERROR_SUCCESS)
  598. {
  599. PTRUSTEE pTrustee;
  600. LPWSTR pName;
  601. pTrustee = (PTRUSTEE) AccAlloc(sizeof(TRUSTEE) + SIZE_PWSTR(pwszName));
  602. if(pTrustee != NULL)
  603. {
  604. pName = (LPWSTR) ((PBYTE)pTrustee + sizeof(TRUSTEE));
  605. CopyMemory(pName,
  606. pwszName,
  607. SIZE_PWSTR(pwszName));
  608. pTrustee->pMultipleTrustee = NULL;
  609. pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
  610. pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
  611. pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
  612. pTrustee->ptstrName = pName;
  613. *ppTrustee = pTrustee;
  614. if(SidType == SidTypeUnknown)
  615. {
  616. pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
  617. }
  618. else
  619. {
  620. pTrustee->TrusteeType = (TRUSTEE_TYPE)(SidType);
  621. }
  622. }
  623. else
  624. {
  625. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  626. }
  627. AccFree(pwszName);
  628. AccFree(pwszDomain);
  629. }
  630. acDebugOut((DEB_TRACE_ACC, "out AccLookupAccountTrustee:%lu\n", dwErr));
  631. return(dwErr);
  632. }
  633. //+---------------------------------------------------------------------------
  634. //
  635. // Function : AccLookupAccountName
  636. //
  637. // Synopsis : Returns the name for the given SID
  638. //
  639. // Arguments: [IN pwszServer] -- The name of the server to remote
  640. // the call to.
  641. // [IN pSid] -- the SID to lookup the name for
  642. // [OUT ppwszName] -- Where the name is returned
  643. // [OUT pSidType] -- Where the SID type is returned
  644. //
  645. // Returns: ERROR_SUCCESS -- Success
  646. // ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed.
  647. //
  648. //----------------------------------------------------------------------------
  649. DWORD AccLookupAccountName(IN PWSTR pwszServer,
  650. IN PSID pSid,
  651. OUT LPWSTR *ppwszName,
  652. OUT LPWSTR *ppwszDomain,
  653. OUT SID_NAME_USE *pSidType)
  654. {
  655. #define BASE_TRUSTEE_NAME_SIZE 256
  656. acDebugOut((DEB_TRACE_ACC,"in AccLookupAccountName\n"));
  657. DWORD dwErr = ERROR_SUCCESS;
  658. SID_NAME_USE esidtype = SidTypeUnknown;
  659. LPWSTR pwszDomain = NULL;
  660. LPWSTR pwszName = NULL;
  661. ULONG cName = 0;
  662. ULONG cDomain = 0;
  663. DebugDumpSid("AccLookupAccountName", pSid);
  664. if(LookupAccountSid(pwszServer,
  665. pSid,
  666. NULL,
  667. &cName,
  668. NULL,
  669. &cDomain,
  670. &esidtype) == FALSE)
  671. {
  672. pwszName = NULL;
  673. dwErr = GetLastError();
  674. if(dwErr == ERROR_INSUFFICIENT_BUFFER)
  675. {
  676. dwErr = ERROR_SUCCESS;
  677. //
  678. // Allocate for the name and the domain
  679. //
  680. pwszName = (PWSTR)AccAlloc(cName * sizeof(WCHAR));
  681. if(pwszName != NULL)
  682. {
  683. pwszDomain = (PWSTR)AccAlloc(cDomain * sizeof(WCHAR));
  684. if(pwszDomain == NULL)
  685. {
  686. AccFree(pwszName);
  687. pwszName = NULL;
  688. }
  689. }
  690. if(pwszName == NULL)
  691. {
  692. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  693. }
  694. if(dwErr == ERROR_SUCCESS)
  695. {
  696. if(LookupAccountSid(pwszServer,
  697. pSid,
  698. pwszName,
  699. &cName,
  700. pwszDomain,
  701. &cDomain,
  702. &esidtype) == FALSE)
  703. {
  704. dwErr = GetLastError();
  705. AccFree(pwszName);
  706. pwszName = NULL;
  707. AccFree(pwszDomain);
  708. pwszDomain = NULL;
  709. }
  710. }
  711. }
  712. else // if(dwErr == ERROR_NONE_MAPPED)
  713. {
  714. dwErr = AccpLoadLocalizedNameTranslations();
  715. if(dwErr == ERROR_SUCCESS)
  716. {
  717. //
  718. // Check our well known sids
  719. //
  720. static SID_IDENTIFIER_AUTHORITY UaspBuiltinAuthority =
  721. SECURITY_NT_AUTHORITY;
  722. DWORD BuiltSid[sizeof(SID)/sizeof(DWORD) + 2 ];
  723. PSID pKnownSid = (PSID)BuiltSid;
  724. RtlInitializeSid( pKnownSid,
  725. &UaspBuiltinAuthority,
  726. 1 );
  727. *(RtlSubAuthoritySid(pKnownSid, 0)) = SECURITY_BUILTIN_DOMAIN_RID;
  728. for( ULONG i = 0;i < sizeof( NameSidLookup ) / sizeof( NAME_RID_INFO ); i++)
  729. {
  730. *(RtlSubAuthoritySid(pKnownSid, 1)) = NameSidLookup[ i ].Rid;
  731. if ( RtlEqualSid( pKnownSid, pSid ) == TRUE )
  732. {
  733. ACC_ALLOC_AND_COPY_STRINGW(NameSidLookup[ i ].pwszName,
  734. pwszName,
  735. dwErr);
  736. break;
  737. }
  738. }
  739. }
  740. //
  741. // If it isn't someone we recognize, convert it to a string..
  742. //
  743. if(dwErr == ERROR_SUCCESS && pwszName == NULL)
  744. {
  745. //
  746. // Ok, return the sid as a name
  747. //
  748. UCHAR String[256];
  749. UNICODE_STRING SidStr;
  750. SidStr.Buffer = (PWSTR)String;
  751. SidStr.Length = SidStr.MaximumLength = 256;
  752. NTSTATUS Status = RtlConvertSidToUnicodeString(&SidStr,
  753. pSid,
  754. FALSE);
  755. if(NT_SUCCESS(Status))
  756. {
  757. ACC_ALLOC_AND_COPY_STRINGW(SidStr.Buffer,
  758. pwszName,
  759. dwErr);
  760. }
  761. else
  762. {
  763. dwErr = RtlNtStatusToDosError(Status);
  764. }
  765. }
  766. }
  767. }
  768. if(dwErr == ERROR_SUCCESS)
  769. {
  770. #if 1
  771. //
  772. // Convert to RDN
  773. //
  774. *ppwszName = pwszName;
  775. *ppwszDomain = pwszDomain;
  776. *pSidType = esidtype;
  777. ULONG cLen = wcslen(pwszName);
  778. if(pwszDomain != NULL && *pwszDomain != L'\0')
  779. {
  780. cLen += wcslen(pwszDomain) + 1;
  781. }
  782. if(cLen != wcslen(pwszName))
  783. {
  784. cLen++;
  785. PWSTR pwszFullName = (PWSTR)AccAlloc(cLen * sizeof(WCHAR));
  786. if(pwszFullName == NULL)
  787. {
  788. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  789. }
  790. else
  791. {
  792. swprintf(pwszFullName,
  793. L"%ws\\%ws",
  794. pwszDomain,
  795. pwszName);
  796. AccFree(pwszName);
  797. pwszName = NULL;
  798. *ppwszName = pwszFullName;
  799. }
  800. }
  801. AccFree(pwszDomain);
  802. pwszDomain = NULL;
  803. *ppwszDomain = NULL;
  804. #else
  805. dwErr = Nt4NameToNt5Name(pwszName,
  806. pwszDomain,
  807. ppwszName);
  808. if(dwErr == ERROR_SUCCESS)
  809. {
  810. AccFree(pwszName);
  811. *ppwszDomain = pwszDomain;
  812. *pSidType = esidtype;
  813. }
  814. #endif
  815. }
  816. if(dwErr != ERROR_SUCCESS)
  817. {
  818. AccFree(pwszDomain);
  819. AccFree(pwszName);
  820. }
  821. acDebugOut((DEB_TRACE_ACC,"Out AccLookupAccountName: %lu\n", dwErr));
  822. return(dwErr);
  823. }
  824. //+---------------------------------------------------------------------------
  825. //
  826. // Function : GetDesiredAccess
  827. //
  828. // Synopsis : Gets the access required to open object to be able to set or
  829. // get the specified security info.
  830. //
  831. // Arguments: IN [SecurityOpenType] - Flag indicating if the object is to be
  832. // opened to read or write the DACL
  833. //
  834. //----------------------------------------------------------------------------
  835. ACCESS_MASK GetDesiredAccess(IN SECURITY_OPEN_TYPE OpenType,
  836. IN SECURITY_INFORMATION SecurityInfo)
  837. {
  838. acDebugOut((DEB_TRACE_ACC, "in GetDesiredAccess \n"));
  839. ACCESS_MASK DesiredAccess = 0;
  840. if ( (SecurityInfo & OWNER_SECURITY_INFORMATION) ||
  841. (SecurityInfo & GROUP_SECURITY_INFORMATION) )
  842. {
  843. switch (OpenType)
  844. {
  845. case READ_ACCESS_RIGHTS:
  846. DesiredAccess |= READ_CONTROL;
  847. break;
  848. case WRITE_ACCESS_RIGHTS:
  849. DesiredAccess |= WRITE_OWNER;
  850. break;
  851. case MODIFY_ACCESS_RIGHTS:
  852. DesiredAccess |= READ_CONTROL | WRITE_OWNER;
  853. break;
  854. }
  855. }
  856. if (SecurityInfo & DACL_SECURITY_INFORMATION)
  857. {
  858. switch (OpenType)
  859. {
  860. case READ_ACCESS_RIGHTS:
  861. DesiredAccess |= READ_CONTROL;
  862. break;
  863. case WRITE_ACCESS_RIGHTS:
  864. DesiredAccess |= WRITE_DAC;
  865. break;
  866. case MODIFY_ACCESS_RIGHTS:
  867. DesiredAccess |= READ_CONTROL | WRITE_DAC;
  868. break;
  869. }
  870. }
  871. if (SecurityInfo & SACL_SECURITY_INFORMATION)
  872. {
  873. DesiredAccess |= ACCESS_SYSTEM_SECURITY;
  874. }
  875. acDebugOut((DEB_TRACE_ACC, "out GetDesiredAccess: %lu\n", DesiredAccess));
  876. return (DesiredAccess);
  877. }
  878. //+---------------------------------------------------------------------------
  879. //
  880. // Function : GetSecurityDescriptorParts
  881. //
  882. // Synopsis : extracts the specified components of a security descriptor
  883. // It is the responsibility of the invoker to free (using AccFree)
  884. // any acquired security components.
  885. //
  886. // Arguments: IN [pSecurityDescriptor] - the input security descriptor
  887. // IN [SecurityInfo] - flag indicating what security info to return
  888. // OUT [psidOwner] - the (optional) returned owner sid
  889. // OUT [psidGroup] - the (optional) returned group sid
  890. // OUT [pDacl] - the (optional) returned DACL
  891. // OUT [pSacl] - the (optional) returned SACL
  892. //
  893. // Returns:
  894. //
  895. //----------------------------------------------------------------------------
  896. DWORD GetSecurityDescriptorParts( IN PISECURITY_DESCRIPTOR pSecurityDescriptor,
  897. IN SECURITY_INFORMATION SecurityInfo,
  898. OUT PSID *psidOwner,
  899. OUT PSID *psidGroup,
  900. OUT PACL *pDacl,
  901. OUT PACL *pSacl,
  902. OUT PSECURITY_DESCRIPTOR *pOutSecurityDescriptor)
  903. {
  904. acDebugOut((DEB_TRACE_ACC, "in GetSecurityDescriptorParts\n"));
  905. NTSTATUS Status;
  906. DWORD dwErr = ERROR_SUCCESS;
  907. //
  908. // if no security descriptor found, don't return one!
  909. //
  910. if(psidOwner)
  911. {
  912. *psidOwner = NULL;
  913. }
  914. if(psidGroup)
  915. {
  916. *psidGroup = NULL;
  917. }
  918. if(pDacl)
  919. {
  920. *pDacl = NULL;
  921. }
  922. if(pSacl)
  923. {
  924. *pSacl = NULL;
  925. }
  926. *pOutSecurityDescriptor = NULL;
  927. if(pSecurityDescriptor)
  928. {
  929. PSID owner = NULL, group = NULL;
  930. PACL dacl = NULL, sacl = NULL;
  931. ULONG cSize = sizeof(SECURITY_DESCRIPTOR);
  932. BOOLEAN bDummy, bParmPresent = FALSE;
  933. PISECURITY_DESCRIPTOR pOutSD;
  934. //
  935. // if the security descriptor is self relative, get absolute
  936. // pointers to the components
  937. //
  938. Status = RtlGetOwnerSecurityDescriptor(pSecurityDescriptor,
  939. &owner,
  940. &bDummy);
  941. if(NT_SUCCESS(Status))
  942. {
  943. Status = RtlGetGroupSecurityDescriptor(pSecurityDescriptor,
  944. &group,
  945. &bDummy);
  946. }
  947. if(NT_SUCCESS(Status))
  948. {
  949. Status = RtlGetDaclSecurityDescriptor(pSecurityDescriptor,
  950. &bParmPresent,
  951. &dacl,
  952. &bDummy);
  953. if(NT_SUCCESS(Status) && !bParmPresent)
  954. {
  955. dacl = NULL;
  956. }
  957. }
  958. if(NT_SUCCESS(Status))
  959. {
  960. Status = RtlGetSaclSecurityDescriptor(pSecurityDescriptor,
  961. &bParmPresent,
  962. &sacl,
  963. &bDummy);
  964. if(NT_SUCCESS(Status) && !bParmPresent)
  965. {
  966. sacl = NULL;
  967. }
  968. }
  969. if(NT_SUCCESS(Status))
  970. {
  971. //
  972. // Build the new security descriptor
  973. //
  974. cSize = RtlLengthSecurityDescriptor( pSecurityDescriptor ) +
  975. sizeof(SECURITY_DESCRIPTOR) - sizeof(SECURITY_DESCRIPTOR_RELATIVE);
  976. pOutSD = (PISECURITY_DESCRIPTOR)AccAlloc(cSize);
  977. if(pOutSD == NULL)
  978. {
  979. return(ERROR_NOT_ENOUGH_MEMORY);
  980. }
  981. RtlCreateSecurityDescriptor(pOutSD, SECURITY_DESCRIPTOR_REVISION);
  982. void *bufptr = Add2Ptr(pOutSD, sizeof(SECURITY_DESCRIPTOR));
  983. if(SecurityInfo & OWNER_SECURITY_INFORMATION)
  984. {
  985. if(NULL != owner)
  986. {
  987. //
  988. // no error checking as these should not fail!!
  989. //
  990. RtlCopySid(RtlLengthSid(owner), (PSID)bufptr, owner);
  991. RtlSetOwnerSecurityDescriptor(pOutSD,
  992. (PSID)bufptr, FALSE);
  993. bufptr = Add2Ptr(bufptr,RtlLengthSid(owner));
  994. if(psidOwner)
  995. {
  996. *psidOwner = pOutSD->Owner;
  997. }
  998. }
  999. else
  1000. {
  1001. AccFree(pOutSD);
  1002. return(ERROR_NO_SECURITY_ON_OBJECT);
  1003. }
  1004. }
  1005. if(SecurityInfo & GROUP_SECURITY_INFORMATION)
  1006. {
  1007. if(NULL != group)
  1008. {
  1009. //
  1010. // no error checking as these should not fail!!
  1011. //
  1012. RtlCopySid(RtlLengthSid(group), (PSID)bufptr, group);
  1013. RtlSetGroupSecurityDescriptor(pOutSD,
  1014. (PSID)bufptr, FALSE);
  1015. bufptr = Add2Ptr(bufptr,RtlLengthSid(group));
  1016. if(psidGroup)
  1017. {
  1018. *psidGroup = pOutSD->Group;
  1019. }
  1020. }
  1021. else
  1022. {
  1023. AccFree(pOutSD);
  1024. return(ERROR_NO_SECURITY_ON_OBJECT);
  1025. }
  1026. }
  1027. //
  1028. // The DACL and SACL may or may not be on the object.
  1029. //
  1030. if(SecurityInfo & DACL_SECURITY_INFORMATION)
  1031. {
  1032. if(NULL != dacl)
  1033. {
  1034. RtlCopyMemory(bufptr, dacl, dacl->AclSize);
  1035. RtlSetDaclSecurityDescriptor(pOutSD,
  1036. TRUE,
  1037. (ACL *)bufptr,
  1038. FALSE);
  1039. if(pDacl)
  1040. {
  1041. *pDacl = pOutSD->Dacl;
  1042. }
  1043. }
  1044. }
  1045. if(SecurityInfo & SACL_SECURITY_INFORMATION)
  1046. {
  1047. if(NULL != sacl)
  1048. {
  1049. RtlCopyMemory(bufptr, sacl, sacl->AclSize);
  1050. RtlSetSaclSecurityDescriptor(pOutSD,
  1051. TRUE,
  1052. (PACL)bufptr,
  1053. FALSE);
  1054. if(pSacl)
  1055. {
  1056. *pSacl = pOutSD->Sacl;
  1057. }
  1058. }
  1059. }
  1060. *pOutSecurityDescriptor = pOutSD;
  1061. }
  1062. if(!NT_SUCCESS(Status))
  1063. {
  1064. dwErr = RtlNtStatusToDosError(Status);
  1065. }
  1066. }
  1067. acDebugOut((DEB_TRACE_ACC, "Out GetSecurityDescriptorParts(%d)\n", dwErr));
  1068. return(dwErr);
  1069. }
  1070. //+---------------------------------------------------------------------------
  1071. //
  1072. // Function : ParseName
  1073. //
  1074. // Synopsis : parses a UNC name for the machine name
  1075. //
  1076. // Arguments: [IN OUT pObjectName] -- the name of the object
  1077. // [OUT pMachineName] -- the machine the object is on
  1078. // [OUT pRemainingName] -- the remaining name after the
  1079. // machine name
  1080. //
  1081. // Returns: ERROR_SUCCESS -- The call succeeded
  1082. //
  1083. //----------------------------------------------------------------------------
  1084. DWORD ParseName(IN OUT LPWSTR pObjectName,
  1085. OUT LPWSTR *pMachineName,
  1086. OUT LPWSTR *pRemainingName)
  1087. {
  1088. acDebugOut((DEB_TRACE_ACC, "in/out ParseName \n"));
  1089. if(pObjectName == wcsstr(pObjectName, L"\\\\"))
  1090. {
  1091. *pMachineName = pObjectName + 2;
  1092. *pRemainingName = wcschr(*pMachineName, L'\\');
  1093. if (*pRemainingName != NULL)
  1094. {
  1095. **pRemainingName = L'\0';
  1096. *pRemainingName += 1;
  1097. }
  1098. }
  1099. else
  1100. {
  1101. *pMachineName = NULL;
  1102. *pRemainingName = pObjectName;
  1103. }
  1104. return(ERROR_SUCCESS);
  1105. }
  1106. //+---------------------------------------------------------------------------
  1107. //
  1108. // Function: DoTrusteesMatch
  1109. //
  1110. // Synopsis: Determines if 2 trustess reference the same thing (ie:
  1111. // (are they equal)
  1112. //
  1113. // Arguments: [IN pwszServer] -- Server to lookup information on
  1114. // [IN pTrustee1] -- First trustee
  1115. // [IN pTrustee2] -- Second trustee
  1116. // [OUT pfMatch] -- Where the match results are
  1117. // returned.
  1118. //
  1119. // Returns: ERROR_SUCCESS -- The operation succeeded
  1120. //
  1121. // Notes:
  1122. //
  1123. //----------------------------------------------------------------------------
  1124. DWORD
  1125. DoTrusteesMatch(IN PWSTR pwszServer,
  1126. IN PTRUSTEE pTrustee1,
  1127. IN PTRUSTEE pTrustee2,
  1128. IN PBOOL pfMatch)
  1129. {
  1130. DWORD dwErr = ERROR_SUCCESS;
  1131. //
  1132. // Assume failure...
  1133. //
  1134. *pfMatch = FALSE;
  1135. //
  1136. // Make sure they are the same type...
  1137. //
  1138. if(pTrustee1->MultipleTrusteeOperation ==
  1139. pTrustee2->MultipleTrusteeOperation)
  1140. {
  1141. //
  1142. // Ok, first compare the base trustee information...
  1143. //
  1144. if(pTrustee1->TrusteeForm == pTrustee2->TrusteeForm)
  1145. {
  1146. //
  1147. // Now, the trustee form... If they match, it's easy... Otherwise,
  1148. // we'll have to do some lookups...
  1149. //
  1150. if(pTrustee1->TrusteeForm == pTrustee2->TrusteeForm)
  1151. {
  1152. if(pTrustee1->TrusteeForm == TRUSTEE_IS_NAME)
  1153. {
  1154. if(_wcsicmp(pTrustee1->ptstrName,
  1155. pTrustee2->ptstrName) == 0)
  1156. {
  1157. *pfMatch = TRUE;
  1158. }
  1159. }
  1160. else
  1161. {
  1162. *pfMatch = RtlEqualSid((PSID)(pTrustee1->ptstrName),
  1163. (PSID)(pTrustee2->ptstrName));
  1164. }
  1165. }
  1166. }
  1167. else
  1168. {
  1169. //
  1170. // We'll look it up...
  1171. //
  1172. PSID pKnownSid;
  1173. PTRUSTEE pLookupTrustee;
  1174. if(pTrustee1->TrusteeForm == TRUSTEE_IS_NAME)
  1175. {
  1176. pLookupTrustee = pTrustee1;
  1177. pKnownSid = (PSID)pTrustee2->ptstrName;
  1178. }
  1179. else
  1180. {
  1181. pLookupTrustee = pTrustee2;
  1182. pKnownSid = (PSID)pTrustee1->ptstrName;
  1183. }
  1184. PSID pNewSid;
  1185. SID_NAME_USE SidType;
  1186. dwErr = AccctrlLookupSid(pwszServer,
  1187. pLookupTrustee->ptstrName,
  1188. TRUE,
  1189. &pNewSid,
  1190. &SidType);
  1191. if(dwErr == ERROR_SUCCESS)
  1192. {
  1193. *pfMatch = RtlEqualSid(pKnownSid,
  1194. pNewSid);
  1195. AccFree(pNewSid);
  1196. }
  1197. }
  1198. //
  1199. // Now, if that worked, look for the multiple trustee case
  1200. //
  1201. if(dwErr == ERROR_SUCCESS && *pfMatch == TRUE &&
  1202. pTrustee1->MultipleTrusteeOperation == TRUSTEE_IS_IMPERSONATE)
  1203. {
  1204. dwErr = DoTrusteesMatch(pwszServer,
  1205. pTrustee1->pMultipleTrustee,
  1206. pTrustee2->pMultipleTrustee,
  1207. pfMatch);
  1208. }
  1209. }
  1210. return(dwErr);
  1211. }
  1212. //+---------------------------------------------------------------------------
  1213. //
  1214. // Function: AccessMaskForAccessEntry
  1215. //
  1216. // Synopsis: Converts a Provider Independent access entry to an NT
  1217. // access mask format.
  1218. //
  1219. // Arguments: [IN pAE] -- The access entry that gets
  1220. // converted
  1221. //
  1222. // Returns: Converted acess mask
  1223. //
  1224. // Notes:
  1225. //
  1226. //----------------------------------------------------------------------------
  1227. ACCESS_MASK
  1228. AccessMaskForAccessEntry(IN PACTRL_ACCESS_ENTRY pAE,
  1229. IN SE_OBJECT_TYPE ObjType)
  1230. {
  1231. ACCESS_MASK RetMask = 0;
  1232. //
  1233. // We have some standard rights, so we'll add those in
  1234. //
  1235. if((pAE->Access & (ACTRL_STD_RIGHTS_ALL)) != 0)
  1236. {
  1237. RetMask = (pAE->Access & ACTRL_STD_RIGHTS_ALL) >> 11;
  1238. }
  1239. if((pAE->Access & (ACTRL_SYSTEM_ACCESS)) != 0)
  1240. {
  1241. RetMask |= ACCESS_SYSTEM_SECURITY;
  1242. }
  1243. //
  1244. // Then, we or in the rest of the access bits, plus the provider specific
  1245. // bits.
  1246. //
  1247. RetMask |= (pAE->Access & ~(ACTRL_STD_RIGHTS_ALL | ACTRL_SYSTEM_ACCESS));
  1248. RetMask |= pAE->ProvSpecificAccess;
  1249. //
  1250. // Handle any special case stuff here
  1251. //
  1252. switch (ObjType)
  1253. {
  1254. case SE_FILE_OBJECT:
  1255. case SE_SERVICE:
  1256. case SE_PRINTER:
  1257. case SE_REGISTRY_KEY:
  1258. case SE_LMSHARE:
  1259. case SE_KERNEL_OBJECT:
  1260. case SE_WINDOW_OBJECT:
  1261. case SE_DS_OBJECT:
  1262. case SE_DS_OBJECT_ALL:
  1263. default:
  1264. break;
  1265. }
  1266. return(RetMask);
  1267. }
  1268. //+---------------------------------------------------------------------------
  1269. //
  1270. // Function: AccConvertAccessMaskToActrlAccess
  1271. //
  1272. // Synopsis: Converts an NT access mask to the appropriate Provider
  1273. // Independent format.
  1274. //
  1275. // Arguments: [IN Access] -- Access mask to convert
  1276. // [IN ObjType] -- Type of the object
  1277. // [IN KernelObjectType] If this is a kernel object, the type of the
  1278. // object
  1279. // [IN pAE] -- The access entry that gets
  1280. // modified
  1281. //
  1282. // Returns: VOID
  1283. //
  1284. // Notes:
  1285. //
  1286. //----------------------------------------------------------------------------
  1287. VOID
  1288. AccConvertAccessMaskToActrlAccess(IN ACCESS_MASK Access,
  1289. IN SE_OBJECT_TYPE ObjType,
  1290. IN MARTA_KERNEL_TYPE KernelObjectType,
  1291. IN PACTRL_ACCESS_ENTRY pAE)
  1292. {
  1293. //
  1294. // Ok, first thing we'll have to do is look for and remove any generic
  1295. // rights.
  1296. //
  1297. GENERIC_MAPPING GenMap = {0, 0, 0, 0};
  1298. switch(ObjType)
  1299. {
  1300. case SE_FILE_OBJECT:
  1301. case SE_LMSHARE:
  1302. GenMap.GenericRead = FILE_GENERIC_READ;
  1303. GenMap.GenericWrite = FILE_GENERIC_WRITE;
  1304. GenMap.GenericExecute = FILE_GENERIC_EXECUTE;
  1305. GenMap.GenericAll = FILE_ALL_ACCESS;
  1306. break;
  1307. case SE_SERVICE:
  1308. GenMap.GenericRead = STANDARD_RIGHTS_READ |
  1309. SERVICE_QUERY_CONFIG |
  1310. SERVICE_QUERY_STATUS |
  1311. SERVICE_ENUMERATE_DEPENDENTS |
  1312. SERVICE_INTERROGATE;
  1313. GenMap.GenericWrite = STANDARD_RIGHTS_WRITE |
  1314. SERVICE_CHANGE_CONFIG;
  1315. GenMap.GenericExecute = STANDARD_RIGHTS_EXECUTE |
  1316. SERVICE_START |
  1317. SERVICE_STOP |
  1318. SERVICE_PAUSE_CONTINUE |
  1319. SERVICE_USER_DEFINED_CONTROL;
  1320. GenMap.GenericAll = SERVICE_ALL_ACCESS;
  1321. break;
  1322. case SE_PRINTER:
  1323. GenMap.GenericRead = PRINTER_READ;
  1324. GenMap.GenericWrite = PRINTER_WRITE;
  1325. GenMap.GenericExecute = PRINTER_EXECUTE;
  1326. GenMap.GenericAll = PRINTER_ALL_ACCESS;
  1327. break;
  1328. case SE_REGISTRY_KEY:
  1329. GenMap.GenericRead = KEY_READ;
  1330. GenMap.GenericWrite = KEY_WRITE;
  1331. GenMap.GenericExecute = KEY_EXECUTE;
  1332. GenMap.GenericAll = KEY_ALL_ACCESS;
  1333. break;
  1334. case SE_KERNEL_OBJECT:
  1335. switch ( KernelObjectType )
  1336. {
  1337. // case MARTA_WMI_GUID:
  1338. // GenMap.GenericRead = WMIGUID_QUERY;
  1339. // GenMap.GenericWrite = WMIGUID_SET;
  1340. // GenMap.GenericExecute = WMIGUID_EXECUTE;
  1341. // GenMap.GenericAll = WMIGUID_QUERY | WMIGUID_SET | WMIGUID_EXECUTE;
  1342. // break;
  1343. case MARTA_EVENT:
  1344. case MARTA_EVENT_PAIR:
  1345. case MARTA_MUTANT:
  1346. case MARTA_PROCESS:
  1347. case MARTA_SECTION:
  1348. case MARTA_SEMAPHORE:
  1349. case MARTA_SYMBOLIC_LINK:
  1350. case MARTA_THREAD:
  1351. case MARTA_TIMER:
  1352. case MARTA_JOB:
  1353. default:
  1354. GenMap.GenericRead = STANDARD_RIGHTS_READ | 0x1;
  1355. GenMap.GenericWrite = STANDARD_RIGHTS_WRITE | 0x2;
  1356. GenMap.GenericExecute = STANDARD_RIGHTS_EXECUTE | 0x4;
  1357. GenMap.GenericAll = STANDARD_RIGHTS_REQUIRED | 0xFFFF;
  1358. break;
  1359. }
  1360. break;
  1361. case SE_WINDOW_OBJECT:
  1362. GenMap.GenericRead = STANDARD_RIGHTS_READ | 0x1;
  1363. GenMap.GenericWrite = STANDARD_RIGHTS_WRITE | 0x2;
  1364. GenMap.GenericExecute = STANDARD_RIGHTS_EXECUTE | 0x4;
  1365. GenMap.GenericAll = STANDARD_RIGHTS_REQUIRED | 0x1FF;
  1366. break;
  1367. case SE_DS_OBJECT:
  1368. case SE_DS_OBJECT_ALL:
  1369. GenMap.GenericRead = GENERIC_READ_MAPPING;
  1370. GenMap.GenericWrite = GENERIC_WRITE_MAPPING;
  1371. GenMap.GenericExecute = GENERIC_EXECUTE_MAPPING;
  1372. GenMap.GenericAll = GENERIC_ALL_MAPPING;
  1373. break;
  1374. }
  1375. MapGenericMask(&Access,
  1376. &GenMap);
  1377. //
  1378. // Look for the known entries first
  1379. //
  1380. if((Access & STANDARD_RIGHTS_ALL) != 0)
  1381. {
  1382. pAE->Access = (Access & STANDARD_RIGHTS_ALL) << 11;
  1383. }
  1384. if((Access & ACCESS_SYSTEM_SECURITY) != 0)
  1385. {
  1386. pAE->Access |= ACTRL_SYSTEM_ACCESS;
  1387. }
  1388. //
  1389. // Add in the remaining rights
  1390. //
  1391. pAE->Access |= (Access & ~(STANDARD_RIGHTS_ALL | ACCESS_SYSTEM_SECURITY ));
  1392. }
  1393. //+---------------------------------------------------------------------------
  1394. //
  1395. // Function: LoadDLLFuncTable
  1396. //
  1397. // Synopsis:
  1398. //
  1399. // Arguments:
  1400. //+---------------------------------------------------------------------------
  1401. DWORD
  1402. LoadDLLFuncTable()
  1403. {
  1404. DWORD dwErr;
  1405. if( !(DLLFuncs.dwFlags & LOADED_ALL_FUNCS))
  1406. {
  1407. HINSTANCE NetApiHandle = NULL;
  1408. HINSTANCE SamLibHandle = NULL;
  1409. HINSTANCE WinspoolHandle = NULL;
  1410. //
  1411. // Load the functions needed from netapi32.dll
  1412. //
  1413. NetApiHandle = LoadLibraryA( "NetApi32" );
  1414. if(NetApiHandle == NULL)
  1415. {
  1416. dwErr = GetLastError();
  1417. return (dwErr);
  1418. }
  1419. DLLFuncs.PNetApiBufferFree = (PNET_API_BUFFER_FREE)
  1420. GetProcAddress( NetApiHandle, "NetApiBufferFree");
  1421. if(DLLFuncs.PNetApiBufferFree == NULL)
  1422. {
  1423. dwErr = GetLastError();
  1424. return (dwErr);
  1425. }
  1426. DLLFuncs.PNetShareGetInfo = (PNET_SHARE_GET_INFO)
  1427. GetProcAddress( NetApiHandle, "NetShareGetInfo");
  1428. if(DLLFuncs.PNetShareGetInfo == NULL)
  1429. {
  1430. dwErr = GetLastError();
  1431. return (dwErr);
  1432. }
  1433. DLLFuncs.PNetShareSetInfo = (PNET_SHARE_SET_INFO)
  1434. GetProcAddress( NetApiHandle, "NetShareSetInfo");
  1435. if(DLLFuncs.PNetShareSetInfo == NULL)
  1436. {
  1437. dwErr = GetLastError();
  1438. return (dwErr);
  1439. }
  1440. DLLFuncs.PNetDfsGetInfo = (PNET_DFS_GET_INFO)
  1441. GetProcAddress( NetApiHandle, "NetDfsGetInfo");
  1442. if(DLLFuncs.PNetDfsGetInfo == NULL)
  1443. {
  1444. dwErr = GetLastError();
  1445. return (dwErr);
  1446. }
  1447. DLLFuncs.PI_NetGetDCList = (PINET_GET_DC_LIST)
  1448. GetProcAddress( NetApiHandle, "I_NetGetDCList");
  1449. if(DLLFuncs.PI_NetGetDCList == NULL)
  1450. {
  1451. dwErr = GetLastError();
  1452. return (dwErr);
  1453. }
  1454. //
  1455. // Load the functions needed from samlib.dll
  1456. //
  1457. SamLibHandle = LoadLibraryA( "Samlib" );
  1458. if(SamLibHandle == NULL)
  1459. {
  1460. dwErr = GetLastError();
  1461. return (dwErr);
  1462. }
  1463. DLLFuncs.PSamCloseHandle = (PSAM_CLOSE_HANDLE)
  1464. GetProcAddress( SamLibHandle, "SamCloseHandle");
  1465. if(DLLFuncs.PSamCloseHandle == NULL)
  1466. {
  1467. dwErr = GetLastError();
  1468. return (dwErr);
  1469. }
  1470. DLLFuncs.PSamOpenDomain = (PSAM_OPEN_DOMAIN)
  1471. GetProcAddress( SamLibHandle, "SamOpenDomain");
  1472. if(DLLFuncs.PSamOpenDomain == NULL)
  1473. {
  1474. dwErr = GetLastError();
  1475. return (dwErr);
  1476. }
  1477. DLLFuncs.PSamConnect = (PSAM_CONNECT)
  1478. GetProcAddress( SamLibHandle, "SamConnect");
  1479. if(DLLFuncs.PSamConnect == NULL)
  1480. {
  1481. dwErr = GetLastError();
  1482. return (dwErr);
  1483. }
  1484. DLLFuncs.PSamGetMembersInGroup = (PSAM_GET_MEMBERS_IN_GROUP)
  1485. GetProcAddress( SamLibHandle, "SamGetMembersInGroup");
  1486. if(DLLFuncs.PSamGetMembersInGroup == NULL)
  1487. {
  1488. dwErr = GetLastError();
  1489. return (dwErr);
  1490. }
  1491. DLLFuncs.PSamOpenGroup = (PSAM_OPEN_GROUP)
  1492. GetProcAddress( SamLibHandle, "SamOpenGroup");
  1493. if(DLLFuncs.PSamOpenGroup == NULL)
  1494. {
  1495. dwErr = GetLastError();
  1496. return (dwErr);
  1497. }
  1498. DLLFuncs.PSamGetMembersInAlias = (PSAM_GET_MEMBERS_IN_ALIAS)
  1499. GetProcAddress( SamLibHandle, "SamGetMembersInAlias");
  1500. if(DLLFuncs.PSamGetMembersInAlias == NULL)
  1501. {
  1502. dwErr = GetLastError();
  1503. return (dwErr);
  1504. }
  1505. DLLFuncs.PSamOpenAlias = (PSAM_OPEN_ALIAS)
  1506. GetProcAddress( SamLibHandle, "SamOpenAlias");
  1507. if(DLLFuncs.PSamOpenAlias == NULL)
  1508. {
  1509. dwErr = GetLastError();
  1510. return (dwErr);
  1511. }
  1512. //
  1513. // Load functions from winspool.drv
  1514. //
  1515. WinspoolHandle = LoadLibraryA( "winspool.drv" );
  1516. if(WinspoolHandle == NULL)
  1517. {
  1518. dwErr = GetLastError();
  1519. return (dwErr);
  1520. }
  1521. DLLFuncs.POpenPrinter = (POPEN_PRINTER)
  1522. GetProcAddress( WinspoolHandle, "OpenPrinterW");
  1523. if(DLLFuncs.POpenPrinter == NULL)
  1524. {
  1525. dwErr = GetLastError();
  1526. return (dwErr);
  1527. }
  1528. DLLFuncs.PClosePrinter = (PCLOSE_PRINTER)
  1529. GetProcAddress( WinspoolHandle, "ClosePrinter");
  1530. if(DLLFuncs.PClosePrinter == NULL)
  1531. {
  1532. dwErr = GetLastError();
  1533. return (dwErr);
  1534. }
  1535. DLLFuncs.PSetPrinter = (PSET_PRINTER)
  1536. GetProcAddress( WinspoolHandle, "SetPrinterW");
  1537. if(DLLFuncs.PSetPrinter == NULL)
  1538. {
  1539. dwErr = GetLastError();
  1540. return (dwErr);
  1541. }
  1542. DLLFuncs.PGetPrinter = (PGET_PRINTER)
  1543. GetProcAddress( WinspoolHandle, "GetPrinterW");
  1544. if(DLLFuncs.PGetPrinter == NULL)
  1545. {
  1546. dwErr = GetLastError();
  1547. return (dwErr);
  1548. }
  1549. DLLFuncs.dwFlags |= LOADED_ALL_FUNCS;
  1550. }
  1551. return (NO_ERROR);
  1552. }
  1553. //+---------------------------------------------------------------------------
  1554. //
  1555. // Function: AccSetEntriesInAList
  1556. //
  1557. // Synopsis: Helper function. Adds the given access entries to an optional
  1558. // existing list, and returns the resultant list
  1559. //
  1560. // Arguments: [IN cEntries] -- Number of items to add
  1561. // [IN pAccessEntryList] List to add
  1562. // [IN AccessMode] -- How to do the add (MERGE or SET)
  1563. // [IN lpProperty] -- Property to do the add for
  1564. // [IN fDoOldStyleMerge] If TRUE, does an NT4 ACLAPI style
  1565. // merge (Existing explicit entries are
  1566. // removed). Otherwise, and new style
  1567. // merge is done.
  1568. // [IN pOldList] -- Optional. If present, the new items
  1569. // are merged with this list [assuming a
  1570. // merge operation].
  1571. // [OUT ppNewList] -- Where the new list is returned.
  1572. //
  1573. // Returns: ERROR_SUCCESS -- Success
  1574. // ERROR_INVALID_PARAMETER A bad parameter was given
  1575. //
  1576. // Notes:
  1577. //
  1578. //----------------------------------------------------------------------------
  1579. DWORD
  1580. AccSetEntriesInAList(IN ULONG cEntries,
  1581. IN PACTRL_ACCESS_ENTRYW pAccessEntryList,
  1582. IN ACCESS_MODE AccessMode,
  1583. IN SECURITY_INFORMATION SeInfo,
  1584. IN LPCWSTR lpProperty,
  1585. IN BOOL fDoOldStyleMerge,
  1586. IN PACTRL_AUDITW pOldList,
  1587. OUT PACTRL_AUDITW *ppNewList)
  1588. {
  1589. DWORD dwErr = ERROR_SUCCESS;
  1590. //
  1591. // First, a little parameter validation...
  1592. //
  1593. if(pAccessEntryList == NULL || ppNewList == NULL ||
  1594. (SeInfo != SACL_SECURITY_INFORMATION &&
  1595. SeInfo != DACL_SECURITY_INFORMATION))
  1596. {
  1597. dwErr = ERROR_INVALID_PARAMETER;
  1598. }
  1599. else
  1600. {
  1601. CAccessList AccList;
  1602. dwErr = AccList.SetObjectType(SE_UNKNOWN_OBJECT_TYPE);
  1603. if(dwErr == ERROR_SUCCESS)
  1604. {
  1605. if(pOldList != NULL && AccessMode != SET_ACCESS)
  1606. {
  1607. dwErr = AccList.AddAccessLists(SeInfo,
  1608. pOldList,
  1609. FALSE);
  1610. }
  1611. }
  1612. if(dwErr == ERROR_SUCCESS)
  1613. {
  1614. //
  1615. // We need to build a ACTRL_ALIST
  1616. //
  1617. ACTRL_ACCESSW AList;
  1618. ACTRL_PROPERTY_ENTRY APE;
  1619. ACTRL_ACCESS_ENTRY_LIST AAEL;
  1620. AAEL.cEntries = cEntries;
  1621. AAEL.pAccessList = pAccessEntryList;
  1622. APE.lpProperty = (PWSTR)lpProperty;
  1623. APE.pAccessEntryList = &(AAEL);
  1624. APE.fListFlags = 0;
  1625. AList.cEntries = 1;
  1626. AList.pPropertyAccessList = &APE;
  1627. //
  1628. // Now, we'll just do another add...
  1629. //
  1630. if(AccessMode == REVOKE_ACCESS)
  1631. {
  1632. dwErr = AccList.RevokeTrusteeAccess(SeInfo,
  1633. &AList,
  1634. (PWSTR)lpProperty);
  1635. }
  1636. else
  1637. {
  1638. dwErr = AccList.AddAccessLists(SeInfo,
  1639. &AList,
  1640. AccessMode == GRANT_ACCESS ?
  1641. TRUE :
  1642. FALSE,
  1643. fDoOldStyleMerge);
  1644. }
  1645. }
  1646. //
  1647. // If all of that worked, we'll simply marshal it up, and return it
  1648. //
  1649. if(dwErr == ERROR_SUCCESS)
  1650. {
  1651. dwErr = AccList.MarshalAccessLists(
  1652. SeInfo,
  1653. FLAG_ON(SeInfo,
  1654. DACL_SECURITY_INFORMATION) ?
  1655. ppNewList :
  1656. NULL,
  1657. FLAG_ON(SeInfo,
  1658. SACL_SECURITY_INFORMATION) ?
  1659. ppNewList :
  1660. NULL);
  1661. }
  1662. }
  1663. return(dwErr);
  1664. }
  1665. //+---------------------------------------------------------------------------
  1666. //
  1667. // Function: AccConvertAccessToSecurityDescriptor
  1668. //
  1669. // Synopsis: Helper function. Converts a set of access lists and owner/
  1670. // group into a security descriptor. Only items that are present
  1671. // are added.
  1672. //
  1673. // Arguments: [IN pAccessList] -- OPTIONAL. Access list to convert
  1674. // [IN pAuditList] -- OPTIONAL. Audit list to add
  1675. // [IN lpOwner] -- OPTIONAL. Owner to add
  1676. // [IN lpGroup] -- OPTIONAL. Group to add
  1677. // [OUT ppSecDescriptor] Where the created security descriptor
  1678. // is returned.
  1679. //
  1680. // Returns: ERROR_SUCCESS -- Success
  1681. // ERROR_INVALID_PARAMETER A bad parameter was given
  1682. //
  1683. // Notes: The returned security descriptor must be freed via LocalFree
  1684. //
  1685. //----------------------------------------------------------------------------
  1686. DWORD
  1687. AccConvertAccessToSecurityDescriptor(IN PACTRL_ACCESSW pAccessList,
  1688. IN PACTRL_AUDITW pAuditList,
  1689. IN LPCWSTR lpOwner,
  1690. IN LPCWSTR lpGroup,
  1691. OUT PSECURITY_DESCRIPTOR *ppSecDescriptor)
  1692. {
  1693. DWORD dwErr = ERROR_SUCCESS;
  1694. //
  1695. // First, verify the parameters. At least one has to be present
  1696. //
  1697. if(pAccessList == NULL && pAuditList == NULL && lpOwner == NULL &&
  1698. lpGroup == NULL)
  1699. {
  1700. dwErr = ERROR_INVALID_PARAMETER;
  1701. }
  1702. else
  1703. {
  1704. //
  1705. // Initialize our access lists
  1706. //
  1707. CAccessList AccList;
  1708. TRUSTEE_W Group;
  1709. TRUSTEE_W Owner;
  1710. dwErr = AccList.SetObjectType(SE_UNKNOWN_OBJECT_TYPE);
  1711. if(dwErr == ERROR_SUCCESS && lpGroup != NULL)
  1712. {
  1713. memset(&Group, 0, sizeof(TRUSTEE_W));
  1714. Group.TrusteeForm = TRUSTEE_IS_NAME;
  1715. Group.ptstrName = (PWSTR)lpGroup;
  1716. dwErr = AccList.AddOwnerGroup(GROUP_SECURITY_INFORMATION,
  1717. NULL,
  1718. &Group);
  1719. }
  1720. if(dwErr == ERROR_SUCCESS && lpOwner)
  1721. {
  1722. memset(&Owner, 0, sizeof(TRUSTEE_W));
  1723. Owner.TrusteeForm = TRUSTEE_IS_NAME;
  1724. Owner.ptstrName = (PWSTR)lpOwner;
  1725. dwErr = AccList.AddOwnerGroup(OWNER_SECURITY_INFORMATION,
  1726. &Owner,
  1727. NULL);
  1728. }
  1729. if(dwErr == ERROR_SUCCESS && pAccessList != NULL)
  1730. {
  1731. dwErr = AccList.AddAccessLists(DACL_SECURITY_INFORMATION,
  1732. pAccessList,
  1733. FALSE);
  1734. }
  1735. if(dwErr == ERROR_SUCCESS && pAuditList != NULL)
  1736. {
  1737. dwErr = AccList.AddAccessLists(SACL_SECURITY_INFORMATION,
  1738. pAuditList,
  1739. FALSE);
  1740. }
  1741. //
  1742. // Now, build the Security Descriptor
  1743. //
  1744. if(dwErr == ERROR_SUCCESS)
  1745. {
  1746. SECURITY_INFORMATION SeInfo;
  1747. dwErr = AccList.BuildSDForAccessList(ppSecDescriptor,
  1748. &SeInfo,
  1749. ACCLIST_SD_ABSOK |
  1750. ACCLIST_SD_NOFREE);
  1751. }
  1752. }
  1753. return(dwErr);
  1754. }
  1755. //+---------------------------------------------------------------------------
  1756. //
  1757. // Function: AccConvertSDToAccess
  1758. //
  1759. // Synopsis: Helper function. "Cracks" a security descriptor into the
  1760. // associated access lists and owner/group. Only the OUT
  1761. // parameters that are supplied will be cracked
  1762. //
  1763. // Arguments: [IN ObjectType] -- What type of object the security
  1764. // descriptor came from
  1765. // [IN pSecDescriptor]-- Security descriptor to crack
  1766. // [OUT ppAccessList] -- OPTIONAL. Where the access list is
  1767. // returned.
  1768. // [OUT ppAuditList] -- OPTIONAL. Where the audit list is
  1769. // returned
  1770. // [OUT lppOwner] -- OPTIONAL. Where the owner is returned
  1771. // [OUT lppGroup] -- OPTIONAL. Where the group is returned
  1772. //
  1773. // Returns: ERROR_SUCCESS -- Success
  1774. // ERROR_INVALID_PARAMETER A bad parameter was given
  1775. //
  1776. // Notes: The returned items must be freed via LocalFree
  1777. //
  1778. //----------------------------------------------------------------------------
  1779. DWORD
  1780. AccConvertSDToAccess(IN SE_OBJECT_TYPE ObjectType,
  1781. IN PSECURITY_DESCRIPTOR pSecDescriptor,
  1782. OUT PACTRL_ACCESSW *ppAccessList,
  1783. OUT PACTRL_AUDITW *ppAuditList,
  1784. OUT LPWSTR *lppOwner,
  1785. OUT LPWSTR *lppGroup)
  1786. {
  1787. DWORD dwErr = ERROR_SUCCESS;
  1788. //
  1789. // Make sure we have valid parameters
  1790. //
  1791. if(pSecDescriptor == NULL || ObjectType == SE_UNKNOWN_OBJECT_TYPE)
  1792. {
  1793. dwErr = ERROR_INVALID_PARAMETER;
  1794. }
  1795. else
  1796. {
  1797. //
  1798. // Make sure we have something to do
  1799. //
  1800. SECURITY_INFORMATION SeInfo = 0;
  1801. if(ppAccessList != NULL)
  1802. {
  1803. SeInfo |= DACL_SECURITY_INFORMATION;
  1804. }
  1805. if(ppAuditList != NULL)
  1806. {
  1807. SeInfo |= SACL_SECURITY_INFORMATION;
  1808. }
  1809. if(lppOwner != NULL)
  1810. {
  1811. SeInfo |= OWNER_SECURITY_INFORMATION;
  1812. }
  1813. if(lppGroup != NULL)
  1814. {
  1815. SeInfo |= GROUP_SECURITY_INFORMATION;
  1816. }
  1817. if(SeInfo != 0)
  1818. {
  1819. CAccessList AccList;
  1820. dwErr = AccList.SetObjectType(ObjectType);
  1821. if(dwErr == ERROR_SUCCESS)
  1822. {
  1823. dwErr = AccList.AddSD(pSecDescriptor,
  1824. SeInfo,
  1825. NULL);
  1826. //
  1827. // Now, build our individual lists from it...
  1828. //
  1829. if(dwErr == ERROR_SUCCESS)
  1830. {
  1831. dwErr = AccList.MarshalAccessLists(SeInfo,
  1832. ppAccessList,
  1833. ppAuditList);
  1834. if(dwErr == ERROR_SUCCESS)
  1835. {
  1836. //
  1837. // Save off the strings
  1838. //
  1839. if(FLAG_ON(SeInfo, OWNER_SECURITY_INFORMATION))
  1840. {
  1841. PTRUSTEE_W pOwner;
  1842. dwErr = AccList.GetSDSidAsTrustee(
  1843. OWNER_SECURITY_INFORMATION,
  1844. &pOwner);
  1845. if(dwErr == ERROR_SUCCESS)
  1846. {
  1847. ACC_ALLOC_AND_COPY_STRINGW(
  1848. pOwner->ptstrName,
  1849. *lppOwner,
  1850. dwErr);
  1851. AccFree(pOwner);
  1852. }
  1853. }
  1854. if(FLAG_ON(SeInfo, GROUP_SECURITY_INFORMATION))
  1855. {
  1856. PTRUSTEE_W pGroup;
  1857. dwErr = AccList.GetSDSidAsTrustee(
  1858. GROUP_SECURITY_INFORMATION,
  1859. &pGroup);
  1860. if(dwErr == ERROR_SUCCESS)
  1861. {
  1862. ACC_ALLOC_AND_COPY_STRINGW(
  1863. pGroup->ptstrName,
  1864. *lppGroup,
  1865. dwErr);
  1866. AccFree(pGroup);
  1867. }
  1868. if(dwErr != ERROR_SUCCESS &&
  1869. FLAG_ON(SeInfo, OWNER_SECURITY_INFORMATION))
  1870. {
  1871. AccFree(*lppOwner);
  1872. }
  1873. }
  1874. if(dwErr != ERROR_SUCCESS)
  1875. {
  1876. if(FLAG_ON(SeInfo, DACL_SECURITY_INFORMATION))
  1877. {
  1878. AccFree(ppAccessList);
  1879. }
  1880. if(FLAG_ON(SeInfo, SACL_SECURITY_INFORMATION))
  1881. {
  1882. AccFree(ppAuditList);
  1883. }
  1884. }
  1885. }
  1886. }
  1887. }
  1888. }
  1889. }
  1890. return(dwErr);
  1891. }
  1892. //+---------------------------------------------------------------------------
  1893. //
  1894. // Function: AccGetAccessForTrustee
  1895. //
  1896. // Synopsis: Helper function. Determines the access/audits for the
  1897. // given trustee
  1898. //
  1899. // Arguments: [IN pTrustee] -- Trustee to check access for
  1900. // [IN pAcl] -- Acl to get information from
  1901. // [IN SeInfo] -- Whether to handle this as an access or
  1902. // audit list
  1903. // [IN pwszProperty] -- Property on the acl to use
  1904. // [OUT pAllowed] -- Where the allowed/success mask is
  1905. // returned
  1906. // [OUT pDenied] -- Where the denied/failure mask is
  1907. // returned
  1908. //
  1909. // Returns: ERROR_SUCCESS -- Success
  1910. // ERROR_INVALID_PARAMETER A bad parameter was given
  1911. //
  1912. // Notes: The returned items must be freed via LocalFree
  1913. //
  1914. //----------------------------------------------------------------------------
  1915. DWORD
  1916. AccGetAccessForTrustee(IN PTRUSTEE pTrustee,
  1917. IN PACL pAcl,
  1918. IN SECURITY_INFORMATION SeInfo,
  1919. IN PWSTR pwszProperty,
  1920. IN PACCESS_RIGHTS pAllowed,
  1921. IN PACCESS_RIGHTS pDenied)
  1922. {
  1923. DWORD dwErr = ERROR_SUCCESS;
  1924. //
  1925. // Ok, first, initialize our access list
  1926. //
  1927. CAccessList AccList;
  1928. PACL pDAcl = NULL, pSAcl = NULL;
  1929. if(FLAG_ON(SeInfo, DACL_SECURITY_INFORMATION))
  1930. {
  1931. pDAcl = pAcl;
  1932. }
  1933. else
  1934. {
  1935. pSAcl = pAcl;
  1936. }
  1937. if(dwErr == ERROR_SUCCESS)
  1938. {
  1939. dwErr = AccList.AddAcl(pDAcl,
  1940. pSAcl,
  1941. NULL,
  1942. NULL,
  1943. SeInfo,
  1944. NULL,
  1945. TRUE);
  1946. }
  1947. if(dwErr == ERROR_SUCCESS)
  1948. {
  1949. //
  1950. // Now, get the rights..
  1951. //
  1952. if(FLAG_ON(SeInfo, DACL_SECURITY_INFORMATION))
  1953. {
  1954. dwErr = AccList.GetExplicitAccess(pTrustee,
  1955. pwszProperty,
  1956. pDenied,
  1957. pAllowed);
  1958. }
  1959. else
  1960. {
  1961. dwErr = AccList.GetExplicitAudits(pTrustee,
  1962. pwszProperty,
  1963. pDenied,
  1964. pAllowed);
  1965. }
  1966. }
  1967. return(dwErr);
  1968. }
  1969. //+---------------------------------------------------------------------------
  1970. //
  1971. // Function: AccConvertAclToAccess
  1972. //
  1973. // Synopsis: Helper function. Converts an ACL into access lists
  1974. //
  1975. // Arguments: [IN ObjectType] -- Type of object the acl came from
  1976. // [IN pAcl] -- Acl to convert
  1977. // [OUT ppAccessList] -- Where to return the access list
  1978. //
  1979. // Returns: ERROR_SUCCESS -- Success
  1980. // ERROR_INVALID_PARAMETER A bad parameter was given
  1981. //
  1982. // Notes: The returned items must be freed via LocalFree
  1983. //
  1984. //----------------------------------------------------------------------------
  1985. DWORD
  1986. AccConvertAclToAccess(IN SE_OBJECT_TYPE ObjectType,
  1987. IN PACL pAcl,
  1988. OUT PACTRL_ACCESSW *ppAccessList)
  1989. {
  1990. DWORD dwErr = ERROR_SUCCESS;
  1991. //
  1992. // Make sure we have valid parameters
  1993. //
  1994. if(pAcl == NULL)
  1995. {
  1996. dwErr = ERROR_INVALID_PARAMETER;
  1997. }
  1998. else
  1999. {
  2000. CAccessList AccList;
  2001. dwErr = AccList.SetObjectType(ObjectType);
  2002. if(dwErr == ERROR_SUCCESS)
  2003. {
  2004. dwErr = AccList.AddAcl(pAcl,
  2005. NULL,
  2006. NULL,
  2007. NULL,
  2008. DACL_SECURITY_INFORMATION,
  2009. NULL,
  2010. TRUE);
  2011. //
  2012. // Now, build our individual lists from it...
  2013. //
  2014. if(dwErr == ERROR_SUCCESS)
  2015. {
  2016. dwErr = AccList.MarshalAccessLists(DACL_SECURITY_INFORMATION,
  2017. ppAccessList,
  2018. NULL);
  2019. }
  2020. }
  2021. }
  2022. return(dwErr);
  2023. }
  2024. //+---------------------------------------------------------------------------
  2025. //
  2026. // Function: AccConvertAccessToSD
  2027. //
  2028. // Synopsis: Helper function. Converts a set of access lists and owner/
  2029. // group into a security descriptor.
  2030. //
  2031. // Arguments: [IN ObjectType] -- Type of object to add
  2032. // [IN SeInfo] -- Items being set in the SD
  2033. // [IN pAccessList] -- OPTIONAL. Access list to convert
  2034. // [IN pAuditList] -- OPTIONAL. Audit list to add
  2035. // [IN lpOwner] -- OPTIONAL. Owner to add
  2036. // [IN lpGroup] -- OPTIONAL. Group to add
  2037. // [IN fOpts] -- Options to use when building the SD
  2038. // [OUT ppSecDescriptor] Where the created security descriptor
  2039. // is returned.
  2040. // [OUT pcSDSize] -- Where the size of the security descriptor
  2041. // is returned
  2042. //
  2043. // Returns: ERROR_SUCCESS -- Success
  2044. // ERROR_INVALID_PARAMETER A bad parameter was given
  2045. //
  2046. // Notes: The returned security descriptor must be freed via LocalFree
  2047. //
  2048. //----------------------------------------------------------------------------
  2049. DWORD
  2050. AccConvertAccessToSD(IN SE_OBJECT_TYPE ObjectType,
  2051. IN SECURITY_INFORMATION SeInfo,
  2052. IN PACTRL_ACCESSW pAccessList,
  2053. IN PACTRL_AUDITW pAuditList,
  2054. IN LPWSTR lpOwner,
  2055. IN LPWSTR lpGroup,
  2056. IN ULONG fOpts,
  2057. OUT PSECURITY_DESCRIPTOR *ppSD,
  2058. OUT PULONG pcSDSize)
  2059. {
  2060. DWORD dwErr = ERROR_SUCCESS;
  2061. //
  2062. // First, verify the parameters.
  2063. //
  2064. if(ObjectType > SE_PROVIDER_DEFINED_OBJECT || ppSD == NULL || pcSDSize == NULL)
  2065. {
  2066. dwErr = ERROR_INVALID_PARAMETER;
  2067. }
  2068. else
  2069. {
  2070. //
  2071. // Verify that we have the proper parameters for our SecurityInfo
  2072. //
  2073. if(FLAG_ON(SeInfo, DACL_SECURITY_INFORMATION) &&
  2074. pAccessList == NULL)
  2075. {
  2076. dwErr = ERROR_INVALID_PARAMETER;
  2077. }
  2078. if(FLAG_ON(SeInfo, SACL_SECURITY_INFORMATION) &&
  2079. pAuditList == NULL)
  2080. {
  2081. dwErr = ERROR_INVALID_PARAMETER;
  2082. }
  2083. if(FLAG_ON(SeInfo, GROUP_SECURITY_INFORMATION) &&
  2084. lpGroup == NULL)
  2085. {
  2086. dwErr = ERROR_INVALID_PARAMETER;
  2087. }
  2088. if(FLAG_ON(SeInfo, OWNER_SECURITY_INFORMATION) &&
  2089. lpOwner == NULL)
  2090. {
  2091. dwErr = ERROR_INVALID_PARAMETER;
  2092. }
  2093. }
  2094. //
  2095. // If we have valid parameters, go do it...
  2096. //
  2097. if(dwErr == ERROR_SUCCESS)
  2098. {
  2099. //
  2100. // Initialize our access lists
  2101. //
  2102. CAccessList AccList;
  2103. TRUSTEE_W Group;
  2104. TRUSTEE_W Owner;
  2105. dwErr = AccList.SetObjectType(ObjectType);
  2106. if(dwErr == ERROR_SUCCESS && lpGroup != NULL)
  2107. {
  2108. memset(&Group, 0, sizeof(TRUSTEE_W));
  2109. Group.TrusteeForm = TRUSTEE_IS_NAME;
  2110. Group.ptstrName = (PWSTR)lpGroup;
  2111. dwErr = AccList.AddOwnerGroup(GROUP_SECURITY_INFORMATION,
  2112. NULL,
  2113. &Group);
  2114. }
  2115. if(dwErr == ERROR_SUCCESS && lpOwner)
  2116. {
  2117. memset(&Owner, 0, sizeof(TRUSTEE_W));
  2118. Owner.TrusteeForm = TRUSTEE_IS_NAME;
  2119. Owner.ptstrName = (PWSTR)lpOwner;
  2120. dwErr = AccList.AddOwnerGroup(OWNER_SECURITY_INFORMATION,
  2121. &Owner,
  2122. NULL);
  2123. }
  2124. if(dwErr == ERROR_SUCCESS && pAccessList != NULL)
  2125. {
  2126. dwErr = AccList.AddAccessLists(DACL_SECURITY_INFORMATION,
  2127. pAccessList,
  2128. FALSE);
  2129. }
  2130. if(dwErr == ERROR_SUCCESS && pAuditList != NULL)
  2131. {
  2132. dwErr = AccList.AddAccessLists(SACL_SECURITY_INFORMATION,
  2133. pAuditList,
  2134. FALSE);
  2135. }
  2136. //
  2137. // Now, build the Security Descriptor
  2138. //
  2139. if(dwErr == ERROR_SUCCESS)
  2140. {
  2141. SECURITY_INFORMATION LocalSeInfo;
  2142. dwErr = AccList.BuildSDForAccessList(ppSD,
  2143. &LocalSeInfo,
  2144. ACCLIST_SD_NOFREE |
  2145. FLAG_ON(fOpts,
  2146. ACCCONVERT_SELF_RELATIVE) ? 0 :
  2147. ACCLIST_SD_ABSOK
  2148. );
  2149. if(dwErr == ERROR_SUCCESS)
  2150. {
  2151. *pcSDSize = AccList.QuerySDSize();
  2152. }
  2153. }
  2154. }
  2155. return(dwErr);
  2156. }
  2157. //+---------------------------------------------------------------------------
  2158. //
  2159. // Function: AccGetExplicitEntries
  2160. //
  2161. // Synopsis: Helper function. Gets the list of explicit entries for
  2162. // the given trustee from the acl.
  2163. //
  2164. // Arguments: [IN pTrustee] -- Trustee to get the list for
  2165. // [IN ObjectType] -- Type of object the acl came from
  2166. // [IN pAcl] -- Acl to examine
  2167. // [IN pwszProperty] -- Which acl property to examine
  2168. // [OUT pcEntries] -- Where the count of entries is returned
  2169. // [OUT ppAEList] -- Where the list of explicit entries
  2170. // is returned.
  2171. //
  2172. // Returns: ERROR_SUCCESS -- Success
  2173. // ERROR_INVALID_PARAMETER A bad parameter was given
  2174. //
  2175. // Notes: The returned list must be freed via LocalFree
  2176. //
  2177. //----------------------------------------------------------------------------
  2178. DWORD
  2179. AccGetExplicitEntries(IN PTRUSTEE pTrustee,
  2180. IN SE_OBJECT_TYPE ObjectType,
  2181. IN PACL pAcl,
  2182. IN PWSTR pwszProperty,
  2183. OUT PULONG pcEntries,
  2184. OUT PACTRL_ACCESS_ENTRYW *ppAEList)
  2185. {
  2186. DWORD dwErr = ERROR_SUCCESS;
  2187. //
  2188. // Make sure we have valid parameters
  2189. //
  2190. if(pAcl == NULL)
  2191. {
  2192. dwErr = ERROR_INVALID_PARAMETER;
  2193. }
  2194. else
  2195. {
  2196. CAccessList AccList;
  2197. dwErr = AccList.SetObjectType(ObjectType);
  2198. if(dwErr == ERROR_SUCCESS)
  2199. {
  2200. dwErr = AccList.AddAcl(pAcl,
  2201. NULL,
  2202. NULL,
  2203. NULL,
  2204. DACL_SECURITY_INFORMATION,
  2205. NULL,
  2206. TRUE);
  2207. //
  2208. // Now, build our individual lists from it...
  2209. //
  2210. if(dwErr == ERROR_SUCCESS)
  2211. {
  2212. dwErr = AccList.GetExplicitEntries(pTrustee,
  2213. pwszProperty,
  2214. DACL_SECURITY_INFORMATION,
  2215. pcEntries,
  2216. ppAEList);
  2217. }
  2218. }
  2219. }
  2220. return(dwErr);
  2221. return(dwErr);
  2222. }
  2223. //+---------------------------------------------------------------------------
  2224. //
  2225. // Function: ConvertStringToSid
  2226. //
  2227. // Synopsis: Converts a string representation of a SID back into a SID.
  2228. // This is the converse of RtlConvertSidToUnicode. If a non-
  2229. // SID string is given, an error is returned.
  2230. //
  2231. // Arguments: [IN pwszString] -- String to convert
  2232. // [OUT ppSid] -- Where the convertd sid is returned
  2233. //
  2234. // Returns: ERROR_SUCCESS -- Success
  2235. // ERROR_INVALID_PARAMETER A bad parameter was given
  2236. // ERROR_NONE_MAPPED -- The given string does not represent
  2237. // a SID
  2238. //
  2239. // Notes: The returned sid must be freed via LocalFree
  2240. //
  2241. //----------------------------------------------------------------------------
  2242. DWORD
  2243. ConvertStringToSid(IN PWSTR pwszString,
  2244. OUT PSID *ppSid)
  2245. {
  2246. DWORD dwErr = ERROR_SUCCESS;
  2247. if(wcslen(pwszString) < 2 ||
  2248. (*pwszString != L'S' && *(pwszString + 1) != L'-'))
  2249. {
  2250. return(ERROR_NONE_MAPPED);
  2251. }
  2252. acDebugOut((DEB_TRACE_SID, "Converting %ws to sid\n", pwszString));
  2253. UCHAR Revision;
  2254. UCHAR cSubs;
  2255. SID_IDENTIFIER_AUTHORITY IDAuth;
  2256. PULONG pSubAuth = NULL;
  2257. PWSTR pwszEnd;
  2258. PWSTR pwszCurr = pwszString + 2;
  2259. Revision = (UCHAR)wcstol(pwszCurr, &pwszEnd, 10);
  2260. pwszCurr = pwszEnd + 1;
  2261. //
  2262. // Count the number of characters in the indentifer authority...
  2263. //
  2264. PWSTR pwszNext = wcschr(pwszCurr, L'-');
  2265. if(pwszNext - pwszCurr == 6)
  2266. {
  2267. for(ULONG iIndex = 0; iIndex < 6; iIndex++)
  2268. {
  2269. IDAuth.Value[iIndex] = (UCHAR)pwszNext[iIndex];
  2270. }
  2271. pwszCurr +=6;
  2272. }
  2273. else
  2274. {
  2275. IDAuth.Value[0] = IDAuth.Value[1] = 0;
  2276. ULONG Auto = wcstoul(pwszCurr, &pwszEnd, 10);
  2277. IDAuth.Value[5] = (UCHAR)Auto & 0xF;
  2278. IDAuth.Value[4] = (UCHAR)((Auto >> 8) & 0xFF);
  2279. IDAuth.Value[3] = (UCHAR)((Auto >> 16) & 0xFF);
  2280. IDAuth.Value[2] = (UCHAR)((Auto >> 24) & 0xFF);
  2281. pwszCurr = pwszEnd;
  2282. }
  2283. pwszCurr++;
  2284. //
  2285. // Now, count the number of sub auths
  2286. //
  2287. cSubs = 0;
  2288. pwszNext = pwszCurr;
  2289. if(pwszCurr != NULL)
  2290. {
  2291. cSubs++;
  2292. }
  2293. while(TRUE)
  2294. {
  2295. pwszNext = wcschr(pwszNext,'-');
  2296. if(pwszNext == NULL || *(pwszNext + 1) == L'\0')
  2297. {
  2298. break;
  2299. }
  2300. pwszNext++;
  2301. cSubs++;
  2302. }
  2303. if(cSubs != 0)
  2304. {
  2305. pSubAuth = (PULONG)AccAlloc(cSubs * sizeof(ULONG));
  2306. if(pSubAuth == NULL)
  2307. {
  2308. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  2309. }
  2310. else
  2311. {
  2312. for(ULONG iIndex = 0; iIndex < cSubs; iIndex++)
  2313. {
  2314. pSubAuth[iIndex] = wcstoul(pwszCurr, &pwszEnd, 10);
  2315. pwszCurr = pwszEnd + 1;
  2316. }
  2317. }
  2318. }
  2319. else
  2320. {
  2321. dwErr = ERROR_NONE_MAPPED;
  2322. }
  2323. //
  2324. // Now, create the SID
  2325. //
  2326. if(dwErr == ERROR_SUCCESS)
  2327. {
  2328. *ppSid = (PSID)AccAlloc(sizeof(SID) + cSubs * sizeof(ULONG));
  2329. if(*ppSid == NULL)
  2330. {
  2331. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  2332. }
  2333. else
  2334. {
  2335. PISID pSid = (PISID)*ppSid;
  2336. pSid->Revision = Revision;
  2337. pSid->SubAuthorityCount = cSubs;
  2338. memcpy(&(pSid->IdentifierAuthority),
  2339. &IDAuth,
  2340. sizeof(SID_IDENTIFIER_AUTHORITY));
  2341. memcpy(pSid->SubAuthority,
  2342. pSubAuth,
  2343. cSubs * sizeof(ULONG));
  2344. #if DBG
  2345. UNICODE_STRING SidString;
  2346. NTSTATUS Status = RtlConvertSidToUnicodeString(&SidString,
  2347. pSid,
  2348. TRUE);
  2349. if(!NT_SUCCESS(Status))
  2350. {
  2351. acDebugOut((DEB_TRACE_SID, "Can't convert sid to string: 0x%lx\n",
  2352. Status));
  2353. }
  2354. else
  2355. {
  2356. acDebugOut((DEB_TRACE_SID, "Converted sid: %wZ\n", &SidString));
  2357. RtlFreeUnicodeString(&SidString);
  2358. }
  2359. if(FLAG_ON(acInfoLevel, DEB_TRACE_SID))
  2360. {
  2361. DebugBreak();
  2362. }
  2363. #endif
  2364. }
  2365. }
  2366. AccFree(pSubAuth);
  2367. return(dwErr);
  2368. }
  2369. //+---------------------------------------------------------------------------
  2370. //
  2371. // Function: GetCurrentToken
  2372. //
  2373. // Synopsis: Gets the token from the current thread, if possible, or the
  2374. // process.
  2375. //
  2376. // Arguments: [IN pHandle] -- Where the token is returned
  2377. //
  2378. // Returns: ERROR_SUCCESS -- Success
  2379. //
  2380. // Notes:
  2381. //
  2382. //----------------------------------------------------------------------------
  2383. DWORD GetCurrentToken( OUT HANDLE *pHandle )
  2384. {
  2385. DWORD dwErr = ERROR_SUCCESS;
  2386. //
  2387. // see if a thread token exists
  2388. //
  2389. if(!OpenThreadToken(GetCurrentThread(),
  2390. TOKEN_QUERY,
  2391. TRUE,
  2392. pHandle))
  2393. {
  2394. dwErr = GetLastError();
  2395. //
  2396. // if not, use the process token
  2397. //
  2398. if(dwErr == ERROR_NO_TOKEN)
  2399. {
  2400. dwErr = ERROR_SUCCESS;
  2401. if (!OpenProcessToken(GetCurrentProcess(),
  2402. TOKEN_QUERY,
  2403. pHandle))
  2404. {
  2405. dwErr = GetLastError();
  2406. }
  2407. }
  2408. }
  2409. return( dwErr );
  2410. }