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.

5049 lines
148 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. dbpolicy.c
  5. Abstract:
  6. LSA Database - Policy Object Private API Workers
  7. Author:
  8. Scott Birrell (ScottBi) January 10, 1992
  9. Environment:
  10. Revision History:
  11. --*/
  12. #include <lsapch2.h>
  13. #include "dbp.h"
  14. #include "lsawmi.h"
  15. #define LSAP_DB_POLICY_MAX_BUFFERS ((ULONG) 0x00000005L)
  16. /////////////////////////////////////////////////////////////////////////////
  17. // //
  18. // Function prototypes private to this module //
  19. // //
  20. /////////////////////////////////////////////////////////////////////////////
  21. #define LsapDbIsCacheValidPolicyInfoClass( InformationClass ) \
  22. (LsapDbPolicy.Info[ InformationClass ].AttributeLength > 0)
  23. NTSTATUS
  24. LsapDbUpdateInformationPolicy(
  25. IN POLICY_INFORMATION_CLASS InformationClass
  26. );
  27. /////////////////////////////////////////////////////////////////////////////
  28. // //
  29. // Code //
  30. // //
  31. /////////////////////////////////////////////////////////////////////////////
  32. NTSTATUS
  33. LsarOpenPolicy(
  34. IN OPTIONAL PLSAPR_SERVER_NAME SystemName,
  35. IN PLSAPR_OBJECT_ATTRIBUTES ObjectAttributes,
  36. IN ACCESS_MASK DesiredAccess,
  37. OUT PLSAPR_HANDLE PolicyHandle
  38. )
  39. /*++
  40. Routine Description:
  41. This function is the LSA server worker dispatch routine for the
  42. LsaOpenPolicy API.
  43. To administer the Local Security Policy of a local or remote system,
  44. this API must be called to establish a session with that system's
  45. Local Security Authority (LSA) subsystem. This API connects to
  46. the LSA of the target system and opens the Policy object
  47. of the target system's Local Security Policy database. A handle to
  48. the Policy object is returned. This handle must be used
  49. on all subsequent API calls to administer the Local Security Policy
  50. information for the target system.
  51. Arguments:
  52. SystemName - Name of the system to be administered. This RPC call
  53. only passes in a single character for system name, so it is not
  54. passed along to the internal routine.
  55. ObjectAttributes - Pointer to the set of attributes to use for this
  56. connection. The security Quality Of Service information is used and
  57. normally should provide Security Identification Class of
  58. impersonation. Some operations, however, require Security
  59. Impersonation Class of impersonation.
  60. DesiredAccess - This is an access mask indicating accesses being
  61. requested for the LSA Subsystem's LSA Database. These access types
  62. are reconciled with the Discretionary Access Control List of the
  63. target Policy object to determine whether the accesses will be granted or denied.
  64. PolicyHandle - Receives a handle to be used in future requests.
  65. Return Values:
  66. NTSTATUS - Standard Nt Result Code
  67. STATUS_ACCESS_DENIED - Caller does not have access to the target
  68. system's LSA Database, or does not have other desired accesses.
  69. --*/
  70. {
  71. NTSTATUS Status = STATUS_SUCCESS;
  72. LsarpReturnCheckSetup();
  73. LsapTraceEvent(EVENT_TRACE_TYPE_START, LsaTraceEvent_OpenPolicy);
  74. Status = LsapDbOpenPolicy( NULL,
  75. ObjectAttributes,
  76. DesiredAccess,
  77. 0, // No special options
  78. PolicyHandle,
  79. FALSE );
  80. LsapTraceEvent(EVENT_TRACE_TYPE_END, LsaTraceEvent_OpenPolicy);
  81. LsarpReturnPrologue();
  82. UNREFERENCED_PARAMETER( SystemName );
  83. return( Status );
  84. }
  85. NTSTATUS
  86. LsarOpenPolicy2(
  87. IN OPTIONAL PLSAPR_SERVER_NAME SystemName,
  88. IN PLSAPR_OBJECT_ATTRIBUTES ObjectAttributes,
  89. IN ACCESS_MASK DesiredAccess,
  90. OUT PLSAPR_HANDLE PolicyHandle
  91. )
  92. /*++
  93. Routine Description:
  94. This function is the LSA server worker dispatch routine for the
  95. LsaOpenPolicy API.
  96. To administer the Local Security Policy of a local or remote system,
  97. this API must be called to establish a session with that system's
  98. Local Security Authority (LSA) subsystem. This API connects to
  99. the LSA of the target system and opens the Policy object
  100. of the target system's Local Security Policy database. A handle to
  101. the Policy object is returned. This handle must be used
  102. on all subsequent API calls to administer the Local Security Policy
  103. information for the target system.
  104. The difference between this call and LsaOpenPolicy is that the entire
  105. system name is passed in instead of the first character.
  106. Arguments:
  107. SystemName - Name of the system to be administered. Administration of
  108. the local system is assumed if NULL is specified.
  109. ObjectAttributes - Pointer to the set of attributes to use for this
  110. connection. The security Quality Of Service information is used and
  111. normally should provide Security Identification Class of
  112. impersonation. Some operations, however, require Security
  113. Impersonation Class of impersonation.
  114. DesiredAccess - This is an access mask indicating accesses being
  115. requested for the LSA Subsystem's LSA Database. These access types
  116. are reconciled with the Discretionary Access Control List of the
  117. target Policy object to determine whether the accesses will be granted or denied.
  118. PolicyHandle - Receives a handle to be used in future requests.
  119. Return Values:
  120. NTSTATUS - Standard Nt Result Code
  121. STATUS_ACCESS_DENIED - Caller does not have access to the target
  122. system's LSA Database, or does not have other desired accesses.
  123. --*/
  124. {
  125. NTSTATUS Status = STATUS_SUCCESS;
  126. LsarpReturnCheckSetup();
  127. Status = LsapDbOpenPolicy( SystemName,
  128. ObjectAttributes,
  129. DesiredAccess,
  130. 0, // No special options
  131. PolicyHandle,
  132. FALSE );
  133. LsarpReturnPrologue();
  134. return( Status );
  135. }
  136. NTSTATUS
  137. LsarOpenPolicySce(
  138. IN OPTIONAL PLSAPR_SERVER_NAME SystemName,
  139. IN PLSAPR_OBJECT_ATTRIBUTES ObjectAttributes,
  140. IN ACCESS_MASK DesiredAccess,
  141. OUT PLSAPR_HANDLE PolicyHandle
  142. )
  143. /*++
  144. Routine Description:
  145. Same as LsarOpenPolicy2, except it provides an additional parameter
  146. to LsapDbOpenPolicy to obtain a special handle synchronized for SCE.
  147. The caller must have TCB privilege in order to successfully perform this call.
  148. Finally, this routine will call SceOpenPolicy() to give SCE the chance to
  149. send all pending policy changes to the SCE.
  150. Arguments:
  151. See LsarOpenPolicy2
  152. Return Values:
  153. NTSTATUS - Standard Nt Result Code
  154. STATUS_ACCESS_DENIED - Caller does not have access to the target
  155. system's LSA Database, or does not have other desired accesses.
  156. STATUS_PRIVILEGE_NOT_HELD - Caller must come in with TCB privilege.
  157. --*/
  158. {
  159. NTSTATUS Status;
  160. HANDLE ClientToken = NULL;
  161. typedef NTSTATUS ( *PfnSceOpenPolicy )();
  162. static PfnSceOpenPolicy SceOpenPolicy = NULL;
  163. static HANDLE DllHandle = NULL;
  164. BOOLEAN NetworkClient;
  165. LsarpReturnCheckSetup();
  166. //
  167. // This function can only be called locally.
  168. // If you are a network client, go away.
  169. //
  170. Status = LsapDbIsRpcClientNetworkClient( &NetworkClient );
  171. if ( NT_SUCCESS( Status ) ) {
  172. if( NetworkClient ) {
  173. Status = STATUS_ACCESS_DENIED;
  174. } else {
  175. Status = I_RpcMapWin32Status( RpcImpersonateClient( 0 ));
  176. }
  177. }
  178. //
  179. // TCB privilege must be held by the client in order to
  180. // make this call. Verify that before doing anything else
  181. //
  182. if ( NT_SUCCESS( Status )) {
  183. NTSTATUS SecondaryStatus;
  184. Status = NtOpenThreadToken(
  185. NtCurrentThread(),
  186. TOKEN_QUERY,
  187. TRUE,
  188. &ClientToken
  189. );
  190. if ( NT_SUCCESS( Status )) {
  191. BOOLEAN Result = FALSE;
  192. PRIVILEGE_SET RequiredPrivileges;
  193. LUID_AND_ATTRIBUTES PrivilegeArray[1];
  194. RequiredPrivileges.PrivilegeCount = 1;
  195. RequiredPrivileges.Control = PRIVILEGE_SET_ALL_NECESSARY;
  196. RequiredPrivileges.Privilege[0].Luid = RtlConvertLongToLuid( SE_TCB_PRIVILEGE );
  197. RequiredPrivileges.Privilege[0].Attributes = 0;
  198. Status = NtPrivilegeCheck(
  199. ClientToken,
  200. &RequiredPrivileges,
  201. &Result
  202. );
  203. if ( NT_SUCCESS( Status ) &&
  204. Result == FALSE ) {
  205. Status = STATUS_PRIVILEGE_NOT_HELD;
  206. }
  207. NtClose( ClientToken );
  208. ClientToken = NULL;
  209. }
  210. SecondaryStatus = I_RpcMapWin32Status( RpcRevertToSelf() );
  211. LsapDbSetStatusFromSecondary( Status, SecondaryStatus );
  212. }
  213. if ( NT_SUCCESS( Status ) && SceOpenPolicy == NULL ) {
  214. if ( DllHandle != NULL ) {
  215. FreeLibrary( DllHandle );
  216. DllHandle = NULL;
  217. }
  218. DllHandle = LoadLibraryW( L"SCECLI" );
  219. if ( DllHandle == NULL ) {
  220. LsapDsDebugOut(( DEB_ERROR, "Failed to load SCECLI.DLL\n" ));
  221. Status = STATUS_DLL_NOT_FOUND;
  222. } else {
  223. SceOpenPolicy = ( PfnSceOpenPolicy )GetProcAddress( DllHandle, "SceOpenPolicy" );
  224. if ( SceOpenPolicy == NULL ) {
  225. LsapDsDebugOut(( DEB_ERROR, "Failed to find SceNotifyPolicyDelta in SCECLI.DLL\n" ));
  226. Status = STATUS_ENTRYPOINT_NOT_FOUND;
  227. }
  228. }
  229. }
  230. //
  231. // Wait for SCECLI.DLL to send all pending policy changes to the SCE.
  232. // Upon success, the routine below returns STATUS_SUCCESS. If the queue
  233. // of pending changes cannot be emptied within 1 second, the routine
  234. // returns STATUS_TIMEOUT.
  235. //
  236. if ( NT_SUCCESS( Status )) {
  237. //
  238. // Grab the SCE policy lock here to give SCE the chance to send pending changes
  239. //
  240. ResetEvent( LsapDbState.SceSyncEvent );
  241. RtlAcquireResourceExclusive( &LsapDbState.ScePolicyLock, TRUE );
  242. Status = ( *SceOpenPolicy )();
  243. if ( !NT_SUCCESS( Status ) || Status == STATUS_TIMEOUT ) {
  244. RtlReleaseResource( &LsapDbState.ScePolicyLock );
  245. SetEvent( LsapDbState.SceSyncEvent );
  246. #ifdef DBG
  247. } else {
  248. ASSERT( !g_ScePolicyLocked );
  249. g_ScePolicyLocked = TRUE;
  250. #endif
  251. }
  252. }
  253. if ( NT_SUCCESS( Status ) && Status != STATUS_TIMEOUT ) {
  254. Status = LsapDbOpenPolicy(
  255. SystemName,
  256. ObjectAttributes,
  257. DesiredAccess,
  258. LSAP_DB_SCE_POLICY_HANDLE,
  259. PolicyHandle,
  260. FALSE
  261. );
  262. if ( !NT_SUCCESS( Status )) {
  263. #ifdef DBG
  264. g_ScePolicyLocked = FALSE;
  265. #endif
  266. RtlReleaseResource( &LsapDbState.ScePolicyLock );
  267. SetEvent( LsapDbState.SceSyncEvent );
  268. }
  269. }
  270. if ( ClientToken ) {
  271. NtClose( ClientToken );
  272. }
  273. LsarpReturnPrologue();
  274. return( Status );
  275. }
  276. NTSTATUS
  277. LsaIOpenPolicyTrusted(
  278. OUT PLSAPR_HANDLE PolicyHandle
  279. )
  280. /*++
  281. Routine Description:
  282. This function opens a handle to the Policy Object and identifies the
  283. caller as a trusted client. Any handles to LSA objects opened via
  284. this handle will also be trusted. This function is specifically
  285. only for use by clients that form part of the Security Process.
  286. Arguments:
  287. PolicyHandle - Receives a handle to the Policy Object.
  288. Return Values:
  289. NTSTATUS - Standard Nt Result Code.
  290. STATUS_SUCCESS - The call completed successfully.
  291. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources,
  292. such as memory, to complete the call.
  293. STATUS_INTERNAL_DB_CORRUPTION - The LSA Policy Database contains
  294. an internal inconsistency or invalid value.
  295. --*/
  296. {
  297. return(LsapDbOpenPolicy(
  298. NULL,
  299. NULL,
  300. 0,
  301. 0, // No special options
  302. PolicyHandle,
  303. TRUE
  304. ));
  305. }
  306. NTSTATUS
  307. LsarSetPolicyReplicationHandle(
  308. IN OUT PLSAPR_HANDLE PolicyHandle
  309. )
  310. /*++
  311. Routine Description:
  312. This function sets the given handle to be the policy replication handle.
  313. Arguments:
  314. PolicyHandle - Handle to be modified
  315. Return Values:
  316. NTSTATUS - Standard Nt Result Code.
  317. --*/
  318. {
  319. //
  320. // This routine is never used and was never properly implemented
  321. //
  322. return STATUS_NOT_IMPLEMENTED;
  323. UNREFERENCED_PARAMETER( PolicyHandle );
  324. }
  325. NTSTATUS
  326. LsapDbOpenPolicy(
  327. IN OPTIONAL PLSAPR_SERVER_NAME SystemName,
  328. IN OPTIONAL PLSAPR_OBJECT_ATTRIBUTES ObjectAttributes,
  329. IN ACCESS_MASK DesiredAccess,
  330. IN ULONG Options,
  331. OUT PLSAPR_HANDLE PolicyHandle,
  332. IN BOOLEAN TrustedClient
  333. )
  334. /*++
  335. Routine Description:
  336. This function is the LSA server worker routine for the LsaOpenPolicy
  337. API and the LsaIOpenPolicy private API for trusted clients.
  338. To administer the Local Security Policy of a local or remote system,
  339. this API must be called to establish a session with that system's
  340. Local Security Authority (LSA) subsystem. This API connects to
  341. the LSA of the target system and opens the Policy object
  342. of the target system's Local Security Policy database. A handle to
  343. the Policy object is returned. This handle must be used
  344. on all subsequent API calls to administer the Local Security Policy
  345. information for the target system.
  346. Arguments:
  347. SystemName - Name of the system to be administered. Administration of
  348. the local system is assumed if NULL is specified.
  349. ObjectAttributes - Pointer to the set of attributes to use for this
  350. connection. The security Quality Of Service information is used and
  351. normally should provide Security Identification Class of
  352. impersonation. Some operations, however, require Security
  353. Impersonation Class of impersonation. This parameter MUST
  354. be specified for non-Trusted clients (TrustedClient = FALSE)
  355. and must not be specified for Trusted Clients.
  356. DesiredAccess - This is an access mask indicating accesses being
  357. requested for the LSA Subsystem's LSA Database. These access types
  358. are reconciled with the Discretionary Access Control List of the
  359. target Policy object to determine whether the accesses will be granted or denied.
  360. Options - Specifies optional additional actions to be taken.
  361. PolicyHandle - Receives a handle to be used in future requests.
  362. TrustedClient - Indicates whether the client is known to be part of
  363. the trusted computer base (TCB). If so (TRUE), no access validation
  364. is performed and all requested accesses are granted. If not
  365. (FALSE), then the client is impersonated and access validation
  366. performed against the SecurityDescriptor on the SERVER object.
  367. Return Values:
  368. NTSTATUS - Standard Nt Result Code
  369. STATUS_SUCCESS - The call completed successfully.
  370. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources,
  371. such as memory, to complete the call.
  372. STATUS_INTERNAL_DB_CORRUPTION - The LSA Policy Database contains
  373. an internal inconsistency or invalid value.
  374. STATUS_ACCESS_DENIED - Caller does not have access to the target
  375. system's LSA Database, or does not have other desired accesses.
  376. STATUS_INVALID_PARAMETER - Invalid parameter or combination
  377. of parameters,
  378. STATUS_BACKUP_CONTROLLER - An update access has been requested
  379. that is not allowed on Backup Domain Controllers for non-
  380. trusted clients.
  381. --*/
  382. {
  383. NTSTATUS Status;
  384. LSAP_DB_OBJECT_INFORMATION ObjectInformation;
  385. BOOLEAN AcquiredLock = FALSE;
  386. LsapEnterFunc( "LsapDbOpenPolicy" );
  387. //
  388. // Verify Object Attributes accoring to client trust status.
  389. //
  390. if (!TrustedClient) {
  391. Status = STATUS_INVALID_PARAMETER;
  392. //
  393. // Client is not trusted. Object Attributes must be specified
  394. // and the RootDirectory field must be NULL.
  395. //
  396. if (!ARGUMENT_PRESENT(ObjectAttributes)) {
  397. goto OpenPolicyError;
  398. }
  399. //
  400. // Verify that NULL has been specified for the RootDirectory
  401. // of ObjectAttributes.
  402. //
  403. if (ObjectAttributes->RootDirectory != NULL) {
  404. goto OpenPolicyError;
  405. }
  406. //
  407. // Copy the supplied ObjectAttributes to the ObjectInformation and
  408. // augment them with the name of the Policy Object.
  409. //
  410. ObjectInformation.ObjectAttributes = *((POBJECT_ATTRIBUTES) ObjectAttributes);
  411. } else {
  412. //
  413. // Trusted Client.
  414. //
  415. Options |= LSAP_DB_TRUSTED;
  416. InitializeObjectAttributes(
  417. &(ObjectInformation.ObjectAttributes),
  418. NULL,
  419. 0L,
  420. NULL,
  421. NULL
  422. );
  423. }
  424. //
  425. // Set the Object Type and Logical Name in the ObjectInformation structure.
  426. //
  427. ObjectInformation.ObjectTypeId = PolicyObject;
  428. ObjectInformation.ObjectAttributes.ObjectName = &LsapDbNames[Policy];
  429. ObjectInformation.ContainerTypeId = 0;
  430. ObjectInformation.Sid = NULL;
  431. ObjectInformation.ObjectAttributeNameOnly = FALSE;
  432. ObjectInformation.DesiredObjectAccess = DesiredAccess;
  433. //
  434. // Acquire the Lsa Database lock
  435. //
  436. LsapDbAcquireLockEx( PolicyObject,
  437. LSAP_DB_READ_ONLY_TRANSACTION );
  438. AcquiredLock = TRUE;
  439. //
  440. // Open the Policy Object. Return the Handle obtained as the
  441. // RPC Context Handle.
  442. //
  443. Status = LsapDbOpenObject(
  444. &ObjectInformation,
  445. DesiredAccess,
  446. Options,
  447. PolicyHandle
  448. );
  449. if (!NT_SUCCESS(Status)) {
  450. goto OpenPolicyError;
  451. }
  452. //
  453. // Release the LSA Database lock and return.
  454. //
  455. OpenPolicyFinish:
  456. //
  457. // If necessary, release the LSA Database lock.
  458. //
  459. if (AcquiredLock) {
  460. LsapDbReleaseLockEx( PolicyObject,
  461. LSAP_DB_READ_ONLY_TRANSACTION );
  462. }
  463. LsapExitFunc( "LsapDbOpenPolicy", Status );
  464. return( Status );
  465. OpenPolicyError:
  466. *PolicyHandle = NULL;
  467. goto OpenPolicyFinish;
  468. //
  469. // Usage of the SystemName parameter is hidden within the RPC stub
  470. // code, so this parameter will be permanently unreferenced.
  471. //
  472. UNREFERENCED_PARAMETER(SystemName);
  473. }
  474. NTSTATUS
  475. LsaIQueryInformationPolicyTrusted(
  476. IN POLICY_INFORMATION_CLASS InformationClass,
  477. OUT PLSAPR_POLICY_INFORMATION *Buffer
  478. )
  479. /*++
  480. Routine Description:
  481. This function is a trusted version of LsarQueryInformationPolicy.
  482. Unlike the standard version, no handle is required to the Policy object
  483. because an internal handle is used. This routine is available only
  484. in the context of the Lsa Process.
  485. Arguments:
  486. InformationClass - Specifies the information to be returned. The
  487. Information Classes and accesses required are as follows:
  488. Information Class Required Access Type
  489. PolicyAuditLogInformation POLICY_VIEW_AUDIT_INFORMATION
  490. PolicyAuditEventsInformation POLICY_VIEW_AUDIT_INFORMATION
  491. PolicyPrimaryDomainInformation POLICY_VIEW_LOCAL_INFORMATION
  492. PolicyAccountDomainInformation POLICY_VIEW_LOCAL_INFORMATION
  493. PolicyPdAccountInformation POLICY_GET_PRIVATE_INFORMATION
  494. PolicyLsaServerRoleInformation POLICY_VIEW_LOCAL_INFORMATION
  495. PolicyReplicaSourceInformation POLICY_VIEW_LOCAL_INFORMATION
  496. PolicyDefaultQuotaInformation POLICY_VIEW_LOCAL_INFORMATION
  497. PolicyAuditFullQueryInformation POLICY_VIEW_AUDIT_INFORMATION
  498. PolicyDnsDomainInformation POLICY_VIEW_LOCAL_INFORMATION
  499. PolicyDnsDomainInformationInt POLICY_VIEW_LOCAL_INFORMATION
  500. Buffer - receives a pointer to the buffer returned comtaining the
  501. requested information. This buffer is allocated by this service
  502. and must be freed when no longer needed by passing the returned
  503. value to the appropriate LsaIFreeLSAPR_POLICY... routine.
  504. Return Values:
  505. NTSTATUS - Standard Nt Result Code.
  506. Result codes returned from LsarQueryInformationPolicy()
  507. --*/
  508. {
  509. if ( InformationClass == PolicyDnsDomainInformation ) {
  510. //
  511. // Make sure NT4 emulation does not interfere with our processing here
  512. //
  513. InformationClass = PolicyDnsDomainInformationInt;
  514. }
  515. return(LsarQueryInformationPolicy(
  516. LsapPolicyHandle,
  517. InformationClass,
  518. Buffer
  519. ));
  520. }
  521. NTSTATUS
  522. LsarQueryInformationPolicy(
  523. IN LSAPR_HANDLE PolicyHandle,
  524. IN POLICY_INFORMATION_CLASS InformationClass,
  525. OUT PLSAPR_POLICY_INFORMATION *Buffer
  526. )
  527. /*++
  528. Routine Description:
  529. This function is the LSA server RPC worker routine for the
  530. LsarQueryInformationPolicy API.
  531. The LsaQueryInformationPolicy API obtains information from the Policy
  532. object. The caller must have access appropriate to the information
  533. being requested (see InformationClass parameter).
  534. Arguments:
  535. PolicyHandle - Handle from an LsaOpenPolicy call.
  536. InformationClass - Specifies the information to be returned. The
  537. Information Classes and accesses required are as follows:
  538. Information Class Required Access Type
  539. PolicyAuditLogInformation POLICY_VIEW_AUDIT_INFORMATION
  540. PolicyAuditEventsInformation POLICY_VIEW_AUDIT_INFORMATION
  541. PolicyPrimaryDomainInformation POLICY_VIEW_LOCAL_INFORMATION
  542. PolicyAccountDomainInformation POLICY_VIEW_LOCAL_INFORMATION
  543. PolicyPdAccountInformation POLICY_GET_PRIVATE_INFORMATION
  544. PolicyLsaServerRoleInformation POLICY_VIEW_LOCAL_INFORMATION
  545. PolicyReplicaSourceInformation POLICY_VIEW_LOCAL_INFORMATION
  546. PolicyDefaultQuotaInformation POLICY_VIEW_LOCAL_INFORMATION
  547. PolicyAuditFullQueryInformation POLICY_VIEW_AUDIT_INFORMATION
  548. PolicyDnsDomainInformation POLICY_VIEW_LOCAL_INFORMATION
  549. PolicyDnsDomainInformationInt POLICY_VIEW_LOCAL_INFORMATION
  550. Buffer - receives a pointer to the buffer returned comtaining the
  551. requested information. This buffer is allocated by this service
  552. and must be freed when no longer needed by passing the returned
  553. value to LsaFreeMemory().
  554. Return Value:
  555. NTSTATUS - Standard Nt Result Code
  556. STATUS_ACCESS_DENIED - Caller does not have the appropriate
  557. access to complete the operation.
  558. STATUS_INTERNAL_DB_CORRUPTION - The Policy Database is possibly
  559. corrupt. The returned Policy Information is invalid for
  560. the given class.
  561. --*/
  562. {
  563. NTSTATUS Status;
  564. ACCESS_MASK DesiredAccess;
  565. ULONG ReferenceOptions;
  566. ULONG DereferenceOptions = 0;
  567. BOOLEAN ObjectReferenced = FALSE;
  568. LSAP_DB_HANDLE InternalHandle = (LSAP_DB_HANDLE) PolicyHandle;
  569. LsarpReturnCheckSetup();
  570. LsapEnterFunc( "LsarQueryInformationPolicy" );
  571. LsapTraceEvent(EVENT_TRACE_TYPE_START, LsaTraceEvent_QueryInformationPolicy);
  572. //
  573. // If NT4 emulation is enabled, fail requests for PolicyDnsDomainInformation
  574. // as if they weren't implemented
  575. //
  576. if ( LsapDbState.EmulateNT4 &&
  577. InformationClass == PolicyDnsDomainInformation &&
  578. !InternalHandle->Trusted ) {
  579. RaiseException( RPC_NT_PROCNUM_OUT_OF_RANGE, 0, 0, NULL );
  580. } else if ( InformationClass == PolicyDnsDomainInformationInt ) {
  581. //
  582. // PolicyDnsDomainInformationInt is a request to override
  583. // NT4 emulation
  584. //
  585. InformationClass = PolicyDnsDomainInformation;
  586. }
  587. //
  588. // Validate the Information Class and determine the access required to
  589. // query this Policy Information Class.
  590. //
  591. Status = LsapDbVerifyInfoQueryPolicy(
  592. PolicyHandle,
  593. InformationClass,
  594. &DesiredAccess
  595. );
  596. if (!NT_SUCCESS(Status)) {
  597. goto QueryInfoPolicyError;
  598. }
  599. //
  600. // If querying the Audit Log Full information, we may need to perform a
  601. // test write to the Audit Log to verify that the Log Full status is
  602. // up to date. The Audit Log Queue Lock must always be taken
  603. // prior to acquiring the LSA Database lock, so take the former lock
  604. // here in case we need it.
  605. //
  606. ReferenceOptions = LSAP_DB_NO_DS_OP_TRANSACTION |
  607. LSAP_DB_READ_ONLY_TRANSACTION;
  608. DereferenceOptions = LSAP_DB_NO_DS_OP_TRANSACTION |
  609. LSAP_DB_READ_ONLY_TRANSACTION;
  610. //
  611. // If we're gettings the server role, don't hold a lock
  612. //
  613. if ( InformationClass != PolicyLsaServerRoleInformation ) {
  614. ReferenceOptions |= LSAP_DB_LOCK;
  615. DereferenceOptions |= LSAP_DB_LOCK;
  616. }
  617. //
  618. // Acquire the Lsa Database lock. Verify that the handle is valid, is
  619. // a handle to the Policy object and has the necessary access granted.
  620. // Reference the handle.
  621. //
  622. Status = LsapDbReferenceObject(
  623. PolicyHandle,
  624. DesiredAccess,
  625. PolicyObject,
  626. PolicyObject,
  627. ReferenceOptions
  628. );
  629. if (!NT_SUCCESS(Status)) {
  630. goto QueryInfoPolicyError;
  631. }
  632. ObjectReferenced = TRUE;
  633. //
  634. // If caching is enabled for this Information Class, grab the info from the
  635. // cache.
  636. //
  637. *Buffer = NULL;
  638. Status = LsapDbQueryInformationPolicy(
  639. LsapPolicyHandle,
  640. InformationClass,
  641. Buffer
  642. );
  643. QueryInfoPolicyFinish:
  644. //
  645. // If necessary, dereference the Policy Object, release the LSA Database lock and
  646. // return.
  647. //
  648. if (ObjectReferenced) {
  649. Status = LsapDbDereferenceObject(
  650. &PolicyHandle,
  651. PolicyObject,
  652. PolicyObject,
  653. DereferenceOptions,
  654. (SECURITY_DB_DELTA_TYPE) 0,
  655. Status
  656. );
  657. }
  658. #if DBG
  659. LsapDsDebugOut(( DEB_POLICY,
  660. "LsarQueryInformationPolicy for info %lu returned 0x%lx\n",
  661. InformationClass,
  662. Status ));
  663. #endif
  664. LsapTraceEvent(EVENT_TRACE_TYPE_END, LsaTraceEvent_QueryInformationPolicy);
  665. LsapExitFunc( "LsarQueryInformationPolicy", Status );
  666. LsarpReturnPrologue();
  667. return(Status);
  668. QueryInfoPolicyError:
  669. goto QueryInfoPolicyFinish;
  670. }
  671. NTSTATUS
  672. LsarQueryInformationPolicy2(
  673. IN LSAPR_HANDLE PolicyHandle,
  674. IN POLICY_INFORMATION_CLASS InformationClass,
  675. OUT PLSAPR_POLICY_INFORMATION *Buffer
  676. )
  677. /*++
  678. Routine Description:
  679. This function is the LSA server RPC worker routine for the
  680. LsarQueryInformationPolicy API.
  681. The LsaQueryInformationPolicy API obtains information from the Policy
  682. object. The caller must have access appropriate to the information
  683. being requested (see InformationClass parameter).
  684. Arguments:
  685. PolicyHandle - Handle from an LsaOpenPolicy call.
  686. InformationClass - Specifies the information to be returned. The
  687. Information Classes and accesses required are as follows:
  688. Information Class Required Access Type
  689. PolicyAuditLogInformation POLICY_VIEW_AUDIT_INFORMATION
  690. PolicyAuditEventsInformation POLICY_VIEW_AUDIT_INFORMATION
  691. PolicyPrimaryDomainInformation POLICY_VIEW_LOCAL_INFORMATION
  692. PolicyAccountDomainInformation POLICY_VIEW_LOCAL_INFORMATION
  693. PolicyPdAccountInformation POLICY_GET_PRIVATE_INFORMATION
  694. PolicyLsaServerRoleInformation POLICY_VIEW_LOCAL_INFORMATION
  695. PolicyReplicaSourceInformation POLICY_VIEW_LOCAL_INFORMATION
  696. PolicyDefaultQuotaInformation POLICY_VIEW_LOCAL_INFORMATION
  697. PolicyAuditFullQueryInformation POLICY_VIEW_AUDIT_INFORMATION
  698. PolicyDnsDomainInformation POLICY_VIEW_LOCAL_INFORMATION
  699. PolicyDnsDomainInformationInt POLICY_VIEW_LOCAL_INFORMATION
  700. Buffer - receives a pointer to the buffer returned comtaining the
  701. requested information. This buffer is allocated by this service
  702. and must be freed when no longer needed by passing the returned
  703. value to LsaFreeMemory().
  704. Return Value:
  705. NTSTATUS - Standard Nt Result Code
  706. Result codes returned from LsarQueryInformationPolicy()
  707. --*/
  708. {
  709. return(LsarQueryInformationPolicy(
  710. PolicyHandle,
  711. InformationClass,
  712. Buffer
  713. ));
  714. }
  715. NTSTATUS
  716. LsapDbQueryInformationPolicy(
  717. IN LSAPR_HANDLE PolicyHandle,
  718. IN POLICY_INFORMATION_CLASS InformationClass,
  719. IN OUT PLSAPR_POLICY_INFORMATION *Buffer
  720. )
  721. /*++
  722. Routine Description:
  723. This function is the fast LSA server RPC worker routine for the
  724. LsarQueryInformationPolicy API. It reads the information
  725. from the Policy object cache.
  726. The LsaQueryInformationPolicy API obtains information from the Policy
  727. object. The caller must have access appropriate to the information
  728. being requested (see InformationClass parameter).
  729. Arguments:
  730. PolicyHandle - Handle from an LsaOpenPolicy call.
  731. NOTE: Currently, this function only allows the
  732. PolicyDefaultQuotaInformation information class to be read from
  733. the Policy Cache. Other information classes can be added
  734. in the future.
  735. InformationClass - Specifies the information to be returned. The
  736. Information Classes and accesses required are as follows:
  737. Information Class Required Access Type
  738. PolicyAuditLogInformation POLICY_VIEW_AUDIT_INFORMATION
  739. PolicyAuditEventsInformation POLICY_VIEW_AUDIT_INFORMATION
  740. PolicyPrimaryDomainInformation POLICY_VIEW_LOCAL_INFORMATION
  741. PolicyAccountDomainInformation POLICY_VIEW_LOCAL_INFORMATION
  742. PolicyPdAccountInformation POLICY_GET_PRIVATE_INFORMATION
  743. PolicyLsaServerRoleInformation POLICY_VIEW_LOCAL_INFORMATION
  744. PolicyReplicaSourceInformation POLICY_VIEW_LOCAL_INFORMATION
  745. PolicyDefaultQuotaInformation POLICY_VIEW_LOCAL_INFORMATION
  746. PolicyAuditFullQueryInformation POLICY_VIEW_AUDIT_INFORMATION
  747. Buffer - Pointer to location that contains either a pointer to the
  748. buffer that will be used to return the information. If NULL
  749. is contained in this location, a buffer will be allocated via
  750. MIDL_user_allocate and a pointer to it returned.
  751. Return Value:
  752. NTSTATUS - Standard Nt Result Code
  753. STATUS_ACCESS_DENIED - Caller does not have the appropriate
  754. access to complete the operation.
  755. STATUS_INTERNAL_DB_CORRUPTION - The Policy Database is possibly
  756. corrupt. The returned Policy Information is invalid for
  757. the given class.
  758. --*/
  759. {
  760. NTSTATUS Status = STATUS_SUCCESS;
  761. PLSAPR_POLICY_INFORMATION OutputBuffer = NULL;
  762. PLSAPR_POLICY_INFORMATION TempBuffer = NULL;
  763. ULONG OutputBufferLength;
  764. BOOLEAN BufferAllocated = FALSE;
  765. PLSAPR_POLICY_AUDIT_EVENTS_INFO PolicyAuditEventsInfo;
  766. PLSAPR_POLICY_PRIMARY_DOM_INFO PolicyPrimaryDomainInfo;
  767. PLSAPR_POLICY_ACCOUNT_DOM_INFO PolicyAccountDomainInfo;
  768. PLSAPR_POLICY_PD_ACCOUNT_INFO PolicyPdAccountInfo;
  769. PLSAPR_POLICY_REPLICA_SRCE_INFO PolicyReplicaSourceInfo;
  770. PLSAPR_POLICY_DNS_DOMAIN_INFO PolicyDnsDomainInfo;
  771. PPOLICY_LSA_SERVER_ROLE PolicyServerRole;
  772. PVOID SourceBuffers[LSAP_DB_POLICY_MAX_BUFFERS];
  773. PVOID DestBuffers[LSAP_DB_POLICY_MAX_BUFFERS];
  774. ULONG CopyLength[LSAP_DB_POLICY_MAX_BUFFERS];
  775. ULONG NextBufferIndex = 0;
  776. ULONG BufferCount = 0;
  777. BOOLEAN BufferProvided = FALSE;
  778. DOMAIN_SERVER_ROLE SamServerRole;
  779. BOOLEAN PolicyCacheLocked = FALSE;
  780. LsapEnterFunc( "LsapDbQueryInformationPolicy" );
  781. if (*Buffer != NULL) {
  782. OutputBuffer = *Buffer;
  783. BufferProvided = TRUE;
  784. }
  785. //
  786. // Special case the ServerRole information. This information is not stored exclusively in
  787. // SAM, so we need to read it directly from there
  788. //
  789. if ( InformationClass == PolicyLsaServerRoleInformation ) {
  790. Status = LsapOpenSam();
  791. if ( !NT_SUCCESS( Status ) ) {
  792. LsapDsDebugOut(( DEB_ERROR,
  793. "LsapDbQueryInformationPolicy: Sam not opened (Error 0x%x)\n", Status ));
  794. } else {
  795. Status = SamIQueryServerRole( LsapAccountDomainHandle, &SamServerRole );
  796. if ( !NT_SUCCESS( Status ) ) {
  797. LsapDsDebugOut(( DEB_ERROR,
  798. "SamIQueryServerRole failed with 0x%x\n", Status ));
  799. } else {
  800. //
  801. // Have to return the information...
  802. //
  803. if ( !BufferProvided ) {
  804. OutputBuffer = MIDL_user_allocate( sizeof( POLICY_LSA_SERVER_ROLE ) );
  805. if ( OutputBuffer == NULL ) {
  806. Status = STATUS_INSUFFICIENT_RESOURCES;
  807. } else {
  808. *Buffer = OutputBuffer;
  809. }
  810. }
  811. if ( NT_SUCCESS( Status ) ) {
  812. PolicyServerRole = ( PPOLICY_LSA_SERVER_ROLE )OutputBuffer;
  813. *PolicyServerRole = ( POLICY_LSA_SERVER_ROLE )SamServerRole;
  814. }
  815. }
  816. }
  817. goto QueryInformationPolicyFinish;
  818. }
  819. //
  820. // If caching of the Policy Object is not supported, or has been disabled
  821. // until the next system reload, call slow query routine to read the
  822. // information from backing storage.
  823. //
  824. if (!LsapDbIsCacheSupported(PolicyObject)) {
  825. Status = LsapDbSlowQueryInformationPolicy(
  826. LsapPolicyHandle,
  827. InformationClass,
  828. Buffer
  829. );
  830. if (!NT_SUCCESS(Status)) {
  831. goto QueryInformationPolicyError;
  832. }
  833. return(Status);
  834. }
  835. //
  836. // Caching of the Policy Object is supported, but it may not be
  837. // valid. If not valid for any information classes, rebuild the cache.
  838. //
  839. SafeAcquireResourceShared( &LsapDbState.PolicyCacheLock, TRUE );
  840. PolicyCacheLocked = TRUE;
  841. if (!LsapDbIsCacheValid(PolicyObject)) {
  842. SafeConvertSharedToExclusive( &LsapDbState.PolicyCacheLock );
  843. if ( !LsapDbIsCacheValid( PolicyObject )) {
  844. Status = LsapDbBuildPolicyCache();
  845. if (!NT_SUCCESS(Status)) {
  846. goto QueryInformationPolicyError;
  847. }
  848. LsapDbMakeCacheValid(PolicyObject);
  849. }
  850. SafeConvertExclusiveToShared( &LsapDbState.PolicyCacheLock );
  851. }
  852. //
  853. // The cache is now valid but may contain out of date information for
  854. // the sepcific Information Class requested. Check for this and rebuild
  855. // if necessary.
  856. //
  857. if (!LsapDbIsCacheValidPolicyInfoClass(InformationClass)) {
  858. SafeConvertSharedToExclusive( &LsapDbState.PolicyCacheLock );
  859. Status = LsapDbUpdateInformationPolicy( InformationClass );
  860. SafeConvertExclusiveToShared( &LsapDbState.PolicyCacheLock );
  861. if (!NT_SUCCESS(Status)) {
  862. goto QueryInformationPolicyError;
  863. }
  864. }
  865. //
  866. // The cache has valid information for this Information Class. Now read
  867. // the information desired from the cache. This information consists
  868. // of a hierarchic structure with a single root node and zero or more
  869. // subnodes. First, read the root node from the cache. We cache its
  870. // length too. We need to allocate a buffer if one was not provided.
  871. //
  872. OutputBufferLength = LsapDbPolicy.Info[ InformationClass].AttributeLength;
  873. if (OutputBuffer == NULL) {
  874. if (OutputBufferLength > 0) {
  875. OutputBuffer = MIDL_user_allocate( OutputBufferLength );
  876. if (OutputBuffer == NULL) {
  877. Status = STATUS_NO_MEMORY;
  878. goto QueryInformationPolicyError;
  879. }
  880. }
  881. BufferAllocated = TRUE;
  882. }
  883. //
  884. // Copy data for the root node from the cache
  885. //
  886. RtlCopyMemory(
  887. OutputBuffer,
  888. LsapDbPolicy.Info[InformationClass].Attribute,
  889. OutputBufferLength
  890. );
  891. //
  892. // Allocate and copy graph of output (if any)
  893. //
  894. NextBufferIndex = 0;
  895. switch (InformationClass) {
  896. case PolicyAuditLogInformation:
  897. break;
  898. case PolicyAuditEventsInformation:
  899. PolicyAuditEventsInfo = (PLSAPR_POLICY_AUDIT_EVENTS_INFO) OutputBuffer;
  900. //
  901. // Setup to copy the Event Auditing Options
  902. //
  903. CopyLength[ NextBufferIndex ] =
  904. (PolicyAuditEventsInfo->MaximumAuditEventCount * sizeof(ULONG));
  905. if (CopyLength[ NextBufferIndex ] > 0) {
  906. DestBuffers[NextBufferIndex] = MIDL_user_allocate( CopyLength[ NextBufferIndex ] );
  907. if (DestBuffers[NextBufferIndex] == NULL) {
  908. Status = STATUS_NO_MEMORY;
  909. break;
  910. }
  911. PolicyAuditEventsInfo->EventAuditingOptions =
  912. (PPOLICY_AUDIT_EVENT_OPTIONS) DestBuffers[NextBufferIndex];
  913. SourceBuffers[NextBufferIndex] =
  914. ((PLSAPR_POLICY_AUDIT_EVENTS_INFO)
  915. LsapDbPolicy.Info[ InformationClass].Attribute)->EventAuditingOptions;
  916. NextBufferIndex++;
  917. }
  918. break;
  919. case PolicyPrimaryDomainInformation:
  920. PolicyPrimaryDomainInfo = (PLSAPR_POLICY_PRIMARY_DOM_INFO) OutputBuffer;
  921. //
  922. // Setup to copy the Unicode Name Buffer
  923. //
  924. CopyLength[ NextBufferIndex ] = (ULONG) PolicyPrimaryDomainInfo->Name.MaximumLength;
  925. if (CopyLength[ NextBufferIndex ] > 0) {
  926. DestBuffers[NextBufferIndex] = MIDL_user_allocate( CopyLength[ NextBufferIndex ] );
  927. if (DestBuffers[NextBufferIndex] == NULL) {
  928. Status = STATUS_NO_MEMORY;
  929. break;
  930. }
  931. PolicyPrimaryDomainInfo->Name.Buffer =
  932. (PWSTR) DestBuffers[NextBufferIndex];
  933. SourceBuffers[NextBufferIndex] =
  934. ((PLSAPR_POLICY_PRIMARY_DOM_INFO) LsapDbPolicy.Info[ InformationClass].Attribute)->Name.Buffer;
  935. NextBufferIndex++;
  936. }
  937. //
  938. // Setup to copy the Sid (if any). Note that the Primary Domain Sid may
  939. // be set to NULL so signify that we have no Primary Domain. This
  940. // situation occurs during installation before a Primary Domain
  941. // has been specified, or if we're a member of a WorkGroup instead
  942. // of a Domain.
  943. //
  944. if ( PolicyPrimaryDomainInfo->Sid != NULL ) {
  945. CopyLength[ NextBufferIndex ] = RtlLengthSid(PolicyPrimaryDomainInfo->Sid);
  946. DestBuffers[NextBufferIndex] = MIDL_user_allocate( CopyLength[ NextBufferIndex ] );
  947. if (DestBuffers[NextBufferIndex] == NULL) {
  948. Status = STATUS_NO_MEMORY;
  949. break;
  950. }
  951. PolicyPrimaryDomainInfo->Sid =
  952. (PLSAPR_SID) DestBuffers[NextBufferIndex];
  953. SourceBuffers[NextBufferIndex] =
  954. ((PLSAPR_POLICY_PRIMARY_DOM_INFO) LsapDbPolicy.Info[ InformationClass].Attribute)->Sid;
  955. NextBufferIndex++;
  956. }
  957. break;
  958. case PolicyDnsDomainInformation:
  959. PolicyDnsDomainInfo = (PLSAPR_POLICY_DNS_DOMAIN_INFO) OutputBuffer;
  960. //
  961. // Setup to copy the Unicode Name Buffer. We get this from the Primary Domain info
  962. //
  963. CopyLength[ NextBufferIndex ] = (ULONG) PolicyDnsDomainInfo->Name.MaximumLength;
  964. if (CopyLength[ NextBufferIndex ] > 0) {
  965. DestBuffers[NextBufferIndex] = MIDL_user_allocate( CopyLength[ NextBufferIndex ] );
  966. if (DestBuffers[NextBufferIndex] == NULL) {
  967. Status = STATUS_NO_MEMORY;
  968. break;
  969. }
  970. PolicyDnsDomainInfo->Name.Buffer =
  971. (PWSTR) DestBuffers[NextBufferIndex];
  972. SourceBuffers[NextBufferIndex] =
  973. ((PLSAPR_POLICY_DNS_DOMAIN_INFO) LsapDbPolicy.Info[
  974. InformationClass ].Attribute)->Name.Buffer;
  975. NextBufferIndex++;
  976. }
  977. //
  978. // Setup to copy the Unicode DNS Domain Name Buffer
  979. //
  980. CopyLength[ NextBufferIndex ] = (ULONG) PolicyDnsDomainInfo->DnsDomainName.MaximumLength;
  981. if (CopyLength[ NextBufferIndex ] > 0) {
  982. DestBuffers[NextBufferIndex] = MIDL_user_allocate( CopyLength[ NextBufferIndex ] );
  983. if (DestBuffers[NextBufferIndex] == NULL) {
  984. Status = STATUS_NO_MEMORY;
  985. break;
  986. }
  987. PolicyDnsDomainInfo->DnsDomainName.Buffer =
  988. (PWSTR) DestBuffers[NextBufferIndex];
  989. SourceBuffers[NextBufferIndex] =
  990. ((PLSAPR_POLICY_DNS_DOMAIN_INFO) LsapDbPolicy.Info[ InformationClass].Attribute)->DnsDomainName.Buffer;
  991. NextBufferIndex++;
  992. }
  993. //
  994. // Setup to copy the Unicode DNS Tree Name Buffer
  995. //
  996. CopyLength[ NextBufferIndex ] = (ULONG) PolicyDnsDomainInfo->DnsForestName.MaximumLength;
  997. if (CopyLength[ NextBufferIndex ] > 0) {
  998. DestBuffers[NextBufferIndex] = MIDL_user_allocate( CopyLength[ NextBufferIndex ] );
  999. if (DestBuffers[NextBufferIndex] == NULL) {
  1000. Status = STATUS_NO_MEMORY;
  1001. break;
  1002. }
  1003. PolicyDnsDomainInfo->DnsForestName.Buffer =
  1004. (PWSTR) DestBuffers[NextBufferIndex];
  1005. SourceBuffers[NextBufferIndex] =
  1006. ((PLSAPR_POLICY_DNS_DOMAIN_INFO) LsapDbPolicy.Info[ InformationClass].Attribute)->DnsForestName.Buffer;
  1007. NextBufferIndex++;
  1008. }
  1009. //
  1010. // Setup to copy the Domain GUID. Note that no allocation will occur here
  1011. // (since the guid exists in the information class itself), so we'll have to
  1012. // do the copy directly
  1013. //
  1014. RtlCopyMemory(
  1015. &(PolicyDnsDomainInfo->DomainGuid),
  1016. &(((PLSAPR_POLICY_DNS_DOMAIN_INFO) LsapDbPolicy.Info[ InformationClass].Attribute)->DomainGuid),
  1017. sizeof(GUID)
  1018. );
  1019. //
  1020. // Setup to copy the Sid from the Primary Domain info (if any).
  1021. // Note that the Primary Domain Sid may be set to NULL to signify
  1022. // signify that we have no Primary Domain. This situation occurs
  1023. // during installation before a Primary Domain has been specified,
  1024. // or if we're a member of a WorkGroup instead of a Domain.
  1025. //
  1026. if ( PolicyDnsDomainInfo->Sid != NULL ) {
  1027. CopyLength[ NextBufferIndex ] = RtlLengthSid(PolicyDnsDomainInfo->Sid);
  1028. DestBuffers[NextBufferIndex] = MIDL_user_allocate( CopyLength[ NextBufferIndex ] );
  1029. if (DestBuffers[NextBufferIndex] == NULL) {
  1030. Status = STATUS_NO_MEMORY;
  1031. break;
  1032. }
  1033. PolicyDnsDomainInfo->Sid =
  1034. (PLSAPR_SID) DestBuffers[NextBufferIndex];
  1035. SourceBuffers[NextBufferIndex] =
  1036. ((PLSAPR_POLICY_DNS_DOMAIN_INFO) LsapDbPolicy.Info[
  1037. InformationClass].Attribute)->Sid;
  1038. NextBufferIndex++;
  1039. }
  1040. //
  1041. // if there is a '.' at the end of DnsDomainName or DnsForestName,
  1042. // remove it
  1043. //
  1044. LsapRemoveTrailingDot(
  1045. (PUNICODE_STRING) &PolicyDnsDomainInfo->DnsDomainName, FALSE);
  1046. LsapRemoveTrailingDot(
  1047. (PUNICODE_STRING) &PolicyDnsDomainInfo->DnsForestName, FALSE);
  1048. break;
  1049. case PolicyAccountDomainInformation:
  1050. PolicyAccountDomainInfo = (PLSAPR_POLICY_ACCOUNT_DOM_INFO) OutputBuffer;
  1051. //
  1052. // Setup to copy the Unicode Name Buffer
  1053. //
  1054. CopyLength[ NextBufferIndex ] = (ULONG) PolicyAccountDomainInfo->DomainName.MaximumLength;
  1055. if (CopyLength[ NextBufferIndex ] > 0) {
  1056. DestBuffers[NextBufferIndex] = MIDL_user_allocate( CopyLength[ NextBufferIndex ] );
  1057. if (DestBuffers[NextBufferIndex] == NULL) {
  1058. Status = STATUS_NO_MEMORY;
  1059. break;
  1060. }
  1061. PolicyAccountDomainInfo->DomainName.Buffer =
  1062. (PWSTR) DestBuffers[NextBufferIndex];
  1063. SourceBuffers[NextBufferIndex] =
  1064. ((PLSAPR_POLICY_ACCOUNT_DOM_INFO) LsapDbPolicy.Info[ InformationClass].Attribute)->DomainName.Buffer;
  1065. NextBufferIndex++;
  1066. }
  1067. //
  1068. // Setup to copy the Sid (if any)
  1069. //
  1070. if (PolicyAccountDomainInfo->DomainSid != NULL) {
  1071. CopyLength[ NextBufferIndex ] = RtlLengthSid(PolicyAccountDomainInfo->DomainSid);
  1072. DestBuffers[NextBufferIndex] = MIDL_user_allocate( CopyLength[ NextBufferIndex ] );
  1073. if (DestBuffers[NextBufferIndex] == NULL) {
  1074. Status = STATUS_NO_MEMORY;
  1075. break;
  1076. }
  1077. PolicyAccountDomainInfo->DomainSid =
  1078. (PLSAPR_SID) DestBuffers[NextBufferIndex];
  1079. SourceBuffers[NextBufferIndex] =
  1080. ((PLSAPR_POLICY_ACCOUNT_DOM_INFO) LsapDbPolicy.Info[ InformationClass].Attribute)->DomainSid;
  1081. NextBufferIndex++;
  1082. }
  1083. break;
  1084. case PolicyPdAccountInformation:
  1085. PolicyPdAccountInfo = (PLSAPR_POLICY_PD_ACCOUNT_INFO) OutputBuffer;
  1086. //
  1087. // Setup to copy the Unicode Name Buffer
  1088. //
  1089. CopyLength[ NextBufferIndex ] = (ULONG) PolicyPdAccountInfo->Name.MaximumLength;
  1090. if (CopyLength[ NextBufferIndex ] > 0) {
  1091. DestBuffers[NextBufferIndex] = MIDL_user_allocate( CopyLength[ NextBufferIndex ] );
  1092. if (DestBuffers[NextBufferIndex] == NULL) {
  1093. Status = STATUS_NO_MEMORY;
  1094. break;
  1095. }
  1096. PolicyPdAccountInfo->Name.Buffer =
  1097. (PWSTR) DestBuffers[NextBufferIndex];
  1098. SourceBuffers[NextBufferIndex] =
  1099. ((PLSAPR_POLICY_PD_ACCOUNT_INFO) LsapDbPolicy.Info[ InformationClass].Attribute)->Name.Buffer;
  1100. NextBufferIndex++;
  1101. }
  1102. break;
  1103. case PolicyReplicaSourceInformation:
  1104. PolicyReplicaSourceInfo = (PLSAPR_POLICY_REPLICA_SRCE_INFO) OutputBuffer;
  1105. //
  1106. // Setup to copy the Unicode Name Buffer
  1107. //
  1108. CopyLength[ NextBufferIndex ] =
  1109. (ULONG) PolicyReplicaSourceInfo->ReplicaSource.MaximumLength;
  1110. if (CopyLength[ NextBufferIndex ] > 0) {
  1111. DestBuffers[NextBufferIndex] = MIDL_user_allocate( CopyLength[ NextBufferIndex ] );
  1112. if (DestBuffers[NextBufferIndex] == NULL) {
  1113. Status = STATUS_NO_MEMORY;
  1114. break;
  1115. }
  1116. PolicyReplicaSourceInfo->ReplicaSource.Buffer =
  1117. (PWSTR) DestBuffers[NextBufferIndex];
  1118. SourceBuffers[NextBufferIndex] =
  1119. ((PLSAPR_POLICY_REPLICA_SRCE_INFO) LsapDbPolicy.Info[ InformationClass].
  1120. Attribute)->ReplicaSource.Buffer;
  1121. NextBufferIndex++;
  1122. }
  1123. CopyLength[ NextBufferIndex ] = (ULONG) PolicyReplicaSourceInfo->ReplicaAccountName.MaximumLength;
  1124. if (CopyLength[ NextBufferIndex ] > 0) {
  1125. DestBuffers[NextBufferIndex] = MIDL_user_allocate( CopyLength[ NextBufferIndex ] );
  1126. if (DestBuffers[NextBufferIndex] == NULL) {
  1127. Status = STATUS_NO_MEMORY;
  1128. break;
  1129. }
  1130. PolicyReplicaSourceInfo->ReplicaAccountName.Buffer =
  1131. (PWSTR) DestBuffers[NextBufferIndex];
  1132. SourceBuffers[NextBufferIndex] =
  1133. ((PLSAPR_POLICY_REPLICA_SRCE_INFO) LsapDbPolicy.Info[ InformationClass].Attribute)->ReplicaAccountName.Buffer;
  1134. NextBufferIndex++;
  1135. }
  1136. break;
  1137. case PolicyDefaultQuotaInformation:
  1138. break;
  1139. case PolicyModificationInformation:
  1140. break;
  1141. case PolicyAuditFullQueryInformation:
  1142. Status = STATUS_NOT_SUPPORTED;
  1143. break;
  1144. default:
  1145. Status = STATUS_INVALID_PARAMETER;
  1146. break;
  1147. }
  1148. if (!NT_SUCCESS(Status)) {
  1149. goto QueryInformationPolicyError;
  1150. }
  1151. BufferCount = NextBufferIndex;
  1152. //
  1153. // Now copy the graph of the output (if any) to the pre-allocated buffers.
  1154. //
  1155. if (BufferCount > 0) {
  1156. for (NextBufferIndex = 0; NextBufferIndex < BufferCount; NextBufferIndex++) {
  1157. RtlCopyMemory(
  1158. DestBuffers[NextBufferIndex],
  1159. SourceBuffers[NextBufferIndex],
  1160. CopyLength[NextBufferIndex]
  1161. );
  1162. }
  1163. }
  1164. if (!BufferProvided) {
  1165. *Buffer = OutputBuffer;
  1166. }
  1167. QueryInformationPolicyFinish:
  1168. if ( PolicyCacheLocked ) {
  1169. SafeReleaseResource( &LsapDbState.PolicyCacheLock );
  1170. }
  1171. LsapExitFunc( "LsapDbQueryInformationPolicy", Status );
  1172. return(Status);
  1173. QueryInformationPolicyError:
  1174. if (BufferAllocated) {
  1175. MIDL_user_free(OutputBuffer);
  1176. OutputBuffer = *Buffer = NULL;
  1177. BufferAllocated = FALSE;
  1178. }
  1179. BufferCount = NextBufferIndex;
  1180. if (BufferCount > 0) {
  1181. for ( NextBufferIndex = 0; NextBufferIndex < BufferCount; NextBufferIndex++ ) {
  1182. MIDL_user_free( DestBuffers[ NextBufferIndex ] );
  1183. DestBuffers[ NextBufferIndex] = NULL;
  1184. }
  1185. }
  1186. goto QueryInformationPolicyFinish;
  1187. }
  1188. NTSTATUS
  1189. LsapDbSlowQueryInformationPolicy(
  1190. IN LSAPR_HANDLE PolicyHandle,
  1191. IN POLICY_INFORMATION_CLASS InformationClass,
  1192. IN OUT PLSAPR_POLICY_INFORMATION *Buffer
  1193. )
  1194. /*++
  1195. Routine Description:
  1196. This function is the slow LSA server RPC worker routine for the
  1197. LsarQueryInformationPolicy API. It actually reads the information
  1198. from backing storage.
  1199. The LsaQueryInformationPolicy API obtains information from the Policy
  1200. object. The caller must have access appropriate to the information
  1201. being requested (see InformationClass parameter).
  1202. N.B. During Ds Repair mode (ie LsaISafeMode() returning TRUE), this
  1203. routines returns the Primary and Dns information as if we are part
  1204. of a workgroup called WORKGROUP. This is because in this diagnostic mode
  1205. we are using the local account database of SAM and do not have a valid
  1206. machine account for a domain. Also the account domain name is the name
  1207. of the computer.
  1208. Arguments:
  1209. PolicyHandle - Handle from an LsaOpenPolicy call.
  1210. InformationClass - Specifies the information to be returned. The
  1211. Information Classes and accesses required are as follows:
  1212. Information Class Required Access Type
  1213. PolicyAuditLogInformation POLICY_VIEW_AUDIT_INFORMATION
  1214. PolicyAuditEventsInformation POLICY_VIEW_AUDIT_INFORMATION
  1215. PolicyPrimaryDomainInformation POLICY_VIEW_LOCAL_INFORMATION
  1216. PolicyAccountDomainInformation POLICY_VIEW_LOCAL_INFORMATION
  1217. PolicyPdAccountInformation POLICY_GET_PRIVATE_INFORMATION
  1218. PolicyReplicaSourceInformation POLICY_VIEW_LOCAL_INFORMATION
  1219. PolicyDefaultQuotaInformation POLICY_VIEW_LOCAL_INFORMATION
  1220. PolicyAuditFullQueryInformation POLICY_VIEW_AUDIT_INFORMATION
  1221. Buffer - Pointer to location that contains either a pointer to the
  1222. buffer that will be used to return the information. If NULL
  1223. is contained in this location, a buffer will be allocated via
  1224. MIDL_user_allocate and a pointer to it returned.
  1225. Return Value:
  1226. NTSTATUS - Standard Nt Result Code
  1227. STATUS_ACCESS_DENIED - Caller does not have the appropriate
  1228. access to complete the operation.
  1229. STATUS_INTERNAL_DB_CORRUPTION - The Policy Database is possibly
  1230. corrupt. The returned Policy Information is invalid for
  1231. the given class.
  1232. --*/
  1233. {
  1234. NTSTATUS Status = STATUS_SUCCESS;
  1235. PPOLICY_AUDIT_EVENTS_INFO PolicyAuditEventsInfo;
  1236. PPOLICY_ACCOUNT_DOMAIN_INFO PolicyAccountDomainInfo;
  1237. PPOLICY_PRIMARY_DOMAIN_INFO PolicyPrimaryDomainInfo;
  1238. PPOLICY_DNS_DOMAIN_INFO PolicyDnsDomainInfo;
  1239. PPOLICY_PD_ACCOUNT_INFO PolicyPdAccountInfo;
  1240. PPOLICY_REPLICA_SOURCE_INFO PolicyReplicaSourceInfo;
  1241. PPOLICY_AUDIT_FULL_QUERY_INFO PolicyAuditFullQueryInfo;
  1242. PLSARM_POLICY_AUDIT_EVENTS_INFO DbPolicyAuditEventsInfo = NULL;
  1243. ULONG PolicyAuditEventsInfoLength = sizeof (LSARM_POLICY_AUDIT_EVENTS_INFO);
  1244. ULONG AttributeCount = 0;
  1245. ULONG AttributeNumber = 0;
  1246. ULONG AuditListCopySize;
  1247. PVOID InformationBuffer = NULL;
  1248. LSAP_DB_ATTRIBUTE Attributes[LSAP_DB_ATTRS_INFO_CLASS_POLICY];
  1249. PLSAP_DB_ATTRIBUTE NextAttribute;
  1250. BOOLEAN ObjectReferenced = FALSE;
  1251. LSAP_DB_HANDLE InternalHandle = (LSAP_DB_HANDLE) PolicyHandle;
  1252. BOOLEAN InfoBufferInAttributeArray = TRUE;
  1253. BOOLEAN BufferProvided = FALSE;
  1254. PVOID FreeList[ 4 ];
  1255. ULONG FreeCount = 0;
  1256. LsapEnterFunc( "LsapDbSlowQueryInformationPolicy" );
  1257. if (*Buffer != NULL) {
  1258. BufferProvided = TRUE;
  1259. }
  1260. //
  1261. // Compile a list of the attributes that hold the Policy Information of
  1262. // the specified class.
  1263. //
  1264. NextAttribute = Attributes;
  1265. switch (InformationClass) {
  1266. case PolicyAuditLogInformation:
  1267. //
  1268. // Request read of the Audit Log Information.
  1269. //
  1270. LsapDbInitializeAttributeDs(
  1271. NextAttribute,
  1272. PolAdtLg,
  1273. NULL,
  1274. sizeof(POLICY_AUDIT_LOG_INFO),
  1275. FALSE
  1276. );
  1277. NextAttribute++;
  1278. AttributeCount++;
  1279. break;
  1280. case PolicyAuditEventsInformation:
  1281. //
  1282. // Request read of the Audit Events Information.
  1283. // intermediate buffer.
  1284. //
  1285. LsapDbInitializeAttributeDs(
  1286. NextAttribute,
  1287. PolAdtEv,
  1288. NULL,
  1289. sizeof(LSARM_POLICY_AUDIT_EVENTS_INFO),
  1290. FALSE
  1291. );
  1292. NextAttribute++;
  1293. AttributeCount++;
  1294. break;
  1295. case PolicyDnsDomainInformation:
  1296. //
  1297. // Request read of the Dns Domain Name attribute
  1298. //
  1299. LsapDbInitializeAttributeDs(
  1300. NextAttribute,
  1301. PolDnDDN,
  1302. NULL,
  1303. 0,
  1304. FALSE
  1305. );
  1306. NextAttribute++;
  1307. AttributeCount++;
  1308. //
  1309. // Request read of the Dns Tree Name attribute
  1310. //
  1311. LsapDbInitializeAttributeDs(
  1312. NextAttribute,
  1313. PolDnTrN,
  1314. NULL,
  1315. 0,
  1316. FALSE
  1317. );
  1318. NextAttribute++;
  1319. AttributeCount++;
  1320. //
  1321. // Request read of the Dns Domain Guid attribute
  1322. //
  1323. LsapDbInitializeAttributeDs(
  1324. NextAttribute,
  1325. PolDnDmG,
  1326. NULL,
  1327. 0,
  1328. FALSE
  1329. );
  1330. NextAttribute++;
  1331. AttributeCount++;
  1332. //
  1333. // FALL THROUGH to PolicyPrimaryDomainInformation
  1334. //
  1335. case PolicyPrimaryDomainInformation:
  1336. //
  1337. // Request read of the DomainName attribute
  1338. //
  1339. LsapDbInitializeAttributeDs(
  1340. NextAttribute,
  1341. PolPrDmN,
  1342. NULL,
  1343. 0,
  1344. FALSE
  1345. );
  1346. NextAttribute++;
  1347. AttributeCount++;
  1348. //
  1349. // Request read of the Sid attribute
  1350. //
  1351. LsapDbInitializeAttributeDs(
  1352. NextAttribute,
  1353. PolPrDmS,
  1354. NULL,
  1355. 0,
  1356. FALSE
  1357. );
  1358. NextAttribute++;
  1359. AttributeCount++;
  1360. break;
  1361. case PolicyAccountDomainInformation:
  1362. //
  1363. // Request read of the DomainName attribute
  1364. //
  1365. LsapDbInitializeAttributeDs(
  1366. NextAttribute,
  1367. PolAcDmN,
  1368. NULL,
  1369. 0,
  1370. FALSE
  1371. );
  1372. NextAttribute++;
  1373. AttributeCount++;
  1374. //
  1375. // Request read of the Sid attribute
  1376. //
  1377. LsapDbInitializeAttributeDs(
  1378. NextAttribute,
  1379. PolAcDmS,
  1380. NULL,
  1381. 0,
  1382. FALSE
  1383. );
  1384. NextAttribute++;
  1385. AttributeCount++;
  1386. break;
  1387. case PolicyPdAccountInformation:
  1388. //
  1389. // Request read of the DomainName attribute
  1390. //
  1391. LsapDbInitializeAttributeDs(
  1392. NextAttribute,
  1393. PolPdAcN,
  1394. NULL,
  1395. 0,
  1396. FALSE
  1397. );
  1398. NextAttribute++;
  1399. AttributeCount++;
  1400. break;
  1401. case PolicyReplicaSourceInformation:
  1402. //
  1403. // Request read of the Replica Source attribute
  1404. //
  1405. LsapDbInitializeAttributeDs(
  1406. NextAttribute,
  1407. PolRepSc,
  1408. NULL,
  1409. 0,
  1410. FALSE
  1411. );
  1412. NextAttribute++;
  1413. AttributeCount++;
  1414. //
  1415. // Request read of the Replica Account Name attribute
  1416. //
  1417. LsapDbInitializeAttributeDs(
  1418. NextAttribute,
  1419. PolRepAc,
  1420. NULL,
  1421. 0,
  1422. FALSE
  1423. );
  1424. NextAttribute++;
  1425. AttributeCount++;
  1426. break;
  1427. case PolicyDefaultQuotaInformation:
  1428. //
  1429. // Request read of the Default Quota attribute.
  1430. //
  1431. LsapDbInitializeAttributeDs(
  1432. NextAttribute,
  1433. DefQuota,
  1434. NULL,
  1435. sizeof (POLICY_DEFAULT_QUOTA_INFO),
  1436. FALSE
  1437. );
  1438. NextAttribute++;
  1439. AttributeCount++;
  1440. break;
  1441. case PolicyModificationInformation:
  1442. //
  1443. // Request read of the Policy Modification Information
  1444. //
  1445. LsapDbInitializeAttributeDs(
  1446. NextAttribute,
  1447. PolMod,
  1448. NULL,
  1449. sizeof (POLICY_MODIFICATION_INFO),
  1450. FALSE
  1451. );
  1452. NextAttribute++;
  1453. AttributeCount++;
  1454. break;
  1455. case PolicyAuditFullQueryInformation:
  1456. Status = STATUS_NOT_SUPPORTED;
  1457. break;
  1458. default:
  1459. Status = STATUS_INVALID_PARAMETER;
  1460. break;
  1461. }
  1462. if (!NT_SUCCESS(Status)) {
  1463. goto SlowQueryInformationPolicyError;
  1464. }
  1465. //
  1466. //
  1467. // Read the attributes corresponding to the given Policy Information
  1468. // Class. Memory will be allocated where required for output
  1469. // Attribute Value buffers, via MIDL_user_allocate().
  1470. //
  1471. Status = LsapDbReadAttributesObject( PolicyHandle,
  1472. 0,
  1473. Attributes,
  1474. AttributeCount );
  1475. if (!NT_SUCCESS(Status)) {
  1476. //
  1477. // Some attributes may not exist because they were never set
  1478. // or were deleted because they were set to NULL values.
  1479. //
  1480. if (Status != STATUS_OBJECT_NAME_NOT_FOUND ) {
  1481. goto SlowQueryInformationPolicyError;
  1482. }
  1483. Status = STATUS_SUCCESS;
  1484. }
  1485. //
  1486. // Now copy the information read to the output. The following flags
  1487. // are used to control freeing of memory buffers:
  1488. //
  1489. // InfoBufferInAttributeArray
  1490. //
  1491. // If set to TRUE (the default), the information to be returned to
  1492. // the caller consists of a single buffer which was read directly
  1493. // from a single attribute of the Policy object and can be returned
  1494. // as is to the caller. The information buffer being returned is
  1495. // therefore referenced by the single Attribute Information block's
  1496. // AttributeValue field.
  1497. //
  1498. // If set to FALSE, the information to be returned to the caller
  1499. // does not satisfy the above. The information to be returned is
  1500. // either obtained from a single attribute, but is in a different form
  1501. // from that read from the Database, or it is complex, consisting
  1502. // of information read from multiple attributes, hung off a top-level
  1503. // node. In these cases, the top level information buffer is not
  1504. // referenced by any member of the Attribute Info Array.
  1505. //
  1506. // Attribute->MemoryAllocated
  1507. //
  1508. // When an attribute is read via LsapDbReadAttributesObject, this
  1509. // field is set to TRUE to indicate that memory was allocated via
  1510. // MIDL_user_allocate() for the AttributeValue. If this memory
  1511. // buffer is to be returned to the caller (i.e. referenced from
  1512. // the output structure graph returned), it is set to FALSE so that
  1513. // the normal success finish part of this routine will not free it.
  1514. // In this case, the calling server RPC stub will free the memory after
  1515. // marshalling its contents into the return buffer. If this memory
  1516. // buffer is not to be returned to the calling RPC server stub (because
  1517. // the memory is an intermediate buffer), the field is left set to TRUE
  1518. // so that normal cleanup will free it.
  1519. //
  1520. NextAttribute = Attributes;
  1521. switch (InformationClass) {
  1522. case PolicyAuditLogInformation:
  1523. InformationBuffer = NextAttribute->AttributeValue;
  1524. //
  1525. // We can use this buffer as is, so we don't want to free it here.
  1526. //
  1527. NextAttribute->MemoryAllocated = FALSE;
  1528. break;
  1529. case PolicyAuditEventsInformation:
  1530. //
  1531. // An intermediate buffer is required, because the Audit Events
  1532. // read from the database are in a different form from those
  1533. // returned.
  1534. //
  1535. DbPolicyAuditEventsInfo = NextAttribute->AttributeValue;
  1536. InfoBufferInAttributeArray = FALSE;
  1537. //
  1538. // Allocate Buffer for output in final format. This differs
  1539. // slightly from the self-relative format in which this
  1540. // Information Class is stored.
  1541. //
  1542. PolicyAuditEventsInfo = MIDL_user_allocate(sizeof (POLICY_AUDIT_EVENTS_INFO));
  1543. if (PolicyAuditEventsInfo == NULL) {
  1544. Status = STATUS_INSUFFICIENT_RESOURCES;
  1545. break;
  1546. }
  1547. FreeList[ FreeCount++ ] = PolicyAuditEventsInfo;
  1548. //
  1549. // Need to allocate memory via MIDL_user_allocate for the
  1550. // EventAuditingOptions pointer since we are not using
  1551. // the midl allocate_all_nodes feature for the LSAPR_POLICY_INFORMATION
  1552. // structure graph on this server side.
  1553. //
  1554. PolicyAuditEventsInfo->EventAuditingOptions =
  1555. MIDL_user_allocate( LSARM_AUDIT_EVENT_OPTIONS_SIZE );
  1556. if (PolicyAuditEventsInfo->EventAuditingOptions == NULL) {
  1557. Status = STATUS_INSUFFICIENT_RESOURCES;
  1558. break;
  1559. }
  1560. FreeList[ FreeCount++ ] = PolicyAuditEventsInfo->EventAuditingOptions;
  1561. RtlZeroMemory( PolicyAuditEventsInfo->EventAuditingOptions,
  1562. LSARM_AUDIT_EVENT_OPTIONS_SIZE );
  1563. //
  1564. // If Policy Audit Event Info was read from the LSA Database, copy
  1565. // its fields to output, otherwise return values with Auditing
  1566. // Disabled and no Auditing set foro any Event Types.
  1567. //
  1568. if (DbPolicyAuditEventsInfo != NULL) {
  1569. PolicyAuditEventsInfo->AuditingMode = DbPolicyAuditEventsInfo->AuditingMode;
  1570. PolicyAuditEventsInfo->MaximumAuditEventCount =
  1571. DbPolicyAuditEventsInfo->MaximumAuditEventCount;
  1572. //
  1573. // We need to be careful here. NT4 stored registry information as:
  1574. // AuditMode - List of Audit Event Entries - Audit Entries Count.
  1575. // Since NT5 added additional audit events, we need to handle that case here...
  1576. //
  1577. AuditListCopySize = POLICY_AUDIT_EVENT_TYPE_COUNT;
  1578. if ( NextAttribute->AttributeValueLength / sizeof( POLICY_AUDIT_EVENT_OPTIONS ) !=
  1579. POLICY_AUDIT_EVENT_TYPE_COUNT + 2 ) {
  1580. ASSERT( NextAttribute->AttributeValueLength / sizeof( POLICY_AUDIT_EVENT_OPTIONS ) ==
  1581. POLICY_AUDIT_EVENT_TYPE_COUNT );
  1582. AuditListCopySize -= 2;
  1583. }
  1584. //
  1585. // Copy over the Event Auditing Options
  1586. //
  1587. RtlCopyMemory(
  1588. PolicyAuditEventsInfo->EventAuditingOptions,
  1589. DbPolicyAuditEventsInfo->EventAuditingOptions,
  1590. AuditListCopySize * sizeof( POLICY_AUDIT_EVENT_OPTIONS ) );
  1591. PolicyAuditEventsInfo->MaximumAuditEventCount = AuditListCopySize;
  1592. } else {
  1593. PolicyAuditEventsInfo->AuditingMode = FALSE;
  1594. PolicyAuditEventsInfo->MaximumAuditEventCount = POLICY_AUDIT_EVENT_TYPE_COUNT;
  1595. }
  1596. InformationBuffer = PolicyAuditEventsInfo;
  1597. break;
  1598. case PolicyDnsDomainInformation:
  1599. //
  1600. // Allocate memory for output buffer top-level structure.
  1601. //
  1602. InfoBufferInAttributeArray = FALSE;
  1603. PolicyDnsDomainInfo = MIDL_user_allocate(sizeof(POLICY_DNS_DOMAIN_INFO));
  1604. if (PolicyDnsDomainInfo == NULL) {
  1605. Status = STATUS_INSUFFICIENT_RESOURCES;
  1606. break;
  1607. }
  1608. FreeList[ FreeCount++ ] = PolicyDnsDomainInfo;
  1609. //
  1610. // Copy the DnsDomain Name field to the output. Original buffer will
  1611. // be freed in Finish section.
  1612. //
  1613. if ( LsaISafeMode() ) {
  1614. RtlInitUnicodeString( &PolicyDnsDomainInfo->DnsDomainName, NULL );
  1615. } else {
  1616. Status = LsapDbCopyUnicodeAttribute(
  1617. &PolicyDnsDomainInfo->DnsDomainName,
  1618. NextAttribute,
  1619. TRUE
  1620. );
  1621. if (!NT_SUCCESS(Status)) {
  1622. break;
  1623. }
  1624. }
  1625. FreeList[ FreeCount++ ] = PolicyDnsDomainInfo->DnsDomainName.Buffer;
  1626. NextAttribute++;
  1627. //
  1628. // Next, the Dns tree name
  1629. if ( LsaISafeMode() ) {
  1630. RtlInitUnicodeString( &PolicyDnsDomainInfo->DnsForestName, NULL );
  1631. } else {
  1632. Status = LsapDbCopyUnicodeAttribute(
  1633. &PolicyDnsDomainInfo->DnsForestName,
  1634. NextAttribute,
  1635. TRUE
  1636. );
  1637. if (!NT_SUCCESS(Status)) {
  1638. break;
  1639. }
  1640. }
  1641. FreeList[ FreeCount++ ] = PolicyDnsDomainInfo->DnsForestName.Buffer;
  1642. NextAttribute++;
  1643. //
  1644. // Next, the Domain Guid
  1645. //
  1646. if ( LsaISafeMode() ) {
  1647. RtlZeroMemory(&PolicyDnsDomainInfo->DomainGuid, sizeof(GUID));
  1648. } else {
  1649. if(NextAttribute->AttributeValue != NULL) {
  1650. RtlCopyMemory(&PolicyDnsDomainInfo->DomainGuid,
  1651. NextAttribute->AttributeValue,
  1652. sizeof(GUID));
  1653. } else {
  1654. RtlZeroMemory(&PolicyDnsDomainInfo->DomainGuid, sizeof(GUID));
  1655. }
  1656. }
  1657. NextAttribute++;
  1658. //
  1659. // Copy the primary domain name field from the Primary Domain information buffer
  1660. //
  1661. if ( LsaISafeMode() ) {
  1662. WCHAR Workgroup[] = L"WORKGROUP";
  1663. LPWSTR Buffer = midl_user_allocate( sizeof(Workgroup) );
  1664. if ( !Buffer ) {
  1665. Status = STATUS_INSUFFICIENT_RESOURCES;
  1666. break;
  1667. }
  1668. wcscpy( Buffer, Workgroup );
  1669. RtlInitUnicodeString( &PolicyDnsDomainInfo->Name, Buffer );
  1670. } else {
  1671. Status = LsapDbCopyUnicodeAttribute(
  1672. &PolicyDnsDomainInfo->Name,
  1673. NextAttribute,
  1674. TRUE
  1675. );
  1676. if (!NT_SUCCESS(Status)) {
  1677. break;
  1678. }
  1679. }
  1680. FreeList[ FreeCount++ ] = PolicyDnsDomainInfo->Name.Buffer;
  1681. NextAttribute++;
  1682. //
  1683. // Finally, the domain SID
  1684. //
  1685. if ( LsaISafeMode() ) {
  1686. PolicyDnsDomainInfo->Sid = NULL;
  1687. } else {
  1688. PolicyDnsDomainInfo->Sid = (PSID) NextAttribute->AttributeValue;
  1689. NextAttribute->MemoryAllocated = FALSE;
  1690. }
  1691. InformationBuffer = PolicyDnsDomainInfo;
  1692. break;
  1693. case PolicyPrimaryDomainInformation:
  1694. //
  1695. // Allocate memory for output buffer top-level structure.
  1696. //
  1697. InfoBufferInAttributeArray = FALSE;
  1698. PolicyPrimaryDomainInfo =
  1699. MIDL_user_allocate(sizeof (POLICY_PRIMARY_DOMAIN_INFO));
  1700. if (PolicyPrimaryDomainInfo == NULL) {
  1701. Status = STATUS_INSUFFICIENT_RESOURCES;
  1702. break;
  1703. }
  1704. FreeList[ FreeCount++ ] = PolicyPrimaryDomainInfo;
  1705. //
  1706. // Copy the Unicode Name field to the output. Original buffer will
  1707. // be freed in Finish section.
  1708. //
  1709. if ( LsaISafeMode() ) {
  1710. WCHAR Workgroup[] = L"WORKGROUP";
  1711. LPWSTR Buffer = midl_user_allocate( sizeof(Workgroup) );
  1712. if ( !Buffer ) {
  1713. Status = STATUS_INSUFFICIENT_RESOURCES;
  1714. break;
  1715. }
  1716. wcscpy( Buffer, Workgroup );
  1717. RtlInitUnicodeString( &PolicyPrimaryDomainInfo->Name, Buffer );
  1718. } else {
  1719. Status = LsapDbCopyUnicodeAttribute(
  1720. &PolicyPrimaryDomainInfo->Name,
  1721. NextAttribute,
  1722. TRUE
  1723. );
  1724. if (!NT_SUCCESS(Status)) {
  1725. break;
  1726. }
  1727. }
  1728. FreeList[ FreeCount++ ] = PolicyPrimaryDomainInfo->Name.Buffer;
  1729. NextAttribute++;
  1730. //
  1731. // Copy the Sid to the output. We can use this buffer as is
  1732. // since it was allocated via MIDL_user_allocate, so just copy the
  1733. // buffer pointer and clear the MemoryAllocated flag in the
  1734. // attribute information so we don't free it in the Finish section.
  1735. //
  1736. if ( LsaISafeMode() ) {
  1737. PolicyPrimaryDomainInfo->Sid = NULL;
  1738. } else {
  1739. PolicyPrimaryDomainInfo->Sid = (PSID) NextAttribute->AttributeValue;
  1740. NextAttribute->MemoryAllocated = FALSE;
  1741. }
  1742. InformationBuffer = PolicyPrimaryDomainInfo;
  1743. break;
  1744. case PolicyAccountDomainInformation:
  1745. //
  1746. // Allocate memory for output buffer top-level structure.
  1747. //
  1748. InfoBufferInAttributeArray = FALSE;
  1749. PolicyAccountDomainInfo =
  1750. MIDL_user_allocate(sizeof(POLICY_ACCOUNT_DOMAIN_INFO));
  1751. if (PolicyAccountDomainInfo == NULL) {
  1752. Status = STATUS_INSUFFICIENT_RESOURCES;
  1753. break;
  1754. }
  1755. FreeList[ FreeCount++ ] = PolicyAccountDomainInfo;
  1756. //
  1757. // Copy the Unicode DomainName field to the output. Original buffer will
  1758. // be freed in Finish section.
  1759. //
  1760. if ( LsaISafeMode() ) {
  1761. WCHAR Buffer[MAX_COMPUTERNAME_LENGTH+1];
  1762. ULONG Size = sizeof(Buffer)/sizeof(Buffer[0]);
  1763. if ( GetComputerName( Buffer, &Size) ) {
  1764. LPWSTR String = MIDL_user_allocate( (Size+1)*sizeof(Buffer[0]) );
  1765. if ( String ) {
  1766. wcscpy( String, Buffer );
  1767. RtlInitUnicodeString( &PolicyAccountDomainInfo->DomainName,
  1768. String );
  1769. } else {
  1770. Status = STATUS_INSUFFICIENT_RESOURCES;
  1771. }
  1772. } else {
  1773. Status = LsapWinerrorToNtStatus( GetLastError() );
  1774. ASSERTMSG( "We need to add the new error code to LsapWinerrorToNtStatus",
  1775. Status != STATUS_INTERNAL_ERROR );
  1776. ASSERTMSG( "Expecting an error!", !NT_SUCCESS( Status ) );
  1777. }
  1778. } else {
  1779. Status = LsapDbCopyUnicodeAttribute(
  1780. &PolicyAccountDomainInfo->DomainName,
  1781. NextAttribute,
  1782. TRUE
  1783. );
  1784. }
  1785. if( NT_SUCCESS( Status ) ) {
  1786. FreeList[ FreeCount++ ] = PolicyAccountDomainInfo->DomainName.Buffer;
  1787. NextAttribute++;
  1788. //
  1789. // Copy the Sid to the output. We can use this buffer as is
  1790. // since it was allocated via MIDL_user_allocate, so just copy the
  1791. // buffer pointer and clear the MemoryAllocated flag in the
  1792. // attribute information so we don't free it in the Finish section.
  1793. //
  1794. PolicyAccountDomainInfo->DomainSid = (PSID) NextAttribute->AttributeValue;
  1795. InformationBuffer = PolicyAccountDomainInfo;
  1796. NextAttribute->MemoryAllocated = FALSE;
  1797. }
  1798. break;
  1799. case PolicyPdAccountInformation:
  1800. //
  1801. // Allocate memory for output buffer top-level structure.
  1802. //
  1803. InfoBufferInAttributeArray = FALSE;
  1804. PolicyPdAccountInfo = MIDL_user_allocate(sizeof(POLICY_PD_ACCOUNT_INFO));
  1805. if (PolicyPdAccountInfo == NULL) {
  1806. Status = STATUS_INSUFFICIENT_RESOURCES;
  1807. break;
  1808. }
  1809. FreeList[ FreeCount++ ] = PolicyPdAccountInfo;
  1810. //
  1811. // Copy the Unicode Name field to the output. Original buffer will
  1812. // be freed in Finish section.
  1813. //
  1814. Status = LsapDbCopyUnicodeAttribute(
  1815. &PolicyPdAccountInfo->Name,
  1816. NextAttribute,
  1817. TRUE
  1818. );
  1819. if (!NT_SUCCESS(Status)) {
  1820. break;
  1821. }
  1822. FreeList[ FreeCount++ ] = PolicyPdAccountInfo->Name.Buffer;
  1823. InformationBuffer = PolicyPdAccountInfo;
  1824. break;
  1825. case PolicyReplicaSourceInformation:
  1826. //
  1827. // Allocate memory for output buffer top-level structure.
  1828. //
  1829. InfoBufferInAttributeArray = FALSE;
  1830. PolicyReplicaSourceInfo =
  1831. MIDL_user_allocate(sizeof(POLICY_REPLICA_SOURCE_INFO));
  1832. if (PolicyReplicaSourceInfo == NULL) {
  1833. Status = STATUS_INSUFFICIENT_RESOURCES;
  1834. break;
  1835. }
  1836. FreeList[ FreeCount++ ] = PolicyReplicaSourceInfo;
  1837. //
  1838. // Copy the Unicode ReplicaSource field to the output. Original buffer will
  1839. // be freed in Finish section.
  1840. //
  1841. Status = LsapDbCopyUnicodeAttribute(
  1842. &PolicyReplicaSourceInfo->ReplicaSource,
  1843. NextAttribute,
  1844. TRUE
  1845. );
  1846. if (!NT_SUCCESS(Status)) {
  1847. break;
  1848. }
  1849. FreeList[ FreeCount++ ] = PolicyReplicaSourceInfo->ReplicaSource.Buffer;
  1850. NextAttribute++;
  1851. //
  1852. // Copy the Unicode ReplicaAccountName field to the output. Original buffer will
  1853. // be freed in Finish section.
  1854. //
  1855. Status = LsapDbCopyUnicodeAttribute(
  1856. &PolicyReplicaSourceInfo->ReplicaAccountName,
  1857. NextAttribute,
  1858. TRUE
  1859. );
  1860. if (!NT_SUCCESS(Status)) {
  1861. break;
  1862. }
  1863. FreeList[ FreeCount++ ] = PolicyReplicaSourceInfo->ReplicaAccountName.Buffer;
  1864. InformationBuffer = PolicyReplicaSourceInfo;
  1865. break;
  1866. case PolicyDefaultQuotaInformation:
  1867. //
  1868. // We can use this buffer as is, so we don't want to free it here.
  1869. //
  1870. InformationBuffer = NextAttribute->AttributeValue;
  1871. NextAttribute->MemoryAllocated = FALSE;
  1872. break;
  1873. case PolicyModificationInformation:
  1874. //
  1875. // We can use this buffer as is, so we don't want to free it here.
  1876. //
  1877. InformationBuffer = NextAttribute->AttributeValue;
  1878. NextAttribute->MemoryAllocated = FALSE;
  1879. break;
  1880. case PolicyAuditFullSetInformation:
  1881. Status = STATUS_NOT_SUPPORTED;
  1882. break;
  1883. case PolicyAuditFullQueryInformation:
  1884. Status = STATUS_NOT_SUPPORTED;
  1885. break;
  1886. default:
  1887. Status = STATUS_INVALID_PARAMETER;
  1888. break;
  1889. }
  1890. if (!NT_SUCCESS(Status)) {
  1891. goto SlowQueryInformationPolicyError;
  1892. }
  1893. //
  1894. // Verify that the returned Policy Information is valid. If not,
  1895. // the Policy Database is corrupt.
  1896. //
  1897. if (!LsapDbValidInfoPolicy(InformationClass, InformationBuffer)) {
  1898. ASSERT( FALSE );
  1899. Status = STATUS_INTERNAL_DB_CORRUPTION;
  1900. PolicyAccountDomainInfo = InformationBuffer;
  1901. goto SlowQueryInformationPolicyError;
  1902. }
  1903. //
  1904. // If the caller provided a buffer, return information there.
  1905. //
  1906. if (BufferProvided && InformationBuffer) {
  1907. RtlCopyMemory(
  1908. *Buffer,
  1909. InformationBuffer,
  1910. LsapDbPolicy.Info[ InformationClass ].AttributeLength
  1911. );
  1912. MIDL_user_free( InformationBuffer );
  1913. InformationBuffer = NULL;
  1914. } else {
  1915. *Buffer = InformationBuffer;
  1916. }
  1917. SlowQueryInformationPolicyFinish:
  1918. //
  1919. // Free any unwanted buffers that were allocated by
  1920. // LsapDbReadAttributesObject() and that are not being returned to the
  1921. // caller server stub. The server stub will free the buffers that we
  1922. // do return after copying them to the return RPC transmit buffer.
  1923. //
  1924. for (NextAttribute = Attributes, AttributeNumber = 0;
  1925. AttributeNumber < AttributeCount;
  1926. NextAttribute++, AttributeNumber++) {
  1927. //
  1928. // If buffer holding attribute is marked as allocated, it is
  1929. // to be freed here.
  1930. //
  1931. if (NextAttribute->MemoryAllocated) {
  1932. if (NextAttribute->AttributeValue != NULL) {
  1933. MIDL_user_free(NextAttribute->AttributeValue);
  1934. NextAttribute->AttributeValue = NULL;
  1935. NextAttribute->MemoryAllocated = FALSE;
  1936. }
  1937. }
  1938. }
  1939. LsapExitFunc( "LsapDbSlowQueryInformationPolicy", Status );
  1940. return(Status);
  1941. SlowQueryInformationPolicyError:
  1942. //
  1943. // If necessary, free the memory allocated for the output buffer.
  1944. // We only do this free if the buffer is not referenced by the
  1945. // attribute array, since all buffers so referenced will be freed
  1946. // here or in the Finish section.
  1947. //
  1948. if ((InformationBuffer != NULL) && !InfoBufferInAttributeArray) {
  1949. MIDL_user_free(InformationBuffer);
  1950. InformationBuffer = NULL;
  1951. }
  1952. //
  1953. // Free the buffers referenced by the attributes array that will not be
  1954. // freed by the Finish section of this routine.
  1955. //
  1956. for (NextAttribute = Attributes, AttributeNumber = 0;
  1957. AttributeNumber < AttributeCount;
  1958. NextAttribute++, AttributeNumber++) {
  1959. //
  1960. // If buffer holding attribute is marked as normally not to be freed,
  1961. // will not get freed by the Finish section so it must be freed here.
  1962. //
  1963. if (!NextAttribute->MemoryAllocated) {
  1964. if (NextAttribute->AttributeValue != NULL) {
  1965. MIDL_user_free(NextAttribute->AttributeValue);
  1966. NextAttribute->AttributeValue = NULL;
  1967. NextAttribute->MemoryAllocated = FALSE;
  1968. }
  1969. NextAttribute->MemoryAllocated = FALSE;
  1970. }
  1971. }
  1972. //
  1973. // Free the free list, if it exists. Always delete the list backwards - the opposite order
  1974. // of allocation
  1975. //
  1976. ASSERT( FreeCount < sizeof( FreeList ) / sizeof( PVOID ) );
  1977. while( FreeCount != 0 ) {
  1978. MIDL_user_free( FreeList[ FreeCount - 1 ]);
  1979. FreeCount--;
  1980. }
  1981. goto SlowQueryInformationPolicyFinish;
  1982. }
  1983. NTSTATUS
  1984. LsarSetInformationPolicy(
  1985. IN LSAPR_HANDLE PolicyHandle,
  1986. IN POLICY_INFORMATION_CLASS InformationClass,
  1987. IN PLSAPR_POLICY_INFORMATION PolicyInformation
  1988. )
  1989. /*++
  1990. Routine Description:
  1991. This function is the LSA server RPC worker routine for the
  1992. LsaSetInformationPolicy API.
  1993. The LsaSetInformationPolicy API modifies information in the Policy Object.
  1994. The caller must have access appropriate to the information to be changed
  1995. in the Policy Object, see the InformationClass parameter.
  1996. Arguments:
  1997. PolicyHandle - Handle from an LsaOpenPolicy call.
  1998. InformationClass - Specifies the type of information being changed.
  1999. The information types and accesses required to change them are as
  2000. follows:
  2001. PolicyAuditLogInformation POLICY_AUDIT_LOG_ADMIN
  2002. PolicyAuditEventsInformation POLICY_SET_AUDIT_REQUIREMENTS
  2003. PolicyPrimaryDomainInformation POLICY_TRUST_ADMIN
  2004. PolicyAccountDomainInformation POLICY_TRUST_ADMIN
  2005. PolicyPdAccountInformation Not settable by this API
  2006. PolicyLsaServerRoleInformation POLICY_SERVER_ADMIN
  2007. PolicyReplicaSourceInformation POLICY_SERVER_ADMIN
  2008. PolicyDefaultQuotaInformation POLICY_SET_DEFAULT_QUOTA_LIMITS
  2009. PolicyAuditFullSetInformation POLICY_AUDIT_LOG_ADMIN
  2010. PolicyDnsDomainInformation POLICY_TRUST_ADMIN
  2011. PolicyDnsDomainInformationInt POLICY_TRUST_ADMIN
  2012. Buffer - Points to a structure containing the information appropriate
  2013. to the information type specified by the InformationClass parameter.
  2014. Return Value:
  2015. NTSTATUS - Standard Nt Result Code
  2016. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  2017. to complete the operation.
  2018. Others TBS
  2019. --*/
  2020. {
  2021. NTSTATUS Status = STATUS_SUCCESS;
  2022. ACCESS_MASK DesiredAccess;
  2023. ULONG ReferenceOptions, DereferenceOptions;
  2024. BOOLEAN ScePolicyLocked = FALSE;
  2025. BOOLEAN NotifySce = FALSE;
  2026. LSAP_DB_HANDLE InternalHandle = (LSAP_DB_HANDLE) PolicyHandle;
  2027. LsarpReturnCheckSetup();
  2028. LsapEnterFunc( "LsarSetInformationPolicy" );
  2029. LsapTraceEvent(EVENT_TRACE_TYPE_START, LsaTraceEvent_SetInformationPolicy);
  2030. //
  2031. // If NT4 emulation is enabled, fail requests for PolicyDnsDomainInformation
  2032. // as if they weren't implemented
  2033. //
  2034. if ( LsapDbState.EmulateNT4 &&
  2035. InformationClass == PolicyDnsDomainInformation &&
  2036. !InternalHandle->Trusted ) {
  2037. RaiseException( RPC_NT_PROCNUM_OUT_OF_RANGE, 0, 0, NULL );
  2038. } else if ( InformationClass == PolicyDnsDomainInformationInt ) {
  2039. //
  2040. // PolicyDnsDomainInformationInt is a request to override
  2041. // NT4 emulation
  2042. //
  2043. InformationClass = PolicyDnsDomainInformation;
  2044. }
  2045. //
  2046. // Grab the SCE policy lock for information classes for which SCE
  2047. // notifications are expected.
  2048. //
  2049. if ( InformationClass == PolicyAuditEventsInformation ) {
  2050. LSAP_DB_HANDLE InternalHandle = ( LSAP_DB_HANDLE )PolicyHandle;
  2051. //
  2052. // Do not grab the SCE policy lock for handles opened as SCE policy handles
  2053. //
  2054. if ( !InternalHandle->SceHandle ) {
  2055. RtlEnterCriticalSection( &LsapDbState.ScePolicyLock.CriticalSection );
  2056. if ( LsapDbState.ScePolicyLock.NumberOfWaitingShared > MAX_SCE_WAITING_SHARED ) {
  2057. Status = STATUS_TOO_MANY_THREADS;
  2058. }
  2059. RtlLeaveCriticalSection( &LsapDbState.ScePolicyLock.CriticalSection );
  2060. if ( !NT_SUCCESS( Status )) {
  2061. goto Cleanup;
  2062. }
  2063. WaitForSingleObject( LsapDbState.SceSyncEvent, INFINITE );
  2064. RtlAcquireResourceShared( &LsapDbState.ScePolicyLock, TRUE );
  2065. ASSERT( !g_ScePolicyLocked );
  2066. ScePolicyLocked = TRUE;
  2067. NotifySce = TRUE;
  2068. }
  2069. }
  2070. Status = LsapDbVerifyInfoSetPolicy(
  2071. PolicyHandle,
  2072. InformationClass,
  2073. PolicyInformation,
  2074. &DesiredAccess
  2075. );
  2076. if (!NT_SUCCESS(Status)) {
  2077. goto Cleanup;
  2078. }
  2079. //
  2080. // Set the options for referencing the Policy Object. We need to
  2081. // acquire the LSA Database Lock and start a transaction. Normally,
  2082. // the object reference routine will disallow updates to a Backup
  2083. // Domain Controller from non-trusted clients, but a non-trusted
  2084. // client is allowed to revert the server role to Primary Controller.
  2085. // A special flag is used to allow this operation to go through.
  2086. //
  2087. ReferenceOptions = LSAP_DB_START_TRANSACTION |
  2088. LSAP_DB_NO_DS_OP_TRANSACTION;
  2089. DereferenceOptions = LSAP_DB_FINISH_TRANSACTION |
  2090. LSAP_DB_NO_DS_OP_TRANSACTION;
  2091. //
  2092. // If we are setting the Policy Audit Log Information, we may need
  2093. // the Audit Log Queue Lock.
  2094. //
  2095. if (InformationClass == PolicyAuditLogInformation) {
  2096. ReferenceOptions |= (LSAP_DB_LOG_QUEUE_LOCK | LSAP_DB_OMIT_REPLICATOR_NOTIFICATION);
  2097. DereferenceOptions |= LSAP_DB_LOG_QUEUE_LOCK;
  2098. }
  2099. //
  2100. // If we're setting the server role, don't hold a lock
  2101. //
  2102. if ( InformationClass != PolicyLsaServerRoleInformation ) {
  2103. ReferenceOptions |= LSAP_DB_LOCK;
  2104. DereferenceOptions |= LSAP_DB_LOCK;
  2105. }
  2106. //
  2107. // Acquire the Lsa Database lock. Verify that the handle is
  2108. // valid, is a handle to the Policy Object and has the necessary accesses
  2109. // granted. Reference the handle and start an Lsa Database transaction.
  2110. //
  2111. Status = LsapDbReferenceObject(
  2112. PolicyHandle,
  2113. DesiredAccess,
  2114. PolicyObject,
  2115. PolicyObject,
  2116. ReferenceOptions
  2117. );
  2118. if (NT_SUCCESS(Status)) {
  2119. //
  2120. // Special case the ServerRole information. This information is not stored exclusively in
  2121. // SAM, so we need to read it directly from there
  2122. //
  2123. if ( InformationClass == PolicyLsaServerRoleInformation ) {
  2124. DOMAIN_SERVER_ROLE SamServerRole;
  2125. //
  2126. // SamIDoFSMORoleChange goes off machine to do its work so do this outside
  2127. // of an LSA policy lock
  2128. //
  2129. Status = LsapDbDereferenceObject(
  2130. &PolicyHandle,
  2131. PolicyObject,
  2132. PolicyObject,
  2133. DereferenceOptions,
  2134. SecurityDbChange,
  2135. Status
  2136. );
  2137. if ( !NT_SUCCESS( Status )) {
  2138. goto Cleanup;
  2139. }
  2140. Status = LsapOpenSam();
  2141. if ( !NT_SUCCESS( Status ) ) {
  2142. LsapDsDebugOut(( DEB_ERROR,
  2143. "LsarSetInformationPolicy: Sam not opened\n"));
  2144. goto Cleanup;
  2145. }
  2146. SamServerRole = ( DOMAIN_SERVER_ROLE )(((PPOLICY_LSA_SERVER_ROLE_INFO)PolicyInformation)->LsaServerRole);
  2147. if ( SamServerRole == DomainServerRolePrimary ) {
  2148. Status = SamIDoFSMORoleChange( LsapAccountDomainHandle );
  2149. if ( !NT_SUCCESS( Status ) ) {
  2150. LsapDsDebugOut(( DEB_ERROR,
  2151. "SamIDoFSMORoleChange failed with %lu\n", Status ));
  2152. }
  2153. } else if ( SamServerRole == DomainServerRoleBackup ) {
  2154. //
  2155. // Do nothing: you do not give up the FSMO, someone grabs it
  2156. //
  2157. } else {
  2158. Status = STATUS_INVALID_PARAMETER;
  2159. goto Cleanup;
  2160. }
  2161. } else {
  2162. Status = LsapDbSetInformationPolicy( PolicyHandle,
  2163. InformationClass,
  2164. PolicyInformation );
  2165. Status = LsapDbDereferenceObject(
  2166. &PolicyHandle,
  2167. PolicyObject,
  2168. PolicyObject,
  2169. DereferenceOptions,
  2170. SecurityDbChange,
  2171. Status
  2172. );
  2173. }
  2174. }
  2175. Cleanup:
  2176. //
  2177. // Notify SCE of the change. Only notify for callers
  2178. // that did not open their policy handles with LsaOpenPolicySce.
  2179. //
  2180. if ( NotifySce && NT_SUCCESS( Status )) {
  2181. LsapSceNotify(
  2182. SecurityDbChange,
  2183. SecurityDbObjectLsaPolicy,
  2184. NULL
  2185. );
  2186. }
  2187. if ( ScePolicyLocked ) {
  2188. RtlReleaseResource( &LsapDbState.ScePolicyLock );
  2189. }
  2190. LsapTraceEvent(EVENT_TRACE_TYPE_END, LsaTraceEvent_SetInformationPolicy);
  2191. LsapExitFunc( "LsarSetInformationPolicy", Status );
  2192. LsarpReturnPrologue();
  2193. return(Status);
  2194. }
  2195. NTSTATUS
  2196. LsapDbSetInformationPolicy(
  2197. IN LSAPR_HANDLE PolicyHandle,
  2198. IN POLICY_INFORMATION_CLASS InformationClass,
  2199. IN PLSAPR_POLICY_INFORMATION PolicyInformation
  2200. )
  2201. /*++
  2202. Routine Description:
  2203. This function is the LSA server RPC worker routine for the
  2204. LsaSetInformationPolicy API.
  2205. The LsaSetInformationPolicy API modifies information in the Policy Object.
  2206. The caller must have access appropriate to the information to be changed
  2207. in the Policy Object, see the InformationClass parameter.
  2208. Arguments:
  2209. PolicyHandle - Handle from an LsaOpenPolicy call.
  2210. InformationClass - Specifies the type of information being changed.
  2211. The information types and accesses required to change them are as
  2212. follows:
  2213. PolicyAuditLogInformation POLICY_AUDIT_LOG_ADMIN
  2214. PolicyAuditEventsInformation POLICY_SET_AUDIT_REQUIREMENTS
  2215. PolicyPrimaryDomainInformation POLICY_TRUST_ADMIN
  2216. PolicyAccountDomainInformation POLICY_TRUST_ADMIN
  2217. PolicyPdAccountInformation Not settable by this API
  2218. PolicyLsaServerRoleInformation POLICY_SERVER_ADMIN
  2219. PolicyReplicaSourceInformation POLICY_SERVER_ADMIN
  2220. PolicyDefaultQuotaInformation POLICY_SET_DEFAULT_QUOTA_LIMITS
  2221. PolicyAuditFullSetInformation POLICY_AUDIT_LOG_ADMIN
  2222. PolicyDnsDomainInformation POLICY_TRUST_ADMIN
  2223. Buffer - Points to a structure containing the information appropriate
  2224. to the information type specified by the InformationClass parameter.
  2225. Return Value:
  2226. NTSTATUS - Standard Nt Result Code
  2227. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  2228. to complete the operation.
  2229. Others TBS
  2230. --*/
  2231. {
  2232. NTSTATUS Status, SavedStatus;
  2233. ACCESS_MASK DesiredAccess;
  2234. PPOLICY_AUDIT_EVENTS_INFO ModifyPolicyAuditEventsInfo;
  2235. PPOLICY_ACCOUNT_DOMAIN_INFO PolicyAccountDomainInfo;
  2236. PPOLICY_PRIMARY_DOMAIN_INFO PolicyPrimaryDomainInfo;
  2237. PPOLICY_REPLICA_SOURCE_INFO PolicyReplicaSourceInfo;
  2238. PPOLICY_DEFAULT_QUOTA_INFO PolicyDefaultQuotaInfo;
  2239. PPOLICY_MODIFICATION_INFO PolicyModificationInfo;
  2240. PPOLICY_AUDIT_FULL_SET_INFO PolicyAuditFullSetInfo;
  2241. PPOLICY_DNS_DOMAIN_INFO PolicyDnsDomainInfo, CurrentDnsDomainInfo = NULL;
  2242. POLICY_DNS_DOMAIN_INFO DnsDomainInfo;
  2243. LSAP_DB_ATTRIBUTE Attributes[LSAP_DB_ATTRS_INFO_CLASS_POLICY];
  2244. PLSAP_DB_ATTRIBUTE NextAttribute;
  2245. ULONG AttributeCount = 0;
  2246. ULONG AttributeNumber;
  2247. POLICY_AUDIT_EVENT_TYPE AuditEventType;
  2248. PLSARM_POLICY_AUDIT_EVENTS_INFO PreviousPolicyAuditEventsInfo = NULL;
  2249. PLSARM_POLICY_AUDIT_EVENTS_INFO UpdatedPolicyAuditEventsInfo = NULL;
  2250. ULONG UpdatedPolicyAuditEventsInfoLength;
  2251. ULONG UpdatedMaximumAuditEventCount;
  2252. ULONG ModifyMaximumAuditEventCount;
  2253. PPOLICY_AUDIT_EVENT_OPTIONS UpdatedEventAuditingOptions;
  2254. PPOLICY_AUDIT_EVENT_OPTIONS ModifyEventAuditingOptions;
  2255. PPOLICY_AUDIT_EVENT_OPTIONS PreviousEventAuditingOptions;
  2256. ULONG PolicyAuditEventsInfoLength = sizeof (LSARM_POLICY_AUDIT_EVENTS_INFO);
  2257. ULONG PreviousPolicyAuditEventsInfoLength = sizeof (LSARM_POLICY_AUDIT_EVENTS_INFO);
  2258. BOOLEAN NeedToFreeUpdatedPolicyAuditEventsInfo = FALSE;
  2259. BOOLEAN NeedToFreePreviousPolicyAuditEventsInfo = FALSE;
  2260. PUNICODE_STRING DomainName = NULL;
  2261. PUNICODE_STRING AccountName = NULL;
  2262. PUNICODE_STRING ReplicaSource = NULL;
  2263. BOOLEAN ObjectReferenced = FALSE;
  2264. LSAP_DB_HANDLE InternalHandle = (LSAP_DB_HANDLE) PolicyHandle;
  2265. ULONG NewMaximumAuditEventCount = 0;
  2266. POLICY_AUDIT_EVENTS_INFO PolicyAuditEventsInfo;
  2267. PLSAPR_TRUST_INFORMATION TrustInformation = NULL;
  2268. POLICY_NOTIFICATION_INFORMATION_CLASS NotifyClass = 0;
  2269. BOOLEAN NotifyPolicyChange = FALSE;
  2270. BOOLEAN DnsDomainNameTruncated;
  2271. BOOLEAN DnsForestNameTruncated;
  2272. LsapEnterFunc( "LsapDbSetInformationPolicy" );
  2273. //
  2274. // Validate the Information Class and Policy Information provided and
  2275. // if valid, return the mask of accesses required to update this
  2276. // class of policy information.
  2277. //
  2278. Status = LsapDbVerifyInfoSetPolicy(
  2279. PolicyHandle,
  2280. InformationClass,
  2281. PolicyInformation,
  2282. &DesiredAccess
  2283. );
  2284. if (!NT_SUCCESS(Status)) {
  2285. goto SetInformationPolicyError;
  2286. }
  2287. //
  2288. // Update the specified information in the Policy Object.
  2289. //
  2290. NextAttribute = Attributes;
  2291. switch (InformationClass) {
  2292. case PolicyLsaServerRoleInformation:
  2293. Status = STATUS_NOT_IMPLEMENTED;
  2294. break;
  2295. case PolicyAuditLogInformation:
  2296. {
  2297. //
  2298. // This operation is no longer supported. Return an
  2299. // error to anyone who tries except trusted clients who
  2300. // are just blindly replcate the entire database.
  2301. //
  2302. LSAP_DB_HANDLE InternalHandle = PolicyHandle;
  2303. if (!InternalHandle->Trusted) {
  2304. Status = STATUS_NOT_IMPLEMENTED;
  2305. }
  2306. }
  2307. break;
  2308. case PolicyAuditEventsInformation:
  2309. //
  2310. // IMPORTANT: To allow new Audit Event Types to be added to the
  2311. // system in successive versions, this code caters for the
  2312. // following situations:
  2313. //
  2314. // (1) The LSA Database is older than the present system and
  2315. // contains information for fewer Audit Event Types than
  2316. // currently supported.
  2317. //
  2318. // (2) The client code is older than the present system and
  2319. // specifies fewer Audit Event Types than currently supported.
  2320. // In this case, the newer options will be left unchanged.
  2321. //
  2322. // In all cases, the updated information written to the LSA Database
  2323. // and transmitted to the Reference Monitor within the Nt Executive
  2324. // contains Event Auditing Options for every Audit Event Type
  2325. // currently supported.
  2326. //
  2327. // Additionally, this code caters for old LSA Databases that have
  2328. // no default Audit Event Information. This is a very temporary
  2329. // situation, since installation now initializes this information.
  2330. //
  2331. // If no information has been provided or there is more information
  2332. // than the current Audit Event Info structure holds, return an error.
  2333. // Note that the caller is allowed to specify infomration for
  2334. // the firt n Audit Events, where n is less than the current
  2335. // number the system supports. This allows new events to be
  2336. // added without the need to change calling code.
  2337. //
  2338. ModifyPolicyAuditEventsInfo = (PPOLICY_AUDIT_EVENTS_INFO) PolicyInformation;
  2339. if (ModifyPolicyAuditEventsInfo == NULL) {
  2340. Status = STATUS_INVALID_PARAMETER;
  2341. break;
  2342. }
  2343. UpdatedMaximumAuditEventCount = POLICY_AUDIT_EVENT_TYPE_COUNT;
  2344. //
  2345. //
  2346. // The following check is disabled so that replication will work when
  2347. // reading from a PDC with pre-Build 354 Auditing Event Information
  2348. // in which there were 12 categories.
  2349. //
  2350. //
  2351. // if (ModifyPolicyAuditEventsInfo->MaximumAuditEventCount >
  2352. // UpdatedMaximumAuditEventCount) {
  2353. //
  2354. // break;
  2355. // }
  2356. //
  2357. if (ModifyPolicyAuditEventsInfo->MaximumAuditEventCount == 0) {
  2358. Status = STATUS_INVALID_PARAMETER;
  2359. break;
  2360. }
  2361. //
  2362. // Read Existing Audit Events. Specify NULL for the buffer pointer
  2363. // so that the read routine will allocate the buffer for us.
  2364. // Specify 0 for the length, because we don't know what it is.
  2365. //
  2366. LsapDbInitializeAttributeDs(
  2367. NextAttribute,
  2368. PolAdtEv,
  2369. NULL,
  2370. 0,
  2371. FALSE
  2372. );
  2373. Status = LsapDbReadAttribute( PolicyHandle, NextAttribute );
  2374. if (NT_SUCCESS(Status)) {
  2375. PreviousPolicyAuditEventsInfo = NextAttribute->AttributeValue;
  2376. NextAttribute->MemoryAllocated = FALSE;
  2377. NeedToFreePreviousPolicyAuditEventsInfo = TRUE;
  2378. if (PreviousPolicyAuditEventsInfo == NULL) {
  2379. Status = STATUS_INTERNAL_DB_CORRUPTION;
  2380. break;
  2381. }
  2382. PreviousPolicyAuditEventsInfoLength = NextAttribute->AttributeValueLength;
  2383. } else {
  2384. //
  2385. // Unable to read existing Audit Event Options. If this is
  2386. // because there is no Audit Event Information in an old
  2387. // Database, then, temorarily, we will proceed as if Auditing
  2388. // and all Options were disabled. NOTE: This situation will NOT
  2389. // occur in the finished product.
  2390. //
  2391. if (Status != STATUS_OBJECT_NAME_NOT_FOUND) {
  2392. break;
  2393. }
  2394. }
  2395. //
  2396. // Setup a buffer to hold the updated Audit Event Information.
  2397. // We try to use the existing buffer if possible.
  2398. //
  2399. if (PreviousPolicyAuditEventsInfo != NULL &&
  2400. PreviousPolicyAuditEventsInfoLength == sizeof( LSARM_POLICY_AUDIT_EVENTS_INFO ) &&
  2401. ( PreviousPolicyAuditEventsInfo->MaximumAuditEventCount ==
  2402. POLICY_AUDIT_EVENT_TYPE_COUNT &&
  2403. ModifyPolicyAuditEventsInfo->MaximumAuditEventCount <=
  2404. PreviousPolicyAuditEventsInfo->MaximumAuditEventCount ) ) {
  2405. //
  2406. // There is an existing Audit Event Info buffer and it is
  2407. // large enough so update it in situ.
  2408. //
  2409. UpdatedPolicyAuditEventsInfo = PreviousPolicyAuditEventsInfo;
  2410. UpdatedPolicyAuditEventsInfoLength = PreviousPolicyAuditEventsInfoLength;
  2411. UpdatedEventAuditingOptions = PreviousPolicyAuditEventsInfo->EventAuditingOptions;
  2412. } else {
  2413. //
  2414. // There is either no existing buffer or it is not large
  2415. // enough. We need to allocate a new one for the updated
  2416. // information. This will store the number of Audit Event
  2417. // Types that the system currently supports.
  2418. //
  2419. UpdatedPolicyAuditEventsInfoLength = sizeof (LSARM_POLICY_AUDIT_EVENTS_INFO);
  2420. SafeAllocaAllocate( UpdatedPolicyAuditEventsInfo, UpdatedPolicyAuditEventsInfoLength );
  2421. if (UpdatedPolicyAuditEventsInfo == 0) {
  2422. Status = STATUS_INSUFFICIENT_RESOURCES;
  2423. goto SetInformationPolicyError;
  2424. }
  2425. NeedToFreeUpdatedPolicyAuditEventsInfo = TRUE;
  2426. UpdatedPolicyAuditEventsInfo->AuditingMode = FALSE;
  2427. UpdatedEventAuditingOptions =
  2428. UpdatedPolicyAuditEventsInfo->EventAuditingOptions;
  2429. for ( AuditEventType=0 ;
  2430. AuditEventType < (POLICY_AUDIT_EVENT_TYPE) UpdatedMaximumAuditEventCount ;
  2431. AuditEventType++ ) {
  2432. UpdatedEventAuditingOptions[ AuditEventType ] = 0;
  2433. }
  2434. if ( PreviousPolicyAuditEventsInfo == NULL ) {
  2435. ASSERT( NeedToFreePreviousPolicyAuditEventsInfo == FALSE );
  2436. PreviousPolicyAuditEventsInfo = UpdatedPolicyAuditEventsInfo;
  2437. }
  2438. }
  2439. //
  2440. // Construct the updated Audit Event Info, applying the Modification
  2441. // information provided. Note that for an old database we may be
  2442. // writing more info back than we read.
  2443. //
  2444. PreviousEventAuditingOptions = PreviousPolicyAuditEventsInfo->EventAuditingOptions;
  2445. ModifyMaximumAuditEventCount = ModifyPolicyAuditEventsInfo->MaximumAuditEventCount;
  2446. ModifyEventAuditingOptions = ModifyPolicyAuditEventsInfo->EventAuditingOptions;
  2447. for ( AuditEventType = 0;
  2448. AuditEventType < (POLICY_AUDIT_EVENT_TYPE) ModifyMaximumAuditEventCount;
  2449. AuditEventType++ ) {
  2450. if ( ModifyEventAuditingOptions[ AuditEventType ] & POLICY_AUDIT_EVENT_NONE ) {
  2451. //
  2452. // Clear all existing flags for this Audit Event Type.
  2453. //
  2454. UpdatedEventAuditingOptions[ AuditEventType ] = 0;
  2455. }
  2456. //
  2457. // Apply new flags.
  2458. //
  2459. UpdatedEventAuditingOptions[ AuditEventType ] |=
  2460. (ModifyEventAuditingOptions[ AuditEventType ] &
  2461. ( POLICY_AUDIT_EVENT_MASK & ~POLICY_AUDIT_EVENT_NONE));
  2462. }
  2463. //
  2464. // Update the Auditing Mode as specified. Set the Maximum Audit Event
  2465. // Count.
  2466. //
  2467. UpdatedPolicyAuditEventsInfo->AuditingMode = ModifyPolicyAuditEventsInfo->AuditingMode;
  2468. UpdatedPolicyAuditEventsInfo->MaximumAuditEventCount = UpdatedMaximumAuditEventCount;
  2469. //
  2470. // Ship the new Auditing Options to the Kernel.
  2471. //
  2472. Status = LsapCallRm(
  2473. RmAuditSetCommand,
  2474. (PVOID) UpdatedPolicyAuditEventsInfo,
  2475. sizeof(LSARM_POLICY_AUDIT_EVENTS_INFO),
  2476. NULL,
  2477. 0
  2478. );
  2479. if (!NT_SUCCESS(Status)) {
  2480. break;
  2481. }
  2482. RtlCopyMemory(
  2483. &LsapAdtEventsInformation,
  2484. UpdatedPolicyAuditEventsInfo,
  2485. sizeof(LSARM_POLICY_AUDIT_EVENTS_INFO)
  2486. );
  2487. //
  2488. // Update Audit Event Category Info held by SAM
  2489. //
  2490. PolicyAuditEventsInfo.AuditingMode = UpdatedPolicyAuditEventsInfo->AuditingMode;
  2491. PolicyAuditEventsInfo.MaximumAuditEventCount = POLICY_AUDIT_EVENT_TYPE_COUNT;
  2492. PolicyAuditEventsInfo.EventAuditingOptions =
  2493. UpdatedPolicyAuditEventsInfo->EventAuditingOptions;
  2494. Status = SamISetAuditingInformation(&PolicyAuditEventsInfo);
  2495. if (!NT_SUCCESS(Status)) {
  2496. break;
  2497. }
  2498. //
  2499. // Setup attribute info for writing the updated Audit Event Info
  2500. // to the LSA Database (PolAdtEv attribute of the Policy Object).
  2501. //
  2502. LsapDbInitializeAttributeDs(
  2503. NextAttribute,
  2504. PolAdtEv,
  2505. UpdatedPolicyAuditEventsInfo,
  2506. UpdatedPolicyAuditEventsInfoLength,
  2507. FALSE
  2508. );
  2509. AttributeCount++;
  2510. NotifyClass = PolicyNotifyAuditEventsInformation;
  2511. NotifyPolicyChange = TRUE;
  2512. break;
  2513. case PolicyPrimaryDomainInformation:
  2514. //
  2515. // Get the current DnsDomainInformation to see if we're changing
  2516. // anything.
  2517. //
  2518. // Use the trusted policy handle
  2519. //
  2520. Status = LsapDbQueryInformationPolicy(
  2521. LsapPolicyHandle,
  2522. PolicyDnsDomainInformation,
  2523. (PLSAPR_POLICY_INFORMATION *) &CurrentDnsDomainInfo );
  2524. if ( !NT_SUCCESS(Status) ) {
  2525. goto SetInformationPolicyError;
  2526. }
  2527. //
  2528. // If the new policy is the same as the old policy,
  2529. // avoid clearing the NT 5 specific information
  2530. //
  2531. PolicyPrimaryDomainInfo = (PPOLICY_PRIMARY_DOMAIN_INFO) PolicyInformation;
  2532. if ( RtlEqualDomainName( &PolicyPrimaryDomainInfo->Name,
  2533. &CurrentDnsDomainInfo->Name ) &&
  2534. (( PolicyPrimaryDomainInfo->Sid == NULL &&
  2535. CurrentDnsDomainInfo->Sid == NULL) ||
  2536. ( PolicyPrimaryDomainInfo->Sid != NULL &&
  2537. CurrentDnsDomainInfo->Sid != NULL &&
  2538. RtlEqualSid( PolicyPrimaryDomainInfo->Sid,
  2539. CurrentDnsDomainInfo->Sid ) ) ) ) {
  2540. //
  2541. // Be sure to invalidate PrimaryDomainInformation since that info
  2542. // level contains this one.
  2543. //
  2544. // LsapDbMakeInvalidInformationPolicy( PolicyDnsDomainInformation );
  2545. Status = STATUS_SUCCESS;
  2546. break;
  2547. }
  2548. //
  2549. // Join domain must fail on personal SKU
  2550. //
  2551. if ( LsapIsRunningOnPersonal()) {
  2552. ASSERT( CurrentDnsDomainInfo->Sid == NULL );
  2553. if ( PolicyPrimaryDomainInfo->Sid != NULL ) {
  2554. Status = STATUS_NOT_SUPPORTED;
  2555. break;
  2556. }
  2557. }
  2558. //
  2559. // Since the PrimaryDomainInformation structure is a subset of the DnsDomainInformation,
  2560. // we'll build the latter, and set that.
  2561. //
  2562. // Clear the NT 5 specific information.
  2563. //
  2564. RtlZeroMemory( &DnsDomainInfo, sizeof(POLICY_DNS_DOMAIN_INFO) );
  2565. DnsDomainInfo.Name = PolicyPrimaryDomainInfo->Name;
  2566. DnsDomainInfo.Sid = PolicyPrimaryDomainInfo->Sid;
  2567. //
  2568. // Ok, set our policy information to be the DnsDomainInfo we just initialized
  2569. //
  2570. PolicyInformation = (PLSAPR_POLICY_INFORMATION)&DnsDomainInfo;
  2571. LsapDbMakeInvalidInformationPolicy( PolicyDnsDomainInformation );
  2572. //
  2573. // FALL THROUGH to PolicyDnsDomainInformation
  2574. //
  2575. case PolicyDnsDomainInformation:
  2576. PolicyDnsDomainInfo = (PPOLICY_DNS_DOMAIN_INFO) PolicyInformation;
  2577. //
  2578. // Join domain must fail on personal SKU
  2579. //
  2580. if ( CurrentDnsDomainInfo == NULL &&
  2581. LsapIsRunningOnPersonal()) {
  2582. //
  2583. // Get the current DnsDomainInformation to see if we're changing
  2584. // anything.
  2585. //
  2586. // Use the trusted policy handle
  2587. //
  2588. Status = LsapDbQueryInformationPolicy(
  2589. LsapPolicyHandle,
  2590. PolicyDnsDomainInformation,
  2591. (PLSAPR_POLICY_INFORMATION *) &CurrentDnsDomainInfo );
  2592. if ( !NT_SUCCESS(Status) ) {
  2593. goto SetInformationPolicyError;
  2594. }
  2595. ASSERT( CurrentDnsDomainInfo->Sid == NULL );
  2596. if ( PolicyDnsDomainInfo->Sid != NULL ) {
  2597. Status = STATUS_NOT_SUPPORTED;
  2598. break;
  2599. }
  2600. }
  2601. //
  2602. // if there is a '.' at the end of DnsDomainName or DnsForestName,
  2603. // remove it
  2604. //
  2605. DnsDomainNameTruncated =
  2606. LsapRemoveTrailingDot(&PolicyDnsDomainInfo->DnsDomainName, TRUE);
  2607. DnsForestNameTruncated =
  2608. LsapRemoveTrailingDot(&PolicyDnsDomainInfo->DnsForestName, TRUE);
  2609. //
  2610. // Make sure we invalidate the PrimaryDomainInformation
  2611. // since the info level is a subset of this one.
  2612. //
  2613. LsapDbMakeInvalidInformationPolicy( PolicyPrimaryDomainInformation );
  2614. //
  2615. // Construct the Domain name attribute info
  2616. //
  2617. Status = LsapDbMakeUnicodeAttributeDs(
  2618. &PolicyDnsDomainInfo->Name,
  2619. PolPrDmN,
  2620. NextAttribute
  2621. );
  2622. if (!NT_SUCCESS(Status)) {
  2623. break;
  2624. }
  2625. DomainName = NextAttribute->AttributeName;
  2626. NextAttribute++;
  2627. AttributeCount++;
  2628. //
  2629. // Construct the DNS Domain name attribute info
  2630. //
  2631. Status = LsapDbMakeUnicodeAttributeDs(
  2632. &PolicyDnsDomainInfo->DnsDomainName,
  2633. PolDnDDN,
  2634. NextAttribute
  2635. );
  2636. NextAttribute++;
  2637. AttributeCount++;
  2638. //
  2639. // Construct the DNS Tree name attribute info
  2640. //
  2641. Status = LsapDbMakeUnicodeAttributeDs(
  2642. &PolicyDnsDomainInfo->DnsForestName,
  2643. PolDnTrN,
  2644. NextAttribute
  2645. );
  2646. NextAttribute++;
  2647. AttributeCount++;
  2648. //
  2649. // Construct the Domain GUID attribute info
  2650. //
  2651. Status = LsapDbMakeGuidAttributeDs(
  2652. &PolicyDnsDomainInfo->DomainGuid,
  2653. PolDnDmG,
  2654. NextAttribute
  2655. );
  2656. NextAttribute++;
  2657. AttributeCount++;
  2658. //
  2659. // Construct the Sid attribute info
  2660. //
  2661. Status = LsapDbMakeSidAttributeDs(
  2662. PolicyDnsDomainInfo->Sid,
  2663. PolPrDmS,
  2664. NextAttribute
  2665. );
  2666. if (!NT_SUCCESS(Status)) {
  2667. break;
  2668. }
  2669. AttributeCount++;
  2670. NotifyClass = PolicyNotifyDnsDomainInformation;
  2671. NotifyPolicyChange = TRUE;
  2672. if (DnsDomainNameTruncated) {
  2673. PolicyDnsDomainInfo->DnsDomainName.Length += sizeof(WCHAR);
  2674. }
  2675. if (DnsForestNameTruncated) {
  2676. PolicyDnsDomainInfo->DnsForestName.Length += sizeof(WCHAR);
  2677. }
  2678. break;
  2679. case PolicyAccountDomainInformation:
  2680. PolicyAccountDomainInfo = (PPOLICY_ACCOUNT_DOMAIN_INFO) PolicyInformation;
  2681. //
  2682. // 368441: NULL account domain SID will cause the machine to
  2683. // fail to boot, even into safe mode
  2684. //
  2685. if ( PolicyAccountDomainInfo->DomainSid == NULL ) {
  2686. Status = STATUS_INVALID_PARAMETER;
  2687. break;
  2688. }
  2689. //
  2690. // Construct the Domain name attribute info
  2691. //
  2692. Status = LsapDbMakeUnicodeAttributeDs(
  2693. &PolicyAccountDomainInfo->DomainName,
  2694. PolAcDmN,
  2695. NextAttribute
  2696. );
  2697. if (!NT_SUCCESS(Status)) {
  2698. break;
  2699. }
  2700. DomainName = NextAttribute->AttributeName;
  2701. AttributeCount++;
  2702. NextAttribute++;
  2703. //
  2704. // Construct the Sid attribute info
  2705. //
  2706. Status = LsapDbMakeSidAttributeDs(
  2707. PolicyAccountDomainInfo->DomainSid,
  2708. PolAcDmS,
  2709. NextAttribute
  2710. );
  2711. if (!NT_SUCCESS(Status)) {
  2712. break;
  2713. }
  2714. AttributeCount++;
  2715. NotifyClass = PolicyNotifyAccountDomainInformation;
  2716. NotifyPolicyChange = TRUE;
  2717. break;
  2718. case PolicyPdAccountInformation:
  2719. Status = STATUS_INVALID_PARAMETER;
  2720. break;
  2721. case PolicyReplicaSourceInformation:
  2722. PolicyReplicaSourceInfo = (PPOLICY_REPLICA_SOURCE_INFO) PolicyInformation;
  2723. //
  2724. // Construct the Replica Source Name attribute info
  2725. //
  2726. Status = LsapDbMakeUnicodeAttributeDs(
  2727. &PolicyReplicaSourceInfo->ReplicaSource,
  2728. PolRepSc,
  2729. NextAttribute
  2730. );
  2731. if (!NT_SUCCESS(Status)) {
  2732. break;
  2733. }
  2734. ReplicaSource = NextAttribute->AttributeName;
  2735. AttributeCount++;
  2736. NextAttribute++;
  2737. //
  2738. // Construct the Replica Account Name attribute info
  2739. //
  2740. Status = LsapDbMakeUnicodeAttributeDs(
  2741. &PolicyReplicaSourceInfo->ReplicaAccountName,
  2742. PolRepAc,
  2743. NextAttribute
  2744. );
  2745. if (!NT_SUCCESS(Status)) {
  2746. break;
  2747. }
  2748. AccountName = NextAttribute->AttributeName;
  2749. AttributeCount++;
  2750. break;
  2751. case PolicyDefaultQuotaInformation:
  2752. PolicyDefaultQuotaInfo = (PPOLICY_DEFAULT_QUOTA_INFO) PolicyInformation;
  2753. LsapDbInitializeAttributeDs(
  2754. NextAttribute,
  2755. DefQuota,
  2756. &PolicyDefaultQuotaInfo->QuotaLimits,
  2757. sizeof (POLICY_DEFAULT_QUOTA_INFO),
  2758. FALSE
  2759. );
  2760. AttributeCount++;
  2761. break;
  2762. case PolicyModificationInformation:
  2763. PolicyModificationInfo = (PPOLICY_MODIFICATION_INFO) PolicyInformation;
  2764. LsapDbInitializeAttributeDs(
  2765. NextAttribute,
  2766. PolMod,
  2767. PolicyModificationInfo,
  2768. sizeof (POLICY_MODIFICATION_INFO),
  2769. FALSE
  2770. );
  2771. AttributeCount++;
  2772. break;
  2773. case PolicyAuditFullSetInformation:
  2774. Status = STATUS_NOT_SUPPORTED;
  2775. break;
  2776. default:
  2777. Status = STATUS_INVALID_PARAMETER;
  2778. break;
  2779. }
  2780. if (!NT_SUCCESS(Status)) {
  2781. goto SetInformationPolicyError;
  2782. }
  2783. //
  2784. // Update the Policy Object attributes
  2785. //
  2786. Status = LsapDbWriteAttributesObject( PolicyHandle,
  2787. Attributes,
  2788. AttributeCount );
  2789. if (!NT_SUCCESS(Status)) {
  2790. goto SetInformationPolicyError;
  2791. }
  2792. //
  2793. // Generate an audit.
  2794. //
  2795. SavedStatus = Status;
  2796. Status = LsapAdtGenerateLsaAuditEvent(
  2797. PolicyHandle,
  2798. SE_CATEGID_POLICY_CHANGE,
  2799. SE_AUDITID_POLICY_CHANGE,
  2800. NULL,
  2801. 0,
  2802. NULL,
  2803. 0,
  2804. NULL,
  2805. &LsapAdtEventsInformation
  2806. );
  2807. //
  2808. // Ignore failure status from auditing.
  2809. //
  2810. Status = SavedStatus;
  2811. //
  2812. // Free the memory containing the TrustInformation.
  2813. //
  2814. LsaIFree_LSAPR_TRUST_INFORMATION ( TrustInformation );
  2815. TrustInformation = NULL;
  2816. if ( NT_SUCCESS( Status ) ) {
  2817. //
  2818. // Invalidate the information in the Policy Cache for this information
  2819. // class
  2820. //
  2821. LsapDbMakeInvalidInformationPolicy( InformationClass );
  2822. }
  2823. //
  2824. // Finally, call the notification routines. We don't care about errors coming back
  2825. // from this.
  2826. //
  2827. if ( NT_SUCCESS( Status ) && NotifyPolicyChange ) {
  2828. LsaINotifyChangeNotification( NotifyClass );
  2829. }
  2830. SetInformationPolicyFinish:
  2831. //
  2832. // If necessary, finish any Lsa Database transaction, notify the
  2833. // LSA Database Replicator of the change, dereference the Policy Object,
  2834. // release the LSA Database lock and return.
  2835. //
  2836. //
  2837. // Free memory allocated by this routine for attribute buffers.
  2838. // These have MemoryAllocated = TRUE in their attribute information.
  2839. // Leave alone buffers allocated by calling RPC stub.
  2840. //
  2841. for( NextAttribute = Attributes, AttributeNumber = 0;
  2842. AttributeNumber < AttributeCount;
  2843. NextAttribute++, AttributeNumber++) {
  2844. if (NextAttribute->MemoryAllocated) {
  2845. if (NextAttribute->AttributeValue != NULL) {
  2846. MIDL_user_free(NextAttribute->AttributeValue);
  2847. NextAttribute->MemoryAllocated = FALSE;
  2848. NextAttribute->AttributeValue = NULL;
  2849. }
  2850. }
  2851. }
  2852. //
  2853. // If necessary, free memory allocated for the Previous Audit Event
  2854. // Information. Only do this if it is not the same as the
  2855. // Updated Audit Event Information pointer.
  2856. //
  2857. if ( NeedToFreePreviousPolicyAuditEventsInfo ) {
  2858. MIDL_user_free( PreviousPolicyAuditEventsInfo );
  2859. }
  2860. if ( NeedToFreeUpdatedPolicyAuditEventsInfo ) {
  2861. SafeAllocaFree( UpdatedPolicyAuditEventsInfo );
  2862. }
  2863. LsaIFree_LSAPR_POLICY_INFORMATION( PolicyDnsDomainInformation,
  2864. (PLSAPR_POLICY_INFORMATION)CurrentDnsDomainInfo );
  2865. LsapExitFunc( "LsapDbSetInformationPolicy", Status );
  2866. return(Status);
  2867. SetInformationPolicyError:
  2868. goto SetInformationPolicyFinish;
  2869. }
  2870. NTSTATUS
  2871. LsarSetInformationPolicy2(
  2872. IN LSAPR_HANDLE PolicyHandle,
  2873. IN POLICY_INFORMATION_CLASS InformationClass,
  2874. IN PLSAPR_POLICY_INFORMATION PolicyInformation
  2875. )
  2876. /*++
  2877. Routine Description:
  2878. This function is the LSA server RPC worker routine for the
  2879. LsaSetInformationPolicy API.
  2880. The LsaSetInformationPolicy API modifies information in the Policy Object.
  2881. The caller must have access appropriate to the information to be changed
  2882. in the Policy Object, see the InformationClass parameter.
  2883. Arguments:
  2884. PolicyHandle - Handle from an LsaOpenPolicy call.
  2885. InformationClass - Specifies the type of information being changed.
  2886. The information types and accesses required to change them are as
  2887. follows:
  2888. PolicyAuditLogInformation POLICY_AUDIT_LOG_ADMIN
  2889. PolicyAuditEventsInformation POLICY_SET_AUDIT_REQUIREMENTS
  2890. PolicyPrimaryDomainInformation POLICY_TRUST_ADMIN
  2891. PolicyAccountDomainInformation POLICY_TRUST_ADMIN
  2892. PolicyPdAccountInformation Not settable by this API
  2893. PolicyLsaServerRoleInformation POLICY_SERVER_ADMIN
  2894. PolicyReplicaSourceInformation POLICY_SERVER_ADMIN
  2895. PolicyDefaultQuotaInformation POLICY_SET_DEFAULT_QUOTA_LIMITS
  2896. PolicyAuditFullSetInformation POLICY_AUDIT_LOG_ADMIN
  2897. PolicyDnsDomainInformation POLICY_TRUST_ADMIN
  2898. PolicyDnsDomainInformationInt POLICY_TRUST_ADMIN
  2899. Buffer - Points to a structure containing the information appropriate
  2900. to the information type specified by the InformationClass parameter.
  2901. Return Value:
  2902. NTSTATUS - Standard Nt Result Code
  2903. Result codes returned from LsarSetInformationPolicy()
  2904. --*/
  2905. {
  2906. return(LsarSetInformationPolicy(
  2907. PolicyHandle,
  2908. InformationClass,
  2909. PolicyInformation
  2910. ));
  2911. }
  2912. VOID
  2913. LsapDbMakeInvalidInformationPolicy(
  2914. IN ULONG InformationClass
  2915. )
  2916. /*++
  2917. Routine Description:
  2918. This function frees and invalidates the information held for a specific
  2919. Information Class in the Policy Object cache. The general cache state
  2920. remains unchanged.
  2921. Arguments:
  2922. InformationClass - Specifies the Information Class whose information is to be
  2923. discarded.
  2924. Return Values:
  2925. --*/
  2926. {
  2927. SafeAcquireResourceExclusive( &LsapDbState.PolicyCacheLock, TRUE );
  2928. //
  2929. // If the Policy Cache is invalid, just return.
  2930. //
  2931. if (!LsapDbIsCacheValid(PolicyObject)) {
  2932. goto Cleanup;
  2933. }
  2934. //
  2935. //
  2936. // If PolicyAuditFullSetInformation is specified, free
  2937. // PolicyAuditFullQueryInformation
  2938. //
  2939. if (InformationClass == PolicyAuditFullSetInformation) {
  2940. InformationClass = PolicyAuditFullQueryInformation;
  2941. }
  2942. //
  2943. // If the information in the cache for this Information Class is invalid,
  2944. // just return
  2945. //
  2946. if (!LsapDbIsCacheValidPolicyInfoClass( InformationClass )) {
  2947. goto Cleanup;
  2948. }
  2949. if (LsapDbPolicy.Info[InformationClass].AttributeLength != 0) {
  2950. LsaIFree_LSAPR_POLICY_INFORMATION (
  2951. InformationClass,
  2952. (PLSAPR_POLICY_INFORMATION) LsapDbPolicy.Info[ InformationClass ].Attribute
  2953. );
  2954. LsapDbPolicy.Info[InformationClass].Attribute = NULL;
  2955. LsapDbPolicy.Info[InformationClass].AttributeLength = 0;
  2956. }
  2957. Cleanup:
  2958. SafeReleaseResource( &LsapDbState.PolicyCacheLock );
  2959. return;
  2960. }
  2961. NTSTATUS
  2962. LsapDbVerifyInfoQueryPolicy(
  2963. IN LSAPR_HANDLE PolicyHandle,
  2964. IN POLICY_INFORMATION_CLASS InformationClass,
  2965. OUT PACCESS_MASK RequiredAccess
  2966. )
  2967. /*++
  2968. Routine Description:
  2969. This function validates a Policy Information Class. If valid, a mask
  2970. of the accesses required to set the Policy Information of the class is
  2971. returned.
  2972. Arguments:
  2973. PolicyHandle - Handle from an LsapDbOpenPolicy call. The handle
  2974. may be trusted.
  2975. InformationClass - Specifies a Policy Information Class.
  2976. RequiredAccess - Points to variable that will receive a mask of the
  2977. accesses required to query the given class of Policy Information.
  2978. If an error is returned, this value is cleared to 0.
  2979. Return Values:
  2980. NTSTATUS - Standard Nt Result Code
  2981. STATUS_SUCCESS - The Policy Information Class provided is
  2982. valid and the information provided is consistent with this
  2983. class.
  2984. STATUS_INVALID_PARAMETER - Invalid parameter:
  2985. Information Class is invalid
  2986. Policy Information not valid for the class
  2987. --*/
  2988. {
  2989. LSAP_DB_HANDLE InternalHandle = (LSAP_DB_HANDLE) PolicyHandle;
  2990. if (LsapDbValidInfoPolicy( InformationClass, NULL)) {
  2991. //
  2992. // Non-trusted callers are not allowed to query the
  2993. // PolicyModificationInformation information class.
  2994. //
  2995. if (!InternalHandle->Trusted) {
  2996. if (InformationClass == PolicyModificationInformation) {
  2997. return(STATUS_INVALID_PARAMETER);
  2998. }
  2999. }
  3000. *RequiredAccess = LsapDbRequiredAccessQueryPolicy[InformationClass];
  3001. return(STATUS_SUCCESS);
  3002. }
  3003. return(STATUS_INVALID_PARAMETER);
  3004. }
  3005. NTSTATUS
  3006. LsapDbVerifyInfoSetPolicy(
  3007. IN LSAPR_HANDLE PolicyHandle,
  3008. IN POLICY_INFORMATION_CLASS InformationClass,
  3009. IN PLSAPR_POLICY_INFORMATION PolicyInformation,
  3010. OUT PACCESS_MASK RequiredAccess
  3011. )
  3012. /*++
  3013. Routine Description:
  3014. This function validates a Policy Information Class and verifies
  3015. that the provided Policy Information is valid for the class.
  3016. If valid, a mask of the accesses required to set the Policy
  3017. Information of the class is returned.
  3018. Arguments:
  3019. PolicyHandle - Handle from an LsapDbOpenPolicy call. The handle
  3020. may be trusted.
  3021. InformationClass - Specifies a Policy Information Class.
  3022. PolicyInformation - Points to Policy Information to be set.
  3023. RequiredAccess - Points to variable that will receive a mask of the
  3024. accesses required to set the given class of Policy Information.
  3025. If an error is returned, this value is cleared to 0.
  3026. Return Values:
  3027. NTSTATUS - Standard Nt Result Code
  3028. STATUS_SUCCESS - The Policy Information Class provided is
  3029. valid and the information provided is consistent with this
  3030. class.
  3031. STATUS_INVALID_PARAMETER - Invalid parameter:
  3032. Information Class is invalid
  3033. Information Class is invalid for non-trusted clients
  3034. Policy Information not valid for the class
  3035. STATUS_SHARED_POLICY - The policy is replicated from the DCs and cannot be modified
  3036. locally
  3037. --*/
  3038. {
  3039. NTSTATUS Status;
  3040. LSAP_DB_HANDLE InternalHandle = (LSAP_DB_HANDLE) PolicyHandle;
  3041. //
  3042. // Verify that the information class is valid and that the Policy
  3043. // Information provided is valid for the class.
  3044. //
  3045. if (LsapDbValidInfoPolicy( InformationClass, PolicyInformation)) {
  3046. //
  3047. // Non-trusted callers are not allowed to set information for
  3048. // the following classes.
  3049. //
  3050. // PolicyPdAccountInformation
  3051. // PolicyModificationInformation
  3052. //
  3053. if (!InternalHandle->Trusted) {
  3054. if ((InformationClass == PolicyPdAccountInformation) ||
  3055. (InformationClass == PolicyModificationInformation)) {
  3056. #ifdef LSA_SAM_ACCOUNTS_DOMAIN_TEST
  3057. if (InformationClass == PolicyPdAccountInformation) {
  3058. Status = LsapDbTestLoadSamAccountsDomain(
  3059. (PUNICODE_STRING) PolicyInformation
  3060. );
  3061. }
  3062. #endif // LSA_SAM_ACCOUNTS_DOMAIN_TEST
  3063. return(STATUS_INVALID_PARAMETER);
  3064. }
  3065. }
  3066. *RequiredAccess = LsapDbRequiredAccessSetPolicy[InformationClass];
  3067. return(STATUS_SUCCESS);
  3068. }
  3069. Status = STATUS_INVALID_PARAMETER;
  3070. return(Status);
  3071. }
  3072. BOOLEAN
  3073. LsapDbValidInfoPolicy(
  3074. IN POLICY_INFORMATION_CLASS InformationClass,
  3075. IN OPTIONAL PLSAPR_POLICY_INFORMATION PolicyInformation
  3076. )
  3077. /*++
  3078. Routine Description:
  3079. This function validates a Policy Information Class and optionally verifies
  3080. that provided Policy Information is valid for the class.
  3081. Arguments:
  3082. InformationClass - Specifies a Policy Information Class.
  3083. PolicyInformation - Optionally points to Policy Information. If
  3084. NULL is specified, no Policy Information checking takes place.
  3085. Return Values:
  3086. BOOLEAN - TRUE if the Policy information class provided is
  3087. valid, else FALSE.
  3088. --*/
  3089. {
  3090. BOOLEAN BooleanStatus = TRUE;
  3091. PPOLICY_AUDIT_LOG_INFO PolicyAuditLogInfo;
  3092. PPOLICY_AUDIT_EVENTS_INFO PolicyAuditEventsInfo;
  3093. PPOLICY_ACCOUNT_DOMAIN_INFO PolicyAccountDomainInfo;
  3094. PPOLICY_PRIMARY_DOMAIN_INFO PolicyPrimaryDomainInfo;
  3095. PPOLICY_DNS_DOMAIN_INFO PolicyDnsDomainInfo;
  3096. PPOLICY_PD_ACCOUNT_INFO PolicyPdAccountInfo;
  3097. PPOLICY_LSA_SERVER_ROLE_INFO PolicyLsaServerRoleInfo;
  3098. PPOLICY_REPLICA_SOURCE_INFO PolicyReplicaSourceInfo;
  3099. PPOLICY_DEFAULT_QUOTA_INFO PolicyDefaultQuotaInfo;
  3100. PPOLICY_MODIFICATION_INFO PolicyModificationInfo;
  3101. POLICY_AUDIT_EVENT_TYPE AuditEventType;
  3102. ULONG MaximumAuditEventCount;
  3103. PPOLICY_AUDIT_EVENT_OPTIONS EventAuditingOptions;
  3104. //
  3105. // Validate the Information Class
  3106. //
  3107. if ((InformationClass >= PolicyAuditLogInformation) &&
  3108. (InformationClass <= PolicyDnsDomainInformation)) {
  3109. if ((InformationClass == PolicyAuditFullSetInformation) ||
  3110. (InformationClass == PolicyAuditFullQueryInformation)) {
  3111. return FALSE;
  3112. }
  3113. if (PolicyInformation == NULL) {
  3114. return(TRUE);
  3115. }
  3116. switch (InformationClass) {
  3117. case PolicyAuditLogInformation:
  3118. PolicyAuditLogInfo = (PPOLICY_AUDIT_LOG_INFO) PolicyInformation;
  3119. //
  3120. // PPOLICY_AUDIT_LOG_INFO is a pointer-free struct;
  3121. // nothing to verify
  3122. //
  3123. break;
  3124. case PolicyAuditEventsInformation:
  3125. PolicyAuditEventsInfo = (PPOLICY_AUDIT_EVENTS_INFO) PolicyInformation;
  3126. MaximumAuditEventCount = PolicyAuditEventsInfo->MaximumAuditEventCount;
  3127. if (MaximumAuditEventCount == 0) {
  3128. BooleanStatus = FALSE;
  3129. break;
  3130. }
  3131. EventAuditingOptions = PolicyAuditEventsInfo->EventAuditingOptions;
  3132. try {
  3133. //
  3134. // Verify that the Event Auditing Options are meaningful.
  3135. //
  3136. for (AuditEventType = 0;
  3137. AuditEventType < (POLICY_AUDIT_EVENT_TYPE) MaximumAuditEventCount;
  3138. AuditEventType++) {
  3139. if (EventAuditingOptions[ AuditEventType ] !=
  3140. (EventAuditingOptions[ AuditEventType ] & POLICY_AUDIT_EVENT_MASK )) {
  3141. BooleanStatus = FALSE;
  3142. break;
  3143. }
  3144. }
  3145. } except (EXCEPTION_EXECUTE_HANDLER) {
  3146. BooleanStatus = FALSE;
  3147. }
  3148. break;
  3149. case PolicyPrimaryDomainInformation:
  3150. PolicyPrimaryDomainInfo = (PPOLICY_PRIMARY_DOMAIN_INFO) PolicyInformation;
  3151. if ( !LsapValidateLsaUnicodeString( &PolicyPrimaryDomainInfo->Name )) {
  3152. BooleanStatus = FALSE;
  3153. break;
  3154. }
  3155. break;
  3156. case PolicyDnsDomainInformation:
  3157. PolicyDnsDomainInfo = (PPOLICY_DNS_DOMAIN_INFO) PolicyInformation;
  3158. if ( !LsapValidateLsaUnicodeString( &PolicyDnsDomainInfo->Name ) ||
  3159. !LsapValidateLsaUnicodeString( &PolicyDnsDomainInfo->DnsDomainName ) ||
  3160. !LsapValidateLsaUnicodeString( &PolicyDnsDomainInfo->DnsForestName )) {
  3161. BooleanStatus = FALSE;
  3162. break;
  3163. }
  3164. break;
  3165. case PolicyAccountDomainInformation:
  3166. PolicyAccountDomainInfo = (PPOLICY_ACCOUNT_DOMAIN_INFO) PolicyInformation;
  3167. if ( !LsapValidateLsaUnicodeString( &PolicyAccountDomainInfo->DomainName )) {
  3168. BooleanStatus = FALSE;
  3169. break;
  3170. }
  3171. break;
  3172. case PolicyPdAccountInformation:
  3173. PolicyPdAccountInfo = (PPOLICY_PD_ACCOUNT_INFO) PolicyInformation;
  3174. if ( !LsapValidateLsaUnicodeString( &PolicyPdAccountInfo->Name )) {
  3175. BooleanStatus = FALSE;
  3176. break;
  3177. }
  3178. break;
  3179. case PolicyLsaServerRoleInformation:
  3180. PolicyLsaServerRoleInfo = (PPOLICY_LSA_SERVER_ROLE_INFO) PolicyInformation;
  3181. break;
  3182. case PolicyReplicaSourceInformation:
  3183. PolicyReplicaSourceInfo = (PPOLICY_REPLICA_SOURCE_INFO) PolicyInformation;
  3184. if ( !LsapValidateLsaUnicodeString( &PolicyReplicaSourceInfo->ReplicaSource ) ||
  3185. !LsapValidateLsaUnicodeString( &PolicyReplicaSourceInfo->ReplicaAccountName )) {
  3186. BooleanStatus = FALSE;
  3187. break;
  3188. }
  3189. break;
  3190. case PolicyDefaultQuotaInformation:
  3191. PolicyDefaultQuotaInfo = (PPOLICY_DEFAULT_QUOTA_INFO) PolicyInformation;
  3192. break;
  3193. case PolicyModificationInformation:
  3194. PolicyModificationInfo = (PPOLICY_MODIFICATION_INFO) PolicyInformation;
  3195. break;
  3196. default:
  3197. BooleanStatus = FALSE;
  3198. break;
  3199. }
  3200. } else {
  3201. BooleanStatus = FALSE;
  3202. }
  3203. return(BooleanStatus);
  3204. }
  3205. NTSTATUS
  3206. LsapDbGetSerialNumberPolicy(
  3207. IN LSAPR_HANDLE PolicyHandle,
  3208. OUT PLARGE_INTEGER ModifiedCount,
  3209. OUT PLARGE_INTEGER ModifiedCountAtLastPromotion,
  3210. OUT PLARGE_INTEGER CreationTime
  3211. )
  3212. /*++
  3213. Routine Description:
  3214. This service retrieves the creation time and the current count of
  3215. modifications to the LSA Database. This information is used as
  3216. a serial number for the LSA Database.
  3217. Arguments:
  3218. PolicyHandle - Trusted handle to Policy object obtained from
  3219. LsaIOpenPolicyTrusted().
  3220. ModifiedCount - Receives the current count of modifications to the
  3221. LSA's database.
  3222. ModifiedCountAtLastPromotion - Receives the modified count the last
  3223. time this machine was promoted to primary domain controller.
  3224. CreationTime - Receives the date/time at which the LSA database
  3225. was created.
  3226. Return Value:
  3227. NTSTATUS - Standard Nt Result Code.
  3228. Same as LsarQueryInformationPolicy.
  3229. --*/
  3230. {
  3231. NTSTATUS Status;
  3232. PPOLICY_MODIFICATION_INFO PolicyModificationInfo = NULL;
  3233. //
  3234. // Query the Policy Modification and internal Information.
  3235. // Note that only a handle marked as Trusted will be accepted.
  3236. //
  3237. Status = LsarQueryInformationPolicy(
  3238. PolicyHandle,
  3239. PolicyModificationInformation,
  3240. (PLSAPR_POLICY_INFORMATION *) &PolicyModificationInfo
  3241. );
  3242. if (!NT_SUCCESS(Status)) {
  3243. goto GetSerialNumberPolicyError;
  3244. }
  3245. GetSerialNumberPolicyFinish:
  3246. if (PolicyModificationInfo != NULL) {
  3247. *ModifiedCount = PolicyModificationInfo->ModifiedId;
  3248. *CreationTime = PolicyModificationInfo->DatabaseCreationTime;
  3249. MIDL_user_free( PolicyModificationInfo );
  3250. }
  3251. ModifiedCountAtLastPromotion->QuadPart = 0;
  3252. return (Status);
  3253. GetSerialNumberPolicyError:
  3254. goto GetSerialNumberPolicyFinish;
  3255. }
  3256. NTSTATUS
  3257. LsaIGetSerialNumberPolicy(
  3258. IN LSAPR_HANDLE PolicyHandle,
  3259. OUT PLARGE_INTEGER ModifiedCount,
  3260. OUT PLARGE_INTEGER CreationTime
  3261. )
  3262. /*++
  3263. Routine Description:
  3264. Thin wrapper to LsapDbGetSerialNumberPolicy().
  3265. See that function for descriptions.
  3266. --*/
  3267. {
  3268. LARGE_INTEGER Ignore1;
  3269. return( LsapDbGetSerialNumberPolicy( PolicyHandle,
  3270. ModifiedCount,
  3271. &Ignore1,
  3272. CreationTime
  3273. ) );
  3274. }
  3275. NTSTATUS
  3276. LsapDbSetSerialNumberPolicy(
  3277. IN LSAPR_HANDLE PolicyHandle,
  3278. IN PLARGE_INTEGER ModifiedCount,
  3279. IN OPTIONAL PLARGE_INTEGER ModifiedCountAtLastPromotion,
  3280. IN PLARGE_INTEGER CreationTime,
  3281. IN BOOLEAN StartOfFullSync
  3282. )
  3283. /*++
  3284. Routine Description:
  3285. Arguments:
  3286. PolicyHandle - Trusted handle to Policy object obtained from
  3287. LsaIOpenPolicyTrusted().
  3288. ModifiedCount - Provides the current count of modifications to the
  3289. LSA's database.
  3290. ModifiedCountAtLastPromotion - If present, provides a new
  3291. ModifiedIdAtLastPromotion value for the LSA database.
  3292. CreationTime - Provides the date/time at which the LSA database
  3293. was created.
  3294. StartOfFullSync - This boolean indicates whether a full sync is
  3295. being initiated. If TRUE is specified, then a full sync is to
  3296. follow and all existing LSA database information will be discarded.
  3297. If FALSE is specified, then only specific LSA Database information
  3298. is to follow and all changes must comply with standard LSA
  3299. operation behavior.
  3300. NOTE: This parameter is not currently used. It is designed
  3301. in for possible future use.
  3302. Return Value:
  3303. NTSTATUS - Standard Nt Result Code.
  3304. STATUS_SUCCESS - The call completed successfully.
  3305. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources,
  3306. such as memory, to complete the call.
  3307. --*/
  3308. {
  3309. NTSTATUS Status;
  3310. LARGE_INTEGER AdjustedModifiedId;
  3311. LARGE_INTEGER One = {1,0};
  3312. BOOLEAN ObjectReferenced = FALSE;
  3313. POLICY_MODIFICATION_INFO OriginalPolicyModificationInfo = {0, 0};
  3314. LsapEnterFunc( "LsaISetSerialNumberPolicy2" );
  3315. //
  3316. // Acquire the Lsa Database lock. Verify that the handle is
  3317. // a valid trusted handle to the Policy Object.
  3318. // Reference the handle and start an Lsa Database transaction.
  3319. //
  3320. Status = LsapDbReferenceObject(
  3321. PolicyHandle,
  3322. (ACCESS_MASK) 0,
  3323. PolicyObject,
  3324. PolicyObject,
  3325. LSAP_DB_LOCK | LSAP_DB_START_TRANSACTION | LSAP_DB_TRUSTED | LSAP_DB_NO_DS_OP_TRANSACTION
  3326. );
  3327. if (!NT_SUCCESS(Status)) {
  3328. goto SetSerialNumberPolicyError;
  3329. }
  3330. ObjectReferenced = TRUE;
  3331. // Since the policy object is in the registry, it grabbed the registry lock too.
  3332. // (The registry lock protects LsapDbState.PolicyModificationInfo)
  3333. ASSERT( LsapDbIsLocked( &LsapDbState.RegistryLock ));
  3334. OriginalPolicyModificationInfo = LsapDbState.PolicyModificationInfo;
  3335. {
  3336. //
  3337. // Set the in-memory copy of the Modified Id to the desired value
  3338. // minus one. The transaction log is empty at this point, but the
  3339. // routine LsapDbApplyTransaction() automatically increments
  3340. // the in-memory Modified Id and then adds an entry to the transaction
  3341. // log to write the Modified Id to the database. The net effect is
  3342. // therefore to set the Modified Id to the value specified.
  3343. //
  3344. AdjustedModifiedId.QuadPart = ModifiedCount->QuadPart - One.QuadPart;
  3345. //
  3346. //
  3347. // Set the Policy Modification Information local copy. When we
  3348. // commit the transaction, the database copy will be updated.
  3349. //
  3350. LsapDbState.PolicyModificationInfo.ModifiedId = AdjustedModifiedId;
  3351. LsapDbState.PolicyModificationInfo.DatabaseCreationTime = *CreationTime;
  3352. LsapDbState.RegistryModificationCount++;
  3353. }
  3354. //
  3355. // Invalidate the cache for the Policy Modification Information
  3356. //
  3357. LsapDbMakeInvalidInformationPolicy( PolicyModificationInformation );
  3358. SetSerialNumberPolicyFinish:
  3359. //
  3360. // If necessary, finish any Lsa Database transaction, notify the
  3361. // LSA Database Replicator of the change, dereference the Policy Object,
  3362. // release the LSA Database lock and return.
  3363. //
  3364. if (ObjectReferenced) {
  3365. Status = LsapDbDereferenceObject(
  3366. &PolicyHandle,
  3367. PolicyObject,
  3368. PolicyObject,
  3369. LSAP_DB_LOCK | LSAP_DB_FINISH_TRANSACTION | LSAP_DB_NO_DS_OP_TRANSACTION,
  3370. SecurityDbChange,
  3371. Status
  3372. );
  3373. ObjectReferenced = FALSE;
  3374. }
  3375. LsapExitFunc( "LsaISetSerialNumberPolicy2", Status );
  3376. return (Status);
  3377. SetSerialNumberPolicyError:
  3378. //
  3379. // Attempt to restore the Serial Number to its original value.
  3380. // We need only reset the in-memory copy.
  3381. //
  3382. if ( ObjectReferenced ) {
  3383. LsapDbState.PolicyModificationInfo = OriginalPolicyModificationInfo;
  3384. }
  3385. goto SetSerialNumberPolicyFinish;
  3386. //
  3387. // Although the StartOfFullSync parameter is included in the specification
  3388. // of this API, it has currently been designed out. The original
  3389. // intent was to disable non-Trusted access to the Policy Database
  3390. // while a full sync was taking place, but such a sync is currently
  3391. // a non-atomic operation.
  3392. //
  3393. UNREFERENCED_PARAMETER( StartOfFullSync );
  3394. UNREFERENCED_PARAMETER( ModifiedCountAtLastPromotion );
  3395. }
  3396. NTSTATUS
  3397. LsaISetSerialNumberPolicy(
  3398. IN LSAPR_HANDLE PolicyHandle,
  3399. IN PLARGE_INTEGER ModifiedCount,
  3400. IN PLARGE_INTEGER CreationTime,
  3401. IN BOOLEAN StartOfFullSync
  3402. )
  3403. /*++
  3404. Routine Description:
  3405. Thin wrapper around LsapDbSetSerialNumberPolicy().
  3406. See that function for descriptions.
  3407. --*/
  3408. {
  3409. return( LsapDbSetSerialNumberPolicy( PolicyHandle,
  3410. ModifiedCount,
  3411. NULL,
  3412. CreationTime,
  3413. StartOfFullSync
  3414. ) );
  3415. }
  3416. NTSTATUS
  3417. LsapDbBuildPolicyCache(
  3418. )
  3419. /*++
  3420. Routine Description:
  3421. This function constructs a cache for the Policy object. The cache
  3422. consists of a single structure containing fixed length attributes
  3423. of the Policy object directly, and pointers or Top level structures
  3424. for (variable length attributes.
  3425. NOTE: Currently, only the PolicyDefaultQuotaInformation information
  3426. class has information in the Policy object Cache.
  3427. Arguments:
  3428. None
  3429. Return Values:
  3430. None
  3431. --*/
  3432. {
  3433. NTSTATUS Status = STATUS_SUCCESS;
  3434. POLICY_INFORMATION_CLASS InformationClass;
  3435. //
  3436. // Do a slow query of each attribute in turn.
  3437. //
  3438. for ( InformationClass = PolicyAuditLogInformation;
  3439. InformationClass <= PolicyDnsDomainInformation;
  3440. InformationClass++ ) {
  3441. if ((InformationClass == PolicyAuditFullSetInformation) ||
  3442. (InformationClass == PolicyAuditFullQueryInformation) ||
  3443. (InformationClass == PolicyLsaServerRoleInformation) ) {
  3444. continue;
  3445. }
  3446. //
  3447. // Throw away current informaiton
  3448. //
  3449. LsaIFree_LSAPR_POLICY_INFORMATION(
  3450. InformationClass,
  3451. ( PLSAPR_POLICY_INFORMATION )LsapDbPolicy.Info[InformationClass].Attribute );
  3452. LsapDbPolicy.Info[InformationClass].Attribute = NULL;
  3453. //
  3454. // ... and obtain new one
  3455. //
  3456. Status = LsapDbSlowQueryInformationPolicy(
  3457. LsapPolicyHandle,
  3458. InformationClass,
  3459. &LsapDbPolicy.Info[InformationClass].Attribute
  3460. );
  3461. if (!NT_SUCCESS(Status)) {
  3462. break;
  3463. }
  3464. LsapDbPolicy.Info[InformationClass].AttributeLength = 0;
  3465. }
  3466. if (!NT_SUCCESS(Status)) {
  3467. goto BuildPolicyCacheError;
  3468. }
  3469. //
  3470. // Store buffer lengths top level nodes of returned information.
  3471. //
  3472. LsapDbPolicy.Info[PolicyAuditLogInformation].AttributeLength
  3473. = sizeof(POLICY_AUDIT_LOG_INFO);
  3474. LsapDbPolicy.Info[PolicyAuditEventsInformation].AttributeLength
  3475. = sizeof(LSAPR_POLICY_AUDIT_EVENTS_INFO);
  3476. LsapDbPolicy.Info[PolicyPrimaryDomainInformation].AttributeLength
  3477. = sizeof(LSAPR_POLICY_PRIMARY_DOM_INFO);
  3478. LsapDbPolicy.Info[PolicyAccountDomainInformation].AttributeLength
  3479. = sizeof(LSAPR_POLICY_ACCOUNT_DOM_INFO);
  3480. LsapDbPolicy.Info[PolicyPdAccountInformation].AttributeLength
  3481. = sizeof(LSAPR_POLICY_PD_ACCOUNT_INFO);
  3482. LsapDbPolicy.Info[PolicyLsaServerRoleInformation].AttributeLength
  3483. = sizeof(POLICY_LSA_SERVER_ROLE_INFO);
  3484. LsapDbPolicy.Info[PolicyReplicaSourceInformation].AttributeLength
  3485. = sizeof(LSAPR_POLICY_REPLICA_SRCE_INFO);
  3486. LsapDbPolicy.Info[PolicyDefaultQuotaInformation].AttributeLength
  3487. = sizeof(POLICY_DEFAULT_QUOTA_INFO);
  3488. LsapDbPolicy.Info[PolicyModificationInformation].AttributeLength
  3489. = sizeof(POLICY_MODIFICATION_INFO);
  3490. LsapDbPolicy.Info[PolicyAuditFullSetInformation].AttributeLength
  3491. = sizeof(POLICY_AUDIT_FULL_SET_INFO);
  3492. LsapDbPolicy.Info[PolicyAuditFullQueryInformation].AttributeLength
  3493. = sizeof(POLICY_AUDIT_FULL_QUERY_INFO);
  3494. LsapDbPolicy.Info[PolicyDnsDomainInformation].AttributeLength
  3495. = sizeof(LSAPR_POLICY_DNS_DOMAIN_INFO);
  3496. LsapDbPolicy.Info[PolicyDnsDomainInformationInt].AttributeLength
  3497. = 0; // dummy value for a dummy information class
  3498. BuildPolicyCacheFinish:
  3499. return(Status);
  3500. BuildPolicyCacheError:
  3501. goto BuildPolicyCacheFinish;
  3502. }
  3503. NTSTATUS
  3504. LsapDbUpdateInformationPolicy(
  3505. IN POLICY_INFORMATION_CLASS InformationClass
  3506. )
  3507. /*++
  3508. Routine Description:
  3509. This function updates the Policy Object Cache for a particular information
  3510. class. When a set of the information for a given class occurs, the
  3511. old information stored in the Policy Object Cache for that class is marked
  3512. invalid and freed. Next time a query is done for that class, this
  3513. routine is called to restore the information from backing storage.
  3514. Arguments:
  3515. InformationClass - Specifies the type of information being changed.
  3516. See LsapDbQueryInformationPolicy for details.
  3517. Buffer - Points to a structure containing the new information.
  3518. If NULL is specified, the information will be updated from backing
  3519. storage. NOTE: Currently, only NULL may be specified.
  3520. Return Value:
  3521. NTSTATUS - Standard Nt Result Code
  3522. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  3523. to complete the operation.
  3524. Others TBS
  3525. --*/
  3526. {
  3527. NTSTATUS Status;
  3528. ULONG TopNodeLength = 0;
  3529. //
  3530. // Just query the information back from disk to the cache.
  3531. //
  3532. Status = LsapDbSlowQueryInformationPolicy(
  3533. LsapPolicyHandle,
  3534. InformationClass,
  3535. &LsapDbPolicy.Info[InformationClass].Attribute
  3536. );
  3537. if (!NT_SUCCESS(Status)) {
  3538. goto UpdateInformationPolicyError;
  3539. }
  3540. //
  3541. // Now compute and store the length of the top node.
  3542. //
  3543. switch (InformationClass) {
  3544. case PolicyAuditLogInformation :
  3545. TopNodeLength = sizeof(POLICY_AUDIT_LOG_INFO);
  3546. break;
  3547. case PolicyAuditEventsInformation :
  3548. TopNodeLength = sizeof(LSAPR_POLICY_AUDIT_EVENTS_INFO);
  3549. break;
  3550. case PolicyPrimaryDomainInformation :
  3551. TopNodeLength = sizeof(LSAPR_POLICY_PRIMARY_DOM_INFO);
  3552. break;
  3553. case PolicyDnsDomainInformation :
  3554. TopNodeLength = sizeof(LSAPR_POLICY_DNS_DOMAIN_INFO);
  3555. break;
  3556. case PolicyAccountDomainInformation :
  3557. TopNodeLength = sizeof(LSAPR_POLICY_ACCOUNT_DOM_INFO);
  3558. break;
  3559. case PolicyPdAccountInformation :
  3560. TopNodeLength = sizeof(LSAPR_POLICY_PD_ACCOUNT_INFO);
  3561. break;
  3562. case PolicyLsaServerRoleInformation :
  3563. TopNodeLength = sizeof(POLICY_LSA_SERVER_ROLE_INFO);
  3564. break;
  3565. case PolicyReplicaSourceInformation :
  3566. TopNodeLength = sizeof(LSAPR_POLICY_REPLICA_SRCE_INFO);
  3567. break;
  3568. case PolicyDefaultQuotaInformation :
  3569. TopNodeLength = sizeof(POLICY_DEFAULT_QUOTA_INFO);
  3570. break;
  3571. case PolicyModificationInformation :
  3572. TopNodeLength = sizeof(POLICY_MODIFICATION_INFO);
  3573. break;
  3574. case PolicyAuditFullSetInformation :
  3575. TopNodeLength = 0;
  3576. break;
  3577. case PolicyAuditFullQueryInformation :
  3578. TopNodeLength = sizeof(POLICY_AUDIT_FULL_QUERY_INFO);
  3579. break;
  3580. }
  3581. LsapDbPolicy.Info[ InformationClass].AttributeLength = TopNodeLength;
  3582. UpdateInformationPolicyFinish:
  3583. return(Status);
  3584. UpdateInformationPolicyError:
  3585. goto UpdateInformationPolicyFinish;
  3586. }