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.

4243 lines
107 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. rpcapi2.c
  5. Abstract:
  6. This module contains the routines for the LSA API that use RPC. The
  7. routines in this module are merely wrappers that work as follows:
  8. o Client program calls LsaFoo in this module
  9. o LsaFoo calls RPC client stub interface routine LsapFoo with
  10. similar parameters. Some parameters are translated from types
  11. (e.g structures containing PVOIDs or certain kinds of variable length
  12. parameters such as pointers to SID's) that are not specifiable on an
  13. RPC interface, to specifiable form.
  14. o RPC client stub LsapFoo calls interface specific marshalling routines
  15. and RPC runtime to marshal parameters into a buffer and send them over
  16. to the server side of the LSA.
  17. o Server side calls RPC runtime and interface specific unmarshalling
  18. routines to unmarshal parameters.
  19. o Server side calls worker LsapFoo to perform API function.
  20. o Server side marshals response/output parameters and communicates these
  21. back to client stub LsapFoo
  22. o LsapFoo exits back to LsaFoo which returns to client program.
  23. Author:
  24. Mike Swift (MikeSw) December 7, 1994
  25. Revision History:
  26. --*/
  27. #define UNICODE // required for TEXT() to be defined properly
  28. #include "lsaclip.h"
  29. #include <lmcons.h>
  30. #include <logonmsv.h>
  31. #include <rc4.h>
  32. #include <rpcasync.h>
  33. typedef struct _LSAP_DB_RIGHT_AND_ACCESS {
  34. UNICODE_STRING UserRight;
  35. ULONG SystemAccess;
  36. } LSAP_DB_RIGHT_AND_ACCESS, *PLSAP_DB_RIGHT_AND_ACCESS;
  37. #define LSAP_DB_SYSTEM_ACCESS_TYPES 4
  38. LSAP_DB_RIGHT_AND_ACCESS LsapDbRightAndAccess[LSAP_DB_SYSTEM_ACCESS_TYPES] = {
  39. {{sizeof(SE_INTERACTIVE_LOGON_NAME)-sizeof(WCHAR),
  40. sizeof(SE_INTERACTIVE_LOGON_NAME),
  41. SE_INTERACTIVE_LOGON_NAME},
  42. SECURITY_ACCESS_INTERACTIVE_LOGON},
  43. {{sizeof(SE_NETWORK_LOGON_NAME)-sizeof(WCHAR),
  44. sizeof(SE_NETWORK_LOGON_NAME),
  45. SE_NETWORK_LOGON_NAME},
  46. SECURITY_ACCESS_NETWORK_LOGON},
  47. {{sizeof(SE_BATCH_LOGON_NAME)-sizeof(WCHAR),
  48. sizeof(SE_BATCH_LOGON_NAME),
  49. SE_BATCH_LOGON_NAME},
  50. SECURITY_ACCESS_BATCH_LOGON},
  51. {{sizeof(SE_SERVICE_LOGON_NAME)-sizeof(WCHAR),
  52. sizeof(SE_SERVICE_LOGON_NAME),
  53. SE_SERVICE_LOGON_NAME},
  54. SECURITY_ACCESS_SERVICE_LOGON}
  55. };
  56. //
  57. // Structure to maintain list of enumerated accounts
  58. //
  59. typedef struct _SID_LIST_ENTRY {
  60. struct _SID_LIST_ENTRY * Next;
  61. PSID Sid;
  62. } SID_LIST_ENTRY, *PSID_LIST_ENTRY;
  63. //
  64. // Functions private to this module
  65. //
  66. NTSTATUS
  67. LsapApiReturnResult(
  68. IN ULONG ExceptionCode
  69. );
  70. NTSTATUS
  71. LsapApiConvertRightsToPrivileges(
  72. IN LSA_HANDLE PolicyHandle,
  73. IN PUNICODE_STRING UserRights,
  74. IN ULONG RightCount,
  75. OUT PPRIVILEGE_SET * Privileges,
  76. OUT PULONG SystemAccess
  77. );
  78. NTSTATUS
  79. LsapApiConvertPrivilegesToRights(
  80. IN LSA_HANDLE PolicyHandle,
  81. IN OPTIONAL PPRIVILEGE_SET Privileges,
  82. IN OPTIONAL ULONG SystemAccess,
  83. OUT PUNICODE_STRING * UserRights,
  84. OUT PULONG RightCount
  85. );
  86. //////////////////////////////////////////////////////////////////////
  87. //
  88. // This set of routines implements the same functionality as the APIs
  89. // below but do it with the APIs present through NT 3.5
  90. //
  91. /////////////////////////////////////////////////////////////////////
  92. NTSTATUS
  93. NTAPI
  94. LsapEnumerateAccountsWithUserRight(
  95. IN LSA_HANDLE PolicyHandle,
  96. IN OPTIONAL PUNICODE_STRING UserRights,
  97. OUT PVOID *EnumerationBuffer,
  98. OUT PULONG CountReturned
  99. )
  100. /*++
  101. Routine Description:
  102. The LsaEnumerateAccountsWithUserRight API returns information about
  103. the accounts in the target system's Lsa Database. This call requires
  104. LSA_ENUMERATE_ACCOUNTS access to the Policy object. Since this call
  105. accesses the privileges of an account, you must have ACCOUNT_VIEW access
  106. access to all accounts.
  107. Arguments:
  108. PolicyHandle - Handle from an LsaOpenPolicy call.
  109. UserRight - Name of the right that the account must have.
  110. Buffer - Receives a pointer to a LSA_ENUMERATION_INFORMATION structure
  111. containing the SIDs of all the accounts.
  112. CountReturned - Receives the number of sids returned.
  113. Return Values:
  114. NTSTATUS - Standard Nt Result Code
  115. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  116. to complete the operation.
  117. STATUS_NO_MORE_ENTRIES - There are no more entries. This warning
  118. is returned if no objects are enumerated because the
  119. EnumerationContext value passed in is too high.
  120. --*/
  121. {
  122. NTSTATUS Status;
  123. PLSA_ENUMERATION_INFORMATION Accounts = NULL;
  124. PPRIVILEGE_SET DesiredPrivilege = NULL;
  125. ULONG DesiredAccess = 0;
  126. PPRIVILEGE_SET Privileges = NULL;
  127. ULONG SystemAccess;
  128. LSA_ENUMERATION_HANDLE EnumContext = 0;
  129. ULONG AccountCount;
  130. ULONG AccountIndex;
  131. LSA_HANDLE AccountHandle = NULL;
  132. PSID_LIST_ENTRY AccountList = NULL;
  133. PSID_LIST_ENTRY NextAccount = NULL;
  134. ULONG AccountSize;
  135. PUCHAR Where;
  136. ULONG PrivilegeIndex;
  137. Status = LsapApiConvertRightsToPrivileges(
  138. PolicyHandle,
  139. UserRights,
  140. (UserRights ? 1 : 0),
  141. &DesiredPrivilege,
  142. &DesiredAccess
  143. );
  144. if (!NT_SUCCESS(Status)) {
  145. goto Cleanup;
  146. }
  147. //
  148. // Enumerate all the accounts.
  149. //
  150. do
  151. {
  152. Status = LsaEnumerateAccounts(
  153. PolicyHandle,
  154. &EnumContext,
  155. &Accounts,
  156. 32000,
  157. &AccountCount
  158. );
  159. if (!NT_SUCCESS(Status)) {
  160. break;
  161. }
  162. //
  163. // For each account, check that it has the desired right
  164. //
  165. for (AccountIndex = 0; AccountIndex < AccountCount ; AccountIndex++ ) {
  166. if ((DesiredPrivilege != NULL) || (DesiredAccess != 0)) {
  167. Status = LsaOpenAccount(
  168. PolicyHandle,
  169. Accounts[AccountIndex].Sid,
  170. ACCOUNT_VIEW,
  171. &AccountHandle
  172. );
  173. if (!NT_SUCCESS(Status) ) {
  174. goto Cleanup;
  175. }
  176. //
  177. // If a privilege was requested, get the privilegs
  178. //
  179. if (DesiredPrivilege != NULL) {
  180. Privileges = NULL;
  181. Status = LsaEnumeratePrivilegesOfAccount(
  182. AccountHandle,
  183. &Privileges
  184. );
  185. if (!NT_SUCCESS(Status)) {
  186. goto Cleanup;
  187. }
  188. //
  189. // Search for the desired privilege
  190. //
  191. for (PrivilegeIndex = 0;
  192. PrivilegeIndex < Privileges->PrivilegeCount ;
  193. PrivilegeIndex++) {
  194. if (RtlEqualLuid(&Privileges->Privilege[PrivilegeIndex].Luid,
  195. &DesiredPrivilege->Privilege[0].Luid)) {
  196. break;
  197. }
  198. }
  199. //
  200. // If we found the privilege, add it to the list.
  201. //
  202. if (PrivilegeIndex != Privileges->PrivilegeCount) {
  203. //
  204. // Add this account to the enumeration.
  205. //
  206. NextAccount = MIDL_user_allocate(sizeof(SID_LIST_ENTRY));
  207. if (NextAccount == NULL) {
  208. Status = STATUS_INSUFFICIENT_RESOURCES;
  209. goto Cleanup;
  210. }
  211. NextAccount->Sid = MIDL_user_allocate(RtlLengthSid(Accounts[AccountIndex].Sid));
  212. if (NextAccount->Sid == NULL) {
  213. MIDL_user_free(NextAccount);
  214. Status = STATUS_INSUFFICIENT_RESOURCES;
  215. goto Cleanup;
  216. }
  217. RtlCopyMemory(
  218. NextAccount->Sid,
  219. Accounts[AccountIndex].Sid,
  220. RtlLengthSid(Accounts[AccountIndex].Sid)
  221. );
  222. NextAccount->Next = AccountList;
  223. AccountList = NextAccount;
  224. }
  225. LsaFreeMemory(Privileges);
  226. Privileges = NULL;
  227. } else {
  228. //
  229. // Otherwise get the system access
  230. //
  231. ASSERT(DesiredAccess != 0);
  232. Status = LsaGetSystemAccessAccount(
  233. AccountHandle,
  234. &SystemAccess
  235. );
  236. if (!NT_SUCCESS(Status)) {
  237. goto Cleanup;
  238. }
  239. //
  240. // Check for the desired access
  241. //
  242. if ((SystemAccess & DesiredAccess) != 0) {
  243. //
  244. // Add this account to the enumeration.
  245. //
  246. NextAccount = MIDL_user_allocate(sizeof(SID_LIST_ENTRY));
  247. if (NextAccount == NULL) {
  248. Status = STATUS_INSUFFICIENT_RESOURCES;
  249. goto Cleanup;
  250. }
  251. NextAccount->Sid = MIDL_user_allocate(RtlLengthSid(Accounts[AccountIndex].Sid));
  252. if (NextAccount->Sid == NULL) {
  253. MIDL_user_free(NextAccount);
  254. Status = STATUS_INSUFFICIENT_RESOURCES;
  255. goto Cleanup;
  256. }
  257. RtlCopyMemory(
  258. NextAccount->Sid,
  259. Accounts[AccountIndex].Sid,
  260. RtlLengthSid(Accounts[AccountIndex].Sid)
  261. );
  262. NextAccount->Next = AccountList;
  263. AccountList = NextAccount;
  264. }
  265. }
  266. LsaClose(AccountHandle);
  267. AccountHandle = NULL;
  268. } else {
  269. //
  270. // always add the account if the caller didn't want
  271. // filtering.
  272. //
  273. NextAccount = MIDL_user_allocate(sizeof(SID_LIST_ENTRY));
  274. if (NextAccount == NULL) {
  275. Status = STATUS_INSUFFICIENT_RESOURCES;
  276. goto Cleanup;
  277. }
  278. NextAccount->Sid = MIDL_user_allocate(RtlLengthSid(Accounts[AccountIndex].Sid));
  279. if (NextAccount->Sid == NULL) {
  280. MIDL_user_free(NextAccount);
  281. Status = STATUS_INSUFFICIENT_RESOURCES;
  282. goto Cleanup;
  283. }
  284. RtlCopyMemory(
  285. NextAccount->Sid,
  286. Accounts[AccountIndex].Sid,
  287. RtlLengthSid(Accounts[AccountIndex].Sid)
  288. );
  289. NextAccount->Next = AccountList;
  290. AccountList = NextAccount;
  291. }
  292. }
  293. LsaFreeMemory(Accounts);
  294. Accounts = NULL;
  295. } while ( 1 );
  296. if (Status != STATUS_NO_MORE_ENTRIES) {
  297. goto Cleanup;
  298. }
  299. AccountSize = 0;
  300. AccountCount = 0;
  301. for (NextAccount = AccountList ; NextAccount != NULL; NextAccount = NextAccount->Next) {
  302. AccountSize += sizeof(LSA_ENUMERATION_INFORMATION) +
  303. RtlLengthSid(NextAccount->Sid);
  304. AccountCount++;
  305. }
  306. //
  307. // If there were no accounts return a warning now.
  308. //
  309. if (AccountCount == 0) {
  310. *EnumerationBuffer = NULL;
  311. *CountReturned = 0;
  312. Status = STATUS_NO_MORE_ENTRIES;
  313. goto Cleanup;
  314. }
  315. Accounts = MIDL_user_allocate(AccountSize);
  316. if (Accounts == NULL) {
  317. Status = STATUS_INSUFFICIENT_RESOURCES;
  318. goto Cleanup;
  319. }
  320. //
  321. // Marshall all the sids into the array.
  322. //
  323. Where = (PUCHAR) Accounts + AccountCount * sizeof(LSA_ENUMERATION_INFORMATION);
  324. for ( NextAccount = AccountList,AccountIndex = 0 ;
  325. NextAccount != NULL;
  326. NextAccount = NextAccount->Next, AccountIndex++) {
  327. Accounts[AccountIndex].Sid = (PSID) Where;
  328. RtlCopyMemory(
  329. Where,
  330. NextAccount->Sid,
  331. RtlLengthSid(NextAccount->Sid)
  332. );
  333. Where += RtlLengthSid(NextAccount->Sid);
  334. }
  335. ASSERT(AccountIndex == AccountCount);
  336. ASSERT(Where - (PUCHAR) Accounts == (LONG) AccountSize);
  337. *EnumerationBuffer = Accounts;
  338. Accounts = NULL;
  339. *CountReturned = AccountCount;
  340. Status = STATUS_SUCCESS;
  341. Cleanup:
  342. if (AccountList != NULL) {
  343. while (AccountList != NULL) {
  344. NextAccount = AccountList->Next;
  345. MIDL_user_free(AccountList->Sid);
  346. MIDL_user_free(AccountList);
  347. AccountList = NextAccount;
  348. }
  349. }
  350. if (Accounts != NULL) {
  351. MIDL_user_free(Accounts);
  352. }
  353. if (Privileges != NULL) {
  354. LsaFreeMemory(Privileges);
  355. }
  356. return(Status);
  357. }
  358. NTSTATUS
  359. NTAPI
  360. LsapEnumerateAccountRights(
  361. IN LSA_HANDLE PolicyHandle,
  362. IN PSID AccountSid,
  363. OUT PUNICODE_STRING *UserRights,
  364. OUT PULONG CountOfRights
  365. )
  366. /*++
  367. Routine Description:
  368. Returns all the rights of an account. This is done by gathering the
  369. privileges and system access of an account and translating that into
  370. an array of strings.
  371. Arguments:
  372. PolicyHandle - Handle from an LsaOpenPolicyCall. This API requires
  373. no special access.
  374. AccountSid - Sid of account to open.
  375. UserRights - receives an array of user rights (UNICODE_STRING) for
  376. the account.
  377. CountOfRights - receives the number of rights returned.
  378. Return Value:
  379. STATUS_ACCESS_DENIED - the caller did not have sufficient access to
  380. return the privileges or system access of the account.
  381. STATUS_OBJECT_NAME_NOT_FOUND - the specified account did not exist.
  382. STATUS_INSUFFICIENT_RESOURCES - not enough memory to process the
  383. request.
  384. --*/
  385. {
  386. NTSTATUS Status;
  387. PPRIVILEGE_SET Privileges = NULL;
  388. ULONG SystemAccess = 0;
  389. PUNICODE_STRING Rights = NULL;
  390. ULONG RightCount = 0;
  391. LSA_HANDLE AccountHandle = NULL;
  392. Status = LsaOpenAccount(
  393. PolicyHandle,
  394. AccountSid,
  395. ACCOUNT_VIEW,
  396. &AccountHandle
  397. );
  398. if (!NT_SUCCESS(Status)) {
  399. goto Cleanup;
  400. }
  401. //
  402. // Query the privilegs and system access
  403. //
  404. Status = LsaEnumeratePrivilegesOfAccount(
  405. AccountHandle,
  406. &Privileges
  407. );
  408. if (!NT_SUCCESS(Status)) {
  409. goto Cleanup;
  410. }
  411. Status = LsaGetSystemAccessAccount(
  412. AccountHandle,
  413. &SystemAccess
  414. );
  415. if (!NT_SUCCESS(Status)) {
  416. goto Cleanup;
  417. }
  418. //
  419. // Convert the privileges and access to rights
  420. //
  421. Status = LsapApiConvertPrivilegesToRights(
  422. PolicyHandle,
  423. Privileges,
  424. SystemAccess,
  425. &Rights,
  426. &RightCount
  427. );
  428. if (NT_SUCCESS(Status)) {
  429. *CountOfRights = RightCount;
  430. *UserRights = Rights;
  431. }
  432. Cleanup:
  433. if (Privileges != NULL) {
  434. LsaFreeMemory(Privileges);
  435. }
  436. if (AccountHandle != NULL) {
  437. LsaClose(AccountHandle);
  438. }
  439. return(Status);
  440. }
  441. NTSTATUS
  442. NTAPI
  443. LsapAddAccountRights(
  444. IN LSA_HANDLE PolicyHandle,
  445. IN PSID AccountSid,
  446. IN PUNICODE_STRING UserRights,
  447. IN ULONG CountOfRights
  448. )
  449. /*++
  450. Routine Description:
  451. Adds rights to the account specified by the account sid. If the account
  452. does not exist, it creates the account.
  453. Arguments:
  454. PolicyHandle - Handle from an LsaOpenPolicy call. The handle must have
  455. POLICY_CREATE_ACCOUNT access if this is the first call for this
  456. AccountSid.
  457. AccountSid - Sid of account to add rights to
  458. UserRights - Array of unicode strings naming rights to add to the
  459. account.
  460. Return Value:
  461. STATUS_INSUFFICIENT_RESOURCES - not enough memory to process the request
  462. STATUS_INVALID_PARAMTER - one of the parameters was not present
  463. STATUS_NO_SUCH_PRIVILEGE - One of the user rights was invalid
  464. STATUS_ACCESS_DENIED - the caller does not have sufficient access to the
  465. account to add privileges.
  466. --*/
  467. {
  468. LSA_HANDLE AccountHandle = NULL;
  469. NTSTATUS Status;
  470. PPRIVILEGE_SET Privileges = NULL;
  471. ULONG SystemAccess;
  472. ULONG OldAccess;
  473. //
  474. // Convert the rights into privileges and system access.
  475. //
  476. Status = LsapApiConvertRightsToPrivileges(
  477. PolicyHandle,
  478. UserRights,
  479. CountOfRights,
  480. &Privileges,
  481. &SystemAccess
  482. );
  483. if (!NT_SUCCESS(Status)) {
  484. goto Cleanup;
  485. }
  486. //
  487. // Open the account. If it does not exist ,create the account.
  488. //
  489. Status = LsaOpenAccount(
  490. PolicyHandle,
  491. AccountSid,
  492. ACCOUNT_ADJUST_PRIVILEGES |
  493. ACCOUNT_ADJUST_SYSTEM_ACCESS |
  494. ACCOUNT_VIEW,
  495. &AccountHandle
  496. );
  497. //
  498. // if the account did not exist, try to create it.
  499. //
  500. if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
  501. Status = LsaCreateAccount(
  502. PolicyHandle,
  503. AccountSid,
  504. ACCOUNT_ADJUST_PRIVILEGES |
  505. ACCOUNT_ADJUST_SYSTEM_ACCESS |
  506. ACCOUNT_VIEW,
  507. &AccountHandle
  508. );
  509. }
  510. if (!NT_SUCCESS(Status)) {
  511. goto Cleanup;
  512. }
  513. Status = LsaGetSystemAccessAccount(
  514. AccountHandle,
  515. &OldAccess
  516. );
  517. if (!NT_SUCCESS(Status)) {
  518. goto Cleanup;
  519. }
  520. Status = LsaSetSystemAccessAccount(
  521. AccountHandle,
  522. OldAccess | SystemAccess
  523. );
  524. if (!NT_SUCCESS(Status)) {
  525. goto Cleanup;
  526. }
  527. Status = LsaAddPrivilegesToAccount(
  528. AccountHandle,
  529. Privileges
  530. );
  531. Cleanup:
  532. if (Privileges != NULL) {
  533. MIDL_user_free(Privileges);
  534. }
  535. if (AccountHandle != NULL) {
  536. LsaClose(AccountHandle);
  537. }
  538. return(Status);
  539. }
  540. NTSTATUS
  541. NTAPI
  542. LsapRemoveAccountRights(
  543. IN LSA_HANDLE PolicyHandle,
  544. IN PSID AccountSid,
  545. IN BOOLEAN AllRights,
  546. IN PUNICODE_STRING UserRights,
  547. IN ULONG CountOfRights
  548. )
  549. /*++
  550. Routine Description:
  551. Removes rights to the account specified by the account sid. If the
  552. AllRights flag is set or if all the rights are removed, the account
  553. is deleted.
  554. Arguments:
  555. PolicyHandle - Handle from an LsaOpenPolicy call
  556. AccountSid - Sid of account to remove rights from
  557. UserRights - Array of unicode strings naming rights to remove from the
  558. account.
  559. Return Value:
  560. STATUS_INSUFFICIENT_RESOURCES - not enough memory to process the request
  561. STATUS_INVALID_PARAMTER - one of the parameters was not present
  562. STATUS_NO_SUCH_PRIVILEGE - One of the user rights was invalid
  563. STATUS_ACCESS_DENIED - the caller does not have sufficient access to the
  564. account to add privileges.
  565. --*/
  566. {
  567. LSA_HANDLE AccountHandle = NULL;
  568. NTSTATUS Status;
  569. PPRIVILEGE_SET Privileges = NULL;
  570. PPRIVILEGE_SET NewPrivileges = NULL;
  571. ULONG SystemAccess = 0 ;
  572. ULONG OldAccess;
  573. ULONG DesiredAccess;
  574. ULONG NewAccess;
  575. //
  576. // Convert the rights into privileges and system access.
  577. //
  578. if (!AllRights) {
  579. Status = LsapApiConvertRightsToPrivileges(
  580. PolicyHandle,
  581. UserRights,
  582. CountOfRights,
  583. &Privileges,
  584. &SystemAccess
  585. );
  586. if (!NT_SUCCESS(Status)) {
  587. goto Cleanup;
  588. }
  589. DesiredAccess = ACCOUNT_ADJUST_PRIVILEGES |
  590. ACCOUNT_ADJUST_SYSTEM_ACCESS |
  591. ACCOUNT_VIEW | DELETE;
  592. } else {
  593. DesiredAccess = DELETE;
  594. }
  595. //
  596. // Open the account.
  597. //
  598. Status = LsaOpenAccount(
  599. PolicyHandle,
  600. AccountSid,
  601. DesiredAccess,
  602. &AccountHandle
  603. );
  604. if (!NT_SUCCESS(Status)) {
  605. goto Cleanup;
  606. }
  607. //
  608. // If we are to remove all rights, just delete the account ,and if that
  609. // succeeds, zero the handle so we don't try to close it later.
  610. //
  611. if (AllRights) {
  612. Status = LsaDelete(
  613. AccountHandle
  614. );
  615. if (NT_SUCCESS(Status)) {
  616. AccountHandle = NULL;
  617. }
  618. goto Cleanup;
  619. }
  620. //
  621. // Get the old system access to adjust
  622. //
  623. Status = LsaGetSystemAccessAccount(
  624. AccountHandle,
  625. &OldAccess
  626. );
  627. if (!NT_SUCCESS(Status)) {
  628. goto Cleanup;
  629. }
  630. NewAccess = OldAccess & ~SystemAccess;
  631. Status = LsaSetSystemAccessAccount(
  632. AccountHandle,
  633. NewAccess
  634. );
  635. if (!NT_SUCCESS(Status)) {
  636. goto Cleanup;
  637. }
  638. Status = LsaRemovePrivilegesFromAccount(
  639. AccountHandle,
  640. FALSE, // don't remove all
  641. Privileges
  642. );
  643. if (!NT_SUCCESS(Status)) {
  644. goto Cleanup;
  645. }
  646. //
  647. // Now query the privilegs to see if they are zero. If so, and
  648. // system access is zero, delete the account.
  649. //
  650. Status = LsaEnumeratePrivilegesOfAccount(
  651. AccountHandle,
  652. &NewPrivileges
  653. );
  654. if (!NT_SUCCESS(Status)) {
  655. goto Cleanup;
  656. }
  657. //
  658. // If the account has no privileges or access, delete it.
  659. //
  660. if ((NewPrivileges->PrivilegeCount == 0) &&
  661. (NewAccess == 0)) {
  662. Status = LsaDelete(
  663. AccountHandle
  664. );
  665. if (NT_SUCCESS(Status)) {
  666. AccountHandle = NULL;
  667. }
  668. }
  669. Status = STATUS_SUCCESS;
  670. Cleanup:
  671. if (Privileges != NULL) {
  672. MIDL_user_free(Privileges);
  673. }
  674. if (AccountHandle != NULL) {
  675. LsaClose(AccountHandle);
  676. }
  677. if (NewPrivileges != NULL) {
  678. LsaFreeMemory(NewPrivileges);
  679. }
  680. return(Status);
  681. }
  682. NTSTATUS
  683. LsapApiBuildSecretName(
  684. PTRUSTED_DOMAIN_NAME_INFO NameInfo,
  685. PUNICODE_STRING OutputSecretName
  686. )
  687. {
  688. UNICODE_STRING SecretName;
  689. //
  690. // The secret name is G$$domain name, where G$ is the global prefix and
  691. // $ is the ssi prefix
  692. //
  693. SecretName.Length = NameInfo->Name.Length +
  694. (SSI_SECRET_PREFIX_LENGTH +
  695. LSA_GLOBAL_SECRET_PREFIX_LENGTH) * sizeof(WCHAR);
  696. SecretName.MaximumLength = SecretName.Length;
  697. SecretName.Buffer = (LPWSTR) MIDL_user_allocate( SecretName.Length );
  698. if (SecretName.Buffer == NULL) {
  699. return(STATUS_INSUFFICIENT_RESOURCES);
  700. }
  701. wcscpy(
  702. SecretName.Buffer,
  703. LSA_GLOBAL_SECRET_PREFIX
  704. );
  705. wcscat(
  706. SecretName.Buffer,
  707. SSI_SECRET_PREFIX
  708. );
  709. RtlCopyMemory(
  710. SecretName.Buffer +
  711. LSA_GLOBAL_SECRET_PREFIX_LENGTH +
  712. SSI_SECRET_PREFIX_LENGTH,
  713. NameInfo->Name.Buffer,
  714. NameInfo->Name.Length
  715. );
  716. *OutputSecretName = SecretName;
  717. return(STATUS_SUCCESS);
  718. }
  719. NTSTATUS
  720. NTAPI
  721. LsapQueryTrustedDomainInfo(
  722. IN LSA_HANDLE PolicyHandle,
  723. IN PSID TrustedDomainSid,
  724. IN TRUSTED_INFORMATION_CLASS InformationClass,
  725. OUT PVOID *Buffer
  726. )
  727. /*++
  728. Routine Description:
  729. The LsaQueryTrustedDomainInfo API obtains information from a
  730. TrustedDomain object. The caller must have access appropriate to the
  731. information being requested (see InformationClass parameter). It also
  732. may query the secret object (for the TrustedDomainPasswordInformation
  733. class).
  734. Arguments:
  735. PolicyHandle - Handle from an LsaOpenPolicy call.
  736. TrustedDomainSid - Sid of domain to query.
  737. InformationClass - Specifies the information to be returned.
  738. Buffer - Receives a pointer to the buffer returned comtaining the
  739. requested information. This buffer is allocated by this service
  740. and must be freed when no longer needed by passing the returned
  741. value to LsaFreeMemory().
  742. Return Value:
  743. NTSTATUS - Standard Nt Result Code
  744. STATUS_ACCESS_DENIED - Caller does not have the appropriate
  745. access to complete the operation.
  746. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources,
  747. such as memory, to complete the call.
  748. --*/
  749. {
  750. NTSTATUS Status;
  751. LSA_HANDLE DomainHandle = NULL;
  752. LSA_HANDLE SecretHandle = NULL;
  753. PUNICODE_STRING OldPassword = NULL;
  754. PUNICODE_STRING Password = NULL;
  755. PTRUSTED_PASSWORD_INFO PasswordInfo = NULL;
  756. PTRUSTED_DOMAIN_NAME_INFO NameInfo = NULL;
  757. ULONG DesiredAccess;
  758. PVOID LocalBuffer = NULL;
  759. TRUSTED_INFORMATION_CLASS LocalInfoClass;
  760. UNICODE_STRING SecretName;
  761. PUCHAR Where;
  762. ULONG PasswordSize;
  763. SecretName.Buffer = NULL;
  764. //
  765. // Find the desired access type for the info we are
  766. // querying.
  767. //
  768. LocalInfoClass = InformationClass;
  769. switch(InformationClass) {
  770. case TrustedDomainNameInformation:
  771. DesiredAccess = TRUSTED_QUERY_DOMAIN_NAME;
  772. break;
  773. case TrustedPosixOffsetInformation:
  774. DesiredAccess = TRUSTED_QUERY_POSIX;
  775. break;
  776. case TrustedPasswordInformation:
  777. DesiredAccess = TRUSTED_QUERY_DOMAIN_NAME;
  778. LocalInfoClass = TrustedDomainNameInformation;
  779. break;
  780. default:
  781. return(STATUS_INVALID_PARAMETER);
  782. }
  783. //
  784. // Open the domain for the desired access
  785. //
  786. Status = LsaOpenTrustedDomain(
  787. PolicyHandle,
  788. TrustedDomainSid,
  789. DesiredAccess,
  790. &DomainHandle
  791. );
  792. if (!NT_SUCCESS(Status)) {
  793. goto Cleanup;
  794. }
  795. Status = LsaQueryInfoTrustedDomain(
  796. DomainHandle,
  797. LocalInfoClass,
  798. &LocalBuffer
  799. );
  800. if (!NT_SUCCESS(Status)) {
  801. goto Cleanup;
  802. }
  803. //
  804. // If the class wasn't trusted password information, return here.
  805. //
  806. if (InformationClass != TrustedPasswordInformation) {
  807. *Buffer = LocalBuffer;
  808. LocalBuffer = NULL;
  809. goto Cleanup;
  810. }
  811. NameInfo = (PTRUSTED_DOMAIN_NAME_INFO) LocalBuffer;
  812. //
  813. // Get the secret name
  814. //
  815. Status = LsapApiBuildSecretName(
  816. NameInfo,
  817. &SecretName
  818. );
  819. if (!NT_SUCCESS(Status)) {
  820. goto Cleanup;
  821. }
  822. Status = LsaOpenSecret(
  823. PolicyHandle,
  824. &SecretName,
  825. SECRET_QUERY_VALUE,
  826. &SecretHandle
  827. );
  828. if (!NT_SUCCESS(Status)) {
  829. goto Cleanup;
  830. }
  831. //
  832. // Query the secret
  833. //
  834. Status = LsaQuerySecret(
  835. SecretHandle,
  836. &Password,
  837. NULL,
  838. &OldPassword,
  839. NULL
  840. );
  841. if (!NT_SUCCESS(Status)) {
  842. goto Cleanup;
  843. }
  844. //
  845. // Marshall the passwords into the output structure.
  846. //
  847. PasswordSize = sizeof(TRUSTED_PASSWORD_INFO);
  848. if (Password != NULL) {
  849. PasswordSize += Password->MaximumLength;
  850. }
  851. if (OldPassword != NULL) {
  852. PasswordSize += OldPassword->MaximumLength;
  853. }
  854. PasswordInfo = (PTRUSTED_PASSWORD_INFO) MIDL_user_allocate(PasswordSize);
  855. if (PasswordInfo == NULL) {
  856. Status = STATUS_INSUFFICIENT_RESOURCES;
  857. goto Cleanup;
  858. }
  859. RtlZeroMemory(
  860. PasswordInfo,
  861. PasswordSize
  862. );
  863. Where = (PUCHAR) (PasswordInfo+1);
  864. if (Password != NULL) {
  865. PasswordInfo->Password = *Password;
  866. PasswordInfo->Password.Buffer = (LPWSTR) Where;
  867. RtlCopyMemory(
  868. Where,
  869. Password->Buffer,
  870. Password->MaximumLength
  871. );
  872. Where += Password->MaximumLength;
  873. }
  874. if (OldPassword != NULL) {
  875. PasswordInfo->OldPassword = *OldPassword;
  876. PasswordInfo->OldPassword.Buffer = (LPWSTR) Where;
  877. RtlCopyMemory(
  878. Where,
  879. OldPassword->Buffer,
  880. OldPassword->MaximumLength
  881. );
  882. Where += OldPassword->MaximumLength;
  883. }
  884. ASSERT(Where - (PUCHAR) PasswordInfo == (LONG) PasswordSize);
  885. *Buffer = PasswordInfo;
  886. Status = STATUS_SUCCESS;
  887. Cleanup:
  888. if (DomainHandle != NULL) {
  889. LsaClose(DomainHandle);
  890. }
  891. if (SecretHandle != NULL) {
  892. LsaClose(SecretHandle);
  893. }
  894. if (LocalBuffer != NULL) {
  895. LsaFreeMemory(LocalBuffer);
  896. }
  897. if (SecretName.Buffer != NULL) {
  898. MIDL_user_free(SecretName.Buffer);
  899. }
  900. return(Status);
  901. }
  902. NTSTATUS
  903. NTAPI
  904. LsapSetTrustedDomainInformation(
  905. IN LSA_HANDLE PolicyHandle,
  906. IN PSID TrustedDomainSid,
  907. IN TRUSTED_INFORMATION_CLASS InformationClass,
  908. IN PVOID Buffer
  909. )
  910. /*++
  911. Routine Description:
  912. The LsaSetTrustedDomainInformation API modifies information in the Trusted
  913. Domain Object and in the Secret Object. The caller must have access
  914. appropriate to the information to be changed in the Policy Object, see
  915. the InformationClass parameter.
  916. If the domain does not yet exist and the information class is
  917. TrustedDomainNameInformation, then the domain is created. If the
  918. domain exists and the class is TrustedDomainNameInformation, an
  919. error is returned.
  920. Arguments:
  921. PolicyHandle - Handle from an LsaOpenPolicy call.
  922. TrustedDomainSid - Sid of domain to modify.
  923. InformationClass - Specifies the type of information being changed.
  924. The information types and accesses required to change them are as
  925. follows:
  926. TrustedDomainNameInformation POLICY_TRUST_ADMIN
  927. TrustedPosixOffsetInformation none
  928. TrustedPasswordInformation POLICY_CREATE_SECRET
  929. Buffer - Points to a structure containing the information appropriate
  930. to the InformationClass parameter.
  931. Return Value:
  932. NTSTATUS - Standard Nt Result Code
  933. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  934. to complete the operation.
  935. Others TBS
  936. --*/
  937. {
  938. LSA_HANDLE DomainHandle = NULL;
  939. LSA_HANDLE SecretHandle = NULL;
  940. NTSTATUS Status;
  941. PUNICODE_STRING OldPassword;
  942. PUNICODE_STRING Password;
  943. LSA_TRUST_INFORMATION DomainInformation;
  944. PTRUSTED_DOMAIN_NAME_INFO NameInfo = NULL;
  945. PTRUSTED_PASSWORD_INFO PasswordInfo;
  946. UNICODE_STRING SecretName;
  947. SecretName.Buffer = NULL;
  948. //
  949. // If the information is the domain name, try to create the domain.
  950. //
  951. if (InformationClass == TrustedDomainNameInformation) {
  952. DomainInformation.Sid = TrustedDomainSid;
  953. DomainInformation.Name = ((PTRUSTED_DOMAIN_NAME_INFO) Buffer)->Name;
  954. Status = LsaCreateTrustedDomain(
  955. PolicyHandle,
  956. &DomainInformation,
  957. 0, //desired access,
  958. &DomainHandle
  959. );
  960. goto Cleanup;
  961. }
  962. //
  963. // For posix offset, open the domain for SET_POSIX and call the old
  964. // LSA API to set the offset.
  965. //
  966. if (InformationClass == TrustedPosixOffsetInformation) {
  967. Status = LsaOpenTrustedDomain(
  968. PolicyHandle,
  969. TrustedDomainSid,
  970. TRUSTED_SET_POSIX,
  971. &DomainHandle
  972. );
  973. if (!NT_SUCCESS(Status)) {
  974. goto Cleanup;
  975. }
  976. Status = LsaSetInformationTrustedDomain(
  977. DomainHandle,
  978. InformationClass,
  979. Buffer
  980. );
  981. goto Cleanup;
  982. }
  983. //
  984. // The only only remaining allowed class is password information.
  985. //
  986. if (InformationClass != TrustedPasswordInformation) {
  987. Status = STATUS_INVALID_PARAMETER;
  988. goto Cleanup;
  989. }
  990. Status = LsaOpenTrustedDomain(
  991. PolicyHandle,
  992. TrustedDomainSid,
  993. TRUSTED_QUERY_DOMAIN_NAME,
  994. &DomainHandle
  995. );
  996. if (!NT_SUCCESS(Status)) {
  997. goto Cleanup;
  998. }
  999. //
  1000. // Get the name so we can find the secret name.
  1001. //
  1002. Status = LsaQueryInfoTrustedDomain(
  1003. DomainHandle,
  1004. TrustedDomainNameInformation,
  1005. &NameInfo
  1006. );
  1007. if (!NT_SUCCESS(Status)) {
  1008. goto Cleanup;
  1009. }
  1010. //
  1011. // Get the secret name
  1012. //
  1013. Status = LsapApiBuildSecretName(
  1014. NameInfo,
  1015. &SecretName
  1016. );
  1017. if (!NT_SUCCESS(Status)) {
  1018. goto Cleanup;
  1019. }
  1020. Status = LsaOpenSecret(
  1021. PolicyHandle,
  1022. &SecretName,
  1023. SECRET_SET_VALUE,
  1024. &SecretHandle
  1025. );
  1026. //
  1027. // If the secret didn't exist, create it now.
  1028. //
  1029. if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
  1030. Status = LsaCreateSecret(
  1031. PolicyHandle,
  1032. &SecretName,
  1033. SECRET_SET_VALUE,
  1034. &SecretHandle
  1035. );
  1036. }
  1037. if (!NT_SUCCESS(Status)) {
  1038. goto Cleanup;
  1039. }
  1040. //
  1041. // If the old password wasn't specified, set it to be the new
  1042. // password.
  1043. //
  1044. PasswordInfo = (PTRUSTED_PASSWORD_INFO) Buffer;
  1045. Password = &PasswordInfo->Password;
  1046. if (PasswordInfo->OldPassword.Buffer == NULL) {
  1047. OldPassword = Password;
  1048. } else {
  1049. OldPassword = &PasswordInfo->OldPassword;
  1050. }
  1051. Status = LsaSetSecret(
  1052. SecretHandle,
  1053. Password,
  1054. OldPassword
  1055. );
  1056. Cleanup:
  1057. if (SecretName.Buffer != NULL) {
  1058. MIDL_user_free(SecretName.Buffer);
  1059. }
  1060. if (DomainHandle != NULL) {
  1061. LsaClose(DomainHandle);
  1062. }
  1063. if (SecretHandle != NULL) {
  1064. LsaClose(SecretHandle);
  1065. }
  1066. if (NameInfo != NULL) {
  1067. LsaFreeMemory(NameInfo);
  1068. }
  1069. return(Status);
  1070. }
  1071. NTSTATUS
  1072. NTAPI
  1073. LsapDeleteTrustedDomain(
  1074. IN LSA_HANDLE PolicyHandle,
  1075. IN PSID TrustedDomainSid
  1076. )
  1077. /*++
  1078. Routine Description:
  1079. This routine deletes a trusted domain and the associated secret.
  1080. Arguments:
  1081. PolicyHandle - Handle from an LsaOpenPolicy call.
  1082. TrustedDomainSid - Sid of domain to delete
  1083. Return Value:
  1084. STATUS_ACCESS_DENIED - caller has insufficient access to delete
  1085. the requested domain.
  1086. STATUS_OBJECT_NAME_NOT_FOUND - The requested domain does not exist.
  1087. --*/
  1088. {
  1089. UNICODE_STRING SecretName;
  1090. NTSTATUS Status;
  1091. PTRUSTED_DOMAIN_NAME_INFO NameInfo = NULL;
  1092. LSA_HANDLE DomainHandle = NULL;
  1093. LSA_HANDLE SecretHandle = NULL;
  1094. SecretName.Buffer = NULL;
  1095. //
  1096. // Open the domain for query name and delete access. We need query name
  1097. // to find the secret name.
  1098. //
  1099. Status = LsaOpenTrustedDomain(
  1100. PolicyHandle,
  1101. TrustedDomainSid,
  1102. TRUSTED_QUERY_DOMAIN_NAME | DELETE,
  1103. &DomainHandle
  1104. );
  1105. if (!NT_SUCCESS(Status)) {
  1106. goto Cleanup;
  1107. }
  1108. //
  1109. // Get the name so we can find the secret name.
  1110. //
  1111. Status = LsaQueryInfoTrustedDomain(
  1112. DomainHandle,
  1113. TrustedDomainNameInformation,
  1114. &NameInfo
  1115. );
  1116. if (!NT_SUCCESS(Status)) {
  1117. goto Cleanup;
  1118. }
  1119. Status = LsaDelete(DomainHandle);
  1120. if (!NT_SUCCESS(Status)) {
  1121. goto Cleanup;
  1122. }
  1123. //
  1124. // Zero the handle so we don't try to free it again.
  1125. //
  1126. DomainHandle = NULL;
  1127. //
  1128. // Get the secret name
  1129. //
  1130. Status = LsapApiBuildSecretName(
  1131. NameInfo,
  1132. &SecretName
  1133. );
  1134. if (!NT_SUCCESS(Status)) {
  1135. goto Cleanup;
  1136. }
  1137. Status = LsaOpenSecret(
  1138. PolicyHandle,
  1139. &SecretName,
  1140. DELETE,
  1141. &SecretHandle
  1142. );
  1143. if (!NT_SUCCESS(Status)) {
  1144. //
  1145. // If the secret does not exist, that is o.k. - it means the password
  1146. // was never set.
  1147. //
  1148. if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
  1149. Status = STATUS_SUCCESS;
  1150. }
  1151. goto Cleanup;
  1152. }
  1153. Status = LsaDelete(SecretHandle);
  1154. if (NT_SUCCESS(Status)) {
  1155. //
  1156. // Zero the handle so we don't try to free it again.
  1157. //
  1158. SecretHandle = NULL;
  1159. }
  1160. Cleanup:
  1161. if (NameInfo != NULL) {
  1162. LsaFreeMemory(NameInfo);
  1163. }
  1164. if (SecretName.Buffer != NULL) {
  1165. MIDL_user_free(SecretName.Buffer);
  1166. }
  1167. if (SecretHandle != NULL) {
  1168. LsaClose(SecretHandle);
  1169. }
  1170. if (DomainHandle != NULL) {
  1171. LsaClose(DomainHandle);
  1172. }
  1173. return(Status);
  1174. }
  1175. NTSTATUS
  1176. NTAPI
  1177. LsapStorePrivateData(
  1178. IN LSA_HANDLE PolicyHandle,
  1179. IN PUNICODE_STRING KeyName,
  1180. IN OPTIONAL PUNICODE_STRING PrivateData
  1181. )
  1182. /*++
  1183. Routine Description:
  1184. This routine stores private data in a secret named KeyName.
  1185. Arguments:
  1186. PolicyHandle - Handle from an LsaOpenPolicyCall. If this is the
  1187. first call, it requres POLICY_CREATE_SECRET access.
  1188. KeyName - Name of secret to store
  1189. PrivateData - Private data to store. If this is null, the secret is
  1190. deleted.
  1191. Return Value:
  1192. STATUS_ACCESS_DENIED - caller has insufficient privilege to set
  1193. the workstation password.
  1194. --*/
  1195. {
  1196. LSA_HANDLE SecretHandle = NULL;
  1197. NTSTATUS Status;
  1198. ULONG DesiredAccess;
  1199. BOOLEAN DeleteSecret = FALSE;
  1200. //
  1201. // check whether to delete the secret or not.
  1202. //
  1203. if (ARGUMENT_PRESENT(PrivateData)) {
  1204. DesiredAccess = SECRET_SET_VALUE;
  1205. } else {
  1206. DesiredAccess = DELETE;
  1207. DeleteSecret = TRUE;
  1208. }
  1209. Status = LsaOpenSecret(
  1210. PolicyHandle,
  1211. KeyName,
  1212. DesiredAccess,
  1213. &SecretHandle
  1214. );
  1215. if ((Status == STATUS_OBJECT_NAME_NOT_FOUND) && !DeleteSecret) {
  1216. Status = LsaCreateSecret(
  1217. PolicyHandle,
  1218. KeyName,
  1219. DesiredAccess,
  1220. &SecretHandle
  1221. );
  1222. }
  1223. if (!NT_SUCCESS(Status)) {
  1224. goto Cleanup;
  1225. }
  1226. if (DeleteSecret) {
  1227. Status = LsaDelete(
  1228. SecretHandle
  1229. );
  1230. if (NT_SUCCESS(Status)) {
  1231. SecretHandle = NULL;
  1232. }
  1233. goto Cleanup;
  1234. }
  1235. Status = LsaSetSecret(
  1236. SecretHandle,
  1237. PrivateData,
  1238. PrivateData
  1239. );
  1240. Cleanup:
  1241. if (SecretHandle != NULL) {
  1242. LsaClose(SecretHandle);
  1243. }
  1244. return(Status);
  1245. }
  1246. NTSTATUS
  1247. NTAPI
  1248. LsapRetrievePrivateData(
  1249. IN LSA_HANDLE PolicyHandle,
  1250. IN PUNICODE_STRING KeyName,
  1251. OUT PUNICODE_STRING * PrivateData
  1252. )
  1253. /*++
  1254. Routine Description:
  1255. This routine returns the secret data stored under KeyName.
  1256. Arguments:
  1257. PolicyHandle - Handle from an LsaOpenPolicyCall
  1258. KeyName - Name of secret data to retrieve
  1259. PrivateData - Receives a pointer private data
  1260. Return Value:
  1261. STATUS_ACCESS_DENIED - caller has insufficient access to get the
  1262. workstation password.
  1263. STATUS_OBJECT_NAME_NOT_FOUND - there is no workstation password.
  1264. --*/
  1265. {
  1266. LSA_HANDLE SecretHandle = NULL;
  1267. NTSTATUS Status;
  1268. //
  1269. // Make the secret name
  1270. //
  1271. Status = LsaOpenSecret(
  1272. PolicyHandle,
  1273. KeyName,
  1274. SECRET_QUERY_VALUE,
  1275. &SecretHandle
  1276. );
  1277. if (!NT_SUCCESS(Status)) {
  1278. goto Cleanup;
  1279. }
  1280. Status = LsaQuerySecret(
  1281. SecretHandle,
  1282. PrivateData,
  1283. NULL,
  1284. NULL,
  1285. NULL
  1286. );
  1287. Cleanup:
  1288. if (SecretHandle != NULL) {
  1289. LsaClose(SecretHandle);
  1290. }
  1291. return(Status);
  1292. }
  1293. /////////////////////////////////////////////////////////////////////////
  1294. //
  1295. // RPC wrappers for LSA APIs added in nt3.51. This routines call the
  1296. // LSA, and if the interface doesn't exist, calls the LsapXXX routine
  1297. // to accomplish the same task using the older routines.
  1298. //
  1299. ////////////////////////////////////////////////////////////////////////
  1300. NTSTATUS
  1301. NTAPI
  1302. LsaEnumerateAccountsWithUserRight(
  1303. IN LSA_HANDLE PolicyHandle,
  1304. IN OPTIONAL PUNICODE_STRING UserRight,
  1305. OUT PVOID *Buffer,
  1306. OUT PULONG CountReturned
  1307. )
  1308. /*++
  1309. Routine Description:
  1310. The LsaEnumerateAccounts API returns information about the accounts
  1311. in the target system's Lsa Database. This call requires
  1312. LSA_ENUMERATE_ACCOUNTS access to the Policy object. Since this call
  1313. accesses the privileges of an account, you must have PRIVILEGE_VIEW
  1314. access to the pseudo-privilege object.
  1315. Arguments:
  1316. PolicyHandle - Handle from an LsaOpenPolicy call.
  1317. UserRight - Name of the right that the account must have.
  1318. Buffer - Receives a pointer to a LSA_ENUMERATION_INFORMATION structure
  1319. containing the SIDs of all the accounts.
  1320. CountReturned - Receives the number of sids returned.
  1321. Return Values:
  1322. NTSTATUS - Standard Nt Result Code
  1323. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  1324. to complete the operation.
  1325. STATUS_NO_MORE_ENTRIES - There are no more entries. This warning
  1326. is returned if no objects are enumerated because the
  1327. EnumerationContext value passed in is too high.
  1328. --*/
  1329. {
  1330. NTSTATUS Status;
  1331. LSAPR_ACCOUNT_ENUM_BUFFER EnumerationBuffer;
  1332. EnumerationBuffer.EntriesRead = 0;
  1333. EnumerationBuffer.Information = NULL;
  1334. RpcTryExcept {
  1335. //
  1336. // Enumerate the Accounts. On successful return,
  1337. // the Enumeration Buffer structure will receive a count
  1338. // of the number of Accounts enumerated this call
  1339. // and a pointer to an array of Account Information Entries.
  1340. //
  1341. // EnumerationBuffer -> EntriesRead
  1342. // Information -> Account Info for Domain 0
  1343. // Account Info for Domain 1
  1344. // ...
  1345. // Account Info for Domain
  1346. // (EntriesRead - 1)
  1347. //
  1348. Status = LsarEnumerateAccountsWithUserRight(
  1349. (LSAPR_HANDLE) PolicyHandle,
  1350. (PLSAPR_UNICODE_STRING) UserRight,
  1351. &EnumerationBuffer
  1352. );
  1353. //
  1354. // Return enumeration information or NULL to caller.
  1355. //
  1356. // NOTE: "Information" is allocated by the called client stub
  1357. // as a single block via MIDL_user_allocate, because Information is
  1358. // allocated all-nodes. We can therefore pass back the pointer
  1359. // directly to the client, who will be able to free the memory after
  1360. // use via LsaFreeMemory() [which makes a MIDL_user_free call].
  1361. //
  1362. *CountReturned = EnumerationBuffer.EntriesRead;
  1363. *Buffer = EnumerationBuffer.Information;
  1364. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1365. //
  1366. // If memory was allocated for the Account Information array,
  1367. // free it.
  1368. //
  1369. if (EnumerationBuffer.Information != NULL) {
  1370. MIDL_user_free(EnumerationBuffer.Information);
  1371. }
  1372. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  1373. } RpcEndExcept;
  1374. //
  1375. // If the RPC server stub didn't exist, use the old version of the
  1376. // API.
  1377. //
  1378. if ((Status == RPC_NT_UNKNOWN_IF) ||
  1379. (Status == RPC_NT_PROCNUM_OUT_OF_RANGE)) {
  1380. Status = LsapEnumerateAccountsWithUserRight(
  1381. PolicyHandle,
  1382. UserRight,
  1383. Buffer,
  1384. CountReturned
  1385. );
  1386. }
  1387. return Status;
  1388. }
  1389. NTSTATUS
  1390. NTAPI
  1391. LsaEnumerateAccountRights(
  1392. IN LSA_HANDLE PolicyHandle,
  1393. IN PSID AccountSid,
  1394. OUT PUNICODE_STRING *UserRights,
  1395. OUT PULONG CountOfRights
  1396. )
  1397. /*++
  1398. Routine Description:
  1399. Returns all the rights of an account. This is done by gathering the
  1400. privileges and system access of an account and translating that into
  1401. an array of strings.
  1402. Arguments:
  1403. PolicyHandle - Handle from an LsaOpenPolicyCall. This API requires
  1404. no special access.
  1405. AccountSid - Sid of account to open.
  1406. UserRights - receives an array of user rights (UNICODE_STRING) for
  1407. the account.
  1408. CountOfRights - receives the number of rights returned.
  1409. Return Value:
  1410. STATUS_ACCESS_DENIED - the caller did not have sufficient access to
  1411. return the privileges or system access of the account.
  1412. STATUS_OBJECT_NAME_NOT_FOUND - the specified account did not exist.
  1413. STATUS_INSUFFICIENT_RESOURCES - not enough memory to process the
  1414. request.
  1415. --*/
  1416. {
  1417. NTSTATUS Status;
  1418. LSAPR_USER_RIGHT_SET UserRightSet;
  1419. UserRightSet.Entries = 0;
  1420. UserRightSet.UserRights = NULL;
  1421. RpcTryExcept {
  1422. Status = LsarEnumerateAccountRights(
  1423. (LSAPR_HANDLE) PolicyHandle,
  1424. (PLSAPR_SID) AccountSid,
  1425. &UserRightSet
  1426. );
  1427. *CountOfRights = UserRightSet.Entries;
  1428. *UserRights = (PUNICODE_STRING) UserRightSet.UserRights;
  1429. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1430. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  1431. if (UserRightSet.UserRights != NULL) {
  1432. MIDL_user_free(UserRightSet.UserRights);
  1433. }
  1434. } RpcEndExcept;
  1435. //
  1436. // If the RPC server stub didn't exist, use the old version of the
  1437. // API.
  1438. //
  1439. if ((Status == RPC_NT_UNKNOWN_IF) ||
  1440. (Status == RPC_NT_PROCNUM_OUT_OF_RANGE)) {
  1441. Status = LsapEnumerateAccountRights(
  1442. PolicyHandle,
  1443. AccountSid,
  1444. UserRights,
  1445. CountOfRights
  1446. );
  1447. }
  1448. return Status;
  1449. }
  1450. NTSTATUS
  1451. NTAPI
  1452. LsaAddAccountRights(
  1453. IN LSA_HANDLE PolicyHandle,
  1454. IN PSID AccountSid,
  1455. IN PUNICODE_STRING UserRights,
  1456. IN ULONG CountOfRights
  1457. )
  1458. /*++
  1459. Routine Description:
  1460. Adds rights to the account specified by the account sid. If the account
  1461. does not exist, it creates the account.
  1462. Arguments:
  1463. PolicyHandle - Handle from an LsaOpenPolicy call. The handle must have
  1464. POLICY_CREATE_ACCOUNT access if this is the first call for this
  1465. AccountSid.
  1466. AccountSid - Sid of account to add rights to
  1467. UserRights - Array of unicode strings naming rights to add to the
  1468. account.
  1469. Return Value:
  1470. STATUS_INSUFFICIENT_RESOURCES - not enough memory to process the request
  1471. STATUS_INVALID_PARAMTER - one of the parameters was not present
  1472. STATUS_NO_SUCH_PRIVILEGE - One of the user rights was invalid
  1473. STATUS_ACCESS_DENIED - the caller does not have sufficient access to the
  1474. account to add privileges.
  1475. --*/
  1476. {
  1477. NTSTATUS Status;
  1478. LSAPR_USER_RIGHT_SET UserRightSet;
  1479. UserRightSet.Entries = CountOfRights;
  1480. UserRightSet.UserRights = (PLSAPR_UNICODE_STRING) UserRights;
  1481. RpcTryExcept {
  1482. Status = LsarAddAccountRights(
  1483. (LSAPR_HANDLE) PolicyHandle,
  1484. (PLSAPR_SID) AccountSid,
  1485. &UserRightSet
  1486. );
  1487. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1488. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  1489. } RpcEndExcept;
  1490. //
  1491. // If the RPC server stub didn't exist, use the old version of the
  1492. // API.
  1493. //
  1494. if ((Status == RPC_NT_UNKNOWN_IF) ||
  1495. (Status == RPC_NT_PROCNUM_OUT_OF_RANGE)) {
  1496. Status = LsapAddAccountRights(
  1497. PolicyHandle,
  1498. AccountSid,
  1499. UserRights,
  1500. CountOfRights
  1501. );
  1502. }
  1503. return Status;
  1504. }
  1505. NTSTATUS
  1506. NTAPI
  1507. LsaRemoveAccountRights(
  1508. IN LSA_HANDLE PolicyHandle,
  1509. IN PSID AccountSid,
  1510. IN BOOLEAN AllRights,
  1511. IN PUNICODE_STRING UserRights,
  1512. IN ULONG CountOfRights
  1513. )
  1514. /*++
  1515. Routine Description:
  1516. Removes rights to the account specified by the account sid. If the
  1517. AllRights flag is set or if all the rights are removed, the account
  1518. is deleted.
  1519. Arguments:
  1520. PolicyHandle - Handle from an LsaOpenPolicy call
  1521. AccountSid - Sid of account to remove rights from
  1522. UserRights - Array of unicode strings naming rights to remove from the
  1523. account.
  1524. Return Value:
  1525. STATUS_INSUFFICIENT_RESOURCES - not enough memory to process the request
  1526. STATUS_INVALID_PARAMTER - one of the parameters was not present
  1527. STATUS_NO_SUCH_PRIVILEGE - One of the user rights was invalid
  1528. STATUS_ACCESS_DENIED - the caller does not have sufficient access to the
  1529. account to add privileges.
  1530. --*/
  1531. {
  1532. NTSTATUS Status;
  1533. LSAPR_USER_RIGHT_SET UserRightSet;
  1534. UserRightSet.Entries = CountOfRights;
  1535. UserRightSet.UserRights = (PLSAPR_UNICODE_STRING) UserRights;
  1536. RpcTryExcept {
  1537. Status = LsarRemoveAccountRights(
  1538. (LSAPR_HANDLE) PolicyHandle,
  1539. (PLSAPR_SID) AccountSid,
  1540. AllRights,
  1541. &UserRightSet
  1542. );
  1543. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1544. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  1545. } RpcEndExcept;
  1546. if ((Status == RPC_NT_UNKNOWN_IF) ||
  1547. (Status == RPC_NT_PROCNUM_OUT_OF_RANGE)) {
  1548. Status = LsapRemoveAccountRights(
  1549. PolicyHandle,
  1550. AccountSid,
  1551. AllRights,
  1552. UserRights,
  1553. CountOfRights
  1554. );
  1555. }
  1556. return Status;
  1557. }
  1558. NTSTATUS
  1559. NTAPI
  1560. LsaQueryTrustedDomainInfo(
  1561. IN LSA_HANDLE PolicyHandle,
  1562. IN PSID TrustedDomainSid,
  1563. IN TRUSTED_INFORMATION_CLASS InformationClass,
  1564. OUT PVOID *Buffer
  1565. )
  1566. /*++
  1567. Routine Description:
  1568. The LsaQueryTrustedDomainInfo API obtains information from a
  1569. TrustedDomain object. The caller must have access appropriate to the
  1570. information being requested (see InformationClass parameter). It also
  1571. may query the secret object (for the TrustedDomainPasswordInformation
  1572. class).
  1573. Arguments:
  1574. PolicyHandle - Handle from an LsaOpenPolicy call.
  1575. TrustedDomainSid - Sid of domain to query.
  1576. InformationClass - Specifies the information to be returned.
  1577. Buffer - Receives a pointer to the buffer returned comtaining the
  1578. requested information. This buffer is allocated by this service
  1579. and must be freed when no longer needed by passing the returned
  1580. value to LsaFreeMemory().
  1581. Return Value:
  1582. NTSTATUS - Standard Nt Result Code
  1583. STATUS_ACCESS_DENIED - Caller does not have the appropriate
  1584. access to complete the operation.
  1585. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources,
  1586. such as memory, to complete the call.
  1587. --*/
  1588. {
  1589. NTSTATUS Status;
  1590. PLSAP_CR_CIPHER_VALUE CipherPassword = NULL;
  1591. PLSAP_CR_CIPHER_VALUE CipherOldPassword = NULL;
  1592. PLSAP_CR_CLEAR_VALUE ClearPassword = NULL;
  1593. PLSAP_CR_CLEAR_VALUE ClearOldPassword = NULL;
  1594. PLSAP_CR_CIPHER_KEY SessionKey = NULL;
  1595. ULONG DomainInfoSize;
  1596. PUCHAR Where = NULL;
  1597. PTRUSTED_PASSWORD_INFO PasswordInformation = NULL;
  1598. PLSAPR_TRUSTED_DOMAIN_INFO TrustedDomainInformation = NULL;
  1599. //
  1600. // Avoid the internal info levels that represent the encrypted version on
  1601. // the wire.
  1602. //
  1603. switch ( InformationClass ) {
  1604. case TrustedDomainAuthInformationInternal:
  1605. case TrustedDomainFullInformationInternal:
  1606. return STATUS_INVALID_INFO_CLASS;
  1607. }
  1608. RpcTryExcept {
  1609. //
  1610. // Call the Client Stub for LsaQueryInformationTrustedDomain.
  1611. //
  1612. Status = LsarQueryTrustedDomainInfo(
  1613. (LSAPR_HANDLE) PolicyHandle,
  1614. (PLSAPR_SID) TrustedDomainSid,
  1615. InformationClass,
  1616. &TrustedDomainInformation
  1617. );
  1618. //
  1619. // Return pointer to Policy Information for the given class, or NULL.
  1620. //
  1621. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1622. //
  1623. // If memory was allocated for the returned Trusted Domain Information,
  1624. // free it.
  1625. //
  1626. if (TrustedDomainInformation != NULL) {
  1627. MIDL_user_free(TrustedDomainInformation);
  1628. }
  1629. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  1630. } RpcEndExcept;
  1631. if (!NT_SUCCESS(Status)) {
  1632. goto Cleanup;
  1633. }
  1634. //
  1635. // if we aren't getting passwords, skip out here. Otherwise we need to
  1636. // decrypt the passwords.
  1637. //
  1638. if (InformationClass != TrustedPasswordInformation) {
  1639. *Buffer = TrustedDomainInformation;
  1640. TrustedDomainInformation = NULL;
  1641. goto Cleanup;
  1642. }
  1643. //
  1644. // Obtain the Session Key to be used to two-way encrypt the
  1645. // Current Value and/or Old Values.
  1646. //
  1647. RpcTryExcept {
  1648. Status = LsapCrClientGetSessionKey( PolicyHandle, &SessionKey );
  1649. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1650. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  1651. } RpcEndExcept;
  1652. if (!NT_SUCCESS(Status)) {
  1653. goto Cleanup;
  1654. }
  1655. //
  1656. // If the Current Value is requested and a Current Value exists,
  1657. // decrypt it using the Session key. Otherwise store NULL for return.
  1658. //
  1659. if (TrustedDomainInformation->TrustedPasswordInfo.Password != NULL) {
  1660. Status = LsapCrDecryptValue(
  1661. (PLSAP_CR_CIPHER_VALUE)
  1662. TrustedDomainInformation->TrustedPasswordInfo.Password,
  1663. SessionKey,
  1664. &ClearPassword
  1665. );
  1666. if (!NT_SUCCESS(Status)) {
  1667. goto Cleanup;
  1668. }
  1669. //
  1670. // Convert Clear Current Value to Unicode
  1671. //
  1672. LsapCrClearValueToUnicode(
  1673. ClearPassword,
  1674. (PUNICODE_STRING) ClearPassword
  1675. );
  1676. }
  1677. //
  1678. // Get the old password
  1679. //
  1680. if (TrustedDomainInformation->TrustedPasswordInfo.OldPassword != NULL) {
  1681. Status = LsapCrDecryptValue(
  1682. (PLSAP_CR_CIPHER_VALUE)
  1683. TrustedDomainInformation->TrustedPasswordInfo.OldPassword,
  1684. SessionKey,
  1685. &ClearOldPassword
  1686. );
  1687. if (!NT_SUCCESS(Status)) {
  1688. goto Cleanup;
  1689. }
  1690. //
  1691. // Convert Clear Current Value to Unicode
  1692. //
  1693. LsapCrClearValueToUnicode(
  1694. ClearOldPassword,
  1695. (PUNICODE_STRING) ClearOldPassword
  1696. );
  1697. }
  1698. MIDL_user_free(TrustedDomainInformation);
  1699. TrustedDomainInformation = NULL;
  1700. //
  1701. // Allocate a buffer for the two passwords and marshall the
  1702. // passwords into the buffer.
  1703. //
  1704. DomainInfoSize = sizeof(TRUSTED_PASSWORD_INFO);
  1705. if (ClearPassword != NULL) {
  1706. DomainInfoSize += ((PUNICODE_STRING) ClearPassword)->MaximumLength;
  1707. }
  1708. if (ClearOldPassword != NULL) {
  1709. DomainInfoSize += ((PUNICODE_STRING) ClearOldPassword)->MaximumLength;
  1710. }
  1711. PasswordInformation = (PTRUSTED_PASSWORD_INFO) MIDL_user_allocate(DomainInfoSize);
  1712. if (PasswordInformation == NULL) {
  1713. Status = STATUS_INSUFFICIENT_RESOURCES;
  1714. goto Cleanup;
  1715. }
  1716. Where = (PUCHAR) (PasswordInformation+1);
  1717. if (ClearPassword != NULL)
  1718. {
  1719. PasswordInformation->Password = *(PUNICODE_STRING) ClearPassword;
  1720. PasswordInformation->Password.Buffer = (LPWSTR) Where;
  1721. Where += PasswordInformation->Password.MaximumLength;
  1722. RtlCopyUnicodeString(
  1723. &PasswordInformation->Password,
  1724. (PUNICODE_STRING) ClearPassword
  1725. );
  1726. }
  1727. if (ClearOldPassword != NULL)
  1728. {
  1729. PasswordInformation->OldPassword = *(PUNICODE_STRING) ClearOldPassword;
  1730. PasswordInformation->OldPassword.Buffer = (LPWSTR) Where;
  1731. Where += PasswordInformation->OldPassword.MaximumLength;
  1732. RtlCopyUnicodeString(
  1733. &PasswordInformation->OldPassword,
  1734. (PUNICODE_STRING) ClearOldPassword
  1735. );
  1736. }
  1737. ASSERT(Where - (PUCHAR) PasswordInformation == (LONG) DomainInfoSize);
  1738. *Buffer = PasswordInformation;
  1739. PasswordInformation = NULL;
  1740. Status = STATUS_SUCCESS;
  1741. Cleanup:
  1742. //
  1743. // If necessary, free memory allocated for the Session Key.
  1744. //
  1745. if (SessionKey != NULL) {
  1746. MIDL_user_free(SessionKey);
  1747. }
  1748. //
  1749. // If necessary, free memory allocated for the returned Encrypted
  1750. // Current Value.
  1751. //
  1752. if (CipherPassword != NULL) {
  1753. LsapCrFreeMemoryValue(CipherPassword);
  1754. }
  1755. //
  1756. // If necessary, free memory allocated for the returned Encrypted
  1757. // Old Value.
  1758. //
  1759. if (CipherOldPassword != NULL) {
  1760. LsapCrFreeMemoryValue(CipherOldPassword);
  1761. }
  1762. if (ClearPassword != NULL) {
  1763. LsapCrFreeMemoryValue(ClearPassword);
  1764. }
  1765. if (ClearOldPassword != NULL) {
  1766. LsapCrFreeMemoryValue(ClearOldPassword);
  1767. }
  1768. if (TrustedDomainInformation != NULL) {
  1769. MIDL_user_free(TrustedDomainInformation);
  1770. }
  1771. if (PasswordInformation != NULL) {
  1772. MIDL_user_free(PasswordInformation);
  1773. }
  1774. //
  1775. // If the error was that the server stub didn't exist, call
  1776. // the old version of the API.
  1777. //
  1778. if ((Status == RPC_NT_UNKNOWN_IF) ||
  1779. (Status == RPC_NT_PROCNUM_OUT_OF_RANGE)) {
  1780. Status = LsapQueryTrustedDomainInfo(
  1781. PolicyHandle,
  1782. TrustedDomainSid,
  1783. InformationClass,
  1784. Buffer
  1785. );
  1786. }
  1787. return Status;
  1788. }
  1789. NTSTATUS
  1790. NTAPI
  1791. LsaSetTrustedDomainInformation(
  1792. IN LSA_HANDLE PolicyHandle,
  1793. IN PSID TrustedDomainSid,
  1794. IN TRUSTED_INFORMATION_CLASS InformationClass,
  1795. IN PVOID Buffer
  1796. )
  1797. /*++
  1798. Routine Description:
  1799. The LsaSetTrustedDomainInformation API modifies information in the Trusted
  1800. Domain Object and in the Secret Object. The caller must have access
  1801. appropriate to the information to be changed in the Policy Object, see
  1802. the InformationClass parameter.
  1803. If the domain does not yet exist and the information class is
  1804. TrustedDomainNameInformation, then the domain is created. If the
  1805. domain exists and the class is TrustedDomainNameInformation, an
  1806. error is returned.
  1807. Arguments:
  1808. PolicyHandle - Handle from an LsaOpenPolicy call.
  1809. TrustedDomainSid - Sid of domain to modify.
  1810. InformationClass - Specifies the type of information being changed.
  1811. The information types and accesses required to change them are as
  1812. follows:
  1813. TrustedDomainNameInformation POLICY_TRUST_ADMIN
  1814. TrustedPosixOffsetInformation none
  1815. TrustedPasswordInformation POLICY_CREATE_SECRET
  1816. Buffer - Points to a structure containing the information appropriate
  1817. to the InformationClass parameter.
  1818. Return Value:
  1819. NTSTATUS - Standard Nt Result Code
  1820. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  1821. to complete the operation.
  1822. STATUS_INVALID_INFO_CLASS - Setting information for specified information class
  1823. is not supported
  1824. Others TBS
  1825. --*/
  1826. {
  1827. NTSTATUS Status;
  1828. PLSAPR_TRUSTED_DOMAIN_INFO DomainInformation;
  1829. LSAPR_TRUSTED_PASSWORD_INFO LsaPasswordInfo;
  1830. PTRUSTED_PASSWORD_INFO PasswordInformation;
  1831. PLSAP_CR_CIPHER_VALUE CipherPassword = NULL;
  1832. LSAP_CR_CLEAR_VALUE ClearPassword;
  1833. PLSAP_CR_CIPHER_VALUE CipherOldPassword = NULL;
  1834. LSAP_CR_CLEAR_VALUE ClearOldPassword;
  1835. PLSAP_CR_CIPHER_KEY SessionKey = NULL;
  1836. PUNICODE_STRING OldPassword;
  1837. //
  1838. // If the infotype is TrustedPasswordInformation, then we need to
  1839. // setup a secure channel to transmit the secret passwords.
  1840. //
  1841. switch ( InformationClass ) {
  1842. case TrustedPasswordInformation:
  1843. PasswordInformation = (PTRUSTED_PASSWORD_INFO) Buffer;
  1844. LsaPasswordInfo.Password = NULL;
  1845. LsaPasswordInfo.OldPassword = NULL;
  1846. //
  1847. // Obtain the Session Key to be used to two-way encrypt the
  1848. // Current Value.
  1849. //
  1850. RpcTryExcept {
  1851. Status = LsapCrClientGetSessionKey( PolicyHandle, &SessionKey );
  1852. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1853. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  1854. } RpcEndExcept;
  1855. if (!NT_SUCCESS(Status)) {
  1856. goto Cleanup;
  1857. }
  1858. //
  1859. // The password must be specified, even if it is an empty string.
  1860. //
  1861. if (PasswordInformation->Password.Buffer != NULL) {
  1862. //
  1863. // Convert input from Unicode Structures to Clear Value Structures.
  1864. //
  1865. LsapCrUnicodeToClearValue(
  1866. &PasswordInformation->Password,
  1867. &ClearPassword
  1868. );
  1869. //
  1870. // Encrypt the Current Value if specified and not too long.
  1871. //
  1872. Status = LsapCrEncryptValue(
  1873. &ClearPassword,
  1874. SessionKey,
  1875. &CipherPassword
  1876. );
  1877. if (!NT_SUCCESS(Status)) {
  1878. goto Cleanup;
  1879. }
  1880. LsaPasswordInfo.Password = (PLSAPR_CR_CIPHER_VALUE) CipherPassword;
  1881. //
  1882. // If the old password wasn't specified, set it to be the
  1883. // new password.
  1884. //
  1885. if (PasswordInformation->OldPassword.Buffer == NULL) {
  1886. OldPassword = &PasswordInformation->Password;
  1887. } else {
  1888. OldPassword = &PasswordInformation->OldPassword;
  1889. }
  1890. //
  1891. // Convert input from Unicode Structures to Clear Value Structures.
  1892. //
  1893. LsapCrUnicodeToClearValue(
  1894. OldPassword,
  1895. &ClearOldPassword
  1896. );
  1897. //
  1898. // Encrypt the Current Value if specified and not too long.
  1899. //
  1900. Status = LsapCrEncryptValue(
  1901. &ClearOldPassword,
  1902. SessionKey,
  1903. &CipherOldPassword
  1904. );
  1905. if (!NT_SUCCESS(Status)) {
  1906. goto Cleanup;
  1907. }
  1908. LsaPasswordInfo.OldPassword = (PLSAPR_CR_CIPHER_VALUE) CipherOldPassword;
  1909. } else {
  1910. Status = STATUS_INVALID_PARAMETER;
  1911. goto Cleanup;
  1912. }
  1913. DomainInformation = (PLSAPR_TRUSTED_DOMAIN_INFO) &LsaPasswordInfo;
  1914. break;
  1915. //
  1916. // There are only two other info levels handled
  1917. //
  1918. case TrustedPosixOffsetInformation:
  1919. case TrustedDomainNameInformation:
  1920. DomainInformation = (PLSAPR_TRUSTED_DOMAIN_INFO) Buffer;
  1921. break;
  1922. //
  1923. // No other info levels are supported
  1924. //
  1925. default:
  1926. return STATUS_INVALID_INFO_CLASS;
  1927. }
  1928. RpcTryExcept {
  1929. //
  1930. // Call the Client Stub for LsaSetInformationTrustedDomain
  1931. //
  1932. Status = LsarSetTrustedDomainInfo
  1933. (
  1934. (LSAPR_HANDLE) PolicyHandle,
  1935. (PLSAPR_SID) TrustedDomainSid,
  1936. InformationClass,
  1937. DomainInformation
  1938. );
  1939. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1940. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  1941. } RpcEndExcept;
  1942. Cleanup:
  1943. if (SessionKey != NULL) {
  1944. MIDL_user_free(SessionKey);
  1945. }
  1946. if (CipherPassword != NULL) {
  1947. LsaFreeMemory(CipherPassword);
  1948. }
  1949. if (CipherOldPassword != NULL) {
  1950. LsaFreeMemory(CipherOldPassword);
  1951. }
  1952. //
  1953. // If the error was that the server stub didn't exist, call
  1954. // the old version of the API.
  1955. //
  1956. if ((Status == RPC_NT_UNKNOWN_IF) ||
  1957. (Status == RPC_NT_PROCNUM_OUT_OF_RANGE)) {
  1958. Status = LsapSetTrustedDomainInformation(
  1959. PolicyHandle,
  1960. TrustedDomainSid,
  1961. InformationClass,
  1962. Buffer
  1963. );
  1964. }
  1965. return Status;
  1966. }
  1967. NTSTATUS
  1968. NTAPI
  1969. LsaDeleteTrustedDomain(
  1970. IN LSA_HANDLE PolicyHandle,
  1971. IN PSID TrustedDomainSid
  1972. )
  1973. /*++
  1974. Routine Description:
  1975. This routine deletes a trusted domain and the associated secret.
  1976. Arguments:
  1977. PolicyHandle - Handle from an LsaOpenPolicy call.
  1978. TrustedDomainSid - Sid of domain to delete
  1979. Return Value:
  1980. STATUS_ACCESS_DENIED - caller has insufficient access to delete
  1981. the requested domain.
  1982. STATUS_OBJECT_NAME_NOT_FOUND - The requested domain does not exist.
  1983. --*/
  1984. {
  1985. NTSTATUS Status;
  1986. RpcTryExcept {
  1987. Status = LsarDeleteTrustedDomain(
  1988. (LSAPR_HANDLE) PolicyHandle,
  1989. (PLSAPR_SID) TrustedDomainSid
  1990. );
  1991. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1992. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  1993. } RpcEndExcept;
  1994. //
  1995. // If the error was that the server stub didn't exist, call
  1996. // the old version of the API.
  1997. //
  1998. if ((Status == RPC_NT_UNKNOWN_IF) ||
  1999. (Status == RPC_NT_PROCNUM_OUT_OF_RANGE)) {
  2000. Status = LsapDeleteTrustedDomain(
  2001. PolicyHandle,
  2002. TrustedDomainSid
  2003. );
  2004. }
  2005. return(Status);
  2006. }
  2007. //
  2008. // This API sets the workstation password (equivalent of setting/getting
  2009. // the SSI_SECRET_NAME secret)
  2010. //
  2011. NTSTATUS
  2012. NTAPI
  2013. LsaStorePrivateData(
  2014. IN LSA_HANDLE PolicyHandle,
  2015. IN PUNICODE_STRING KeyName,
  2016. IN OPTIONAL PUNICODE_STRING PrivateData
  2017. )
  2018. /*++
  2019. Routine Description:
  2020. This routine stores private data in an LSA secret named KeyName.
  2021. Arguments:
  2022. PolicyHandle - Handle from an LsaOpenPolicyCall. If this is the
  2023. first call, it requres POLICY_CREATE_SECRET access.
  2024. KeyName - Name of secret to store.
  2025. PrivateData - Data to store. If not present, the secret is deleted.
  2026. Return Value:
  2027. STATUS_ACCESS_DENIED - caller has insufficient privilege to set
  2028. the workstation password.
  2029. --*/
  2030. {
  2031. NTSTATUS Status;
  2032. PLSAP_CR_CIPHER_VALUE CipherCurrentValue = NULL;
  2033. LSAP_CR_CLEAR_VALUE ClearCurrentValue;
  2034. PLSAP_CR_CIPHER_KEY SessionKey = NULL;
  2035. if (ARGUMENT_PRESENT(PrivateData)) {
  2036. //
  2037. // Convert input from Unicode Structures to Clear Value Structures.
  2038. //
  2039. LsapCrUnicodeToClearValue( PrivateData, &ClearCurrentValue );
  2040. //
  2041. // Obtain the Session Key to be used to two-way encrypt the
  2042. // Current Value.
  2043. //
  2044. RpcTryExcept {
  2045. Status = LsapCrClientGetSessionKey( PolicyHandle, &SessionKey );
  2046. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  2047. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  2048. } RpcEndExcept;
  2049. if (!NT_SUCCESS(Status)) {
  2050. goto Cleanup;
  2051. }
  2052. //
  2053. // Encrypt the Current Value if specified and not too long.
  2054. //
  2055. Status = LsapCrEncryptValue(
  2056. &ClearCurrentValue,
  2057. SessionKey,
  2058. &CipherCurrentValue
  2059. );
  2060. if (!NT_SUCCESS(Status)) {
  2061. goto Cleanup;
  2062. }
  2063. }
  2064. //
  2065. // Set the Secret Values.
  2066. //
  2067. RpcTryExcept {
  2068. Status = LsarStorePrivateData(
  2069. (LSAPR_HANDLE) PolicyHandle,
  2070. (PLSAPR_UNICODE_STRING) KeyName,
  2071. (PLSAPR_CR_CIPHER_VALUE) CipherCurrentValue
  2072. );
  2073. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  2074. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  2075. } RpcEndExcept;
  2076. if (!NT_SUCCESS(Status)) {
  2077. goto Cleanup;
  2078. }
  2079. Cleanup:
  2080. //
  2081. // If necessary, free memory allocated for the Encrypted Current Value.
  2082. //
  2083. if (CipherCurrentValue != NULL) {
  2084. LsaFreeMemory(CipherCurrentValue);
  2085. }
  2086. //
  2087. // If necessary, free memory allocated for the Session Key.
  2088. //
  2089. if (SessionKey != NULL) {
  2090. MIDL_user_free(SessionKey);
  2091. }
  2092. //
  2093. // If the error was that the server stub didn't exist, call
  2094. // the old version of the API.
  2095. //
  2096. if ((Status == RPC_NT_UNKNOWN_IF) ||
  2097. (Status == RPC_NT_PROCNUM_OUT_OF_RANGE)) {
  2098. Status = LsapStorePrivateData(
  2099. PolicyHandle,
  2100. KeyName,
  2101. PrivateData
  2102. );
  2103. }
  2104. return(Status);
  2105. }
  2106. NTSTATUS
  2107. NTAPI
  2108. LsaRetrievePrivateData(
  2109. IN LSA_HANDLE PolicyHandle,
  2110. IN PUNICODE_STRING KeyName,
  2111. OUT PUNICODE_STRING *PrivateData
  2112. )
  2113. /*++
  2114. Routine Description:
  2115. This routine returns the secret stored in KeyName.
  2116. Arguments:
  2117. PolicyHandle - Handle from an LsaOpenPolicyCall
  2118. KeyName - Name of secret to retrieve
  2119. PrivateData - Receives private data, should be freed with LsaFreeMemory.
  2120. Return Value:
  2121. STATUS_ACCESS_DENIED - caller has insufficient access to get the
  2122. private data.
  2123. STATUS_OBJECT_NAME_NOT_FOUND - there is no private data stored under
  2124. KeyName.
  2125. --*/
  2126. {
  2127. NTSTATUS Status = STATUS_SUCCESS;
  2128. PLSAP_CR_CIPHER_VALUE CipherCurrentValue = NULL;
  2129. PLSAP_CR_CLEAR_VALUE ClearCurrentValue = NULL;
  2130. PLSAP_CR_CIPHER_KEY SessionKey = NULL;
  2131. RpcTryExcept {
  2132. Status = LsarRetrievePrivateData(
  2133. (PLSAPR_HANDLE) PolicyHandle,
  2134. (PLSAPR_UNICODE_STRING) KeyName,
  2135. (PLSAPR_CR_CIPHER_VALUE *) &CipherCurrentValue
  2136. );
  2137. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  2138. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  2139. } RpcEndExcept;
  2140. if (!NT_SUCCESS(Status)) {
  2141. goto QuerySecretError;
  2142. }
  2143. //
  2144. // Obtain the Session Key to be used to two-way encrypt the
  2145. // Current Value and/or Old Values.
  2146. //
  2147. RpcTryExcept {
  2148. Status = LsapCrClientGetSessionKey( PolicyHandle, &SessionKey );
  2149. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  2150. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  2151. } RpcEndExcept;
  2152. if (!NT_SUCCESS(Status)) {
  2153. goto QuerySecretError;
  2154. }
  2155. //
  2156. // If the Current Value is requested and a Current Value exists,
  2157. // decrypt it using the Session key. Otherwise store NULL for return.
  2158. //
  2159. if (CipherCurrentValue != NULL) {
  2160. Status = LsapCrDecryptValue(
  2161. CipherCurrentValue,
  2162. SessionKey,
  2163. &ClearCurrentValue
  2164. );
  2165. if (!NT_SUCCESS(Status)) {
  2166. goto QuerySecretError;
  2167. }
  2168. //
  2169. // Convert Clear Current Value to Unicode
  2170. //
  2171. LsapCrClearValueToUnicode(
  2172. ClearCurrentValue,
  2173. (PUNICODE_STRING) ClearCurrentValue
  2174. );
  2175. *PrivateData = (PUNICODE_STRING) ClearCurrentValue;
  2176. } else {
  2177. *PrivateData = NULL;
  2178. }
  2179. QuerySecretFinish:
  2180. //
  2181. // If necessary, free memory allocated for the Session Key.
  2182. //
  2183. if (SessionKey != NULL) {
  2184. MIDL_user_free(SessionKey);
  2185. }
  2186. //
  2187. // If necessary, free memory allocated for the returned Encrypted
  2188. // Current Value.
  2189. //
  2190. if (CipherCurrentValue != NULL) {
  2191. LsapCrFreeMemoryValue(CipherCurrentValue);
  2192. }
  2193. //
  2194. // If the error was that the server stub didn't exist, call
  2195. // the old version of the API.
  2196. //
  2197. if ((Status == RPC_NT_UNKNOWN_IF) ||
  2198. (Status == RPC_NT_PROCNUM_OUT_OF_RANGE)) {
  2199. Status = LsapRetrievePrivateData(
  2200. PolicyHandle,
  2201. KeyName,
  2202. PrivateData
  2203. );
  2204. }
  2205. return(Status);
  2206. QuerySecretError:
  2207. //
  2208. // If necessary, free memory allocated for the Clear Current Value
  2209. //
  2210. if (ClearCurrentValue != NULL) {
  2211. LsapCrFreeMemoryValue(ClearCurrentValue);
  2212. }
  2213. *PrivateData = NULL;
  2214. goto QuerySecretFinish;
  2215. }
  2216. NTSTATUS
  2217. LsapApiConvertRightsToPrivileges(
  2218. IN LSA_HANDLE PolicyHandle,
  2219. IN PUNICODE_STRING UserRights,
  2220. IN ULONG RightCount,
  2221. OUT PPRIVILEGE_SET * Privileges,
  2222. OUT PULONG SystemAccess
  2223. )
  2224. /*++
  2225. Routine Description:
  2226. Converts an array of user rights (unicode strings) into a privilege set
  2227. and a system access flag.
  2228. Arguments:
  2229. PolicyHandle - Handle from an LsaOpenPolicyCall, requires POLICY_LOOKUP_NAME
  2230. access.
  2231. UserRights - Array of user rights
  2232. RightCount - Count of user rights
  2233. Privileges - Receives privilege set, should be freed with MIDL_user_free
  2234. SystemAccess - Receives system access flags.
  2235. Return Value:
  2236. --*/
  2237. {
  2238. ULONG RightIndex;
  2239. ULONG PrivilegeIndex;
  2240. ULONG AccessIndex;
  2241. PPRIVILEGE_SET PrivilegeSet = NULL;
  2242. ULONG Access = 0;
  2243. ULONG PrivilegeSetSize = 0;
  2244. NTSTATUS Status;
  2245. LUID PrivilegeValue;
  2246. //
  2247. // if we weren't passed any privileges, don't allocate anything.
  2248. //
  2249. if (RightCount == 0) {
  2250. *Privileges = NULL;
  2251. *SystemAccess = 0;
  2252. return(STATUS_SUCCESS);
  2253. }
  2254. //
  2255. // Compute the size of the privilege set. We actually over estimate
  2256. // by assuming that all the rights are privileges. We subtract one
  2257. // from RightCount to take into account the fact that a PRIVILEGE_SET
  2258. // has one LUID_AND_ATTRIBUTE in it.
  2259. //
  2260. PrivilegeSetSize = sizeof(PRIVILEGE_SET) +
  2261. (RightCount-1) * sizeof(LUID_AND_ATTRIBUTES);
  2262. PrivilegeSet = (PPRIVILEGE_SET) MIDL_user_allocate(PrivilegeSetSize);
  2263. if (PrivilegeSet == NULL) {
  2264. Status = STATUS_INSUFFICIENT_RESOURCES;
  2265. goto Cleanup;
  2266. }
  2267. //
  2268. // Try looking up every right. If we find it as a privilege,
  2269. // add it to the privilege set.
  2270. //
  2271. PrivilegeIndex = 0;
  2272. for (RightIndex = 0; RightIndex < RightCount ; RightIndex++) {
  2273. Status = LsaLookupPrivilegeValue(
  2274. PolicyHandle,
  2275. &UserRights[RightIndex],
  2276. &PrivilegeValue
  2277. );
  2278. if (NT_SUCCESS(Status)) {
  2279. PrivilegeSet->Privilege[PrivilegeIndex].Luid = PrivilegeValue;
  2280. PrivilegeSet->Privilege[PrivilegeIndex].Attributes = 0;
  2281. PrivilegeIndex++;
  2282. } else if (Status != STATUS_NO_SUCH_PRIVILEGE) {
  2283. //
  2284. // This is a more serious error - bail here.
  2285. //
  2286. goto Cleanup;
  2287. } else {
  2288. //
  2289. // Try looking up the right as a system access type.
  2290. //
  2291. for (AccessIndex = 0; AccessIndex < LSAP_DB_SYSTEM_ACCESS_TYPES ; AccessIndex++) {
  2292. if (RtlCompareUnicodeString(
  2293. &UserRights[RightIndex],
  2294. &LsapDbRightAndAccess[AccessIndex].UserRight,
  2295. FALSE // case sensitive
  2296. ) == 0) {
  2297. Access |= LsapDbRightAndAccess[AccessIndex].SystemAccess;
  2298. break;
  2299. }
  2300. }
  2301. //
  2302. // If we went through the access types without finding the right,
  2303. // it must not be valid so escape here.
  2304. //
  2305. if (AccessIndex == LSAP_DB_SYSTEM_ACCESS_TYPES) {
  2306. Status = STATUS_NO_SUCH_PRIVILEGE;
  2307. goto Cleanup;
  2308. }
  2309. }
  2310. }
  2311. PrivilegeSet->Control = 0;
  2312. PrivilegeSet->PrivilegeCount = PrivilegeIndex;
  2313. *Privileges = PrivilegeSet;
  2314. *SystemAccess = Access;
  2315. Status = STATUS_SUCCESS;
  2316. Cleanup:
  2317. if (!NT_SUCCESS(Status)) {
  2318. if (PrivilegeSet != NULL) {
  2319. LsaFreeMemory(PrivilegeSet);
  2320. }
  2321. }
  2322. return(Status);
  2323. }
  2324. NTSTATUS
  2325. LsapApiConvertPrivilegesToRights(
  2326. IN LSA_HANDLE PolicyHandle,
  2327. IN OPTIONAL PPRIVILEGE_SET Privileges,
  2328. IN OPTIONAL ULONG SystemAccess,
  2329. OUT PUNICODE_STRING * UserRights,
  2330. OUT PULONG RightCount
  2331. )
  2332. /*++
  2333. Routine Description:
  2334. Converts a privilege set and a system access flag into an array of
  2335. user rights (unicode strings).
  2336. Arguments:
  2337. PolicyHandle - Handle from an LsaOpenPolicy call, must have
  2338. POLICY_LOOKUP_NAMES access.
  2339. Privileges - Privilege set to convert
  2340. SystemAccess - System access flags to convert
  2341. UserRights - Receives an array of user rights (unicode strings). Should
  2342. be freed with MIDL_user_free
  2343. RightCount - Receives count of rights in UserRights array
  2344. Return Value:
  2345. --*/
  2346. {
  2347. NTSTATUS Status;
  2348. PUNICODE_STRING OutputRights = NULL;
  2349. PUNICODE_STRING * PrivilegeNames = NULL;
  2350. UNICODE_STRING AccessNames[LSAP_DB_SYSTEM_ACCESS_TYPES];
  2351. ULONG RightSize;
  2352. ULONG PrivilegeSize;
  2353. ULONG Count;
  2354. ULONG PrivilegeIndex;
  2355. ULONG AccessIndex;
  2356. ULONG RightIndex;
  2357. ULONG AccessCount = 0;
  2358. PUCHAR Where;
  2359. //
  2360. // Compute the size of the temporary array. This is just an array of
  2361. // pointers to unicode strings to hold the privilege names until
  2362. // we reallocate them into one big buffer.
  2363. //
  2364. RightSize = 0;
  2365. Count = 0;
  2366. if (ARGUMENT_PRESENT(Privileges)) {
  2367. PrivilegeSize = Privileges->PrivilegeCount * sizeof(PUNICODE_STRING);
  2368. PrivilegeNames = (PUNICODE_STRING *) MIDL_user_allocate(PrivilegeSize);
  2369. if (PrivilegeNames == NULL) {
  2370. Status = STATUS_INSUFFICIENT_RESOURCES;
  2371. goto Cleanup;
  2372. }
  2373. RtlZeroMemory(
  2374. PrivilegeNames,
  2375. PrivilegeSize
  2376. );
  2377. //
  2378. // Lookup the privilge name and store it in the temporary array
  2379. //
  2380. for (PrivilegeIndex = 0; PrivilegeIndex < Privileges->PrivilegeCount ;PrivilegeIndex++ ) {
  2381. Status = LsaLookupPrivilegeName(
  2382. PolicyHandle,
  2383. &Privileges->Privilege[PrivilegeIndex].Luid,
  2384. &PrivilegeNames[PrivilegeIndex]
  2385. );
  2386. if (!NT_SUCCESS(Status)) {
  2387. goto Cleanup;
  2388. }
  2389. RightSize += sizeof(UNICODE_STRING) + PrivilegeNames[PrivilegeIndex]->MaximumLength;
  2390. }
  2391. }
  2392. //
  2393. // Now convert the system access flags to user rights.
  2394. //
  2395. if (ARGUMENT_PRESENT( (ULONG_PTR)SystemAccess )) {
  2396. AccessCount = 0;
  2397. for (AccessIndex = 0; AccessIndex < LSAP_DB_SYSTEM_ACCESS_TYPES ; AccessIndex++) {
  2398. if ((SystemAccess & LsapDbRightAndAccess[AccessIndex].SystemAccess) != 0) {
  2399. AccessNames[AccessCount] = LsapDbRightAndAccess[AccessIndex].UserRight;
  2400. RightSize += sizeof(UNICODE_STRING) + AccessNames[AccessCount].MaximumLength;
  2401. AccessCount++;
  2402. }
  2403. }
  2404. }
  2405. //
  2406. // Allocate the output buffer and start copying the strings into the
  2407. // buffer.
  2408. //
  2409. Count = Privileges->PrivilegeCount + AccessCount;
  2410. OutputRights = (PUNICODE_STRING) MIDL_user_allocate(RightSize);
  2411. if (OutputRights == NULL) {
  2412. Status = STATUS_INSUFFICIENT_RESOURCES;
  2413. goto Cleanup;
  2414. }
  2415. Where = (PUCHAR) OutputRights + (Count * sizeof(UNICODE_STRING));
  2416. //
  2417. // Copy in the privileges first
  2418. //
  2419. RightIndex = 0;
  2420. for (PrivilegeIndex = 0; PrivilegeIndex < Privileges->PrivilegeCount ; PrivilegeIndex ++) {
  2421. OutputRights[RightIndex] = *PrivilegeNames[PrivilegeIndex];
  2422. OutputRights[RightIndex].Buffer = (LPWSTR) Where;
  2423. RtlCopyMemory(
  2424. Where,
  2425. PrivilegeNames[PrivilegeIndex]->Buffer,
  2426. OutputRights[RightIndex].MaximumLength
  2427. );
  2428. Where += OutputRights[RightIndex].MaximumLength;
  2429. RightIndex++;
  2430. }
  2431. //
  2432. // Now copy in the access types
  2433. //
  2434. for (AccessIndex = 0; AccessIndex < AccessCount; AccessIndex++) {
  2435. OutputRights[RightIndex] = AccessNames[AccessIndex];
  2436. OutputRights[RightIndex].Buffer = (LPWSTR) Where;
  2437. RtlCopyMemory(
  2438. Where,
  2439. AccessNames[AccessIndex].Buffer,
  2440. OutputRights[RightIndex].MaximumLength
  2441. );
  2442. Where += OutputRights[RightIndex].MaximumLength;
  2443. RightIndex++;
  2444. }
  2445. ASSERT(RightIndex == Count);
  2446. *UserRights = OutputRights;
  2447. OutputRights = NULL;
  2448. *RightCount = Count;
  2449. Status = STATUS_SUCCESS;
  2450. Cleanup:
  2451. if (PrivilegeNames != NULL) {
  2452. for (PrivilegeIndex = 0; PrivilegeIndex < Privileges->PrivilegeCount ; PrivilegeIndex++) {
  2453. if (PrivilegeNames[PrivilegeIndex] != NULL) {
  2454. LsaFreeMemory(PrivilegeNames[PrivilegeIndex]);
  2455. }
  2456. }
  2457. MIDL_user_free(PrivilegeNames);
  2458. }
  2459. if (OutputRights != NULL) {
  2460. MIDL_user_free(OutputRights);
  2461. }
  2462. return(Status);
  2463. }
  2464. NTSTATUS
  2465. NTAPI
  2466. LsaQueryTrustedDomainInfoByName(
  2467. IN LSA_HANDLE PolicyHandle,
  2468. IN PUNICODE_STRING TrustedDomainName,
  2469. IN TRUSTED_INFORMATION_CLASS InformationClass,
  2470. OUT PVOID *Buffer
  2471. )
  2472. {
  2473. NTSTATUS Status;
  2474. //
  2475. // Avoid the internal info levels that represent the encrypted version on
  2476. // the wire.
  2477. //
  2478. switch ( InformationClass ) {
  2479. case TrustedDomainAuthInformationInternal:
  2480. case TrustedDomainFullInformationInternal:
  2481. return STATUS_INVALID_INFO_CLASS;
  2482. }
  2483. RpcTryExcept {
  2484. //
  2485. // Call the Client Stub for LsaClearAuditLog.
  2486. //
  2487. Status = LsarQueryTrustedDomainInfoByName(
  2488. (LSAPR_HANDLE) PolicyHandle,
  2489. (PLSAPR_UNICODE_STRING) TrustedDomainName,
  2490. InformationClass,
  2491. (PLSAPR_TRUSTED_DOMAIN_INFO *) Buffer
  2492. );
  2493. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  2494. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  2495. } RpcEndExcept;
  2496. return(Status);
  2497. }
  2498. NTSTATUS
  2499. LsapRandomFill(
  2500. IN ULONG BufferSize,
  2501. IN OUT PUCHAR Buffer
  2502. )
  2503. /*++
  2504. Routine Description:
  2505. This routine fills a buffer with random data.
  2506. Parameters:
  2507. BufferSize - Length of the input buffer, in bytes.
  2508. Buffer - Input buffer to be filled with random data.
  2509. Return Values:
  2510. Errors from NtQuerySystemTime()
  2511. --*/
  2512. {
  2513. ULONG Index;
  2514. LARGE_INTEGER Time;
  2515. ULONG Seed;
  2516. NTSTATUS NtStatus;
  2517. NtStatus = NtQuerySystemTime(&Time);
  2518. if (!NT_SUCCESS(NtStatus)) {
  2519. return(NtStatus);
  2520. }
  2521. Seed = Time.LowPart ^ Time.HighPart;
  2522. for (Index = 0 ; Index < BufferSize ; Index++ )
  2523. {
  2524. *Buffer++ = (UCHAR) (RtlRandom(&Seed) % 256);
  2525. }
  2526. return(STATUS_SUCCESS);
  2527. }
  2528. NTSTATUS
  2529. LsapEncryptAuthInfo(
  2530. IN LSA_HANDLE PolicyHandle,
  2531. IN PLSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION ClearAuthInfo,
  2532. IN PLSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION_INTERNAL *EncryptedAuthInfo
  2533. )
  2534. /*++
  2535. Routine Description:
  2536. This routine takes a cleartext auth info and returns an encrypted auth info.
  2537. Parameters:
  2538. PolicyHandle - Handle to the LSA policy.
  2539. ClearAuthInfo - Cleartext of the authentication info.
  2540. EncryptedAuthInfo - Returns an allocated buffer containing the encrypted form
  2541. of the auth info. The caller should free this buffer using LocalFree.
  2542. Return Values:
  2543. STATUS_SUCCESS - the routine has completed successfully.
  2544. --*/
  2545. {
  2546. NTSTATUS Status;
  2547. USER_SESSION_KEY UserSessionKey;
  2548. ULONG IncomingAuthInfoSize = 0;
  2549. PUCHAR IncomingAuthInfo = NULL;
  2550. ULONG OutgoingAuthInfoSize = 0;
  2551. PUCHAR OutgoingAuthInfo = NULL;
  2552. ULONG EncryptedSize;
  2553. PUCHAR EncryptedBuffer;
  2554. PUCHAR AllocatedBuffer = NULL;
  2555. PUCHAR Where;
  2556. struct RC4_KEYSTRUCT Rc4Key;
  2557. //
  2558. // Get the encryption key
  2559. //
  2560. Status = RtlGetUserSessionKeyClient(
  2561. (RPC_BINDING_HANDLE)PolicyHandle,
  2562. &UserSessionKey );
  2563. if ( !NT_SUCCESS(Status)) {
  2564. goto Cleanup;
  2565. }
  2566. //
  2567. // Marshal the incoming and outgoing auth info halfs into contiguous buffers
  2568. //
  2569. Status = LsapDsMarshalAuthInfoHalf(
  2570. LsapDsAuthHalfFromAuthInfo( ClearAuthInfo, TRUE ),
  2571. &IncomingAuthInfoSize,
  2572. &IncomingAuthInfo );
  2573. if ( !NT_SUCCESS(Status)) {
  2574. goto Cleanup;
  2575. }
  2576. Status = LsapDsMarshalAuthInfoHalf(
  2577. LsapDsAuthHalfFromAuthInfo( ClearAuthInfo, FALSE ),
  2578. &OutgoingAuthInfoSize,
  2579. &OutgoingAuthInfo );
  2580. if ( !NT_SUCCESS(Status)) {
  2581. goto Cleanup;
  2582. }
  2583. //
  2584. // Build a buffer of:
  2585. // 512 random bytes
  2586. // The Outgoing auth info buffer.
  2587. // The Incoming auth info buffer.
  2588. // The length of the outgoing auth info buffer.
  2589. // The length of the incoming auth info buffer.
  2590. //
  2591. // (Notice that a hacker might surmise the length of the auth data by
  2592. // observing the length of the encrypted blob. However, the auth data is typically
  2593. // fixed length anyway. So the above seems adequate.)
  2594. //
  2595. EncryptedSize = LSAP_ENCRYPTED_AUTH_DATA_FILL +
  2596. OutgoingAuthInfoSize +
  2597. IncomingAuthInfoSize +
  2598. sizeof(ULONG) +
  2599. sizeof(ULONG);
  2600. AllocatedBuffer = LocalAlloc( 0, sizeof(LSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION_INTERNAL) + EncryptedSize );
  2601. if ( AllocatedBuffer == NULL ) {
  2602. Status = STATUS_INSUFFICIENT_RESOURCES;
  2603. goto Cleanup;
  2604. }
  2605. EncryptedBuffer = AllocatedBuffer + sizeof(LSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION_INTERNAL);
  2606. Where = EncryptedBuffer;
  2607. Status = LsapRandomFill( LSAP_ENCRYPTED_AUTH_DATA_FILL,
  2608. Where );
  2609. if ( !NT_SUCCESS(Status)) {
  2610. goto Cleanup;
  2611. }
  2612. Where += LSAP_ENCRYPTED_AUTH_DATA_FILL;
  2613. RtlCopyMemory( Where, OutgoingAuthInfo, OutgoingAuthInfoSize );
  2614. Where += OutgoingAuthInfoSize;
  2615. RtlCopyMemory( Where, IncomingAuthInfo, IncomingAuthInfoSize );
  2616. Where += IncomingAuthInfoSize;
  2617. RtlCopyMemory( Where, &OutgoingAuthInfoSize, sizeof(ULONG) );
  2618. Where += sizeof(ULONG);
  2619. RtlCopyMemory( Where, &IncomingAuthInfoSize, sizeof(ULONG) );
  2620. Where += sizeof(ULONG);
  2621. //
  2622. // Encrypt the result.
  2623. //
  2624. rc4_key( &Rc4Key,
  2625. sizeof(USER_SESSION_KEY),
  2626. (PUCHAR) &UserSessionKey );
  2627. rc4( &Rc4Key,
  2628. EncryptedSize,
  2629. EncryptedBuffer );
  2630. //
  2631. // Return the result to the caller.
  2632. //
  2633. *EncryptedAuthInfo =
  2634. (PLSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION_INTERNAL) AllocatedBuffer;
  2635. (*EncryptedAuthInfo)->AuthBlob.AuthBlob = EncryptedBuffer;
  2636. (*EncryptedAuthInfo)->AuthBlob.AuthSize = EncryptedSize;
  2637. Status = STATUS_SUCCESS;
  2638. Cleanup:
  2639. if ( !NT_SUCCESS(Status) ) {
  2640. if ( AllocatedBuffer != NULL ) {
  2641. LocalFree( AllocatedBuffer );
  2642. }
  2643. *EncryptedAuthInfo = NULL;
  2644. }
  2645. if ( IncomingAuthInfo != NULL ) {
  2646. MIDL_user_free( IncomingAuthInfo );
  2647. }
  2648. if ( OutgoingAuthInfo != NULL ) {
  2649. MIDL_user_free( OutgoingAuthInfo );
  2650. }
  2651. return Status;
  2652. }
  2653. NTSTATUS
  2654. NTAPI
  2655. LsaSetTrustedDomainInfoByName(
  2656. IN LSA_HANDLE PolicyHandle,
  2657. IN PUNICODE_STRING TrustedDomainName,
  2658. IN TRUSTED_INFORMATION_CLASS InformationClass,
  2659. IN PVOID Buffer
  2660. )
  2661. {
  2662. NTSTATUS Status;
  2663. PLSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION_INTERNAL InternalAuthBuffer = NULL;
  2664. PVOID InternalBuffer;
  2665. TRUSTED_INFORMATION_CLASS InternalInformationClass;
  2666. LSAPR_TRUSTED_DOMAIN_FULL_INFORMATION_INTERNAL InternalFullBuffer;
  2667. //
  2668. // Initialization
  2669. //
  2670. InternalInformationClass = InformationClass;
  2671. InternalBuffer = Buffer;
  2672. //
  2673. // Avoid the internal info levels that represent the encrypted version on
  2674. // the wire.
  2675. //
  2676. switch ( InformationClass ) {
  2677. case TrustedPasswordInformation:
  2678. case TrustedDomainAuthInformationInternal:
  2679. case TrustedDomainFullInformationInternal:
  2680. //
  2681. // TrustedDomainNameInformation is not allowed, either (RAID #416784)
  2682. //
  2683. case TrustedDomainNameInformation:
  2684. Status = STATUS_INVALID_INFO_CLASS;
  2685. goto Cleanup;
  2686. //
  2687. // Handle the info classes that need to be encrypted on the wire
  2688. //
  2689. case TrustedDomainAuthInformation: {
  2690. //
  2691. // Encrypt the data into an internal buffer.
  2692. //
  2693. Status = LsapEncryptAuthInfo( PolicyHandle,
  2694. (PLSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION) Buffer,
  2695. &InternalAuthBuffer );
  2696. if ( !NT_SUCCESS(Status)) {
  2697. goto Cleanup;
  2698. }
  2699. //
  2700. // Use an internal info level to tell the server that the data is
  2701. // encrypted.
  2702. //
  2703. InternalInformationClass = TrustedDomainAuthInformationInternal;
  2704. InternalBuffer = InternalAuthBuffer;
  2705. break;
  2706. }
  2707. //
  2708. // Handle the info classes that need to be encrypted on the wire
  2709. //
  2710. case TrustedDomainFullInformation: {
  2711. PLSAPR_TRUSTED_DOMAIN_FULL_INFORMATION FullBuffer =
  2712. (PLSAPR_TRUSTED_DOMAIN_FULL_INFORMATION) Buffer;
  2713. //
  2714. // Encrypt the data into an internal buffer.
  2715. //
  2716. Status = LsapEncryptAuthInfo( PolicyHandle,
  2717. &FullBuffer->AuthInformation,
  2718. &InternalAuthBuffer );
  2719. if ( !NT_SUCCESS(Status)) {
  2720. goto Cleanup;
  2721. }
  2722. //
  2723. // Copy all of the information into a single new structure.
  2724. //
  2725. InternalFullBuffer.Information = FullBuffer->Information;
  2726. InternalFullBuffer.PosixOffset = FullBuffer->PosixOffset;
  2727. InternalFullBuffer.AuthInformation = *InternalAuthBuffer;
  2728. //
  2729. // Use an internal info level to tell the server that the data is
  2730. // encrypted.
  2731. //
  2732. InternalInformationClass = TrustedDomainFullInformationInternal;
  2733. InternalBuffer = &InternalFullBuffer;
  2734. break;
  2735. }
  2736. }
  2737. //
  2738. // If the information class was morphed,
  2739. // try the morphed class.
  2740. //
  2741. if ( InternalInformationClass != InformationClass ) {
  2742. RpcTryExcept {
  2743. //
  2744. // Call the Client Stub
  2745. //
  2746. Status = LsarSetTrustedDomainInfoByName(
  2747. (LSAPR_HANDLE) PolicyHandle,
  2748. (PLSAPR_UNICODE_STRING) TrustedDomainName,
  2749. InternalInformationClass,
  2750. (PLSAPR_TRUSTED_DOMAIN_INFO) InternalBuffer
  2751. );
  2752. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  2753. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  2754. } RpcEndExcept;
  2755. //
  2756. // If the morphed info class is valid,
  2757. // we're all done with this call.
  2758. // (Otherwise, drop through to try the non-morphed class.)
  2759. //
  2760. if ( Status != RPC_NT_INVALID_TAG ) {
  2761. goto Cleanup;
  2762. }
  2763. }
  2764. //
  2765. // Handle non-morphed information classes.
  2766. //
  2767. RpcTryExcept {
  2768. //
  2769. // Call the Client Stub
  2770. //
  2771. Status = LsarSetTrustedDomainInfoByName(
  2772. (LSAPR_HANDLE) PolicyHandle,
  2773. (PLSAPR_UNICODE_STRING) TrustedDomainName,
  2774. InformationClass,
  2775. (PLSAPR_TRUSTED_DOMAIN_INFO) Buffer
  2776. );
  2777. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  2778. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  2779. } RpcEndExcept;
  2780. Cleanup:
  2781. if ( InternalAuthBuffer != NULL ) {
  2782. LocalFree( InternalAuthBuffer );
  2783. }
  2784. return(Status);
  2785. }
  2786. NTSTATUS
  2787. NTAPI
  2788. LsaEnumerateTrustedDomainsEx(
  2789. IN LSA_HANDLE PolicyHandle,
  2790. IN OUT PLSA_ENUMERATION_HANDLE EnumerationContext,
  2791. OUT PVOID *Buffer,
  2792. IN ULONG PreferedMaximumLength,
  2793. OUT PULONG CountReturned
  2794. )
  2795. {
  2796. NTSTATUS Status;
  2797. LSAPR_TRUSTED_ENUM_BUFFER_EX EnumerationBuffer;
  2798. EnumerationBuffer.EntriesRead = 0;
  2799. EnumerationBuffer.EnumerationBuffer = NULL;
  2800. //
  2801. // Verify that caller has provided a return buffer pointer.
  2802. //
  2803. if (!ARGUMENT_PRESENT(Buffer)) {
  2804. return(STATUS_INVALID_PARAMETER);
  2805. }
  2806. RpcTryExcept {
  2807. //
  2808. // Enumerate the Trusted Domains. On successful return,
  2809. // the Enumeration Buffer structure will receive a count
  2810. // of the number of Trusted Domains enumerated this call
  2811. // and a pointer to an array of Trust Information Entries.
  2812. //
  2813. // EnumerationBuffer -> EntriesRead
  2814. // Information -> Trust Info for Domain 0
  2815. // Trust Info for Domain 1
  2816. // ...
  2817. // Trust Info for Domain
  2818. // (EntriesRead - 1)
  2819. //
  2820. //
  2821. Status = LsarEnumerateTrustedDomainsEx(
  2822. (LSAPR_HANDLE) PolicyHandle,
  2823. EnumerationContext,
  2824. &EnumerationBuffer,
  2825. PreferedMaximumLength
  2826. );
  2827. //
  2828. // Return enumeration information or NULL to caller.
  2829. //
  2830. // NOTE: "Information" is allocated by the called client stub
  2831. // as a single block via MIDL_user_allocate, because Information is
  2832. // allocated all-nodes. We can therefore pass back the pointer
  2833. // directly to the client, who will be able to free the memory after
  2834. // use via LsaFreeMemory() [which makes a MIDL_user_free call].
  2835. //
  2836. *CountReturned = EnumerationBuffer.EntriesRead;
  2837. *Buffer = EnumerationBuffer.EnumerationBuffer;
  2838. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  2839. //
  2840. // If memory was allocated for the Trust Information array,
  2841. // free it.
  2842. //
  2843. if (EnumerationBuffer.EnumerationBuffer != NULL) {
  2844. MIDL_user_free(EnumerationBuffer.EnumerationBuffer);
  2845. }
  2846. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  2847. } RpcEndExcept;
  2848. return(Status);
  2849. }
  2850. NTSTATUS
  2851. NTAPI
  2852. LsaCreateTrustedDomainEx(
  2853. IN LSA_HANDLE PolicyHandle,
  2854. IN PTRUSTED_DOMAIN_INFORMATION_EX TrustedDomainInformation,
  2855. IN PTRUSTED_DOMAIN_AUTH_INFORMATION AuthenticationInformation,
  2856. IN ACCESS_MASK DesiredAccess,
  2857. OUT PLSA_HANDLE TrustedDomainHandle
  2858. )
  2859. {
  2860. NTSTATUS Status;
  2861. PLSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION_INTERNAL InternalAuthBuffer = NULL;
  2862. //
  2863. // Encrypt the auth data
  2864. //
  2865. Status = LsapEncryptAuthInfo( PolicyHandle,
  2866. (PLSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION) AuthenticationInformation,
  2867. &InternalAuthBuffer );
  2868. if ( !NT_SUCCESS(Status)) {
  2869. goto Cleanup;
  2870. }
  2871. //
  2872. // Try the version of the API that takes encrypted data
  2873. //
  2874. RpcTryExcept {
  2875. //
  2876. // Call the Client Stub
  2877. //
  2878. Status = LsarCreateTrustedDomainEx2(
  2879. (LSAPR_HANDLE) PolicyHandle,
  2880. (PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX) TrustedDomainInformation,
  2881. InternalAuthBuffer,
  2882. DesiredAccess,
  2883. (PLSAPR_HANDLE) TrustedDomainHandle
  2884. );
  2885. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  2886. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  2887. } RpcEndExcept;
  2888. //
  2889. // If the server doesn't accept the new api,
  2890. // try the old one.
  2891. // (The old API was only supported in beta versions of NT 5.
  2892. // After NT 5 ships we no longer need to be able to fall back.)
  2893. //
  2894. if (Status == RPC_NT_PROCNUM_OUT_OF_RANGE) {
  2895. RpcTryExcept {
  2896. //
  2897. // Call the Client Stub
  2898. //
  2899. Status = LsarCreateTrustedDomainEx(
  2900. (LSAPR_HANDLE) PolicyHandle,
  2901. (PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX) TrustedDomainInformation,
  2902. (PLSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION) AuthenticationInformation,
  2903. DesiredAccess,
  2904. (PLSAPR_HANDLE) TrustedDomainHandle
  2905. );
  2906. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  2907. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  2908. } RpcEndExcept;
  2909. }
  2910. Cleanup:
  2911. if ( InternalAuthBuffer != NULL ) {
  2912. LocalFree( InternalAuthBuffer );
  2913. }
  2914. return(Status);
  2915. }
  2916. NTSTATUS
  2917. NTAPI
  2918. LsaQueryDomainInformationPolicy(
  2919. IN LSA_HANDLE PolicyHandle,
  2920. IN POLICY_DOMAIN_INFORMATION_CLASS InformationClass,
  2921. OUT PVOID *Buffer
  2922. )
  2923. {
  2924. NTSTATUS Status;
  2925. PLSAPR_POLICY_DOMAIN_INFORMATION PolicyDomainInformation = NULL;
  2926. RpcTryExcept {
  2927. Status = LsarQueryDomainInformationPolicy(
  2928. (LSAPR_HANDLE) PolicyHandle,
  2929. InformationClass,
  2930. &PolicyDomainInformation
  2931. );
  2932. *Buffer = PolicyDomainInformation;
  2933. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  2934. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  2935. } RpcEndExcept;
  2936. return(Status);
  2937. }
  2938. NTSTATUS
  2939. NTAPI
  2940. LsaSetDomainInformationPolicy(
  2941. IN LSA_HANDLE PolicyHandle,
  2942. IN POLICY_DOMAIN_INFORMATION_CLASS InformationClass,
  2943. IN PVOID Buffer
  2944. )
  2945. {
  2946. NTSTATUS Status;
  2947. if ( InformationClass == PolicyDomainKerberosTicketInformation &&
  2948. Buffer == NULL ) {
  2949. return STATUS_INVALID_PARAMETER;
  2950. }
  2951. RpcTryExcept {
  2952. Status = LsarSetDomainInformationPolicy(
  2953. (LSAPR_HANDLE) PolicyHandle,
  2954. InformationClass,
  2955. Buffer
  2956. );
  2957. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  2958. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  2959. } RpcEndExcept;
  2960. return(Status);
  2961. }
  2962. NTSTATUS
  2963. LsaOpenTrustedDomainByName(
  2964. IN LSA_HANDLE PolicyHandle,
  2965. IN PUNICODE_STRING TrustedDomainName,
  2966. IN ACCESS_MASK DesiredAccess,
  2967. OUT PLSA_HANDLE TrustedDomainHandle
  2968. )
  2969. /*++
  2970. Routine Description:
  2971. The LsaOpenTrustedDomain API opens an existing TrustedDomain object
  2972. using the Name as the primary key value.
  2973. Arguments:
  2974. PolicyHandle - An open handle to a Policy object.
  2975. TrustedDomainName - Name of the trusted domain
  2976. DesiredAccess - This is an access mask indicating accesses being
  2977. requested to the target object.
  2978. TrustedDomainHandle - Receives a handle to be used in future requests.
  2979. Return Values:
  2980. NTSTATUS - Standard Nt Result Code
  2981. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  2982. to complete the operation.
  2983. STATUS_TRUSTED_DOMAIN_NOT_FOUND - There is no TrustedDomain object in the
  2984. target system's LSA Database having the specified AccountSid.
  2985. --*/
  2986. {
  2987. NTSTATUS Status;
  2988. RpcTryExcept {
  2989. Status = LsarOpenTrustedDomainByName(
  2990. ( LSAPR_HANDLE ) PolicyHandle,
  2991. ( PLSAPR_UNICODE_STRING )TrustedDomainName,
  2992. DesiredAccess,
  2993. ( PLSAPR_HANDLE )TrustedDomainHandle
  2994. );
  2995. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  2996. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  2997. } RpcEndExcept;
  2998. return Status;
  2999. }
  3000. NTSTATUS
  3001. LsaQueryForestTrustInformation(
  3002. IN LSA_HANDLE PolicyHandle,
  3003. IN PLSA_UNICODE_STRING TrustedDomainName,
  3004. OUT PLSA_FOREST_TRUST_INFORMATION * ForestTrustInfo
  3005. )
  3006. /*++
  3007. Routine Description
  3008. The LsaQueryForestTrustInformation API returns forest trust information
  3009. for the given trusted domain object.
  3010. Arguments:
  3011. PolicyHandle - An open handle to a Policy object
  3012. TrustedDomainName - Name of the trusted domain object
  3013. ForestTrustInfo - Used to return forest trust information
  3014. Returns:
  3015. NTSTATUS - Standard Nt Result Code
  3016. STATUS_SUCCESS
  3017. STATUS_INVALID_PARAMETER Parameters were somehow invalid
  3018. Most likely, the TRUST_ATTRIBUTE_FOREST_TRANSITIVE
  3019. trust attribute bit is not set on the TDO
  3020. STATUS_NOT_FOUND Forest trust information does not exist for this TDO
  3021. STATUS_NO_SUCH_DOMAIN The specified TDO does not exist
  3022. STATUS_INSUFFICIENT_RESOURCES Ran out of memory
  3023. STATUS_INVALID_DOMAIN_STATE Operation is only legal on domain controllers in root domain
  3024. --*/
  3025. {
  3026. NTSTATUS Status;
  3027. RpcTryExcept {
  3028. Status = LsarQueryForestTrustInformation(
  3029. PolicyHandle,
  3030. TrustedDomainName,
  3031. ForestTrustRecordTypeLast,
  3032. ForestTrustInfo
  3033. );
  3034. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  3035. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  3036. } RpcEndExcept;
  3037. return Status;
  3038. }
  3039. NTSTATUS
  3040. LsaSetForestTrustInformation(
  3041. IN LSA_HANDLE PolicyHandle,
  3042. IN PLSA_UNICODE_STRING TrustedDomainName,
  3043. IN PLSA_FOREST_TRUST_INFORMATION ForestTrustInfo,
  3044. IN BOOLEAN CheckOnly,
  3045. OUT PLSA_FOREST_TRUST_COLLISION_INFORMATION * CollisionInfo
  3046. )
  3047. /*++
  3048. Routine Description
  3049. The LsarSetForestTrustInformation API sets forest trust information
  3050. on the given trusted domain object.
  3051. In case if it fails the operation due to a collision, it will return
  3052. the list of entries that conflicted.
  3053. Arguments:
  3054. PolicyHandle - An open handle to a Policy object
  3055. TrustedDomainName - Name of the trusted domain object
  3056. ForestTrustInfo - Contains forest trust information to set
  3057. CheckOnly - Check for collisions only, do not commit changes to disk
  3058. CollisionInfo - In case of collisoin error, used to return collision info
  3059. Returns:
  3060. STATUS_SUCCESS operation completed successfully
  3061. STATUS_INVALID_PARAMETER did not like one of the parameters
  3062. STATUS_INSUFFICIENT_RESOURCES out of memory
  3063. STATUS_INVALID_DOMAIN_STATE Operation is only legal on domain
  3064. controllers in the root domain
  3065. STATUS_INVALID_DOMAIN_ROLE Operation is only legal on the primary
  3066. domain controller
  3067. STATUS_INVALID_SERVER_STATE The server is shutting down and can not
  3068. process the request
  3069. --*/
  3070. {
  3071. NTSTATUS Status;
  3072. RpcTryExcept {
  3073. Status = LsarSetForestTrustInformation(
  3074. PolicyHandle,
  3075. TrustedDomainName,
  3076. ForestTrustRecordTypeLast,
  3077. ForestTrustInfo,
  3078. CheckOnly,
  3079. CollisionInfo
  3080. );
  3081. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  3082. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  3083. } RpcEndExcept;
  3084. return Status;
  3085. }
  3086. #ifdef TESTING_MATCHING_ROUTINE
  3087. #include <sddl.h> // ConvertStringSidToSidW
  3088. NTSTATUS
  3089. NTAPI
  3090. LsaForestTrustFindMatch(
  3091. IN LSA_HANDLE PolicyHandle,
  3092. IN ULONG Type,
  3093. IN PLSA_UNICODE_STRING Name,
  3094. OUT PLSA_UNICODE_STRING * Match
  3095. )
  3096. /*++
  3097. Routine Description:
  3098. A debug-only hook for testing the LsaIForestTrustFindMatch API
  3099. Arguments:
  3100. Type type of match
  3101. Name name to match
  3102. Match used to return the name of match
  3103. Returns:
  3104. STATUS_SUCCESS
  3105. --*/
  3106. {
  3107. NTSTATUS Status;
  3108. RpcTryExcept {
  3109. Status = LsarForestTrustFindMatch(
  3110. PolicyHandle,
  3111. Type,
  3112. Name,
  3113. Match
  3114. );
  3115. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  3116. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  3117. } RpcEndExcept;
  3118. return(Status);
  3119. }
  3120. #endif