Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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