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.

4232 lines
114 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. dbaccnt.c
  5. Abstract:
  6. LSA - Database - Account Object Private API Workers
  7. NOTE: This module should remain as portable code that is independent
  8. of the implementation of the LSA Database. As such, it is
  9. permitted to use only the exported LSA Database interfaces
  10. contained in db.h and NOT the private implementation
  11. dependent functions in dbp.h.
  12. Author:
  13. Scott Birrell (ScottBi) April 29, 1991
  14. Environment:
  15. Revision History:
  16. --*/
  17. #include <lsapch2.h>
  18. #include "dbp.h"
  19. /////////////////////////////////////////////////////////////////////////////
  20. // //
  21. // Private Datatypes //
  22. // //
  23. /////////////////////////////////////////////////////////////////////////////
  24. //
  25. // The following structures define output for the LsarQueryInformationAccount()
  26. // API. Curerently, this API is internal. If made external, these structures
  27. // should be moved to lsarpc.idl and annotated with MIDL qualifiers [..].
  28. //
  29. //
  30. // This data type defines the following information classes that may be
  31. // queried or set.
  32. //
  33. typedef enum _ACCOUNT_INFORMATION_CLASS {
  34. AccountSystemAccessInformation = 1,
  35. AccountPrivilegeInformation,
  36. AccountQuotaInformation
  37. } ACCOUNT_INFORMATION_CLASS, *PACCOUNT_INFORMATION_CLASS;
  38. typedef PRIVILEGE_SET LSAPR_ACCOUNT_PRIVILEGE_INFO;
  39. typedef QUOTA_LIMITS LSAPR_ACCOUNT_QUOTA_INFO;
  40. typedef ULONG LSAPR_ACCOUNT_SYSTEM_ACCESS_INFO;
  41. typedef union _LSAPR_ACCOUNT_INFO {
  42. LSAPR_ACCOUNT_PRIVILEGE_INFO AccountPrivilegeInfo;
  43. LSAPR_ACCOUNT_QUOTA_INFO AccountQuotaInfo;
  44. LSAPR_ACCOUNT_SYSTEM_ACCESS_INFO AccountSystemAccessInfo;
  45. } LSAPR_ACCOUNT_INFO, *PLSAPR_ACCOUNT_INFO;
  46. #define LsapDbFirstAccount() \
  47. ((PLSAP_DB_ACCOUNT) LsapDbAccountList.Links.Flink)
  48. #define LsapDbNextAccount( Account ) \
  49. ((PLSAP_DB_ACCOUNT) Account->Links.Flink)
  50. #define LSAP_DB_BUILD_ACCOUNT_LIST_LENGTH ((ULONG) 0x00001000L)
  51. /////////////////////////////////////////////////////////////////////////////
  52. // //
  53. // Private Function Prototypes //
  54. // //
  55. /////////////////////////////////////////////////////////////////////////////
  56. NTSTATUS
  57. LsarQueryInformationAccount(
  58. IN LSAPR_HANDLE AccountHandle,
  59. IN ACCOUNT_INFORMATION_CLASS InformationClass,
  60. OUT PLSAPR_ACCOUNT_INFO *AccountInformation
  61. );
  62. NTSTATUS
  63. LsapDbQueryInformationAccount(
  64. IN LSAPR_HANDLE AccountHandle,
  65. IN ACCOUNT_INFORMATION_CLASS InformationClass,
  66. OUT PLSAPR_ACCOUNT_INFO *AccountInformation
  67. );
  68. NTSTATUS
  69. LsapDbQueryAllInformationAccounts(
  70. IN LSAPR_HANDLE PolicyHandle,
  71. IN ULONG IdCount,
  72. IN PSID_AND_ATTRIBUTES Ids,
  73. OUT PLSAP_DB_ACCOUNT_TYPE_SPECIFIC_INFO AccountInfo
  74. );
  75. NTSTATUS
  76. LsapDbSlowQueryAllInformationAccounts(
  77. IN LSAPR_HANDLE PolicyHandle,
  78. IN ULONG IdCount,
  79. IN PSID_AND_ATTRIBUTES Ids,
  80. OUT PLSAP_DB_ACCOUNT_TYPE_SPECIFIC_INFO AccountInfo
  81. );
  82. NTSTATUS
  83. LsapDbSlowQueryInformationAccount(
  84. IN LSAPR_HANDLE AccountHandle,
  85. IN ACCOUNT_INFORMATION_CLASS InformationClass,
  86. OUT PLSAPR_ACCOUNT_INFO *AccountInformation
  87. );
  88. NTSTATUS
  89. LsapDbSlowQueryPrivilegesAccount(
  90. IN LSAPR_HANDLE AccountHandle,
  91. OUT PLSAPR_PRIVILEGE_SET *Privileges
  92. );
  93. NTSTATUS
  94. LsapDbSlowQueryQuotasAccount(
  95. IN LSAPR_HANDLE AccountHandle,
  96. OUT PQUOTA_LIMITS QuotaLimits
  97. );
  98. NTSTATUS
  99. LsapDbSlowQuerySystemAccessAccount(
  100. IN LSAPR_HANDLE AccountHandle,
  101. OUT PULONG SystemAccess
  102. );
  103. NTSTATUS
  104. LsapDbLookupAccount(
  105. IN PSID AccountSid,
  106. OUT PLSAP_DB_ACCOUNT *Account
  107. );
  108. NTSTATUS
  109. LsapDbUpdateSystemAccessAccount(
  110. IN PLSAPR_SID AccountSid,
  111. IN PULONG SystemAccess
  112. );
  113. NTSTATUS
  114. LsapDbUpdatePrivilegesAccount(
  115. IN PLSAPR_SID AccountSid,
  116. IN OPTIONAL PPRIVILEGE_SET Privileges
  117. );
  118. NTSTATUS
  119. LsapDbUpdateQuotasAccount(
  120. IN PLSAPR_SID AccountSid,
  121. IN PQUOTA_LIMITS QuotaLimits
  122. );
  123. NTSTATUS
  124. LsapDbCreateAccountList(
  125. OUT PLSAP_DB_ACCOUNT_LIST AccountList
  126. );
  127. /////////////////////////////////////////////////////////////////////////////
  128. // //
  129. // Private Global Data //
  130. // //
  131. /////////////////////////////////////////////////////////////////////////////
  132. LSAP_DB_ACCOUNT_LIST LsapDbAccountList;
  133. /////////////////////////////////////////////////////////////////////////////
  134. // //
  135. // Code //
  136. // //
  137. /////////////////////////////////////////////////////////////////////////////
  138. NTSTATUS
  139. LsarCreateAccount(
  140. IN LSAPR_HANDLE PolicyHandle,
  141. IN PLSAPR_SID AccountSid,
  142. IN ACCESS_MASK DesiredAccess,
  143. OUT PLSAPR_HANDLE AccountHandle
  144. )
  145. /*++
  146. Routine Description:
  147. This function is the LSA server RPC worker routine for the
  148. LsaCreateAccount API.
  149. The LsaCreateAccount API creates a new Account Object. The account will
  150. be opened with the specified accesses granted. The caller must
  151. have POLICY_CREATE_ACCOUNT access to the Policy Object.
  152. Note that no verification is done to ensure the SID actually represents
  153. a valid user, group or alias in any trusted domain.
  154. Arguments:
  155. PolicyHandle - Handle from an LsaOpenPolicy call.
  156. AccountSid - Points to the SID of the account.
  157. DesiredAccess - Specifies the accesses to be granted to the newly
  158. created and opened account at this time.
  159. AccountHandle - Receives a handle referencing the newly created
  160. account. This handle is used on subsequent accesses to the
  161. account object.
  162. Return Values:
  163. NTSTATUS - Standard Nt Result Code
  164. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  165. to complete the operation.
  166. STATUS_OBJECT_NAME_EXISTS - An account object having the given Sid
  167. already exists and has been opened because LSA_OBJECT_OPEN_IF
  168. disposition has been specified. This is a warning only.
  169. STATUS_OBJECT_NAME_COLLISION - An account object having the given Sid
  170. already exists but has not been opened because LSA_OBJECT_CREATE
  171. disposition has been specified. This is an error.
  172. STATUS_INVALID_PARAMETER - An invalid parameter has been specified.
  173. --*/
  174. {
  175. NTSTATUS Status;
  176. LSAP_DB_OBJECT_INFORMATION ObjectInformation;
  177. LSAP_DB_ATTRIBUTE Attributes[LSAP_DB_ATTRS_ACCOUNT];
  178. PLSAP_DB_ATTRIBUTE NextAttribute;
  179. UNICODE_STRING LogicalNameU;
  180. ULONG AttributeCount;
  181. BOOLEAN ContainerReferenced = FALSE;
  182. LsarpReturnCheckSetup();
  183. LsapDsDebugOut(( DEB_FTRACE, "LsarCreateAccount\n" ));
  184. LogicalNameU.Length = 0;
  185. //
  186. // Set up the object's attributes specific to the Account object type.
  187. // These are the Account Type and the Sid.
  188. //
  189. AttributeCount = 0;
  190. NextAttribute = Attributes;
  191. //
  192. // Validate the Account Sid.
  193. //
  194. if (!RtlValidSid( (PSID) AccountSid )) {
  195. Status = STATUS_INVALID_PARAMETER;
  196. goto CreateAccountError;
  197. }
  198. Status = LsapDbMakeSidAttributeDs(
  199. AccountSid,
  200. Sid,
  201. NextAttribute
  202. );
  203. if (!NT_SUCCESS(Status)) {
  204. goto CreateAccountError;
  205. }
  206. AttributeCount++;
  207. NextAttribute++;
  208. //
  209. // Acquire the Lsa Database lock. Verify that the PolicyHandle
  210. // is valid and has the necessary access granted. Reference the Policy
  211. // Object handle (as container object).
  212. //
  213. Status = LsapDbReferenceObject(
  214. PolicyHandle,
  215. POLICY_CREATE_ACCOUNT,
  216. PolicyObject,
  217. AccountObject,
  218. LSAP_DB_LOCK | LSAP_DB_NO_DS_OP_TRANSACTION | LSAP_DB_READ_ONLY_TRANSACTION
  219. );
  220. if (!NT_SUCCESS(Status)) {
  221. goto CreateAccountError;
  222. }
  223. ContainerReferenced = TRUE;
  224. //
  225. // Construct the Logical Name (Internal LSA Database Name) of the
  226. // account object. The Logical Name is constructed from the account
  227. // Sid by extracting the Relative Id (lowest subauthority) and converting
  228. // it to an 8-digit numeric Unicode String in which leading zeros are
  229. // added if needed.
  230. //
  231. Status = LsapDbSidToLogicalNameObject(AccountSid, &LogicalNameU);
  232. if (!NT_SUCCESS(Status)) {
  233. goto CreateAccountError;
  234. }
  235. //
  236. // Fill in the ObjectInformation structure. Initialize the
  237. // embedded Object Attributes with the PolicyHandle as the
  238. // Root Directory (Container Object) handle and the Logical Name
  239. // of the account. Store the types of the object and its container.
  240. //
  241. InitializeObjectAttributes(
  242. &ObjectInformation.ObjectAttributes,
  243. &LogicalNameU,
  244. OBJ_CASE_INSENSITIVE,
  245. PolicyHandle,
  246. NULL
  247. );
  248. ObjectInformation.ObjectTypeId = AccountObject;
  249. ObjectInformation.ContainerTypeId = PolicyObject;
  250. ObjectInformation.Sid = AccountSid;
  251. ObjectInformation.ObjectAttributeNameOnly = FALSE;
  252. ObjectInformation.DesiredObjectAccess = DesiredAccess;
  253. //
  254. // Create the Account Object. We fail if the object already exists.
  255. // Note that the object create routine performs a Database transaction.
  256. // If caching is supported, the object will also be added to the cache.
  257. //
  258. Status = LsapDbCreateObject(
  259. &ObjectInformation,
  260. DesiredAccess,
  261. LSAP_DB_OBJECT_CREATE,
  262. 0,
  263. Attributes,
  264. &AttributeCount,
  265. RTL_NUMBER_OF(Attributes),
  266. AccountHandle
  267. );
  268. if (!NT_SUCCESS(Status)) {
  269. goto CreateAccountError;
  270. }
  271. CreateAccountFinish:
  272. //
  273. // If necessary, release the LSA Database lock.
  274. //
  275. if (ContainerReferenced) {
  276. LsapDbApplyTransaction( PolicyHandle,
  277. LSAP_DB_NO_DS_OP_TRANSACTION |
  278. LSAP_DB_READ_ONLY_TRANSACTION,
  279. (SECURITY_DB_DELTA_TYPE) 0 );
  280. LsapDbReleaseLockEx( AccountObject,
  281. LSAP_DB_READ_ONLY_TRANSACTION );
  282. }
  283. //
  284. // If necessary, free the Unicode String buffer allocated for the Logical Name
  285. //
  286. if (LogicalNameU.Length > 0) {
  287. RtlFreeUnicodeString(&LogicalNameU);
  288. }
  289. LsarpReturnPrologue();
  290. LsapDsDebugOut(( DEB_FTRACE, "LsarCreateAccount: 0x%lx\n", Status ));
  291. return( Status );
  292. CreateAccountError:
  293. //
  294. // If necessary, dereference the Container Object, release the LSA
  295. // Database Lock and return.
  296. //
  297. if (ContainerReferenced) {
  298. Status = LsapDbDereferenceObject(
  299. &PolicyHandle,
  300. PolicyObject,
  301. AccountObject,
  302. LSAP_DB_LOCK | LSAP_DB_NO_DS_OP_TRANSACTION | LSAP_DB_READ_ONLY_TRANSACTION,
  303. (SECURITY_DB_DELTA_TYPE) 0,
  304. Status
  305. );
  306. ContainerReferenced = FALSE;
  307. }
  308. goto CreateAccountFinish;
  309. }
  310. NTSTATUS
  311. LsarOpenAccount(
  312. IN LSAPR_HANDLE PolicyHandle,
  313. IN PLSAPR_SID AccountSid,
  314. IN ACCESS_MASK DesiredAccess,
  315. OUT PLSAPR_HANDLE AccountHandle
  316. )
  317. /*++
  318. Routine Description:
  319. This function is the LSA server RPC worker routine for the LsaOpenAccount
  320. API.
  321. The LsaOpenAccount API opens an account object in the Lsa Database of the
  322. target system. An account must be opened before any operation can be
  323. performed, including deletion of the account. A handle to the account
  324. object is returned for use on subsequent API calls that access the
  325. account. Before calling this API, the caller must have connected to
  326. the target system's LSA and opened the LsaDatabase object by means
  327. of a preceding call to LsaOpenPolicy.
  328. Arguments:
  329. PolicyHandle - Handle from an LsaOpenPolicy call.
  330. AccountSid - Pointer to the account's Sid.
  331. DesiredAccess - This is an access mask indicating accesses being
  332. requested for the Account object. These access types
  333. are reconciled with the Discretionary Access Control List of the
  334. object to determine whether the accesses will be granted or denied.
  335. AccountHandle - Pointer to location in which a handle to the opened
  336. account object will be returned if the call succeeds.
  337. Return Values:
  338. NTSTATUS - Standard Nt Result Code
  339. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  340. to complete the operation.
  341. STATUS_OBJECT_NAME_NOT_FOUND - There is no account object in the
  342. target system's LSA Database having the specified AccountSid.
  343. --*/
  344. {
  345. NTSTATUS Status;
  346. LSAP_DB_OBJECT_INFORMATION ObjectInformation;
  347. UNICODE_STRING LogicalNameU;
  348. BOOLEAN ContainerReferenced = FALSE;
  349. BOOLEAN AcquiredLock = FALSE;
  350. LsarpReturnCheckSetup();
  351. LsapDsDebugOut(( DEB_FTRACE, "LsarOpenAccount\n" ));
  352. //
  353. // Validate the Account Sid.
  354. //
  355. if (!RtlValidSid( AccountSid )) {
  356. Status = STATUS_INVALID_PARAMETER;
  357. goto OpenAccountError;
  358. }
  359. //
  360. // Acquire the Lsa Database lock. Verify that the connection handle
  361. // (container object handle) is valid, and is of the expected type.
  362. // Reference the container object handle. This reference remains in
  363. // effect until the child object handle is closed.
  364. //
  365. // We can't check access on the policy handle. Too many applications
  366. // rely on no access being acquired.
  367. //
  368. Status = LsapDbReferenceObject(
  369. PolicyHandle,
  370. 0,
  371. PolicyObject,
  372. AccountObject,
  373. LSAP_DB_LOCK |
  374. LSAP_DB_NO_DS_OP_TRANSACTION |
  375. LSAP_DB_READ_ONLY_TRANSACTION
  376. );
  377. if (!NT_SUCCESS(Status)) {
  378. goto OpenAccountError;
  379. }
  380. AcquiredLock = TRUE;
  381. ContainerReferenced =TRUE;
  382. //
  383. // Setup Object Information prior to calling the Object
  384. // Open routine. The Object Type, Container Object Type and
  385. // Logical Name (derived from the Sid) need to be filled in.
  386. //
  387. ObjectInformation.ObjectTypeId = AccountObject;
  388. ObjectInformation.ContainerTypeId = PolicyObject;
  389. ObjectInformation.Sid = AccountSid;
  390. ObjectInformation.ObjectAttributeNameOnly = FALSE;
  391. ObjectInformation.DesiredObjectAccess = DesiredAccess;
  392. //
  393. // Construct the Logical Name (Internal LSA Database Name) of the
  394. // account object. The Logical Name is constructed from the account
  395. // Sid by extracting the Relative Id (lowest subauthority) and converting
  396. // it to an 8-digit numeric Unicode String in which leading zeros are
  397. // added if needed.
  398. //
  399. Status = LsapDbSidToLogicalNameObject(AccountSid,&LogicalNameU);
  400. if (!NT_SUCCESS(Status)) {
  401. goto OpenAccountError;
  402. }
  403. //
  404. // Initialize the Object Attributes. The Container Object Handle and
  405. // Logical Name (Internal Name) of the object must be set up.
  406. //
  407. InitializeObjectAttributes(
  408. &ObjectInformation.ObjectAttributes,
  409. &LogicalNameU,
  410. 0,
  411. PolicyHandle,
  412. NULL
  413. );
  414. //
  415. // Open the specific account object. Note that the account object
  416. // handle returned is an RPC Context Handle.
  417. //
  418. Status = LsapDbOpenObject(
  419. &ObjectInformation,
  420. DesiredAccess,
  421. 0,
  422. AccountHandle
  423. );
  424. RtlFreeUnicodeString( &LogicalNameU );
  425. if (!NT_SUCCESS(Status)) {
  426. goto OpenAccountError;
  427. }
  428. OpenAccountFinish:
  429. //
  430. // If necessary, release the LSA Database lock.
  431. //
  432. if (AcquiredLock) {
  433. LsapDbApplyTransaction( PolicyHandle,
  434. LSAP_DB_NO_DS_OP_TRANSACTION |
  435. LSAP_DB_READ_ONLY_TRANSACTION,
  436. (SECURITY_DB_DELTA_TYPE) 0 );
  437. LsapDbReleaseLockEx( AccountObject,
  438. LSAP_DB_READ_ONLY_TRANSACTION );
  439. AcquiredLock = FALSE;
  440. }
  441. LsarpReturnPrologue();
  442. LsapDsDebugOut(( DEB_FTRACE, "LsarOpenAccount: 0x%lx\n", Status ));
  443. return( Status );
  444. OpenAccountError:
  445. //
  446. // If necessary, dereference the Container Object handle. Note that
  447. // this is only done in the error case. In the non-error case, the
  448. // Container handle stays referenced until the Account object is
  449. // closed.
  450. //
  451. if (ContainerReferenced) {
  452. *AccountHandle = NULL;
  453. Status = LsapDbDereferenceObject(
  454. &PolicyHandle,
  455. PolicyObject,
  456. AccountObject,
  457. LSAP_DB_LOCK | LSAP_DB_NO_DS_OP_TRANSACTION | LSAP_DB_READ_ONLY_TRANSACTION,
  458. (SECURITY_DB_DELTA_TYPE) 0,
  459. Status
  460. );
  461. ContainerReferenced = FALSE;
  462. AcquiredLock = FALSE;
  463. }
  464. goto OpenAccountFinish;
  465. }
  466. NTSTATUS
  467. LsarEnumerateAccounts(
  468. IN LSAPR_HANDLE PolicyHandle,
  469. IN OUT PLSA_ENUMERATION_HANDLE EnumerationContext,
  470. OUT PLSAPR_ACCOUNT_ENUM_BUFFER EnumerationBuffer,
  471. IN ULONG PreferedMaximumLength
  472. )
  473. /*++
  474. Routine Description:
  475. This function is the LSA server RPC worker routine for the
  476. LsaEnumerateAccounts API.
  477. The LsaEnumerateAccounts API returns information about the accounts
  478. in the target system's Lsa Database. This call requires
  479. POLICY_VIEW_LOCAL_INFORMATION access to the Policy object. Since there
  480. may be more information than can be returned in a single call of the
  481. routine, multiple calls can be made to get all of the information. To
  482. support this feature, the caller is provided with a handle that can be
  483. used across calls to the API. On the initial call, EnumerationContext
  484. should point to a variable that has been initialized to 0. On each
  485. subsequent call, the value returned by the preceding call should be passed
  486. in unchanged. The enumeration is complete when the warning
  487. STATUS_NO_MORE_ENTRIES is returned.
  488. Arguments:
  489. PolicyHandle - Handle from an LsaOpenPolicy call.
  490. EnumerationContext - API-specific handle to allow multiple calls
  491. (see Routine Description above).
  492. EnumerationBuffer - Pointer to an enumeration structure that will receive
  493. a count of the accounts enumerated on this call and a pointer to
  494. an array of entries containing information for each enumerated
  495. account.
  496. PreferedMaximumLength - Prefered maximum length of returned data (in 8-bit
  497. bytes). This is not a hard upper limit, but serves as a guide. Due to
  498. data conversion between systems with different natural data sizes, the
  499. actual amount of data returned may be greater than this value.
  500. Return Values:
  501. NTSTATUS - Standard Nt Result Code
  502. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  503. to complete the operation.
  504. STATUS_NO_MORE_ENTRIES - There are no more entries. This warning
  505. is returned if no objects are enumerated because the
  506. EnumerationContext value passed in is too high.
  507. --*/
  508. {
  509. NTSTATUS Status;
  510. LSAP_DB_SID_ENUMERATION_BUFFER DbEnumerationBuffer;
  511. ULONG MaxLength;
  512. LsarpReturnCheckSetup();
  513. LsapDsDebugOut(( DEB_FTRACE, "LsarEnumerateAccounts\n" ));
  514. //
  515. // If no Enumeration Structure or index is provided, return an error.
  516. //
  517. if ( !ARGUMENT_PRESENT(EnumerationBuffer) ||
  518. !ARGUMENT_PRESENT(EnumerationContext) ) {
  519. return(STATUS_INVALID_PARAMETER);
  520. }
  521. //
  522. // Initialize the internal Lsa Database Enumeration Buffer, and
  523. // the provided Enumeration Buffer to NULL.
  524. //
  525. DbEnumerationBuffer.EntriesRead = 0;
  526. DbEnumerationBuffer.Sids = NULL;
  527. EnumerationBuffer->EntriesRead = 0;
  528. EnumerationBuffer->Information = NULL;
  529. //
  530. // Bug #340164: anonymous users are not allowed to look at accounts
  531. //
  532. if ( LsapGlobalRestrictAnonymous &&
  533. PolicyHandle != NULL &&
  534. ((LSAP_DB_HANDLE)PolicyHandle)->Options & LSAP_DB_OPENED_BY_ANONYMOUS ) {
  535. return STATUS_ACCESS_DENIED;
  536. }
  537. //
  538. // Acquire the Lsa Database lock. Verify that the connection handle is
  539. // valid, is of the expected type and has all of the desired accesses
  540. // granted. Reference the handle.
  541. //
  542. Status = LsapDbReferenceObject(
  543. PolicyHandle,
  544. POLICY_VIEW_LOCAL_INFORMATION,
  545. PolicyObject,
  546. AccountObject,
  547. LSAP_DB_LOCK |
  548. LSAP_DB_NO_DS_OP_TRANSACTION |
  549. LSAP_DB_READ_ONLY_TRANSACTION
  550. );
  551. if ( NT_SUCCESS( Status )) {
  552. //
  553. // Limit the enumeration length except for trusted callers
  554. //
  555. if ( !((LSAP_DB_HANDLE)PolicyHandle)->Trusted &&
  556. (PreferedMaximumLength > LSA_MAXIMUM_ENUMERATION_LENGTH)
  557. ) {
  558. MaxLength = LSA_MAXIMUM_ENUMERATION_LENGTH;
  559. } else {
  560. MaxLength = PreferedMaximumLength;
  561. }
  562. //
  563. // Call general Sid enumeration routine.
  564. //
  565. Status = LsapDbEnumerateSids(
  566. PolicyHandle,
  567. AccountObject,
  568. EnumerationContext,
  569. &DbEnumerationBuffer,
  570. MaxLength
  571. );
  572. LsapDbDereferenceObject(
  573. &PolicyHandle,
  574. PolicyObject,
  575. AccountObject,
  576. LSAP_DB_LOCK |
  577. LSAP_DB_NO_DS_OP_TRANSACTION |
  578. LSAP_DB_READ_ONLY_TRANSACTION,
  579. (SECURITY_DB_DELTA_TYPE) 0,
  580. Status
  581. );
  582. }
  583. //
  584. // Copy the enumerated information to the output. We can use the
  585. // information actually returned by LsapDbEnumerateSids because it
  586. // happens to be in exactly the correct form.
  587. //
  588. EnumerationBuffer->EntriesRead = DbEnumerationBuffer.EntriesRead;
  589. EnumerationBuffer->Information = (PLSAPR_ACCOUNT_INFORMATION) DbEnumerationBuffer.Sids;
  590. LsarpReturnPrologue();
  591. LsapDsDebugOut(( DEB_FTRACE, "LsarEnumerateAccounts:0x%lx\n", Status ));
  592. return(Status);
  593. }
  594. NTSTATUS
  595. LsarEnumeratePrivilegesAccount(
  596. IN LSAPR_HANDLE AccountHandle,
  597. OUT PLSAPR_PRIVILEGE_SET *Privileges
  598. )
  599. /*++
  600. Routine Description:
  601. This function is the LSA server RPC worker routine for the
  602. LsaEnumeratePrivilegesOfAccount API.
  603. The LsaEnumeratePrivilegesOfAccount API obtains information which
  604. describes the privileges assigned to an account. This call requires
  605. ACCOUNT_VIEW access to the account object.
  606. Arguments:
  607. AccountHandle - The handle to the open account object whose privilege
  608. information is to be obtained. This handle will have been returned
  609. from a prior LsaOpenAccount or LsaCreateAccountInLsa API call.
  610. Privileges - Receives a pointer to a buffer containing the Privilege
  611. Set. The Privilege Set is an array of structures, one for each
  612. privilege. Each structure contains the LUID of the privilege and
  613. a mask of the privilege's attributes.
  614. Return Values:
  615. NTSTATUS - Standard Nt Result Code
  616. STATUS_SUCCESS - The call completed successfully.
  617. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  618. to complete the operation.
  619. STATUS_INVALID_HANDLE - The specified AccountHandle is not valid.
  620. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources,
  621. such as memory, to complete the call.
  622. --*/
  623. {
  624. return(LsarQueryInformationAccount(
  625. AccountHandle,
  626. AccountPrivilegeInformation,
  627. (PLSAPR_ACCOUNT_INFO *) Privileges
  628. ));
  629. }
  630. NTSTATUS
  631. LsarAddPrivilegesToAccount(
  632. IN LSAPR_HANDLE AccountHandle,
  633. IN PLSAPR_PRIVILEGE_SET Privileges
  634. )
  635. /*++
  636. Routine Description:
  637. This function is the LSA server RPC worker routine for the
  638. LsaAddPrivilegesToAccount API.
  639. The LsaAddPrivilegesToAccount API adds privileges and their attributes
  640. to an account object. If any provided privilege is already assigned
  641. to the account object, the attributes of that privilege are replaced
  642. by the newly rpovided values. This API call requires
  643. ACCOUNT_ADJUST_PRIVILEGES access to the account object.
  644. Arguments:
  645. AccountHandle - The handle to the open account object to which
  646. privileges are to be added. This handle will have been returned
  647. from a prior LsaOpenAccount or LsaCreateAccountInLsa API call.
  648. Privileges - Points to a set of privileges (and their attributes) to
  649. be assigned to the account.
  650. Return Values:
  651. NTSTATUS - Standard Nt Result Code
  652. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  653. to complete the operation.
  654. STATUS_INVALID_HANDLE - The specified AccountHandle is not valid.
  655. --*/
  656. {
  657. return LsapAddPrivilegesToAccount( AccountHandle, Privileges, TRUE );
  658. }
  659. NTSTATUS
  660. LsapAddPrivilegesToAccount(
  661. IN LSAPR_HANDLE AccountHandle,
  662. IN PLSAPR_PRIVILEGE_SET Privileges,
  663. IN BOOL LockSce
  664. )
  665. /*++
  666. Routine Description:
  667. This is the worker routine for LsarAddPrivilegesToAccount, with an added
  668. semantics of not locking the SCE policy.
  669. --*/
  670. {
  671. NTSTATUS Status;
  672. LsarpReturnCheckSetup();
  673. LsapDsDebugOut(( DEB_FTRACE, "LsapAddPrivilegesToAccount\n" ));
  674. Status = LsapDbChangePrivilegesAccount( AccountHandle,
  675. AddPrivileges,
  676. FALSE,
  677. (PPRIVILEGE_SET) Privileges,
  678. LockSce );
  679. LsarpReturnPrologue();
  680. LsapDsDebugOut(( DEB_FTRACE, "LsapAddPrivilegesToAccount: 0x%lx\n", Status ));
  681. return( Status );
  682. }
  683. NTSTATUS
  684. LsarRemovePrivilegesFromAccount(
  685. IN LSAPR_HANDLE AccountHandle,
  686. IN BOOLEAN AllPrivileges,
  687. IN OPTIONAL PLSAPR_PRIVILEGE_SET Privileges
  688. )
  689. /*++
  690. Routine Description:
  691. This function is the RPC server worker routine for the
  692. LsaRemovePrivilegesFromAccount API.
  693. The LsaRemovePrivilegesFromAccount API removes privileges from an
  694. account object. This API call requires ACCOUNT_ADJUST_PRIVILEGES
  695. access to the account object. Note that if all privileges are removed
  696. from the account object, the account object remains in existence until
  697. deleted explicitly via a call to the LsaDeleteAccount API.
  698. Arguments:
  699. AccountHandle - The handle to the open account object to which
  700. privileges are to be removed. This handle will have been returned
  701. from a prior LsaOpenAccount or LsaCreateAccountInLsa API call.
  702. AllPrivileges - If TRUE, then all privileges are to be removed from
  703. the account. In this case, the Privileges parameter must be
  704. specified as NULL. If FALSE, the Privileges parameter specifies
  705. the privileges to be removed, and must be non NULL.
  706. Privileges - Optionally points to a set of privileges (and their
  707. attributes) to be removed from the account object. The attributes
  708. fields of this structure are ignored. This parameter must
  709. be specified as non-NULL if and only if AllPrivileges is set to
  710. FALSE.
  711. Return Values:
  712. NTSTATUS - Standard Nt Result Code
  713. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  714. to complete the operation.
  715. STATUS_INVALID_HANDLE - The specified AccountHandle is not valid.
  716. STATUS_INVALID_PARAMETER - The optional Privileges paraemter was
  717. specified as NULL and AllPrivileges was set to FALSE.
  718. --*/
  719. {
  720. return LsapRemovePrivilegesFromAccount( AccountHandle, AllPrivileges, Privileges, TRUE );
  721. }
  722. NTSTATUS
  723. LsapRemovePrivilegesFromAccount(
  724. IN LSAPR_HANDLE AccountHandle,
  725. IN BOOLEAN AllPrivileges,
  726. IN OPTIONAL PLSAPR_PRIVILEGE_SET Privileges,
  727. IN BOOL LockSce
  728. )
  729. /*++
  730. Routine Description:
  731. This is the worker routine for LsarRemovePrivilegesFromAccount, with an added
  732. semantics of not locking the SCE policy.
  733. --*/
  734. {
  735. NTSTATUS Status;
  736. LsarpReturnCheckSetup();
  737. LsapDsDebugOut(( DEB_FTRACE, "LsapRemovePrivilegesFromAccount\n" ));
  738. //
  739. // Verify that a meaningful combination of AllPrivileges and Privileges
  740. // has been specified.
  741. //
  742. if (AllPrivileges) {
  743. if (Privileges != NULL) {
  744. return STATUS_INVALID_PARAMETER;
  745. }
  746. } else {
  747. if (Privileges == NULL) {
  748. return STATUS_INVALID_PARAMETER;
  749. }
  750. }
  751. //
  752. // Remove the privileges requested.
  753. //
  754. Status = LsapDbChangePrivilegesAccount(
  755. AccountHandle,
  756. RemovePrivileges,
  757. AllPrivileges,
  758. (PPRIVILEGE_SET) Privileges,
  759. LockSce
  760. );
  761. LsarpReturnPrologue();
  762. LsapDsDebugOut(( DEB_FTRACE, "LsapRemovePrivilegesFromAccount: 0x%lx\n", Status ));
  763. return(Status);
  764. }
  765. NTSTATUS
  766. LsapDbChangePrivilegesAccount(
  767. IN LSAPR_HANDLE AccountHandle,
  768. IN LSAP_DB_CHANGE_PRIVILEGE_MODE ChangeMode,
  769. IN BOOLEAN AllPrivileges,
  770. IN OPTIONAL PPRIVILEGE_SET Privileges,
  771. IN BOOL LockSce
  772. )
  773. /*++
  774. Routine Description:
  775. This function changes the privileges assigned to an account. It is
  776. called only by LsarAddPrivilegesToAccount and LsarRemovePrivilegesFrom-
  777. Account.
  778. WARNING: The Lsa Database must be in the locked state when this function
  779. is called.
  780. Arguments:
  781. AccountHandle - Handle to open Account object obtained from LsaOpenAccount.
  782. ChangeMode - Specifies the change mode
  783. AddPrivileges - Add the privileges
  784. RemovePrivileges - Delete the privileges
  785. AllPrivileges - If removing privileges from an account and this boolean
  786. is set to TRUE, all privileges are to be removed. In this case,
  787. the Privileges parameter must be set to NULL. In all other cases,
  788. AllPrivileges must be set to FALSE and Privileges must be non-NULL.
  789. Privileges - Specifies set of privileges to be changed. This parameter
  790. must be set to NULL if and only if removing all privileges.
  791. LockSce - Specifies whether SCE policy should be locked or not (should be FALSE
  792. for situations where the caller already has it locked)
  793. Return Value:
  794. NTSTATUS - Standard Nt Result Code
  795. --*/
  796. {
  797. NTSTATUS Status = STATUS_SUCCESS, IgnoreStatus;
  798. ULONG ExistingPrivilegesSize;
  799. LSAPR_HANDLE SubKeyHandle = NULL;
  800. PPRIVILEGE_SET ExistingPrivileges = NULL;
  801. PPRIVILEGE_SET PrivilegesToAudit = NULL;
  802. BOOLEAN TransactionAbort = FALSE;
  803. ULONG AuditEventId;
  804. PLUID_AND_ATTRIBUTES Luids = NULL;
  805. BOOLEAN ObjectReferenced = FALSE;
  806. PLSAPR_SID AccountSid = NULL;
  807. BOOLEAN bAudit = FALSE;
  808. LSAP_DB_HANDLE InternalHandle = AccountHandle;
  809. BOOLEAN ScePolicyLocked = FALSE;
  810. BOOLEAN NotifySce = FALSE;
  811. ULONG MaxPrivileges = 0;
  812. #if DBG
  813. if( AllPrivileges ) {
  814. //
  815. // If AllPrivileges is TRUE then we must be removing privileges
  816. // and Privileges must be NULL
  817. //
  818. ASSERT( ChangeMode == RemovePrivileges );
  819. ASSERT( Privileges == NULL );
  820. } else {
  821. //
  822. // If AllPrivileges is FALSE then
  823. // Privileges must be non-NULL
  824. //
  825. ASSERT( Privileges != NULL );
  826. }
  827. //
  828. // Does ChangeMode has a valid value?
  829. //
  830. switch( ChangeMode ) {
  831. case AddPrivileges:
  832. case RemovePrivileges:
  833. case SetPrivileges:
  834. break;
  835. default:
  836. ASSERT( !"Change mode doesn't have a valid value" );
  837. break;
  838. }
  839. #endif
  840. //
  841. // Do not grab the SCE policy lock for handles opened as SCE policy handles
  842. //
  843. if ( !InternalHandle->SceHandleChild ) {
  844. if ( LockSce ) {
  845. RtlEnterCriticalSection( &LsapDbState.ScePolicyLock.CriticalSection );
  846. if ( LsapDbState.ScePolicyLock.NumberOfWaitingShared > MAX_SCE_WAITING_SHARED ) {
  847. Status = STATUS_TOO_MANY_THREADS;
  848. }
  849. RtlLeaveCriticalSection( &LsapDbState.ScePolicyLock.CriticalSection );
  850. if ( !NT_SUCCESS( Status )) {
  851. goto ChangePrivilegesError;
  852. }
  853. WaitForSingleObject( LsapDbState.SceSyncEvent, INFINITE );
  854. RtlAcquireResourceShared( &LsapDbState.ScePolicyLock, TRUE );
  855. ASSERT( !g_ScePolicyLocked );
  856. ScePolicyLocked = TRUE;
  857. }
  858. NotifySce = TRUE;
  859. }
  860. //
  861. // Acquire the Lsa Database lock. Verify that the Account Object handle is
  862. // valid, is of the expected type and has all of the desired accesses
  863. // granted. Reference the handle and open a database transaction.
  864. //
  865. Status = LsapDbReferenceObject(
  866. AccountHandle,
  867. ACCOUNT_ADJUST_PRIVILEGES,
  868. AccountObject,
  869. AccountObject,
  870. LSAP_DB_LOCK |
  871. LSAP_DB_START_TRANSACTION |
  872. LSAP_DB_NO_DS_OP_TRANSACTION
  873. );
  874. if (!NT_SUCCESS(Status)) {
  875. goto ChangePrivilegesError;
  876. }
  877. ObjectReferenced = TRUE;
  878. //
  879. // Query size of buffer needed for the existing Privileges.
  880. // Read the Account Object's Privileges data from the LSA Database
  881. //
  882. ExistingPrivilegesSize = 0;
  883. //
  884. // If we're doing a SetPrivileges and we're in registry mode, we'll just pretend we
  885. // have no existing privs and do an add
  886. //
  887. if ( ChangeMode == SetPrivileges ) {
  888. ExistingPrivileges = NULL;
  889. ChangeMode = AddPrivileges;
  890. } else {
  891. Status = LsapDbReadAttributeObject(
  892. AccountHandle,
  893. &LsapDbNames[Privilgs],
  894. NULL,
  895. &ExistingPrivilegesSize
  896. );
  897. if (!NT_SUCCESS(Status)) {
  898. //
  899. // The only error permitted is STATUS_OBJECT_NAME_NOT_FOUND
  900. // because the account object does not have any privileges
  901. // assigned and has no Privilgs attribute.
  902. //
  903. if (Status != STATUS_OBJECT_NAME_NOT_FOUND) {
  904. goto ChangePrivilegesError;
  905. }
  906. //
  907. // Account has no existing privileges.
  908. //
  909. ExistingPrivileges = NULL;
  910. } else {
  911. //
  912. // Account already has privileges. Allocate buffer for reading
  913. // the existing privilege set and read them in.
  914. //
  915. ExistingPrivileges = LsapAllocateLsaHeap( ExistingPrivilegesSize );
  916. if (ExistingPrivileges == NULL) {
  917. Status = STATUS_INSUFFICIENT_RESOURCES;
  918. goto ChangePrivilegesError;
  919. }
  920. Status = LsapDbReadAttributeObject(
  921. AccountHandle,
  922. &LsapDbNames[Privilgs],
  923. ExistingPrivileges,
  924. &ExistingPrivilegesSize
  925. );
  926. if (!NT_SUCCESS(Status)) {
  927. goto ChangePrivilegesError;
  928. }
  929. }
  930. }
  931. //
  932. // when caller wants to remove privileges and AllPrivileges == TRUE,
  933. // the passed value of Privileges is NULL. This poses a problem for
  934. // the auditing code as we wnat to see what privileges got removed
  935. // in the audit event. Therefore, in this case, make a copy of the
  936. // existing privileges so that we can use it later in auditing.
  937. //
  938. if (AllPrivileges && (ChangeMode == RemovePrivileges)) {
  939. PrivilegesToAudit = ExistingPrivileges;
  940. ExistingPrivileges = NULL;
  941. } else {
  942. PrivilegesToAudit = Privileges;
  943. //
  944. // Now query the size of buffer required for the updated privilege
  945. // set
  946. //
  947. if ( ExistingPrivileges ) {
  948. MaxPrivileges = ExistingPrivileges->PrivilegeCount;
  949. }
  950. if (ChangeMode == AddPrivileges) {
  951. BOOLEAN Changed = FALSE;
  952. Status = LsapRtlAddPrivileges(
  953. &ExistingPrivileges,
  954. &MaxPrivileges,
  955. Privileges,
  956. RTL_SUPERSEDE_PRIVILEGE_ATTRIBUTES,
  957. &Changed
  958. );
  959. if ( NT_SUCCESS( Status ) && !Changed ) {
  960. //
  961. // Nothing has changed, so bail
  962. //
  963. goto ChangePrivilegesFinish;
  964. }
  965. } else {
  966. Status = LsapRtlRemovePrivileges(
  967. ExistingPrivileges,
  968. Privileges
  969. );
  970. }
  971. }
  972. //
  973. // If privileges remain, write the updated privilege set back to
  974. // the LSA Database as the value of the Privilgs attribute of the
  975. // account object. If no privileges remain, delete the Privilgs
  976. // attribute.
  977. //
  978. if (ExistingPrivileges && (ExistingPrivileges->PrivilegeCount > 0)) {
  979. Status = LsapDbWriteAttributeObject(
  980. AccountHandle,
  981. &LsapDbNames[Privilgs],
  982. ExistingPrivileges,
  983. sizeof (PRIVILEGE_SET) + (ExistingPrivileges->PrivilegeCount - 1)*sizeof(LUID_AND_ATTRIBUTES)
  984. );
  985. } else {
  986. Status = LsapDbDeleteAttributeObject(
  987. AccountHandle,
  988. &LsapDbNames[Privilgs],
  989. FALSE
  990. );
  991. //
  992. // The only error permitted is STATUS_OBJECT_NAME_NOT_FOUND
  993. // because the account object does not have any privileges
  994. // assigned and so has no Privilgs attribute.
  995. //
  996. if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
  997. Status = STATUS_SUCCESS;
  998. }
  999. }
  1000. //
  1001. // If auditing of policy changes is enabled, generate an audit.
  1002. //
  1003. AccountSid = LsapDbSidFromHandle( AccountHandle );
  1004. IgnoreStatus = LsapAdtAuditingEnabledBySid(
  1005. AuditCategoryPolicyChange,
  1006. AccountSid,
  1007. EVENTLOG_AUDIT_SUCCESS,
  1008. &bAudit
  1009. );
  1010. if (NT_SUCCESS(IgnoreStatus) && bAudit &&
  1011. PrivilegesToAudit && PrivilegesToAudit->PrivilegeCount) {
  1012. AuditEventId = ((ChangeMode == AddPrivileges) ?
  1013. SE_AUDITID_USER_RIGHT_ASSIGNED :
  1014. SE_AUDITID_USER_RIGHT_REMOVED);
  1015. //
  1016. // Audit the privilege set change. Ignore failures from Auditing.
  1017. //
  1018. IgnoreStatus = LsapAdtGenerateLsaAuditEvent(
  1019. AccountHandle,
  1020. SE_CATEGID_POLICY_CHANGE,
  1021. AuditEventId,
  1022. PrivilegesToAudit,
  1023. 1,
  1024. (PSID *) &AccountSid,
  1025. 0,
  1026. NULL,
  1027. NULL
  1028. );
  1029. }
  1030. //
  1031. // Update the Account Object Cache while holding the Lsa Database Lock.
  1032. // If the commit to backing storage below fails, caching will automatically
  1033. // be turned off.
  1034. //
  1035. // NOTE: A pointer to the UpdatedPrivileges buffer will be placed directly
  1036. // in the cached Account Object, so it should not be freed by this routine.
  1037. //
  1038. if (ExistingPrivileges && (ExistingPrivileges->PrivilegeCount > 0)) {
  1039. IgnoreStatus = LsapDbUpdatePrivilegesAccount(
  1040. AccountSid,
  1041. ExistingPrivileges
  1042. );
  1043. //
  1044. // The cache takes ownership of the privileges structure, so we don't
  1045. // want to free it.
  1046. //
  1047. if( NT_SUCCESS( IgnoreStatus ) ) {
  1048. ExistingPrivileges = NULL;
  1049. }
  1050. } else {
  1051. IgnoreStatus = LsapDbUpdatePrivilegesAccount(
  1052. AccountSid,
  1053. NULL
  1054. );
  1055. }
  1056. ChangePrivilegesFinish:
  1057. //
  1058. // free the allocated privileges
  1059. //
  1060. if ( AllPrivileges && (ChangeMode == RemovePrivileges) && PrivilegesToAudit )
  1061. {
  1062. LsapFreeLsaHeap( PrivilegesToAudit );
  1063. }
  1064. //
  1065. // If necessary, free the ExistingPrivileges buffer.
  1066. //
  1067. if (ExistingPrivileges != NULL) {
  1068. LsapFreeLsaHeap(ExistingPrivileges);
  1069. ExistingPrivileges = NULL;
  1070. }
  1071. //
  1072. // If necessary, dereference the Account object, close the database
  1073. // transaction, release the LSA Database lock and return.
  1074. //
  1075. if (ObjectReferenced) {
  1076. IgnoreStatus = LsapDbDereferenceObject(
  1077. &AccountHandle,
  1078. AccountObject,
  1079. AccountObject,
  1080. LSAP_DB_LOCK |
  1081. LSAP_DB_FINISH_TRANSACTION |
  1082. LSAP_DB_NO_DS_OP_TRANSACTION,
  1083. SecurityDbChange,
  1084. Status
  1085. );
  1086. }
  1087. //
  1088. // Notify SCE of the change. Only notify for callers
  1089. // that did not open their policy handles with LsaOpenPolicySce.
  1090. //
  1091. if ( NotifySce && NT_SUCCESS( Status )) {
  1092. LsapSceNotify(
  1093. SecurityDbChange,
  1094. SecurityDbObjectLsaAccount,
  1095. InternalHandle->Sid
  1096. );
  1097. }
  1098. if ( ScePolicyLocked ) {
  1099. RtlReleaseResource( &LsapDbState.ScePolicyLock );
  1100. }
  1101. return Status;
  1102. ChangePrivilegesError:
  1103. goto ChangePrivilegesFinish;
  1104. }
  1105. NTSTATUS
  1106. LsarGetQuotasForAccount(
  1107. IN LSAPR_HANDLE AccountHandle,
  1108. OUT PQUOTA_LIMITS QuotaLimits
  1109. )
  1110. /*++
  1111. Routine Description:
  1112. This function is the LSA server RPC worker routine for the
  1113. LsarGetQuotasForAccount API.
  1114. The LsaGetQuotasForAccount API obtains the quota limits for pageable and
  1115. non-pageable memory (in Kilobytes) and the maximum execution time (in
  1116. seconds) for any session logged on to the account specified by
  1117. AccountHandle.
  1118. Quotas is not supported any more. In the past, we need LSA_ACCOUNT_VIEW
  1119. access to the object, but currently, there is no such access right &
  1120. you don't need any right to call this function. We will return QuotaLimits
  1121. as 0 and return SUCCESS.
  1122. Arguments:
  1123. AccountHandle - The handle to the open account object whose quotas
  1124. are to be obtained. This handle will have been returned
  1125. from a prior LsaOpenAccount or LsaCreateAccountInLsa API call.
  1126. QuotaLimits - Pointer to structure in which the system resource
  1127. quota limits applicable to each session logged on to this account
  1128. will be returned. Note that all quotas, including those specified
  1129. as being the system default values, are returned as actual values.
  1130. Return Values:
  1131. NTSTATUS - Standard Nt Result Code
  1132. --*/
  1133. {
  1134. NTSTATUS Status;
  1135. PLSAPR_ACCOUNT_INFO AccountInformation = NULL;
  1136. LsarpReturnCheckSetup();
  1137. //
  1138. // Stub it out
  1139. //
  1140. LsapDsDebugOut(( DEB_TRACE,
  1141. "LsarGetQuotasForAccount has been removed. Returning STATUS_SUCCESS anyway\n" ));
  1142. RtlZeroMemory( QuotaLimits, sizeof( QUOTA_LIMITS ) );
  1143. LsarpReturnPrologue();
  1144. return( STATUS_SUCCESS );
  1145. }
  1146. NTSTATUS
  1147. LsarSetQuotasForAccount(
  1148. IN LSAPR_HANDLE AccountHandle,
  1149. IN PQUOTA_LIMITS QuotaLimits
  1150. )
  1151. /*++
  1152. Routine Description:
  1153. This function is the LSA server RPC worker routine for the
  1154. LsaSetQuotasForAccount API.
  1155. The LsaSetQuotasForAccount API sets the quota limits for pageable and
  1156. non-pageable memory (in Kilobytes) and the maximum execution time (in
  1157. seconds) for any session logged on to the account specified by
  1158. AccountHandle. For each quota an explicit value or the system default
  1159. may be specified.
  1160. Quotas is not supported any more. In the past, we need LSA_ACCOUNT_ADJUST_QUOTAS
  1161. access to the account, but currently, there is no such access right &
  1162. you don't need any right to call this function. We will return SUCCESS.
  1163. Arguments:
  1164. AccountHandle - The handle to the open account object whose quotas
  1165. are to be set. This handle will have been returned from a prior
  1166. LsaOpenAccount or LsaCreateAccountInLsa API call.
  1167. QuotaLimits - Pointer to structure containing the system resource
  1168. quota limits applicable to each session logged on to this account.
  1169. A zero value specified in any field indicates that the current
  1170. System Default Quota Limit is to be applied.
  1171. Return Values:
  1172. NTSTATUS - Standard Nt Result Code
  1173. --*/
  1174. {
  1175. LsarpReturnCheckSetup();
  1176. //
  1177. // Quotas have been disabled.
  1178. //
  1179. LsapDsDebugOut(( DEB_TRACE,
  1180. "LsarSetQuotasForAccount has been removed: Returning STATUS_SUCCESS anyway\n" ));
  1181. return( STATUS_SUCCESS );
  1182. }
  1183. NTSTATUS
  1184. LsarGetSystemAccessAccount(
  1185. IN LSAPR_HANDLE AccountHandle,
  1186. OUT PULONG SystemAccess
  1187. )
  1188. /*++
  1189. Routine Description:
  1190. The LsaGetSystemAccessAccount() service returns the System Access
  1191. account flags for an Account object.
  1192. Arguments:
  1193. AccountHandle - The handle to the Account object whose system access
  1194. flags are to be read. This handle will have been returned
  1195. from a preceding LsaOpenAccount() or LsaCreateAccount() call
  1196. an must be open for ACCOUNT_VIEW access.
  1197. SystemAccess - Points to location that will receive the system access
  1198. flags for the account.
  1199. Return Values:
  1200. NTSTATUS - Standard Nt Result Code
  1201. STATUS_SUCCESS - The call was successful.
  1202. STATUS_ACCESS_DENIED - The AccountHandle does not specify
  1203. ACCOUNT_VIEW access.
  1204. STATUS_INVALID_HANDLE - The specified AccountHandle is invalid.
  1205. --*/
  1206. {
  1207. NTSTATUS Status;
  1208. PLSAPR_ACCOUNT_INFO AccountInformation = NULL;
  1209. LsarpReturnCheckSetup();
  1210. LsapDsDebugOut(( DEB_FTRACE, "LsarGetSystemAccessAccount\n" ));
  1211. Status = LsarQueryInformationAccount(
  1212. AccountHandle,
  1213. AccountSystemAccessInformation,
  1214. &AccountInformation
  1215. );
  1216. if (!NT_SUCCESS(Status)) {
  1217. goto GetSystemAccessAccountError;
  1218. }
  1219. *SystemAccess = *((PULONG) AccountInformation);
  1220. GetSystemAccessAccountFinish:
  1221. //
  1222. // If necessary, free the buffer in which the Account Information was
  1223. // returned.
  1224. //
  1225. if (AccountInformation != NULL) {
  1226. MIDL_user_free( AccountInformation );
  1227. AccountInformation = NULL;
  1228. }
  1229. LsarpReturnPrologue();
  1230. LsapDsDebugOut(( DEB_FTRACE, "LsarGetSystemAccessAccount: 0x%lx\n", Status ));
  1231. return(Status);
  1232. GetSystemAccessAccountError:
  1233. *SystemAccess = 0;
  1234. goto GetSystemAccessAccountFinish;
  1235. }
  1236. NTSTATUS
  1237. LsarSetSystemAccessAccount(
  1238. IN LSAPR_HANDLE AccountHandle,
  1239. IN ULONG SystemAccess
  1240. )
  1241. /*++
  1242. Routine Description:
  1243. The LsaSetSystemAccessAccount() service sets the System Access
  1244. account flags for an Account object.
  1245. Arguments:
  1246. AccountHandle - The handle to the Account object whose system access
  1247. flags are to be read. This handle will have been returned
  1248. from a preceding LsaOpenAccount() or LsaCreateAccount() call
  1249. an must be open for ACCOUNT_ADJUST_SYSTEM_ACCESS access.
  1250. SystemAccess - A mask of the system access flags to assign to the
  1251. Account object. The valid access flags include:
  1252. POLICY_MODE_INTERACTIVE - Account can be accessed interactively
  1253. POLICY_MODE_NETWORK - Account can be accessed remotely
  1254. POLICY_MODE_SERVICE - TBS
  1255. Return Values:
  1256. NTSTATUS - Standard Nt Result Code
  1257. STATUS_SUCCESS - The call was successful.
  1258. STATUS_ACCESS_DENIED - The AccountHandle does not specify
  1259. ACCOUNT_VIEW access.
  1260. STATUS_INVALID_HANDLE - The specified AccountHandle is invalid.
  1261. STATUS_INVALID_PARAMETER - The specified Access Flags are invalid.
  1262. --*/
  1263. {
  1264. return LsapSetSystemAccessAccount( AccountHandle, SystemAccess, TRUE );
  1265. }
  1266. NTSTATUS
  1267. LsapSetSystemAccessAccount(
  1268. IN LSAPR_HANDLE AccountHandle,
  1269. IN ULONG SystemAccess,
  1270. IN BOOL LockSce
  1271. )
  1272. /*++
  1273. Routine Description:
  1274. This is the worker routine for LsarSetSystemAccessAccount, with an added
  1275. semantics of not locking the SCE policy.
  1276. --*/
  1277. {
  1278. NTSTATUS Status = STATUS_SUCCESS, IgnoreStatus;
  1279. BOOLEAN ObjectReferenced = FALSE;
  1280. PLSAPR_SID AccountSid = NULL;
  1281. LSAP_DB_HANDLE InternalHandle = ( LSAP_DB_HANDLE )AccountHandle;
  1282. BOOLEAN ScePolicyLocked = FALSE;
  1283. BOOLEAN NotifySce = FALSE;
  1284. PLSAPR_ACCOUNT_INFO pAccountInfo = NULL;
  1285. LONG i;
  1286. BOOLEAN bObtainedPreviousAccountInfo = TRUE;
  1287. BOOLEAN bAudit = FALSE;
  1288. LsarpReturnCheckSetup();
  1289. LsapDsDebugOut(( DEB_FTRACE, "LsarSetSystemAccessAccount\n" ));
  1290. //
  1291. // Verify that the specified flags are valid
  1292. //
  1293. if (SystemAccess != (SystemAccess & (POLICY_MODE_ALL))) {
  1294. Status = STATUS_INVALID_PARAMETER;
  1295. goto SetSystemAccessAccountError;
  1296. }
  1297. //
  1298. // Do not grab the SCE policy lock for handles opened as SCE policy handles
  1299. //
  1300. if ( !InternalHandle->SceHandleChild ) {
  1301. if ( LockSce ) {
  1302. RtlEnterCriticalSection( &LsapDbState.ScePolicyLock.CriticalSection );
  1303. if ( LsapDbState.ScePolicyLock.NumberOfWaitingShared > MAX_SCE_WAITING_SHARED ) {
  1304. Status = STATUS_TOO_MANY_THREADS;
  1305. }
  1306. RtlLeaveCriticalSection( &LsapDbState.ScePolicyLock.CriticalSection );
  1307. if ( !NT_SUCCESS( Status )) {
  1308. goto SetSystemAccessAccountError;
  1309. }
  1310. WaitForSingleObject( LsapDbState.SceSyncEvent, INFINITE );
  1311. RtlAcquireResourceShared( &LsapDbState.ScePolicyLock, TRUE );
  1312. ASSERT( !g_ScePolicyLocked );
  1313. ScePolicyLocked = TRUE;
  1314. }
  1315. NotifySce = TRUE;
  1316. }
  1317. //
  1318. // Acquire the Lsa Database lock. Verify that the Account Object handle is
  1319. // valid, is of the expected type and has all of the desired accesses
  1320. // granted. Reference the handle and open a database transaction.
  1321. //
  1322. Status = LsapDbReferenceObject(
  1323. AccountHandle,
  1324. ACCOUNT_ADJUST_SYSTEM_ACCESS,
  1325. AccountObject,
  1326. AccountObject,
  1327. LSAP_DB_LOCK | LSAP_DB_START_TRANSACTION | LSAP_DB_NO_DS_OP_TRANSACTION
  1328. );
  1329. if (!NT_SUCCESS(Status)) {
  1330. goto SetSystemAccessAccountError;
  1331. }
  1332. ObjectReferenced = TRUE;
  1333. //
  1334. // Record the previous access flags for auditing.
  1335. //
  1336. bObtainedPreviousAccountInfo = FALSE;
  1337. if( LsapDbIsCacheValid( AccountObject ) ) {
  1338. Status = LsapDbQueryInformationAccount(
  1339. AccountHandle,
  1340. AccountSystemAccessInformation,
  1341. &pAccountInfo
  1342. );
  1343. if( NT_SUCCESS( Status ) ) {
  1344. bObtainedPreviousAccountInfo = TRUE;
  1345. }
  1346. }
  1347. //
  1348. // Write the System Access flags
  1349. //
  1350. Status = LsapDbWriteAttributeObject(
  1351. AccountHandle,
  1352. &LsapDbNames[ActSysAc],
  1353. &SystemAccess,
  1354. sizeof (ULONG)
  1355. );
  1356. if (!NT_SUCCESS(Status)) {
  1357. goto SetSystemAccessAccountError;
  1358. }
  1359. AccountSid = LsapDbSidFromHandle( AccountHandle );
  1360. //
  1361. // Update the Account Object Cache while holding the Lsa Database Lock.
  1362. // If the commit to backing storage below fails, caching will automatically
  1363. // be turned off.
  1364. //
  1365. IgnoreStatus = LsapDbUpdateSystemAccessAccount(
  1366. AccountSid,
  1367. &SystemAccess
  1368. );
  1369. //
  1370. // If auditing of policy changes is enabled, generate an audit.
  1371. //
  1372. IgnoreStatus = LsapAdtAuditingEnabledBySid(
  1373. AuditCategoryPolicyChange,
  1374. AccountSid,
  1375. EVENTLOG_AUDIT_SUCCESS,
  1376. &bAudit
  1377. );
  1378. if (bObtainedPreviousAccountInfo && NT_SUCCESS(IgnoreStatus) && bAudit) {
  1379. //
  1380. // Audit the system access change. Ignore failures from Auditing.
  1381. //
  1382. NTSTATUS Status2 = STATUS_SUCCESS;
  1383. LUID ClientAuthenticationId;
  1384. PTOKEN_USER TokenUserInformation;
  1385. PSID ClientSid;
  1386. PWCHAR GrantedAccess[11];
  1387. LONG GrantedAccessCount = 0;
  1388. ULONG GrantedAccessMask = 0;
  1389. PWCHAR RemovedAccess[11];
  1390. LONG RemovedAccessCount = 0;
  1391. ULONG RemovedAccessMask = 0;
  1392. USHORT EventType = EVENTLOG_AUDIT_SUCCESS;
  1393. //
  1394. // Determine the rights that were enabled.
  1395. //
  1396. GrantedAccessMask = (pAccountInfo != NULL ) ? SystemAccess & (~pAccountInfo->AccountSystemAccessInfo) : SystemAccess;
  1397. if (FLAG_ON(GrantedAccessMask, POLICY_MODE_INTERACTIVE)) {
  1398. GrantedAccess[GrantedAccessCount++] = SE_INTERACTIVE_LOGON_NAME;
  1399. }
  1400. if (FLAG_ON(GrantedAccessMask, POLICY_MODE_NETWORK)) {
  1401. GrantedAccess[GrantedAccessCount++] = SE_NETWORK_LOGON_NAME;
  1402. }
  1403. if (FLAG_ON(GrantedAccessMask, POLICY_MODE_BATCH)) {
  1404. GrantedAccess[GrantedAccessCount++] = SE_BATCH_LOGON_NAME;
  1405. }
  1406. if (FLAG_ON(GrantedAccessMask, POLICY_MODE_SERVICE)) {
  1407. GrantedAccess[GrantedAccessCount++] = SE_SERVICE_LOGON_NAME;
  1408. }
  1409. if (FLAG_ON(GrantedAccessMask, POLICY_MODE_REMOTE_INTERACTIVE)) {
  1410. GrantedAccess[GrantedAccessCount++] = SE_REMOTE_INTERACTIVE_LOGON_NAME;
  1411. }
  1412. if (FLAG_ON(GrantedAccessMask, POLICY_MODE_DENY_INTERACTIVE)) {
  1413. GrantedAccess[GrantedAccessCount++] = SE_DENY_INTERACTIVE_LOGON_NAME;
  1414. }
  1415. if (FLAG_ON(GrantedAccessMask, POLICY_MODE_DENY_NETWORK)) {
  1416. GrantedAccess[GrantedAccessCount++] = SE_DENY_NETWORK_LOGON_NAME;
  1417. }
  1418. if (FLAG_ON(GrantedAccessMask, POLICY_MODE_DENY_BATCH)) {
  1419. GrantedAccess[GrantedAccessCount++] = SE_DENY_BATCH_LOGON_NAME;
  1420. }
  1421. if (FLAG_ON(GrantedAccessMask, POLICY_MODE_DENY_SERVICE)) {
  1422. GrantedAccess[GrantedAccessCount++] = SE_DENY_SERVICE_LOGON_NAME;
  1423. }
  1424. if (FLAG_ON(GrantedAccessMask, POLICY_MODE_DENY_REMOTE_INTERACTIVE)) {
  1425. GrantedAccess[GrantedAccessCount++] = SE_DENY_REMOTE_INTERACTIVE_LOGON_NAME;
  1426. }
  1427. //
  1428. // Determine the rights which were turned off.
  1429. //
  1430. RemovedAccessMask = (pAccountInfo != NULL) ? pAccountInfo->AccountSystemAccessInfo & (~SystemAccess) : SystemAccess;
  1431. if (FLAG_ON(RemovedAccessMask, POLICY_MODE_INTERACTIVE)) {
  1432. RemovedAccess[RemovedAccessCount++] = SE_INTERACTIVE_LOGON_NAME;
  1433. }
  1434. if (FLAG_ON(RemovedAccessMask, POLICY_MODE_NETWORK)) {
  1435. RemovedAccess[RemovedAccessCount++] = SE_NETWORK_LOGON_NAME;
  1436. }
  1437. if (FLAG_ON(RemovedAccessMask, POLICY_MODE_BATCH)) {
  1438. RemovedAccess[RemovedAccessCount++] = SE_BATCH_LOGON_NAME;
  1439. }
  1440. if (FLAG_ON(RemovedAccessMask, POLICY_MODE_SERVICE)) {
  1441. RemovedAccess[RemovedAccessCount++] = SE_SERVICE_LOGON_NAME;
  1442. }
  1443. if (FLAG_ON(RemovedAccessMask, POLICY_MODE_REMOTE_INTERACTIVE)) {
  1444. RemovedAccess[RemovedAccessCount++] = SE_REMOTE_INTERACTIVE_LOGON_NAME;
  1445. }
  1446. if (FLAG_ON(RemovedAccessMask, POLICY_MODE_DENY_INTERACTIVE)) {
  1447. RemovedAccess[RemovedAccessCount++] = SE_DENY_INTERACTIVE_LOGON_NAME;
  1448. }
  1449. if (FLAG_ON(RemovedAccessMask, POLICY_MODE_DENY_NETWORK)) {
  1450. RemovedAccess[RemovedAccessCount++] = SE_DENY_NETWORK_LOGON_NAME;
  1451. }
  1452. if (FLAG_ON(RemovedAccessMask, POLICY_MODE_DENY_BATCH)) {
  1453. RemovedAccess[RemovedAccessCount++] = SE_DENY_BATCH_LOGON_NAME;
  1454. }
  1455. if (FLAG_ON(RemovedAccessMask, POLICY_MODE_DENY_SERVICE)) {
  1456. RemovedAccess[RemovedAccessCount++] = SE_DENY_SERVICE_LOGON_NAME;
  1457. }
  1458. if (FLAG_ON(RemovedAccessMask, POLICY_MODE_DENY_REMOTE_INTERACTIVE)) {
  1459. RemovedAccess[RemovedAccessCount++] = SE_DENY_REMOTE_INTERACTIVE_LOGON_NAME;
  1460. }
  1461. Status2 = LsapQueryClientInfo(
  1462. &TokenUserInformation,
  1463. &ClientAuthenticationId
  1464. );
  1465. if ( NT_SUCCESS( Status2 )) {
  1466. //
  1467. // We can't generate an audit without a
  1468. // user Sid.
  1469. //
  1470. ClientSid = TokenUserInformation->User.Sid;
  1471. //
  1472. // Audit any granted system access rights
  1473. //
  1474. for (i = 0; i < GrantedAccessCount; i++) {
  1475. LsapAdtGenerateLsaAuditSystemAccessChange(
  1476. SE_CATEGID_POLICY_CHANGE,
  1477. SE_AUDITID_SYSTEM_ACCESS_GRANTED,
  1478. EventType,
  1479. ClientSid,
  1480. ClientAuthenticationId,
  1481. AccountSid,
  1482. GrantedAccess[i]
  1483. );
  1484. }
  1485. //
  1486. // Audit any removed system access rights
  1487. //
  1488. for (i = 0; i < RemovedAccessCount; i++) {
  1489. LsapAdtGenerateLsaAuditSystemAccessChange(
  1490. SE_CATEGID_POLICY_CHANGE,
  1491. SE_AUDITID_SYSTEM_ACCESS_REMOVED,
  1492. EventType,
  1493. ClientSid,
  1494. ClientAuthenticationId,
  1495. AccountSid,
  1496. RemovedAccess[i]
  1497. );
  1498. }
  1499. LsapFreeLsaHeap( TokenUserInformation );
  1500. }
  1501. }
  1502. SetSystemAccessAccountFinish:
  1503. if (NULL != pAccountInfo) {
  1504. LsaFreeMemory(pAccountInfo);
  1505. }
  1506. //
  1507. // If necessary, dereference the Account object, close the database
  1508. // transaction, notify the LSA Database Replicator of the change,
  1509. // release the LSA Database lock and return.
  1510. //
  1511. if (ObjectReferenced) {
  1512. LsapDbDereferenceObject(
  1513. &AccountHandle,
  1514. AccountObject,
  1515. AccountObject,
  1516. LSAP_DB_LOCK | LSAP_DB_FINISH_TRANSACTION | LSAP_DB_NO_DS_OP_TRANSACTION,
  1517. SecurityDbChange,
  1518. Status
  1519. );
  1520. }
  1521. //
  1522. // Notify SCE of the change. Only notify for callers
  1523. // that did not open their policy handles with LsaOpenPolicySce.
  1524. //
  1525. if ( NotifySce && NT_SUCCESS( Status )) {
  1526. LsapSceNotify(
  1527. SecurityDbChange,
  1528. SecurityDbObjectLsaAccount,
  1529. AccountSid
  1530. );
  1531. }
  1532. if ( ScePolicyLocked ) {
  1533. RtlReleaseResource( &LsapDbState.ScePolicyLock );
  1534. }
  1535. LsarpReturnPrologue();
  1536. LsapDsDebugOut(( DEB_FTRACE, "LsarSetSystemAccessAccount: 0x%lx\n", Status ));
  1537. return(Status);
  1538. SetSystemAccessAccountError:
  1539. goto SetSystemAccessAccountFinish;
  1540. }
  1541. NTSTATUS
  1542. LsarQueryInformationAccount(
  1543. IN LSAPR_HANDLE AccountHandle,
  1544. IN ACCOUNT_INFORMATION_CLASS InformationClass,
  1545. OUT PLSAPR_ACCOUNT_INFO *AccountInformation
  1546. )
  1547. /*++
  1548. Routine Description:
  1549. This function is the LSA server RPC worker routine for the
  1550. (as yet non-existent) LsarQueryInformationAccount API. Currently,
  1551. LsarGet...Account() API call this routine. In the future, this
  1552. routine may be added as an API.
  1553. The LsaQueryInformationAccount API obtains information from the Policy
  1554. object. The caller must have access appropriate to the information
  1555. being requested (see InformationClass parameter).
  1556. Arguments:
  1557. AccountHandle - Handle from an LsaOpenAccount call.
  1558. InformationClass - Specifies the information to be returned. The
  1559. Information Classes and accesses required are as follows:
  1560. Information Class Required Access Type
  1561. AccountPrivilegeInformation ACCOUNT_VIEW
  1562. AccountQuotaInformation ACCOUNT_VIEW
  1563. AccountSystemAccessInformation ACCOUNT_VIEW
  1564. AccountInformation - Receives a pointer to the buffer returned comtaining the
  1565. requested information. This buffer is allocated by this service
  1566. and must be freed when no longer needed by passing the returned
  1567. value to LsaFreeMemory().
  1568. Return Value:
  1569. NTSTATUS - Standard Nt Result Code
  1570. STATUS_ACCESS_DENIED - Caller does not have the appropriate
  1571. access to complete the operation.
  1572. STATUS_INTERNAL_DB_CORRUPTION - The Policy Database is possibly
  1573. corrupt. The returned Policy Information is invalid for
  1574. the given class.
  1575. --*/
  1576. {
  1577. NTSTATUS Status;
  1578. PLSAP_DB_ACCOUNT Account = NULL;
  1579. PLSAPR_ACCOUNT_INFO CachedAccountInformation = NULL;
  1580. LsarpReturnCheckSetup();
  1581. LsapDsDebugOut(( DEB_FTRACE, "LsarQueryInformationAccount\n" ));
  1582. //
  1583. // Acquire the Lsa Database lock. Verify that the Account Object handle is
  1584. // valid, is of the expected type and has all of the desired accesses
  1585. // granted. Reference the handle.
  1586. //
  1587. Status = LsapDbReferenceObject(
  1588. AccountHandle,
  1589. ACCOUNT_VIEW,
  1590. AccountObject,
  1591. AccountObject,
  1592. LSAP_DB_LOCK |
  1593. LSAP_DB_NO_DS_OP_TRANSACTION |
  1594. LSAP_DB_READ_ONLY_TRANSACTION
  1595. );
  1596. if (NT_SUCCESS(Status)) {
  1597. if (LsapDbIsCacheValid(AccountObject)) {
  1598. Status = LsapDbQueryInformationAccount(
  1599. AccountHandle,
  1600. InformationClass,
  1601. AccountInformation
  1602. );
  1603. } else {
  1604. Status = LsapDbSlowQueryInformationAccount(
  1605. AccountHandle,
  1606. InformationClass,
  1607. AccountInformation
  1608. );
  1609. }
  1610. Status = LsapDbDereferenceObject(
  1611. &AccountHandle,
  1612. AccountObject,
  1613. AccountObject,
  1614. LSAP_DB_LOCK |
  1615. LSAP_DB_NO_DS_OP_TRANSACTION |
  1616. LSAP_DB_READ_ONLY_TRANSACTION,
  1617. (SECURITY_DB_DELTA_TYPE) 0,
  1618. Status
  1619. );
  1620. }
  1621. LsarpReturnPrologue();
  1622. LsapDsDebugOut(( DEB_FTRACE, "LsarQueryInformationAccount: 0x%lx\n", Status ));
  1623. return(Status);
  1624. }
  1625. NTSTATUS
  1626. LsapDbQueryInformationAccount(
  1627. IN LSAPR_HANDLE AccountHandle,
  1628. IN ACCOUNT_INFORMATION_CLASS InformationClass,
  1629. OUT PLSAPR_ACCOUNT_INFO *AccountInformation
  1630. )
  1631. /*++
  1632. Routine Description:
  1633. This function is the fast LSA server RPC worker routine for the
  1634. (as yet non-existent) LsarQueryInformationAccount API. It is called
  1635. when the in-memory Account List is valid.
  1636. Arguments:
  1637. AccountHandle - Handle from an LsaOpenAccount call.
  1638. InformationClass - Specifies the information to be returned. The
  1639. Information Classes and accesses required are as follows:
  1640. Information Class Required Access Type
  1641. AccountPrivilegeInformation ACCOUNT_VIEW
  1642. AccountQuotaInformation ACCOUNT_VIEW
  1643. AccountSystemAccessInformation ACCOUNT_VIEW
  1644. AccountInformation - Receives a pointer to the buffer returned containing
  1645. the requested information. This buffer is allocated by this service
  1646. and must be freed when no longer needed by passing the returned
  1647. value to LsaFreeMemory().
  1648. Return Value:
  1649. NTSTATUS - Standard Nt Result Code
  1650. STATUS_ACCESS_DENIED - Caller does not have the appropriate
  1651. access to complete the operation.
  1652. STATUS_INTERNAL_DB_CORRUPTION - The Policy Database is possibly
  1653. corrupt. The returned Policy Information is invalid for
  1654. the given class.
  1655. --*/
  1656. {
  1657. NTSTATUS Status;
  1658. PLSAP_DB_ACCOUNT Account = NULL;
  1659. ULONG AccountInformationLength = 0;
  1660. PLSAPR_ACCOUNT_INFO CachedAccountInformation = NULL;
  1661. ULONG PrivilegesCount;
  1662. PLSAPR_PRIVILEGE_SET OutputPrivilegeSet = NULL;
  1663. ASSERTMSG( "Account Cache is not valid!", LsapDbIsCacheValid( AccountObject ) );
  1664. (*AccountInformation) = NULL;
  1665. //
  1666. // Lookup the Account.
  1667. //
  1668. Status = LsapDbLookupAccount(
  1669. LsapDbSidFromHandle( AccountHandle ),
  1670. &Account
  1671. );
  1672. if (!NT_SUCCESS(Status)) {
  1673. goto QueryInformationAccountError;
  1674. }
  1675. //
  1676. // Branch on Information Class.
  1677. //
  1678. switch (InformationClass) {
  1679. case AccountPrivilegeInformation:
  1680. //
  1681. // Calculate size of buffer needed for the output privilege set.
  1682. //
  1683. PrivilegesCount = 0;
  1684. if (Account->Info.PrivilegeSet != NULL) {
  1685. PrivilegesCount = Account->Info.PrivilegeSet->PrivilegeCount;
  1686. }
  1687. AccountInformationLength = sizeof(PRIVILEGE_SET) +
  1688. (PrivilegesCount * sizeof(LUID_AND_ATTRIBUTES)) -
  1689. (sizeof(LUID_AND_ATTRIBUTES));
  1690. CachedAccountInformation = (PLSAPR_ACCOUNT_INFO) Account->Info.PrivilegeSet;
  1691. break;
  1692. case AccountQuotaInformation:
  1693. //
  1694. // Calculate size of buffer needed for the output privilege set.
  1695. //
  1696. AccountInformationLength = sizeof(QUOTA_LIMITS);
  1697. CachedAccountInformation = (PLSAPR_ACCOUNT_INFO) &Account->Info.QuotaLimits;
  1698. break;
  1699. case AccountSystemAccessInformation:
  1700. //
  1701. // Calculate size of buffer needed for the output privilege set.
  1702. //
  1703. AccountInformationLength = sizeof(ULONG);
  1704. CachedAccountInformation = (PLSAPR_ACCOUNT_INFO) &Account->Info.SystemAccess;
  1705. break;
  1706. default:
  1707. Status = STATUS_INVALID_PARAMETER;
  1708. break;
  1709. }
  1710. if (!NT_SUCCESS(Status)) {
  1711. goto QueryInformationAccountError;
  1712. }
  1713. //
  1714. // Allocate output buffer.
  1715. //
  1716. *AccountInformation = MIDL_user_allocate( AccountInformationLength );
  1717. if (*AccountInformation == NULL) {
  1718. Status = STATUS_NO_MEMORY;
  1719. goto QueryInformationAccountError;
  1720. }
  1721. //
  1722. // Copy the data requested if the cached information is non-NULL.
  1723. //
  1724. if (CachedAccountInformation != NULL) {
  1725. RtlCopyMemory(
  1726. *AccountInformation,
  1727. CachedAccountInformation,
  1728. AccountInformationLength
  1729. );
  1730. goto QueryInformationAccountFinish;
  1731. }
  1732. //
  1733. // The cached information is NULL. The only information class for which
  1734. // this can happen is AccountPrivilegeInformation, since this is the
  1735. // only class for which a pointer is kept rather than in-structure data.
  1736. //
  1737. if (InformationClass == AccountPrivilegeInformation) {
  1738. OutputPrivilegeSet = (PLSAPR_PRIVILEGE_SET) *AccountInformation;
  1739. OutputPrivilegeSet->PrivilegeCount = 0;
  1740. OutputPrivilegeSet->Control = 0;
  1741. } else {
  1742. Status = STATUS_INTERNAL_DB_CORRUPTION;
  1743. }
  1744. if (!NT_SUCCESS(Status)) {
  1745. goto QueryInformationAccountError;
  1746. }
  1747. QueryInformationAccountFinish:
  1748. return(Status);
  1749. QueryInformationAccountError:
  1750. if (*AccountInformation) {
  1751. MIDL_user_free(*AccountInformation);
  1752. }
  1753. (*AccountInformation) = NULL;
  1754. goto QueryInformationAccountFinish;
  1755. }
  1756. NTSTATUS
  1757. LsapDbSlowQueryInformationAccount(
  1758. IN LSAPR_HANDLE AccountHandle,
  1759. IN ACCOUNT_INFORMATION_CLASS InformationClass,
  1760. OUT PLSAPR_ACCOUNT_INFO *Buffer
  1761. )
  1762. /*++
  1763. Routine Description:
  1764. This function is the slow LSA server RPC worker routine for the
  1765. (as yet non-existent) LsarQueryInformationAccount API. It is called
  1766. when the in-memory Account List is valid.
  1767. Arguments:
  1768. AccountHandle - Handle from an LsaOpenAccount call.
  1769. InformationClass - Specifies the information to be returned. The
  1770. Information Classes and accesses required are as follows:
  1771. Information Class Required Access Type
  1772. AccountPrivilegeInformation ACCOUNT_VIEW
  1773. AccountQuotaInformation ACCOUNT_VIEW
  1774. AccountSystemAccessInformation ACCOUNT_VIEW
  1775. Buffer - Receives a pointer to the buffer returned comtaining the
  1776. requested information. This buffer is allocated by this service
  1777. and must be freed when no longer needed by passing the returned
  1778. value to LsaFreeMemory().
  1779. Return Value:
  1780. NTSTATUS - Standard Nt Result Code
  1781. STATUS_ACCESS_DENIED - Caller does not have the appropriate
  1782. access to complete the operation.
  1783. STATUS_INTERNAL_DB_CORRUPTION - The Policy Database is possibly
  1784. corrupt. The returned Policy Information is invalid for
  1785. the given class.
  1786. --*/
  1787. {
  1788. NTSTATUS Status;
  1789. QUOTA_LIMITS QuotaLimits;
  1790. ULONG SystemAccess;
  1791. PLSAPR_ACCOUNT_INFO OutputBuffer = NULL;
  1792. //
  1793. // Branch on Information Class.
  1794. //
  1795. switch (InformationClass) {
  1796. case AccountPrivilegeInformation:
  1797. Status = LsapDbSlowQueryPrivilegesAccount(
  1798. AccountHandle,
  1799. (PLSAPR_PRIVILEGE_SET *) &OutputBuffer
  1800. );
  1801. break;
  1802. case AccountQuotaInformation:
  1803. Status = LsapDbSlowQueryQuotasAccount(
  1804. AccountHandle,
  1805. &QuotaLimits
  1806. );
  1807. if (!NT_SUCCESS(Status)) {
  1808. break;
  1809. }
  1810. OutputBuffer = MIDL_user_allocate( sizeof(QUOTA_LIMITS));
  1811. if (OutputBuffer == NULL) {
  1812. Status = STATUS_NO_MEMORY;
  1813. break;
  1814. }
  1815. *((PQUOTA_LIMITS) OutputBuffer) = QuotaLimits;
  1816. break;
  1817. case AccountSystemAccessInformation:
  1818. Status = LsapDbSlowQuerySystemAccessAccount(
  1819. AccountHandle,
  1820. &SystemAccess
  1821. );
  1822. if (!NT_SUCCESS(Status)) {
  1823. break;
  1824. }
  1825. OutputBuffer = MIDL_user_allocate( sizeof(ULONG));
  1826. if (OutputBuffer == NULL) {
  1827. Status = STATUS_NO_MEMORY;
  1828. break;
  1829. }
  1830. *((PULONG) OutputBuffer) = SystemAccess;
  1831. break;
  1832. default:
  1833. Status = STATUS_INVALID_PARAMETER;
  1834. break;
  1835. }
  1836. if (!NT_SUCCESS(Status)) {
  1837. goto SlowQueryInformationAccountError;
  1838. }
  1839. *Buffer = OutputBuffer;
  1840. SlowQueryInformationAccountFinish:
  1841. return(Status);
  1842. SlowQueryInformationAccountError:
  1843. *Buffer = NULL;
  1844. goto SlowQueryInformationAccountFinish;
  1845. }
  1846. NTSTATUS
  1847. LsapDbQueryAllInformationAccounts(
  1848. IN LSAPR_HANDLE PolicyHandle,
  1849. IN ULONG IdCount,
  1850. IN PSID_AND_ATTRIBUTES Ids,
  1851. OUT PLSAP_DB_ACCOUNT_TYPE_SPECIFIC_INFO AccountInfo
  1852. )
  1853. /*++
  1854. Routine Description:
  1855. This routine:
  1856. 1) Gets all privileges assigned to the user (or any group/alias
  1857. the user is a member of).
  1858. 2) Establishes the quotas assigned to the user. This is the
  1859. maximum of the system default quotas or any quotas assigned
  1860. to the user (or any group/alias the user is a member of).
  1861. 3) Gets all the System Accesses assigned to the user.
  1862. Arguments:
  1863. PolicyHandle - Handle from an LsaOpenPolicy call. The handle must
  1864. have POLICY_VIEW_LOCAL_INFORMATION access granted.
  1865. IdCount - Indicates the number of IDs being provided in the Ids array.
  1866. Ids - Points to an array of SIDs.
  1867. AccountInfo - Pointer to buffer that will receive the Account information
  1868. comprising its Privilege Set, System Access Flags and Quotas.
  1869. Return Value:
  1870. STATUS_SUCCESS - Succeeded.
  1871. STATUS_LOGON_TYPE_NOT_GRANTED - Indicates the specified type of logon
  1872. has not been granted to any of the IDs in the passed set.
  1873. --*/
  1874. {
  1875. NTSTATUS Status;
  1876. BOOLEAN ObjectReferenced = FALSE;
  1877. PPRIVILEGE_SET RunningPrivileges = NULL;
  1878. ULONG MaxRunningPrivileges = 0;
  1879. PPRIVILEGE_SET NextPrivileges = NULL;
  1880. ULONG RunningSystemAccess;
  1881. QUOTA_LIMITS NextQuotaLimits;
  1882. QUOTA_LIMITS RunningQuotaLimits;
  1883. PQUOTA_LIMITS PolicyDefaultQuotaLimits = NULL;
  1884. PPOLICY_DEFAULT_QUOTA_INFO PolicyDefaultQuotaInfo = NULL;
  1885. ULONG SidIndex;
  1886. PLSAP_DB_ACCOUNT Account = NULL;
  1887. //
  1888. // If we are unable to use the Account List, use the slow method
  1889. // for querying Privileges and Quotas
  1890. //
  1891. if (!LsapDbIsCacheValid(AccountObject)) {
  1892. return(LsapDbSlowQueryAllInformationAccounts(
  1893. PolicyHandle,
  1894. IdCount,
  1895. Ids,
  1896. AccountInfo
  1897. ));
  1898. }
  1899. //
  1900. // The Account List is valid. We'll use it instead of opening individual
  1901. // Account objects. Verify that the Policy Handle is valid, is the handle
  1902. // object and has the necessary access granted. Reference the handle.
  1903. //
  1904. Status = LsapDbReferenceObject(
  1905. PolicyHandle,
  1906. POLICY_VIEW_LOCAL_INFORMATION,
  1907. PolicyObject,
  1908. AccountObject,
  1909. LSAP_DB_LOCK | LSAP_DB_NO_DS_OP_TRANSACTION
  1910. );
  1911. if (!NT_SUCCESS(Status)) {
  1912. goto QueryAllInformationAccountsError;
  1913. }
  1914. ObjectReferenced = TRUE;
  1915. //
  1916. // Obtain the Master Default Quota Limits from the Policy Object. If
  1917. // the Policy Object is cached (partially for now) instruct the query
  1918. // routine to just copy the data.
  1919. PolicyDefaultQuotaLimits = &RunningQuotaLimits;
  1920. Status = LsapDbQueryInformationPolicy(
  1921. PolicyHandle,
  1922. PolicyDefaultQuotaInformation,
  1923. (PLSAPR_POLICY_INFORMATION *) &PolicyDefaultQuotaLimits
  1924. );
  1925. if (!NT_SUCCESS(Status)) {
  1926. goto QueryAllInformationAccountsError;
  1927. }
  1928. //
  1929. // Iterate through all of the Sids provided. For each one, check if the
  1930. // Sid is that of an Account object in the local LSA. If it is,
  1931. //
  1932. // (1) Obtain the System Accesses and add those found so far.
  1933. // (2) Obtain the Account Privileges and add to those found so far.
  1934. // (3) Obtain the Quota Limits (if any) assigned to the account.
  1935. // Compare these with the quota limits obtained so far. If any
  1936. // limits are more generous than the running values, update
  1937. // the running values.
  1938. //
  1939. RunningSystemAccess = 0;
  1940. for( SidIndex = 0; SidIndex < IdCount; SidIndex++) {
  1941. //
  1942. // Locate the Account information block for this Sid.
  1943. //
  1944. Status = LsapDbLookupAccount( Ids[SidIndex].Sid, &Account );
  1945. if (!NT_SUCCESS(Status)) {
  1946. if (Status == STATUS_NO_SUCH_USER) {
  1947. Status = STATUS_SUCCESS;
  1948. continue;
  1949. }
  1950. break;
  1951. }
  1952. //
  1953. // We have found the Account information. Add in the System Accesses
  1954. // for this account.
  1955. //
  1956. RunningSystemAccess |= Account->Info.SystemAccess;
  1957. //
  1958. // Obtain the account's Special privileges.
  1959. //
  1960. NextPrivileges = Account->Info.PrivilegeSet;
  1961. //
  1962. // Add the Privileges of this account (if any) to the running set.
  1963. //
  1964. if (NextPrivileges != NULL) {
  1965. Status = LsapRtlAddPrivileges(
  1966. &RunningPrivileges,
  1967. &MaxRunningPrivileges,
  1968. NextPrivileges,
  1969. RTL_COMBINE_PRIVILEGE_ATTRIBUTES,
  1970. NULL // don't care if the set has changed or not
  1971. );
  1972. if (!NT_SUCCESS(Status)) {
  1973. goto QueryAllInformationAccountsError;
  1974. }
  1975. }
  1976. //
  1977. // Obtain the special Quota Limits for this account (if any).
  1978. //
  1979. RtlMoveMemory(&NextQuotaLimits, &Account->Info.QuotaLimits, sizeof(QUOTA_LIMITS));
  1980. //
  1981. // Special Quota Limits are assigned. Compare each of the quota
  1982. // limits obtained with the running values. If a quota limit just
  1983. // obtained is less restrictive than the running value, supersede the
  1984. // running value.
  1985. //
  1986. if (RunningQuotaLimits.PagedPoolLimit < NextQuotaLimits.PagedPoolLimit) {
  1987. RunningQuotaLimits.PagedPoolLimit = NextQuotaLimits.PagedPoolLimit;
  1988. }
  1989. if (RunningQuotaLimits.NonPagedPoolLimit < NextQuotaLimits.NonPagedPoolLimit) {
  1990. RunningQuotaLimits.NonPagedPoolLimit = NextQuotaLimits.NonPagedPoolLimit;
  1991. }
  1992. if (RunningQuotaLimits.MinimumWorkingSetSize > NextQuotaLimits.MinimumWorkingSetSize) {
  1993. RunningQuotaLimits.MinimumWorkingSetSize = NextQuotaLimits.MinimumWorkingSetSize;
  1994. }
  1995. if (RunningQuotaLimits.MaximumWorkingSetSize < NextQuotaLimits.MaximumWorkingSetSize) {
  1996. RunningQuotaLimits.MaximumWorkingSetSize = NextQuotaLimits.MaximumWorkingSetSize;
  1997. }
  1998. if (RunningQuotaLimits.PagefileLimit < NextQuotaLimits.PagefileLimit) {
  1999. RunningQuotaLimits.PagefileLimit = NextQuotaLimits.PagefileLimit;
  2000. }
  2001. if (RunningQuotaLimits.TimeLimit.QuadPart < NextQuotaLimits.TimeLimit.QuadPart) {
  2002. RunningQuotaLimits.TimeLimit = NextQuotaLimits.TimeLimit;
  2003. }
  2004. }
  2005. if (!NT_SUCCESS(Status)) {
  2006. goto QueryAllInformationAccountsError;
  2007. }
  2008. //
  2009. // Return the collective Privilege Set
  2010. //
  2011. AccountInfo->PrivilegeSet = RunningPrivileges;
  2012. //
  2013. // Return the collective System Accesses
  2014. AccountInfo->SystemAccess = RunningSystemAccess;
  2015. //
  2016. // Return the collective Quota Limits
  2017. //
  2018. AccountInfo->QuotaLimits = RunningQuotaLimits;
  2019. QueryAllInformationAccountsFinish:
  2020. //
  2021. // If necessary, dereference the Policy Object.
  2022. //
  2023. if (ObjectReferenced) {
  2024. LsapDbDereferenceObject(
  2025. &PolicyHandle,
  2026. PolicyObject,
  2027. AccountObject,
  2028. LSAP_DB_LOCK | LSAP_DB_NO_DS_OP_TRANSACTION,
  2029. (SECURITY_DB_DELTA_TYPE) 0,
  2030. Status
  2031. );
  2032. }
  2033. return(Status);
  2034. QueryAllInformationAccountsError:
  2035. //
  2036. // If necessary, free the memory allocated for the Privilege Set.
  2037. //
  2038. if (RunningPrivileges != NULL) {
  2039. MIDL_user_free( RunningPrivileges );
  2040. RunningPrivileges = NULL;
  2041. }
  2042. //
  2043. // Return null values
  2044. //
  2045. RtlZeroMemory( &AccountInfo->QuotaLimits, sizeof(QUOTA_LIMITS) );
  2046. AccountInfo->SystemAccess = 0;
  2047. AccountInfo->PrivilegeSet = NULL;
  2048. goto QueryAllInformationAccountsFinish;
  2049. }
  2050. NTSTATUS
  2051. LsapDbSlowQueryAllInformationAccounts(
  2052. IN LSAPR_HANDLE PolicyHandle,
  2053. IN ULONG IdCount,
  2054. IN PSID_AND_ATTRIBUTES Ids,
  2055. OUT PLSAP_DB_ACCOUNT_TYPE_SPECIFIC_INFO AccountInfo
  2056. )
  2057. /*++
  2058. Routine Description:
  2059. This routine is the slow version of LsapDbQueryInformation().
  2060. It is called when the Account List is not available, and assembles the
  2061. necessary information from the Policy Database.
  2062. This routine:
  2063. 1) Gets all privileges assigned to the user (or any group/alias
  2064. the user is a member of).
  2065. 2) Establishes the quotas assigned to the user. This is the
  2066. maximum of the system default quotas or any quotas assigned
  2067. to the user (or any group/alias the user is a member of).
  2068. 3) Gets all the System Accesses assigned to the user.
  2069. Arguments:
  2070. PolicyHandle - Handle from an LsaOpenPolicy call. The handle must
  2071. have POLICY_VIEW_LOCAL_INFORMATION access granted.
  2072. IdCount - Indicates the number of IDs being provided in the Ids array.
  2073. Ids - Points to an array of SIDs.
  2074. AccountInfo - Pointer to buffer that will receive the Account information
  2075. comprising its Privilege Set, System Access Flags and Quotas.
  2076. Return Value:
  2077. STATUS_SUCCESS - Succeeded.
  2078. STATUS_LOGON_TYPE_NOT_GRANTED - Indicates the specified type of logon
  2079. has not been granted to any of the IDs in the passed set.
  2080. --*/
  2081. {
  2082. NTSTATUS Status = STATUS_SUCCESS;
  2083. NTSTATUS LocalStatus;
  2084. BOOLEAN ObjectReferenced = FALSE;
  2085. PPRIVILEGE_SET RunningPrivileges = NULL;
  2086. ULONG MaxRunningPrivileges = 0;
  2087. PPRIVILEGE_SET NextPrivileges = NULL;
  2088. ULONG RunningSystemAccess;
  2089. QUOTA_LIMITS NextQuotaLimits;
  2090. QUOTA_LIMITS RunningQuotaLimits;
  2091. PQUOTA_LIMITS PointerToNextQuotaLimits = NULL;
  2092. PQUOTA_LIMITS PolicyDefaultQuotaLimits = NULL;
  2093. ULONG SidIndex;
  2094. LSAPR_HANDLE AccountHandle = NULL;
  2095. PULONG SystemAccessThisId = NULL;
  2096. //
  2097. // Verify that the Policy Handle is valid, is the handle to the Policy
  2098. // object and has the necessary access granted. Reference the handle.
  2099. // Note that the Lsa Database lock is NOT held at this point. Instead,
  2100. // the lock is taken and released by called routines where required.
  2101. //
  2102. Status = LsapDbReferenceObject(
  2103. PolicyHandle,
  2104. POLICY_VIEW_LOCAL_INFORMATION,
  2105. PolicyObject,
  2106. AccountObject,
  2107. LSAP_DB_LOCK | LSAP_DB_START_TRANSACTION |
  2108. LSAP_DB_NO_DS_OP_TRANSACTION | LSAP_DB_READ_ONLY_TRANSACTION
  2109. );
  2110. if (!NT_SUCCESS(Status)) {
  2111. goto SlowQueryAllInformationAccountsError;
  2112. }
  2113. ObjectReferenced = TRUE;
  2114. PolicyDefaultQuotaLimits = &RunningQuotaLimits;
  2115. //
  2116. // Obtain the Master Default Quota Limits from the Policy Object.
  2117. //
  2118. Status = LsapDbQueryInformationPolicy(
  2119. LsapPolicyHandle,
  2120. PolicyDefaultQuotaInformation,
  2121. (PLSAPR_POLICY_INFORMATION *) &PolicyDefaultQuotaLimits
  2122. );
  2123. if (!NT_SUCCESS(Status)) {
  2124. goto SlowQueryAllInformationAccountsError;
  2125. }
  2126. //
  2127. // Iterate through all of the Sids provided. For each one, check if the
  2128. // Sid is that of an Account object in the local LSA. If it is,
  2129. //
  2130. // (1) Obtain the System Accesses and add those found so far.
  2131. // (2) Obtain the Account Privileges and add to thosde found so far.
  2132. // (3) Obtain the Quota Limits (if any) assigned to the account.
  2133. // Compare these with the quota limits obtained so far. If any
  2134. // limits are more generous than the running values, update
  2135. // the running values.
  2136. //
  2137. RunningSystemAccess = 0;
  2138. for( SidIndex = 0; SidIndex < IdCount; SidIndex++) {
  2139. //
  2140. // Attempt to open an Lsa Account object specifying the next Sid.
  2141. // If successful, the open returns a Trusted handle to the account.
  2142. //
  2143. Status = LsarOpenAccount(
  2144. PolicyHandle,
  2145. Ids[SidIndex].Sid,
  2146. ACCOUNT_VIEW,
  2147. (LSAPR_HANDLE *) &AccountHandle
  2148. );
  2149. if (!NT_SUCCESS(Status)) {
  2150. if (Status != STATUS_OBJECT_NAME_NOT_FOUND) {
  2151. break;
  2152. }
  2153. Status = STATUS_SUCCESS;
  2154. continue;
  2155. }
  2156. //
  2157. // An account object has been successfully opened. Obtain
  2158. // its system accesses.
  2159. //
  2160. Status = LsapDbSlowQueryInformationAccount(
  2161. AccountHandle,
  2162. AccountSystemAccessInformation,
  2163. (PLSAPR_ACCOUNT_INFO *) &SystemAccessThisId
  2164. );
  2165. if (!NT_SUCCESS(Status)) {
  2166. goto SlowQueryAllInformationAccountsError;
  2167. }
  2168. RunningSystemAccess |= *SystemAccessThisId;
  2169. MIDL_user_free(SystemAccessThisId);
  2170. SystemAccessThisId = NULL;
  2171. //
  2172. // Obtain the account's Special privileges.
  2173. //
  2174. ASSERT( NextPrivileges == NULL );
  2175. Status = LsapDbSlowQueryInformationAccount(
  2176. AccountHandle,
  2177. AccountPrivilegeInformation,
  2178. (PLSAPR_ACCOUNT_INFO *) &NextPrivileges
  2179. );
  2180. if (!NT_SUCCESS(Status)) {
  2181. goto SlowQueryAllInformationAccountsError;
  2182. }
  2183. //
  2184. // Add the Privileges of this account (if any) to the running set.
  2185. //
  2186. if (NextPrivileges != NULL) {
  2187. Status = LsapRtlAddPrivileges(
  2188. &RunningPrivileges,
  2189. &MaxRunningPrivileges,
  2190. NextPrivileges,
  2191. RTL_COMBINE_PRIVILEGE_ATTRIBUTES,
  2192. NULL // don't care if the set has changed or not
  2193. );
  2194. MIDL_user_free(NextPrivileges);
  2195. NextPrivileges = NULL;
  2196. if (!NT_SUCCESS(Status)) {
  2197. goto SlowQueryAllInformationAccountsError;
  2198. }
  2199. }
  2200. //
  2201. // Obtain the special Quota Limits for this account (if any).
  2202. //
  2203. Status = LsapDbSlowQueryInformationAccount(
  2204. AccountHandle,
  2205. AccountQuotaInformation,
  2206. (PLSAPR_ACCOUNT_INFO *) &PointerToNextQuotaLimits
  2207. );
  2208. if (Status == STATUS_NO_QUOTAS_FOR_ACCOUNT) {
  2209. LocalStatus = LsapCloseHandle( &AccountHandle, STATUS_SUCCESS );
  2210. continue;
  2211. }
  2212. if (!NT_SUCCESS(Status)) {
  2213. goto SlowQueryAllInformationAccountsError;
  2214. }
  2215. NextQuotaLimits = *PointerToNextQuotaLimits;
  2216. MIDL_user_free(PointerToNextQuotaLimits);
  2217. PointerToNextQuotaLimits = NULL;
  2218. //
  2219. // Special Quota Limits are assigned. Compare each of the quota
  2220. // limits obtained with the running values. If a quota limit just
  2221. // obtained is less restrictive than the running value, supersede the
  2222. // running value.
  2223. //
  2224. if (RunningQuotaLimits.PagedPoolLimit < NextQuotaLimits.PagedPoolLimit) {
  2225. RunningQuotaLimits.PagedPoolLimit = NextQuotaLimits.PagedPoolLimit;
  2226. }
  2227. if (RunningQuotaLimits.NonPagedPoolLimit < NextQuotaLimits.NonPagedPoolLimit) {
  2228. RunningQuotaLimits.NonPagedPoolLimit = NextQuotaLimits.NonPagedPoolLimit;
  2229. }
  2230. if (RunningQuotaLimits.MinimumWorkingSetSize > NextQuotaLimits.MinimumWorkingSetSize) {
  2231. RunningQuotaLimits.MinimumWorkingSetSize = NextQuotaLimits.MinimumWorkingSetSize;
  2232. }
  2233. if (RunningQuotaLimits.MaximumWorkingSetSize < NextQuotaLimits.MaximumWorkingSetSize) {
  2234. RunningQuotaLimits.MaximumWorkingSetSize = NextQuotaLimits.MaximumWorkingSetSize;
  2235. }
  2236. if (RunningQuotaLimits.PagefileLimit < NextQuotaLimits.PagefileLimit) {
  2237. RunningQuotaLimits.PagefileLimit = NextQuotaLimits.PagefileLimit;
  2238. }
  2239. if (RunningQuotaLimits.TimeLimit.QuadPart < NextQuotaLimits.TimeLimit.QuadPart) {
  2240. RunningQuotaLimits.TimeLimit = NextQuotaLimits.TimeLimit;
  2241. }
  2242. //
  2243. // Close the account handle
  2244. //
  2245. LocalStatus = LsapCloseHandle( &AccountHandle, STATUS_SUCCESS );
  2246. }
  2247. if (!NT_SUCCESS(Status)) {
  2248. goto SlowQueryAllInformationAccountsError;
  2249. }
  2250. //
  2251. // Return the collective Privilege Set
  2252. //
  2253. AccountInfo->PrivilegeSet = RunningPrivileges;
  2254. //
  2255. // Return the collective System Accesses
  2256. AccountInfo->SystemAccess = RunningSystemAccess;
  2257. //
  2258. // Return the collective Quota Limits
  2259. //
  2260. AccountInfo->QuotaLimits = RunningQuotaLimits;
  2261. SlowQueryAllInformationAccountsFinish:
  2262. if ( NextPrivileges != NULL ) {
  2263. MIDL_user_free( NextPrivileges );
  2264. }
  2265. //
  2266. // If necessary, dereference the Policy Object.
  2267. //
  2268. if (ObjectReferenced) {
  2269. LsapDbDereferenceObject(
  2270. &PolicyHandle,
  2271. PolicyObject,
  2272. AccountObject,
  2273. LSAP_DB_LOCK | LSAP_DB_FINISH_TRANSACTION |
  2274. LSAP_DB_NO_DS_OP_TRANSACTION | LSAP_DB_READ_ONLY_TRANSACTION,
  2275. (SECURITY_DB_DELTA_TYPE) 0,
  2276. Status
  2277. );
  2278. }
  2279. return(Status);
  2280. SlowQueryAllInformationAccountsError:
  2281. //
  2282. // If necessary, free the memory allocated for the Privilege Set.
  2283. //
  2284. if (RunningPrivileges != NULL) {
  2285. MIDL_user_free( RunningPrivileges );
  2286. RunningPrivileges = NULL;
  2287. }
  2288. //
  2289. // Close an account handle, if one is open
  2290. //
  2291. if (AccountHandle != NULL) {
  2292. LocalStatus = LsapCloseHandle( &AccountHandle, Status );
  2293. }
  2294. //
  2295. // Return null values
  2296. //
  2297. RtlZeroMemory( &AccountInfo->QuotaLimits, sizeof(QUOTA_LIMITS) );
  2298. AccountInfo->SystemAccess = 0;
  2299. AccountInfo->PrivilegeSet = NULL;
  2300. goto SlowQueryAllInformationAccountsFinish;
  2301. }
  2302. NTSTATUS
  2303. LsapDbSlowQueryPrivilegesAccount(
  2304. IN LSAPR_HANDLE AccountHandle,
  2305. OUT PLSAPR_PRIVILEGE_SET *Privileges
  2306. )
  2307. /*++
  2308. Routine Description:
  2309. This function is the slow LSA server RPC worker routine for the
  2310. LsaEnumeratePrivilegesOfAccount API.
  2311. The LsaEnumeratePrivilegesOfAccount API obtains information which
  2312. describes the privileges assigned to an account. This call requires
  2313. ACCOUNT_VIEW access to the account object.
  2314. Arguments:
  2315. AccountHandle - The handle to the open account object whose privilege
  2316. information is to be obtained. This handle will have been returned
  2317. from a prior LsaOpenAccount or LsaCreateAccountInLsa API call.
  2318. Privileges - Receives a pointer to a buffer containing the Privilege
  2319. Set. The Privilege Set is an array of structures, one for each
  2320. privilege. Each structure contains the LUID of the privilege and
  2321. a mask of the privilege's attributes.
  2322. Return Values:
  2323. NTSTATUS - Standard Nt Result Code
  2324. STATUS_SUCCESS - The call completed successfully.
  2325. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  2326. to complete the operation.
  2327. STATUS_INVALID_HANDLE - The specified AccountHandle is not valid.
  2328. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources,
  2329. such as memory, to complete the call.
  2330. --*/
  2331. {
  2332. NTSTATUS Status;
  2333. PPRIVILEGE_SET PrivilegeSet = NULL;
  2334. ULONG PrivilegeSetLength;
  2335. BOOLEAN ObjectReferenced = FALSE;
  2336. LSAP_DB_ATTRIBUTE Attribute;
  2337. PPRIVILEGE_SET DsPrivs;
  2338. UCHAR FastBuffer[ 256 ];
  2339. //
  2340. // Attempt query of attribute using fast stack buffer.
  2341. //
  2342. PrivilegeSetLength = sizeof(FastBuffer);
  2343. Status = LsapDbReadAttributeObject(
  2344. AccountHandle,
  2345. &LsapDbNames[Privilgs],
  2346. FastBuffer,
  2347. &PrivilegeSetLength
  2348. );
  2349. if(NT_SUCCESS(Status)) {
  2350. if( PrivilegeSetLength <= (sizeof(PRIVILEGE_SET) - sizeof (LUID_AND_ATTRIBUTES)) )
  2351. {
  2352. //
  2353. // The privilege set attribute exists but has zero entries.
  2354. // fall-through and handle it same way as non-existent entry.
  2355. //
  2356. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  2357. } else {
  2358. //
  2359. // Success! copy the fast buffer for the caller.
  2360. //
  2361. PrivilegeSet = MIDL_user_allocate ( PrivilegeSetLength );
  2362. if (PrivilegeSet == NULL) {
  2363. Status = STATUS_INSUFFICIENT_RESOURCES;
  2364. goto SlowQueryPrivilegesError;
  2365. }
  2366. RtlCopyMemory( PrivilegeSet, FastBuffer, PrivilegeSetLength );
  2367. *Privileges = (PLSAPR_PRIVILEGE_SET) PrivilegeSet;
  2368. goto SlowQueryPrivilegesFinish;
  2369. }
  2370. }
  2371. if ((Status == STATUS_OBJECT_NAME_NOT_FOUND)) {
  2372. //
  2373. // If the Privileg attribute does not exist, convert the status
  2374. // back to STATUS_SUCCESS. Note that an account object need not
  2375. // have any privileges assigned so STATUS_OBJECT_NAME_NOT_FOUND is
  2376. // not an error in this case. Return a Privilege Set containing
  2377. // a zero Count.
  2378. //
  2379. PrivilegeSetLength = sizeof(PRIVILEGE_SET) - sizeof(LUID_AND_ATTRIBUTES);
  2380. PrivilegeSet = MIDL_user_allocate ( PrivilegeSetLength );
  2381. if (PrivilegeSet == NULL) {
  2382. Status = STATUS_INSUFFICIENT_RESOURCES;
  2383. goto SlowQueryPrivilegesError;
  2384. }
  2385. Status = STATUS_SUCCESS;
  2386. PrivilegeSet->Control = (ULONG) 0L;
  2387. PrivilegeSet->PrivilegeCount = (ULONG) 0L;
  2388. *Privileges = (PLSAPR_PRIVILEGE_SET) PrivilegeSet;
  2389. goto SlowQueryPrivilegesFinish;
  2390. }
  2391. //
  2392. // The Privileg attribute exists and has a value assigned. Allocate
  2393. // a buffer for its value.
  2394. //
  2395. PrivilegeSet = MIDL_user_allocate ( PrivilegeSetLength );
  2396. if (PrivilegeSet == NULL) {
  2397. Status = STATUS_INSUFFICIENT_RESOURCES;
  2398. goto SlowQueryPrivilegesError;
  2399. }
  2400. //
  2401. // Read the Privilgs attribute into the buffer. Note that although
  2402. // the value of this attribute has a variable length, it is bounded
  2403. // above.
  2404. //
  2405. Status = LsapDbReadAttributeObject(
  2406. AccountHandle,
  2407. &LsapDbNames[Privilgs],
  2408. PrivilegeSet,
  2409. &PrivilegeSetLength
  2410. );
  2411. if (!NT_SUCCESS(Status)) {
  2412. MIDL_user_free(PrivilegeSet);
  2413. goto SlowQueryPrivilegesError;
  2414. }
  2415. //
  2416. // Return the Privilege Set or NULL
  2417. //
  2418. *Privileges = (PLSAPR_PRIVILEGE_SET) PrivilegeSet;
  2419. SlowQueryPrivilegesFinish:
  2420. return( Status );
  2421. SlowQueryPrivilegesError:
  2422. *Privileges = NULL;
  2423. goto SlowQueryPrivilegesFinish;
  2424. }
  2425. NTSTATUS
  2426. LsapDbSlowQueryQuotasAccount(
  2427. IN LSAPR_HANDLE AccountHandle,
  2428. OUT PQUOTA_LIMITS QuotaLimits
  2429. )
  2430. /*++
  2431. Routine Description:
  2432. This function is the slow LSA server RPC worker routine for the
  2433. LsarGetQuotasForAccount API.
  2434. The LsaGetQuotasForAccount API obtains the quota limits for pageable and
  2435. non-pageable memory (in Kilobytes) and the maximum execution time (in
  2436. seconds) for any session logged on to the account specified by
  2437. AccountHandle. For each quota and explicit value is returned.
  2438. Quotas is not supported any more. In the past, we need LSA_ACCOUNT_VIEW
  2439. access to the object, but currently, there is no such access right &
  2440. you don't need any right to call this function. We will return QuotaLimits
  2441. as 0 and return STATUS_NO_QUOTAS_FOR_ACCOUNT.
  2442. Arguments:
  2443. AccountHandle - The handle to the open account object whose quotas
  2444. are to be obtained. This handle will have been returned
  2445. from a prior LsaOpenAccount or LsaCreateAccountInLsa API call.
  2446. QuotaLimits - Pointer to structure in which the system resource
  2447. quota limits applicable to each session logged on to this account
  2448. will be returned. Note that all quotas, including those specified
  2449. as being the system default values, are returned as actual values.
  2450. Return Values:
  2451. NTSTATUS - Standard Nt Result Code
  2452. STATUS_INVALID_HANDLE - The specified AccountHandle is not valid.
  2453. --*/
  2454. {
  2455. //
  2456. // Quotas are defunct.
  2457. //
  2458. QuotaLimits->PagedPoolLimit = 0;
  2459. QuotaLimits->NonPagedPoolLimit = 0;
  2460. QuotaLimits->MinimumWorkingSetSize = 0;
  2461. QuotaLimits->MaximumWorkingSetSize = 0;
  2462. return( STATUS_NO_QUOTAS_FOR_ACCOUNT );
  2463. }
  2464. NTSTATUS
  2465. LsapDbSlowQuerySystemAccessAccount(
  2466. IN LSAPR_HANDLE AccountHandle,
  2467. OUT PULONG SystemAccess
  2468. )
  2469. /*++
  2470. Routine Description:
  2471. This function is the Slow worker for the LsaGetSystemAccessAccount()
  2472. API.
  2473. Arguments:
  2474. AccountHandle - The handle to the Account object whose system access
  2475. flags are to be read. This handle will have been returned
  2476. from a preceding LsaOpenAccount() or LsaCreateAccount() call
  2477. an must be open for ACCOUNT_VIEW access.
  2478. SystemAccess - Points to location that will receive the system access
  2479. flags for the account.
  2480. Return Values:
  2481. NTSTATUS - Standard Nt Result Code
  2482. STATUS_SUCCESS - The call was successful.
  2483. STATUS_ACCESS_DENIED - The AccountHandle does not specify
  2484. ACCOUNT_VIEW access.
  2485. STATUS_INVALID_HANDLE - The specified AccountHandle is invalid.
  2486. --*/
  2487. {
  2488. NTSTATUS Status;
  2489. ULONG ReturnedSystemAccess;
  2490. ULONG ReturnedSystemAccessLength;
  2491. //
  2492. // Read the Account Object's System Access Flags
  2493. //
  2494. ReturnedSystemAccessLength = sizeof(ULONG);
  2495. Status = LsapDbReadAttributeObject(
  2496. AccountHandle,
  2497. &LsapDbNames[ActSysAc],
  2498. &ReturnedSystemAccess,
  2499. &ReturnedSystemAccessLength
  2500. );
  2501. if (!NT_SUCCESS(Status)) {
  2502. //
  2503. // If there is no System Access attribute, return the system default
  2504. // access.
  2505. //
  2506. // NOTE: The Master Default for the System Access attribute is
  2507. // currently hardwired.
  2508. //
  2509. if (Status != STATUS_OBJECT_NAME_NOT_FOUND) {
  2510. goto SlowQuerySystemAccessAccountError;
  2511. }
  2512. ReturnedSystemAccess = LSAP_DB_ACCOUNT_DEFAULT_SYS_ACCESS;
  2513. Status = STATUS_SUCCESS;
  2514. } else {
  2515. //
  2516. // Verify that the returned flags are valid
  2517. //
  2518. if (ReturnedSystemAccess != (ReturnedSystemAccess & POLICY_MODE_ALL)) {
  2519. if ( ReturnedSystemAccess == 0 && LsapDsWriteDs ) {
  2520. ReturnedSystemAccess = LSAP_DB_ACCOUNT_DEFAULT_SYS_ACCESS;
  2521. Status = STATUS_SUCCESS;
  2522. } else {
  2523. Status = STATUS_INTERNAL_DB_CORRUPTION;
  2524. goto SlowQuerySystemAccessAccountError;
  2525. }
  2526. }
  2527. }
  2528. *SystemAccess = ReturnedSystemAccess;
  2529. SlowQuerySystemAccessAccountFinish:
  2530. return(Status);
  2531. SlowQuerySystemAccessAccountError:
  2532. *SystemAccess = 0;
  2533. goto SlowQuerySystemAccessAccountFinish;
  2534. }
  2535. NTSTATUS
  2536. LsapDbLookupAccount(
  2537. IN PSID AccountSid,
  2538. OUT PLSAP_DB_ACCOUNT *Account
  2539. )
  2540. /*++
  2541. Routine Description:
  2542. This function looks up the Account information for a given Lsa Account.
  2543. Arguments:
  2544. AccountSid - Sid of the account
  2545. Account - Receives a pointer to the Account information.
  2546. --*/
  2547. {
  2548. PLSAP_DB_ACCOUNT NextAccount = NULL;
  2549. ULONG AccountIndex;
  2550. BOOLEAN AccountFound = FALSE;
  2551. ASSERTMSG( "Account Cache is not valid!", LsapDbIsCacheValid( AccountObject ) );
  2552. //
  2553. // Scan the list of Accounts.
  2554. //
  2555. for (AccountIndex = 0, NextAccount = LsapDbFirstAccount();
  2556. AccountIndex < LsapDbAccountList.AccountCount;
  2557. AccountIndex++, NextAccount = LsapDbNextAccount( NextAccount)
  2558. ) {
  2559. //
  2560. // If the Sids match, we've found the account.
  2561. //
  2562. if (RtlEqualSid( AccountSid, NextAccount->Sid )) {
  2563. *Account = NextAccount;
  2564. AccountFound = TRUE;
  2565. break;
  2566. }
  2567. }
  2568. if (AccountFound) {
  2569. return(STATUS_SUCCESS);
  2570. }
  2571. return(STATUS_NO_SUCH_USER);
  2572. }
  2573. NTSTATUS
  2574. LsapDbCreateAccount(
  2575. IN PLSAPR_SID AccountSid,
  2576. OUT OPTIONAL PLSAP_DB_ACCOUNT *Account
  2577. )
  2578. /*++
  2579. Routine Description:
  2580. This function creates an Account's information block
  2581. Arguments:
  2582. AccountSid - Specifies the Sid of the Account
  2583. Account - Optionally receives a pointer to the newly created Account
  2584. information block.
  2585. --*/
  2586. {
  2587. NTSTATUS Status;
  2588. PLSAPR_SID CopiedSid = NULL;
  2589. PLSAP_DB_ACCOUNT OutputAccount = NULL;
  2590. //
  2591. // Verify that the Account List is valid.
  2592. //
  2593. if ((!LsapDbIsCacheValid(AccountObject)) && LsapInitialized ) {
  2594. Status = STATUS_INVALID_PARAMETER;
  2595. goto CreateAccountError;
  2596. }
  2597. //
  2598. // Make a copy of the Sid.
  2599. //
  2600. Status = LsapRpcCopySid(
  2601. NULL,
  2602. (PSID *) &CopiedSid,
  2603. (PSID) AccountSid
  2604. );
  2605. if (!NT_SUCCESS(Status)) {
  2606. goto CreateAccountError;
  2607. }
  2608. //
  2609. // Allocate memory for the Account information block.
  2610. //
  2611. OutputAccount = MIDL_user_allocate( sizeof(LSAP_DB_ACCOUNT) );
  2612. if (OutputAccount == NULL) {
  2613. Status = STATUS_NO_MEMORY;
  2614. goto CreateAccountError;
  2615. }
  2616. //
  2617. // Zeroise the new block.
  2618. //
  2619. RtlZeroMemory( OutputAccount, sizeof(LSAP_DB_ACCOUNT) );
  2620. //
  2621. // Copy in the Sid.
  2622. //
  2623. OutputAccount->Sid = CopiedSid;
  2624. //
  2625. // Link the Account to the head of the Account List.
  2626. //
  2627. InsertHeadList( &LsapDbAccountList.Links, &OutputAccount->Links );
  2628. //
  2629. // If requested, return a pointer to the Account.
  2630. //
  2631. if (Account != NULL) {
  2632. *Account = OutputAccount;
  2633. }
  2634. LsapDbAccountList.AccountCount++;
  2635. Status = STATUS_SUCCESS;
  2636. CreateAccountFinish:
  2637. return(Status);
  2638. CreateAccountError:
  2639. //
  2640. // If necessary, free the copied Sid.
  2641. //
  2642. if (CopiedSid != NULL) {
  2643. MIDL_user_free( CopiedSid );
  2644. CopiedSid = NULL;
  2645. }
  2646. //
  2647. // If necessary, free the memory allocated for the Account block.
  2648. //
  2649. if (OutputAccount != NULL) {
  2650. MIDL_user_free( OutputAccount);
  2651. OutputAccount = NULL;
  2652. }
  2653. //
  2654. // If a return pointer was specified, return NULL.
  2655. //
  2656. if (Account != NULL) {
  2657. *Account = NULL;
  2658. }
  2659. goto CreateAccountFinish;
  2660. }
  2661. NTSTATUS
  2662. LsapDbDeleteAccount(
  2663. IN PLSAPR_SID AccountSid
  2664. )
  2665. /*++
  2666. Routine Description:
  2667. This function deletes an Account's information block
  2668. Arguments:
  2669. AccountSid - Specifies the Sid of the Account
  2670. --*/
  2671. {
  2672. NTSTATUS Status;
  2673. PLSAP_DB_ACCOUNT Account = NULL;
  2674. //
  2675. // Verify that the Account List is valid.
  2676. //
  2677. if (!LsapDbIsCacheValid(AccountObject)) {
  2678. Status = STATUS_INVALID_PARAMETER;
  2679. goto DeleteAccountError;
  2680. }
  2681. //
  2682. // Lookup the Account Information Block to be deleted
  2683. //
  2684. Status = LsapDbLookupAccount( AccountSid, &Account);
  2685. if (!NT_SUCCESS(Status)) {
  2686. goto DeleteAccountError;
  2687. }
  2688. //
  2689. // We found the account. Unlink it from the Account List
  2690. //
  2691. RemoveEntryList( &Account->Links );
  2692. //
  2693. // Now free the Account Information
  2694. //
  2695. if (Account->Sid != NULL) {
  2696. MIDL_user_free( Account->Sid);
  2697. Account->Sid = NULL;
  2698. }
  2699. if (Account->Info.PrivilegeSet != NULL) {
  2700. MIDL_user_free( Account->Info.PrivilegeSet );
  2701. Account->Info.PrivilegeSet = NULL;
  2702. }
  2703. MIDL_user_free( Account );
  2704. LsapDbAccountList.AccountCount--;
  2705. DeleteAccountFinish:
  2706. return(Status);
  2707. DeleteAccountError:
  2708. goto DeleteAccountFinish;
  2709. }
  2710. NTSTATUS
  2711. LsapDbUpdateSystemAccessAccount(
  2712. IN PLSAPR_SID AccountSid,
  2713. IN PULONG SystemAccess
  2714. )
  2715. /*++
  2716. Routine Description:
  2717. This function updates the System Access flags in an Account's information
  2718. block.
  2719. Arguments:
  2720. AccountSid - Sid of account
  2721. SystemAccess - Pointer to new System Access flags. These flags
  2722. will overwrite the old value
  2723. Return Values:
  2724. NTSTATUS - Standard Nt Result Code
  2725. --*/
  2726. {
  2727. NTSTATUS Status;
  2728. PLSAP_DB_ACCOUNT Account = NULL;
  2729. //
  2730. // Verify that the Account List is valid.
  2731. //
  2732. if (!LsapDbIsCacheValid(AccountObject)) {
  2733. Status = STATUS_INVALID_PARAMETER;
  2734. goto UpdateSystemAccessAccountError;
  2735. }
  2736. //
  2737. // Lookup the Account
  2738. //
  2739. Status = LsapDbLookupAccount( AccountSid, &Account );
  2740. if (!NT_SUCCESS(Status)) {
  2741. goto UpdateSystemAccessAccountError;
  2742. }
  2743. //
  2744. // Update the System Access Flags
  2745. //
  2746. Account->Info.SystemAccess = *SystemAccess;
  2747. UpdateSystemAccessAccountFinish:
  2748. return(Status);
  2749. UpdateSystemAccessAccountError:
  2750. goto UpdateSystemAccessAccountFinish;
  2751. }
  2752. NTSTATUS
  2753. LsapDbUpdateQuotasAccount(
  2754. IN PLSAPR_SID AccountSid,
  2755. IN PQUOTA_LIMITS QuotaLimits
  2756. )
  2757. /*++
  2758. Routine Description:
  2759. This function updates the Quota Limits an Account's information
  2760. block.
  2761. Arguments:
  2762. AccountSid - Sid of Account
  2763. Quotas - Pointer to new Quota Limits flags. These flags
  2764. will overwrite the old value
  2765. Return Values:
  2766. NTSTATUS - Standard Nt Result Code
  2767. --*/
  2768. {
  2769. NTSTATUS Status;
  2770. PLSAP_DB_ACCOUNT Account = NULL;
  2771. //
  2772. // Verify that the Account List is valid.
  2773. //
  2774. if (!LsapDbIsCacheValid(AccountObject)) {
  2775. Status = STATUS_INVALID_PARAMETER;
  2776. goto UpdateQuotasAccountError;
  2777. }
  2778. //
  2779. // Lookup the Account
  2780. //
  2781. Status = LsapDbLookupAccount( AccountSid, &Account );
  2782. if (!NT_SUCCESS(Status)) {
  2783. goto UpdateQuotasAccountError;
  2784. }
  2785. //
  2786. // Update the System Access Flags
  2787. //
  2788. Account->Info.QuotaLimits = *QuotaLimits;
  2789. UpdateQuotasAccountFinish:
  2790. return(Status);
  2791. UpdateQuotasAccountError:
  2792. goto UpdateQuotasAccountFinish;
  2793. }
  2794. NTSTATUS
  2795. LsapDbUpdatePrivilegesAccount(
  2796. IN PLSAPR_SID AccountSid,
  2797. IN OPTIONAL PPRIVILEGE_SET Privileges
  2798. )
  2799. /*++
  2800. Routine Description:
  2801. This function replates the Privilege Set in an Account's information
  2802. block with the one given. The existing Privilege Set (if any) in the
  2803. block will be freed.
  2804. Arguments:
  2805. AccountSid - Sid of account
  2806. Privileges - Optional pointer to new Privilege Set. These flags
  2807. will overwrite the old value. if NULL is specified, a Privilege
  2808. Set containing 0 entries will be written.
  2809. Return Values:
  2810. NTSTATUS - Standard Nt Result Code
  2811. --*/
  2812. {
  2813. NTSTATUS Status;
  2814. PLSAP_DB_ACCOUNT Account = NULL;
  2815. PPRIVILEGE_SET OutputPrivileges = Privileges;
  2816. //
  2817. // Verify that the Account List is valid.
  2818. //
  2819. if (!LsapDbIsCacheValid( AccountObject)) {
  2820. Status = STATUS_INVALID_PARAMETER;
  2821. goto UpdatePrivilegesAccountError;
  2822. }
  2823. //
  2824. // Lookup the Account
  2825. //
  2826. Status = LsapDbLookupAccount( AccountSid, &Account );
  2827. if (!NT_SUCCESS(Status)) {
  2828. goto UpdatePrivilegesAccountError;
  2829. }
  2830. //
  2831. // If NULL was specified for the Privileges, construct a Privilege Set
  2832. // having 0 entries.
  2833. //
  2834. if (OutputPrivileges == NULL) {
  2835. OutputPrivileges = MIDL_user_allocate( sizeof(PRIVILEGE_SET) );
  2836. if (OutputPrivileges == NULL) {
  2837. Status = STATUS_NO_MEMORY;
  2838. goto UpdatePrivilegesAccountError;
  2839. }
  2840. OutputPrivileges->PrivilegeCount = 0;
  2841. OutputPrivileges->Control = 0;
  2842. }
  2843. //
  2844. // If there is an existing Privilege Set in the cache, free it.
  2845. //
  2846. if (Account->Info.PrivilegeSet != NULL) {
  2847. MIDL_user_free( Account->Info.PrivilegeSet );
  2848. Account->Info.PrivilegeSet = NULL;
  2849. }
  2850. //
  2851. // Update the Privileges
  2852. //
  2853. Account->Info.PrivilegeSet = OutputPrivileges;
  2854. UpdatePrivilegesAccountFinish:
  2855. return(Status);
  2856. UpdatePrivilegesAccountError:
  2857. if (Account != NULL) {
  2858. if( Account->Info.PrivilegeSet ) {
  2859. MIDL_user_free( Account->Info.PrivilegeSet );
  2860. }
  2861. Account->Info.PrivilegeSet = NULL;
  2862. }
  2863. goto UpdatePrivilegesAccountFinish;
  2864. }
  2865. NTSTATUS
  2866. LsapDbCreateAccountList(
  2867. OUT PLSAP_DB_ACCOUNT_LIST AccountList
  2868. )
  2869. /*++
  2870. Routine Description:
  2871. This function creates an empty Account List
  2872. Arguments
  2873. AccountList - Pointer to Account List structure that will be initialized.
  2874. Return Values:
  2875. NTSTATUS - Standard Nt Result Code
  2876. --*/
  2877. {
  2878. NTSTATUS Status = STATUS_SUCCESS;
  2879. AccountList->AccountCount = 0;
  2880. InitializeListHead( &AccountList->Links );
  2881. return(Status);
  2882. }
  2883. NTSTATUS
  2884. LsapDbBuildAccountCache(
  2885. )
  2886. /*++
  2887. Routine Description:
  2888. This function constructs a cache for the Account objects. The cache
  2889. is a counted doubly linked list of blocks, one for each Account Object
  2890. found in the LSA Policy Database.
  2891. Arguments:
  2892. None.
  2893. Return Values:
  2894. NTSTATUS - Standard Nt Result Code
  2895. --*/
  2896. {
  2897. NTSTATUS Status = STATUS_SUCCESS;
  2898. SID_AND_ATTRIBUTES AccountSidAndAttributes;
  2899. ULONG EnumerationIndex, EnumerationContext;
  2900. LSAPR_ACCOUNT_ENUM_BUFFER EnumerationBuffer;
  2901. PLSAPR_SID AccountSid = NULL;
  2902. PLSAP_DB_ACCOUNT Account = NULL;
  2903. //
  2904. // Ensure caching of Account objects is turned off.
  2905. //
  2906. LsapDbMakeCacheBuilding( AccountObject );
  2907. //
  2908. // Initialize the Account List header with a skeleton entry for the
  2909. // System Account.
  2910. //
  2911. Status = LsapDbCreateAccountList(&LsapDbAccountList);
  2912. if (!NT_SUCCESS(Status)) {
  2913. goto BuildAccountCacheError;
  2914. }
  2915. LsapDbMakeCacheInvalid( AccountObject );
  2916. //
  2917. // Enumerate each of the LSA Account objects
  2918. //
  2919. Status = STATUS_MORE_ENTRIES;
  2920. EnumerationContext = 0;
  2921. while (Status == STATUS_MORE_ENTRIES) {
  2922. //
  2923. // Enumerate the next bunch of accounts.
  2924. //
  2925. Status = LsarEnumerateAccounts(
  2926. LsapPolicyHandle,
  2927. &EnumerationContext,
  2928. &EnumerationBuffer,
  2929. LSAP_DB_BUILD_ACCOUNT_LIST_LENGTH
  2930. );
  2931. if (!NT_SUCCESS(Status)) {
  2932. //
  2933. // We might just have got the warning that there are no more
  2934. // accounts. Reset to STATUS_SUCCESS and break out.
  2935. //
  2936. if (Status == STATUS_NO_MORE_ENTRIES) {
  2937. Status = STATUS_SUCCESS;
  2938. }
  2939. break;
  2940. }
  2941. //
  2942. // We've got some more accounts. Add them to the Account List
  2943. //
  2944. for( EnumerationIndex = 0;
  2945. EnumerationIndex < EnumerationBuffer.EntriesRead;
  2946. EnumerationIndex++ ) {
  2947. AccountSid = EnumerationBuffer.Information[ EnumerationIndex ].Sid;
  2948. Status = LsapDbCreateAccount( AccountSid, &Account );
  2949. if (!NT_SUCCESS(Status)) {
  2950. break;
  2951. }
  2952. AccountSidAndAttributes.Sid = (PSID) AccountSid;
  2953. AccountSidAndAttributes.Attributes = 0;
  2954. Status = LsapDbSlowQueryAllInformationAccounts(
  2955. LsapPolicyHandle,
  2956. 1,
  2957. &AccountSidAndAttributes,
  2958. &Account->Info
  2959. );
  2960. if (!NT_SUCCESS(Status)) {
  2961. if (Status != STATUS_NO_MORE_ENTRIES) {
  2962. break;
  2963. }
  2964. Status = STATUS_SUCCESS;
  2965. }
  2966. }
  2967. if (!NT_SUCCESS(Status)) {
  2968. break;
  2969. }
  2970. Status = STATUS_MORE_ENTRIES;
  2971. LsaIFree_LSAPR_ACCOUNT_ENUM_BUFFER( &EnumerationBuffer );
  2972. }
  2973. if (!NT_SUCCESS(Status)) {
  2974. goto BuildAccountCacheError;
  2975. }
  2976. //
  2977. // Turn on caching for Account objects.
  2978. //
  2979. LsapDbMakeCacheValid( AccountObject );
  2980. Status = STATUS_SUCCESS;
  2981. BuildAccountCacheFinish:
  2982. return(Status);
  2983. BuildAccountCacheError:
  2984. LsapDbMakeCacheInvalid(AccountObject);
  2985. LsapDbMakeCacheUnsupported(AccountObject);
  2986. goto BuildAccountCacheFinish;
  2987. }