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

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