Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2095 lines
48 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. setutl.c
  5. Abstract:
  6. Miscellaneous helper functions
  7. Author:
  8. Mac McLain (MacM) Feb 10, 1997
  9. Environment:
  10. User Mode
  11. Revision History:
  12. --*/
  13. #include <setpch.h>
  14. #include <dssetp.h>
  15. #include <lsarpc.h>
  16. #include <samrpc.h>
  17. #include <samisrv.h>
  18. #include <db.h>
  19. #include <confname.h>
  20. #include <loadfn.h>
  21. #include <ntdsa.h>
  22. #include <dsconfig.h>
  23. #include <attids.h>
  24. #include <samisrv.h>
  25. #include <dsp.h>
  26. #include <lsaisrv.h>
  27. #include <malloc.h>
  28. #include <dsgetdc.h>
  29. #include <lmcons.h>
  30. #include <lmaccess.h>
  31. #include <lmapibuf.h>
  32. #include <lmerr.h>
  33. #include <netsetp.h>
  34. #include <winsock2.h>
  35. #include <nspapi.h>
  36. #include <dsgetdcp.h>
  37. #include <lmremutl.h>
  38. #include <spmgr.h> // For SetupPhase definition
  39. #include <ntdsetup.h>
  40. #include <shlwapi.h>
  41. #include "secure.h"
  42. #include "cancel.h"
  43. #if DBG
  44. DEFINE_DEBUG2(DsRole);
  45. DEBUG_KEY DsRoleDebugKeys[] = {
  46. {DEB_ERROR, "Error"},
  47. {DEB_WARN, "Warn"},
  48. {DEB_TRACE, "Trace"},
  49. {DEB_TRACE_DS, "NtDs"},
  50. {DEB_TRACE_UPDATE, "Update"},
  51. {DEB_TRACE_LOCK, "Lock"},
  52. {DEB_TRACE_SERVICES,"Services"},
  53. {DEB_TRACE_NET, "Net"},
  54. {0, NULL }
  55. };
  56. VOID
  57. DsRoleDebugInitialize()
  58. {
  59. DsRoleInitDebug(DsRoleDebugKeys);
  60. }
  61. #endif // DBG
  62. BOOL
  63. DsRolepShutdownNotification(
  64. DWORD dwCtrlType
  65. );
  66. //
  67. // Global data for this module
  68. //
  69. BOOLEAN GlobalOpLockHeld = FALSE;
  70. NTSTATUS
  71. DsRolepInitialize(
  72. VOID
  73. )
  74. /*++
  75. Routine Description:
  76. Initializes the server portion of the DsRole APIs. Called from LsaSrv
  77. DsRolerGetDcOperationProgress return init
  78. Arguments:
  79. VOID
  80. Returns:
  81. STATUS_SUCCESS - Success
  82. --*/
  83. {
  84. NTSTATUS Status = STATUS_SUCCESS;
  85. RPC_STATUS RPCError = RPC_S_OK;
  86. PWSTR KerbPrinc;
  87. //
  88. // Zero out global operation handle
  89. //
  90. RtlZeroMemory( &DsRolepCurrentOperationHandle, sizeof(DsRolepCurrentOperationHandle));
  91. //
  92. // Init the lock
  93. //
  94. RtlInitializeResource( &DsRolepCurrentOperationHandle.CurrentOpLock );
  95. //
  96. // Grab the lock
  97. //
  98. LockOpHandle();
  99. GlobalOpLockHeld = TRUE;
  100. DsRolepResetOperationHandleLockHeld();
  101. DsRoleDebugInitialize();
  102. RPCError = RpcServerRegisterIf( dssetup_ServerIfHandle,
  103. NULL,
  104. NULL );
  105. if (RPC_S_OK != RPCError) {
  106. DsRoleDebugOut(( DEB_ERROR,
  107. "RpcServerRegisterIf failed %d\n",
  108. RPCError ));
  109. }
  110. DsRolepInitSetupFunctions();
  111. //
  112. // Create the SD's that are used to perform access checks for DsRoler
  113. // callers
  114. //
  115. if ( !DsRolepCreateInterfaceSDs() ) {
  116. return STATUS_NO_MEMORY;
  117. }
  118. try {
  119. Status = RtlInitializeCriticalSection( &LogFileCriticalSection );
  120. } except ( 1 ) {
  121. Status = STATUS_NO_MEMORY;
  122. }
  123. if(NT_SUCCESS(Status)) {
  124. //
  125. // Register our shutdown routine
  126. //
  127. if (!SetConsoleCtrlHandler(DsRolepShutdownNotification, TRUE)) {
  128. DsRoleDebugOut(( DEB_ERROR,
  129. "SetConsoleCtrlHandler failed %d\n",
  130. GetLastError() ));
  131. }
  132. if (!SetProcessShutdownParameters(480, SHUTDOWN_NORETRY)) {
  133. DsRoleDebugOut(( DEB_ERROR,
  134. "SetProcessShutdownParameters failed %d\n",
  135. GetLastError() ));
  136. }
  137. }
  138. return( Status );
  139. }
  140. NTSTATUS
  141. DsRolepInitializePhase2(
  142. VOID
  143. )
  144. /*++
  145. Routine Description:
  146. Second phase of the promotion/demotion api initialization. This initialization is slated
  147. to happen after the Lsa has finished all of it's initializations
  148. Arguments:
  149. VOID
  150. Returns:
  151. STATUS_SUCCESS - Success
  152. STATUS_UNSUCCESSFUL -- The function was called when the global lock wasn't held
  153. --*/
  154. {
  155. ULONG RpcStatus = STATUS_SUCCESS;
  156. PWSTR KerbPrinc;
  157. ASSERT( GlobalOpLockHeld );
  158. if ( !GlobalOpLockHeld ) {
  159. return( STATUS_UNSUCCESSFUL );
  160. }
  161. if ( !SetupPhase ) {
  162. //
  163. // Register the Rpc authenticated server info
  164. //
  165. RpcStatus = RpcServerInqDefaultPrincName(RPC_C_AUTHN_GSS_KERBEROS,
  166. &KerbPrinc);
  167. if ( RpcStatus == RPC_S_OK ) {
  168. DsRoleDebugOut(( DEB_TRACE_DS, "Kerberos Principal name: %ws\n",
  169. KerbPrinc ));
  170. RpcStatus = RpcServerRegisterAuthInfo(KerbPrinc,
  171. RPC_C_AUTHN_GSS_NEGOTIATE,
  172. NULL,
  173. NULL);
  174. RpcStringFree( &KerbPrinc );
  175. } else {
  176. DsRoleDebugOut(( DEB_TRACE_DS, "RpcServerInqDefaultPrincName failed with %lu\n",
  177. RpcStatus ));
  178. RpcStatus = RPC_S_OK;
  179. }
  180. if ( RpcStatus == RPC_S_OK) {
  181. RpcStatus = RpcServerRegisterAuthInfo( DSROLEP_SERVER_PRINCIPAL_NAME,
  182. RPC_C_AUTHN_GSS_NEGOTIATE,
  183. NULL,
  184. NULL );
  185. if ( RpcStatus != RPC_S_OK ) {
  186. DsRoleDebugOut(( DEB_ERROR,
  187. "RpcServerRegisterAuthInfo for %ws failed with 0x%lx\n",
  188. DSROLEP_SERVER_PRINCIPAL_NAME,
  189. RpcStatus ));
  190. RpcStatus = RPC_S_OK;
  191. }
  192. }
  193. }
  194. //
  195. // Release the lock, as was opened in Initialization, phase 1
  196. //
  197. GlobalOpLockHeld = FALSE;
  198. RtlReleaseResource( &DsRolepCurrentOperationHandle.CurrentOpLock );
  199. return( RpcStatus == RPC_S_OK ? STATUS_SUCCESS : RPC_NT_UNKNOWN_AUTHZ_SERVICE );
  200. }
  201. DWORD
  202. DsRolepGetMachineType(
  203. IN OUT PDSROLEP_MACHINE_TYPE MachineType
  204. )
  205. /*++
  206. Routine Description:
  207. Determines the type of machine this is being run on.
  208. Arguments:
  209. MachineType - Where the machine type is being returned
  210. Returns:
  211. STATUS_SUCCESS - Success
  212. --*/
  213. {
  214. DWORD Win32Err = ERROR_SUCCESS;
  215. if ( LsapProductType == NtProductWinNt ) {
  216. *MachineType = DSROLEP_MT_CLIENT;
  217. } else if ( LsapProductType == NtProductServer ) {
  218. *MachineType = DSROLEP_MT_STANDALONE;
  219. } else {
  220. *MachineType = DSROLEP_MT_MEMBER;
  221. }
  222. return( Win32Err );
  223. }
  224. DWORD
  225. DsRolepSetProductType(
  226. IN DSROLEP_MACHINE_TYPE MachineType
  227. )
  228. /*++
  229. Routine Description:
  230. Changes the role of the product to the type specified.
  231. Arguments:
  232. MachineType - Type of ProductRole to set
  233. Returns:
  234. ERROR_SUCCESS - Success
  235. ERROR_INVALID_PARAMETER - A bad service option was given
  236. --*/
  237. {
  238. DWORD Win32Err = ERROR_SUCCESS;
  239. PWSTR MachineSz = NULL;
  240. HKEY ProductHandle;
  241. ULONG Size = 0;
  242. switch ( MachineType ) {
  243. case DSROLEP_MT_STANDALONE:
  244. MachineSz = L"ServerNT";
  245. Size = sizeof( L"ServerNT" );
  246. break;
  247. case DSROLEP_MT_MEMBER:
  248. MachineSz = L"LanmanNT";
  249. Size = sizeof( L"LanmanNT");
  250. break;
  251. case DSROLEP_MT_CLIENT:
  252. default:
  253. Win32Err = ERROR_INVALID_PARAMETER;
  254. break;
  255. }
  256. if ( Win32Err == ERROR_SUCCESS ) {
  257. Win32Err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  258. DSROLEP_PROD_KEY_PATH,
  259. REG_OPTION_NON_VOLATILE,
  260. KEY_WRITE, // desired access
  261. &ProductHandle );
  262. if ( Win32Err == ERROR_SUCCESS ) {
  263. Win32Err = RegSetValueEx( ProductHandle,
  264. (LPCWSTR)DSROLEP_PROD_VALUE,
  265. 0,
  266. REG_SZ,
  267. (CONST BYTE *)MachineSz,
  268. Size );
  269. RegCloseKey( ProductHandle );
  270. }
  271. }
  272. DsRoleDebugOut(( DEB_TRACE_DS, "SetProductType to %ws returned %lu\n",
  273. MachineSz, Win32Err ));
  274. DsRolepLogPrint(( DEB_TRACE,
  275. "SetProductType to %lu [%ws] returned %lu\n",
  276. MachineType,
  277. DsRolepDisplayOptional(MachineSz),
  278. Win32Err ));
  279. DSROLEP_FAIL1( Win32Err, DSROLERES_PRODUCT_TYPE, MachineSz );
  280. return( Win32Err );
  281. }
  282. DWORD
  283. DsRolepCreateAuthIdentForCreds(
  284. IN PWSTR Account,
  285. IN PWSTR Password,
  286. OUT PSEC_WINNT_AUTH_IDENTITY *AuthIdent
  287. )
  288. /*++
  289. Routine Description:
  290. Internal routine to create an AuthIdent structure for the given creditentials
  291. Arguments:
  292. Account - Account name
  293. Password - Password for the account
  294. AuthIdent - AuthIdentity struct to allocate and fill in.
  295. Returns:
  296. ERROR_SUCCESS - Success
  297. ERROR_NOT_ENOUGH_MEMORY - A memory allocation failed.
  298. --*/
  299. {
  300. DWORD Win32Err = ERROR_SUCCESS;
  301. PWSTR UserCredentialString = NULL;
  302. ASSERT( AuthIdent );
  303. //
  304. // If there are no creds, just return
  305. //
  306. if ( Account == NULL ) {
  307. *AuthIdent = NULL;
  308. return( Win32Err );
  309. }
  310. *AuthIdent = RtlAllocateHeap( RtlProcessHeap(), 0, sizeof( SEC_WINNT_AUTH_IDENTITY ) );
  311. if ( *AuthIdent == NULL ) {
  312. Win32Err = ERROR_NOT_ENOUGH_MEMORY;
  313. } else {
  314. RtlZeroMemory( *AuthIdent, sizeof( SEC_WINNT_AUTH_IDENTITY ) );
  315. UserCredentialString = RtlAllocateHeap( RtlProcessHeap(), 0,
  316. ( wcslen( Account ) + 1 ) * sizeof( WCHAR ) );
  317. if ( UserCredentialString ) {
  318. wcscpy( UserCredentialString, Account );
  319. ( *AuthIdent )->User = wcsstr( UserCredentialString, L"\\" );
  320. if ( ( *AuthIdent )->User ) {
  321. //
  322. // There is a domain name
  323. //
  324. *( ( *AuthIdent )->User ) = L'\0';
  325. ( ( *AuthIdent )->User )++;
  326. ( *AuthIdent )->Domain = UserCredentialString;
  327. } else {
  328. ( *AuthIdent )->User = UserCredentialString;
  329. ( *AuthIdent )->Domain = L"";
  330. }
  331. if ( ( *AuthIdent )->User ) {
  332. ( *AuthIdent )->UserLength = wcslen( ( *AuthIdent )->User );
  333. }
  334. if ( ( *AuthIdent )->Domain ) {
  335. ( *AuthIdent )->DomainLength = wcslen( ( *AuthIdent )->Domain );
  336. }
  337. ( *AuthIdent )->Password = Password;
  338. if ( Password ) {
  339. ( *AuthIdent )->PasswordLength = wcslen( Password );
  340. }
  341. ( *AuthIdent )->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
  342. } else {
  343. Win32Err = ERROR_NOT_ENOUGH_MEMORY;
  344. //
  345. // Free the memory allocated for the top level structure
  346. //
  347. RtlFreeHeap( RtlProcessHeap(), 0, *AuthIdent );
  348. *AuthIdent = NULL;
  349. }
  350. }
  351. return( Win32Err );
  352. }
  353. VOID
  354. DsRolepFreeAuthIdentForCreds(
  355. IN PSEC_WINNT_AUTH_IDENTITY AuthIdent
  356. )
  357. /*++
  358. Routine Description:
  359. Free the authident structure allocated above
  360. Arguments:
  361. AuthIdent - AuthIdentity struct to free
  362. Returns:
  363. VOID
  364. --*/
  365. {
  366. if ( AuthIdent ) {
  367. if ( AuthIdent->Domain == NULL ) {
  368. RtlFreeHeap( RtlProcessHeap(), 0, AuthIdent->User );
  369. } else {
  370. if ( *AuthIdent->Domain != L'\0' ) {
  371. RtlFreeHeap( RtlProcessHeap(), 0, AuthIdent->Domain );
  372. }
  373. }
  374. RtlFreeHeap( RtlProcessHeap(), 0, AuthIdent );
  375. }
  376. }
  377. NTSTATUS
  378. ImpLsaOpenPolicy(
  379. IN HANDLE CallerToken,
  380. IN PLSA_UNICODE_STRING SystemName OPTIONAL,
  381. IN PLSA_OBJECT_ATTRIBUTES ObjectAttributes,
  382. IN ACCESS_MASK DesiredAccess,
  383. IN OUT PLSA_HANDLE PolicyHandle
  384. )
  385. /*++
  386. Routine Description:
  387. This routine impersonates CallerToken and then calls into LsaOpenPolicy.
  388. This purpose of this routine is call into the LSA on a different machine
  389. using the RDR session for the caller of the DsRole API. The caller is
  390. represented by CallerToken. This is necessary because the RDR sessions
  391. are keyed by (logon id/remote server name) and we don't want to use the
  392. logon id of the lsass.exe process since this is a shared logon id for
  393. lsass.exe and services.exe and will lead to unresolable credentials
  394. conflict.
  395. N.B. The LSA rpc calls that follow the (Imp)LsaOpenPolicy will use the
  396. handle returned by this function and then magically uses the right RDR
  397. session to make the RPC call.
  398. Arguments:
  399. CallerToken - the token of the DsRole involker
  400. Others -- see LsaOpenPolicy
  401. Returns:
  402. STATUS_ACCESS_DENIED if the impersonattion fails.
  403. --*/
  404. {
  405. NTSTATUS Status = STATUS_SUCCESS;
  406. BOOL fSuccess;
  407. fSuccess = ImpersonateLoggedOnUser( CallerToken );
  408. if ( fSuccess ) {
  409. Status = LsaOpenPolicy( SystemName,
  410. ObjectAttributes,
  411. DesiredAccess,
  412. PolicyHandle );
  413. fSuccess = RevertToSelf();
  414. ASSERT( fSuccess );
  415. } else {
  416. DsRolepLogPrint(( DEB_TRACE,
  417. "Failed to impersonate caller, error %lu\n",
  418. GetLastError() ));
  419. //
  420. // We couldn't impersonate?
  421. //
  422. Status = STATUS_ACCESS_DENIED;
  423. }
  424. return Status;
  425. }
  426. DWORD
  427. ImpDsRolepDsGetDcForAccount(
  428. IN HANDLE CallerToken,
  429. IN LPWSTR Server OPTIONAL,
  430. IN LPWSTR Domain,
  431. IN LPWSTR Account,
  432. IN ULONG Flags,
  433. IN ULONG AccountBits,
  434. OUT PDOMAIN_CONTROLLER_INFOW *DomainControllerInfo
  435. )
  436. /*++
  437. Routine Description:
  438. This function will impersoniate logged on user and call DsRolepDsGetDcForAccount
  439. Arguments:
  440. CallerToken - The Token of the DsRole involker.
  441. Server - The server to call GetDc on.
  442. Domain - Domain to find the Dc for
  443. Account - Account to look for. If NULL, the current computer name is used
  444. Flags - Flags to bas in to the GetDc call
  445. AccountBits - Account control bits to search for
  446. DomainControllerInfo - Where the info is returned
  447. Returns:
  448. ERROR_SUCCESS - Success
  449. --*/
  450. {
  451. DWORD WinError = ERROR_SUCCESS;
  452. BOOL fSuccess;
  453. fSuccess = ImpersonateLoggedOnUser( CallerToken );
  454. if ( fSuccess ) {
  455. WinError = DsRolepDsGetDcForAccount(Server,
  456. Domain,
  457. Account,
  458. Flags,
  459. AccountBits,
  460. DomainControllerInfo
  461. );
  462. fSuccess = RevertToSelf();
  463. ASSERT( fSuccess );
  464. } else {
  465. DsRolepLogPrint(( DEB_TRACE,
  466. "Failed to impersonate caller, error %lu\n",
  467. GetLastError() ));
  468. //
  469. // We couldn't impersonate?
  470. //
  471. WinError = ERROR_ACCESS_DENIED;
  472. }
  473. return WinError;
  474. }
  475. NET_API_STATUS
  476. NET_API_FUNCTION
  477. ImpNetpManageIPCConnect(
  478. IN HANDLE CallerToken,
  479. IN LPWSTR lpServer,
  480. IN LPWSTR lpAccount,
  481. IN LPWSTR lpPassword,
  482. IN ULONG fOptions
  483. )
  484. /*++
  485. Routine Description:
  486. This routine impersonates CallerToken and then calls into
  487. NetpManageIPCConnect.
  488. This purpose of this routine is to create a RDR using the logon id of
  489. the caller of the DsRole api's. The caller is represented by CallerToken.
  490. This is necessary because the RDR sessions are keyed by
  491. (logon id/remote server name) and we don't want to use the
  492. logon id of the lsass.exe process since this is a shared logon id for
  493. lsass.exe and services.exe and will lead to unresolable credentials
  494. conflict.
  495. Arguments:
  496. CallerToken - the token of the DsRole involker
  497. Others -- see LsaOpenPolicy
  498. Returns:
  499. STATUS_ACCESS_DENIED if the impersonattion fails.
  500. --*/
  501. {
  502. DWORD WinError = ERROR_SUCCESS;
  503. BOOL fSuccess;
  504. fSuccess = ImpersonateLoggedOnUser( CallerToken );
  505. if ( fSuccess ) {
  506. WinError = NetpManageIPCConnect( lpServer,
  507. lpAccount,
  508. lpPassword,
  509. fOptions );
  510. fSuccess = RevertToSelf();
  511. ASSERT( fSuccess );
  512. } else {
  513. DsRolepLogPrint(( DEB_TRACE,
  514. "Failed to impersonate caller, error %lu\n",
  515. GetLastError() ));
  516. //
  517. // We couldn't impersonate?
  518. //
  519. WinError = ERROR_ACCESS_DENIED;
  520. }
  521. return WinError;
  522. }
  523. DWORD
  524. DsRolepGenerateRandomPassword(
  525. IN ULONG Length,
  526. IN WCHAR *Buffer
  527. )
  528. /*++
  529. Routine Description:
  530. This local function is used to generate a random password of no more than the
  531. specified length. It is assumed that the destination buffer is of sufficient length.
  532. Arguments:
  533. Length - Length of the buffer
  534. Buffer - Buffer to fill
  535. Return Values:
  536. ERROR_SUCCESS - Success
  537. --*/
  538. {
  539. DWORD Win32Err = ERROR_SUCCESS;
  540. ULONG PwdLength, i;
  541. LARGE_INTEGER Time;
  542. HCRYPTPROV CryptProvider = 0;
  543. PwdLength = Length;
  544. //
  545. // Generate a random password.
  546. //
  547. if ( CryptAcquireContext( &CryptProvider,
  548. NULL,
  549. NULL,
  550. PROV_RSA_FULL,
  551. CRYPT_VERIFYCONTEXT ) ) {
  552. if ( CryptGenRandom( CryptProvider,
  553. PwdLength * sizeof( WCHAR ),
  554. ( LPBYTE )Buffer ) ) {
  555. Buffer[ PwdLength ] = UNICODE_NULL;
  556. //
  557. // Make sure there are no NULL's in the middle of the list
  558. //
  559. for ( i = 0; i < PwdLength; i++ ) {
  560. if ( Buffer[ i ] == UNICODE_NULL ) {
  561. Buffer[ i ] = 0xe;
  562. }
  563. }
  564. } else {
  565. Win32Err = GetLastError();
  566. }
  567. CryptReleaseContext( CryptProvider, 0 );
  568. } else {
  569. Win32Err = GetLastError();
  570. }
  571. return( Win32Err );
  572. }
  573. DWORD
  574. DsRolepCopyDsDitFiles(
  575. IN LPWSTR DsPath
  576. )
  577. /*++
  578. Routine Description:
  579. This function copies the initial database files from the install point to the
  580. specified Ds database directory
  581. Arguments:
  582. DsPath - Path where the Ds database files are to reside
  583. Returns:
  584. ERROR_SUCCESS - Success
  585. --*/
  586. {
  587. DWORD Win32Err = ERROR_SUCCESS;
  588. WCHAR Source[MAX_PATH + 1];
  589. WCHAR Dest[MAX_PATH + 1];
  590. ULONG SrcLen = 0, DestLen = 0;
  591. PWSTR Current;
  592. ULONG i;
  593. PWSTR DsDitFiles[] = {
  594. L"ntds.dit"
  595. };
  596. if( ExpandEnvironmentStrings( L"%WINDIR%\\system32\\", Source, MAX_PATH ) == FALSE ) {
  597. Win32Err = GetLastError();
  598. } else {
  599. SrcLen = wcslen( Source );
  600. wcscpy( Dest, DsPath );
  601. if ( *(Dest + (wcslen( DsPath ) - 1 )) != L'\\' ) {
  602. wcscat( Dest, L"\\" );
  603. }
  604. DestLen = wcslen( Dest );
  605. }
  606. //
  607. // Then, create the destination directory
  608. //
  609. if ( Win32Err == ERROR_SUCCESS ) {
  610. Current = wcschr( DsPath + 4, L'\\' );
  611. while ( Win32Err == ERROR_SUCCESS ) {
  612. if ( Current != NULL ) {
  613. *Current = UNICODE_NULL;
  614. }
  615. if ( CreateDirectory( DsPath, NULL ) == FALSE ) {
  616. Win32Err = GetLastError();
  617. if ( Win32Err == ERROR_ALREADY_EXISTS) {
  618. Win32Err = ERROR_SUCCESS;
  619. } else if ( Win32Err == ERROR_ACCESS_DENIED ) {
  620. if ( PathIsRoot(DsPath) ) {
  621. //If the path given to CreateDirectory is a root path then
  622. //it will fail with ERROR_ACCESS_DENIED instead of
  623. //ERROR_ALREADY_EXISTS but the path is still a valid one for
  624. //ntds.dit and the log files to be placed in.
  625. Win32Err = ERROR_SUCCESS;
  626. }
  627. }
  628. }
  629. if ( Current != NULL ) {
  630. *Current = L'\\';
  631. Current = wcschr( Current + 1, L'\\' );
  632. } else {
  633. break;
  634. }
  635. }
  636. }
  637. //
  638. // Then copy them.
  639. //
  640. for ( i = 0; i < sizeof( DsDitFiles) / sizeof( PWSTR ) && Win32Err == ERROR_SUCCESS ; i++ ) {
  641. wcscpy( Source + SrcLen, DsDitFiles[i] );
  642. wcscpy( Dest + DestLen, DsDitFiles[i] );
  643. DSROLEP_CURRENT_OP2( DSROLEEVT_COPY_DIT, Source, Dest );
  644. if ( CopyFile( Source, Dest, TRUE ) == FALSE ) {
  645. Win32Err = GetLastError();
  646. if ( Win32Err == ERROR_ALREADY_EXISTS ||
  647. Win32Err == ERROR_FILE_EXISTS ) {
  648. Win32Err = ERROR_SUCCESS;
  649. } else {
  650. DsRolepLogPrint(( DEB_ERROR, "Failed to copy install file %ws to %ws: %lu\n",
  651. Source, Dest, Win32Err ));
  652. }
  653. }
  654. }
  655. return( Win32Err );
  656. }
  657. #define DSROLEP_SEC_SYSVOL L"SYSVOL"
  658. #define DSROLEP_SEC_DSDIT L"DSDIT"
  659. #define DSROLEP_SEC_DSLOG L"DSLOG"
  660. DWORD
  661. DsRolepSetDcSecurity(
  662. IN HANDLE ClientToken,
  663. IN LPWSTR SysVolRootPath,
  664. IN LPWSTR DsDatabasePath,
  665. IN LPWSTR DsLogPath,
  666. IN BOOLEAN Upgrade,
  667. IN BOOLEAN Replica
  668. )
  669. /*++
  670. Routine Description:
  671. This function will invoke the security editor to set the security on the Dc install files
  672. Arguments:
  673. SysVolRootPath - Root used for the system volume
  674. DsDatabasePath - Path to where the Ds database files go
  675. DsLogPath - Path to where the Ds log files go
  676. Upgrade - If TRUE, the machine is undergoing an upgrade
  677. Replica - If TRUE, the machine is going through an upgrade
  678. Returns:
  679. ERROR_SUCCESS - Success
  680. --*/
  681. {
  682. DWORD Win32Err = ERROR_SUCCESS, i;
  683. WCHAR InfPath[ MAX_PATH + 1 ];
  684. PWSTR Paths[ 3 ], Tags[ 3 ];
  685. ULONG Options = 0;
  686. Paths[ 0 ] = SysVolRootPath;
  687. Paths[ 1 ] = DsDatabasePath;
  688. Paths[ 2 ] = DsLogPath;
  689. Tags[ 0 ] = DSROLEP_SEC_SYSVOL;
  690. Tags[ 1 ] = DSROLEP_SEC_DSDIT;
  691. Tags[ 2 ] = DSROLEP_SEC_DSLOG;
  692. //
  693. // Set the environment variables. secedt uses the environment variables to pass around
  694. // information, so we will set the for the duration of this function
  695. //
  696. if ( Win32Err == ERROR_SUCCESS ) {
  697. ASSERT( sizeof( Paths ) / sizeof( PWSTR ) == sizeof( Tags ) / sizeof( PWSTR ) );
  698. for ( i = 0; i < sizeof( Paths ) / sizeof( PWSTR ) && Win32Err == ERROR_SUCCESS; i++ ) {
  699. if ( SetEnvironmentVariable( Tags[ i ], Paths[ i ] ) == FALSE ) {
  700. Win32Err = GetLastError();
  701. DsRolepLogPrint(( DEB_TRACE,
  702. "SetEnvironmentVariable %ws = %ws failed with %lu\n",
  703. Tags[ i ],
  704. Paths[ i ],
  705. Win32Err ));
  706. break;
  707. }
  708. }
  709. }
  710. //
  711. // Now, invoke the security editing code
  712. //
  713. if ( Win32Err == ERROR_SUCCESS ) {
  714. DsRolepSetAndClearLog();
  715. DSROLEP_CURRENT_OP0( DSROLEEVT_SETTING_SECURITY );
  716. Options |= Upgrade ? SCE_PROMOTE_FLAG_UPGRADE : 0;
  717. Options |= Replica ? SCE_PROMOTE_FLAG_REPLICA : 0;
  718. Win32Err = ( *DsrSceDcPromoteSecurityEx )( ClientToken,
  719. Options,
  720. DsRolepStringUpdateCallback );
  721. DsRolepSetAndClearLog();
  722. DsRolepLogOnFailure( Win32Err,
  723. DsRolepLogPrint(( DEB_ERROR,
  724. "Setting security on Dc files failed with %lu\n",
  725. Win32Err )) );
  726. }
  727. //
  728. // Delete the environment variables
  729. //
  730. for ( i = 0; i < sizeof( Paths ) / sizeof( PWSTR ); i++ ) {
  731. if ( SetEnvironmentVariable( Tags[ i ], NULL ) == FALSE ) {
  732. DsRolepLogPrint(( DEB_TRACE,
  733. "SetEnvironmentVariable %ws = NULL failed with %lu\n",
  734. Tags[ i ],
  735. GetLastError() ));
  736. }
  737. }
  738. //
  739. // Currently, setting the security will not cause the promote to fail
  740. //
  741. if ( Win32Err != ERROR_SUCCESS ) {
  742. //
  743. // Raise an event
  744. //
  745. SpmpReportEvent( TRUE,
  746. EVENTLOG_WARNING_TYPE,
  747. DSROLERES_FAIL_SET_SECURITY,
  748. 0,
  749. sizeof( ULONG ),
  750. &Win32Err,
  751. 1,
  752. SCE_DCPROMO_LOG_PATH );
  753. DSROLEP_SET_NON_FATAL_ERROR( Win32Err );
  754. }
  755. Win32Err = ERROR_SUCCESS;
  756. return( Win32Err );
  757. }
  758. DWORD
  759. DsRolepDsGetDcForAccount(
  760. IN LPWSTR Server OPTIONAL,
  761. IN LPWSTR Domain,
  762. IN LPWSTR Account,
  763. IN ULONG Flags,
  764. IN ULONG AccountBits,
  765. OUT PDOMAIN_CONTROLLER_INFOW *DomainControllerInfo
  766. )
  767. /*++
  768. Routine Description:
  769. This function is equivalent to DsGetDcName but will search for the Dc that holds the
  770. specified account.
  771. Arguments:
  772. ReplicaServer - The server to call GetDc on.
  773. Domain - Domain to find the Dc for
  774. Account - Account to look for. If NULL, the current computer name is used
  775. Flags - Flags to bas in to the GetDc call
  776. AccountBits - Account control bits to search for
  777. DomainControllerInfo - Where the info is returned
  778. Returns:
  779. ERROR_SUCCESS - Success
  780. --*/
  781. {
  782. DWORD Win32Err = ERROR_SUCCESS;
  783. WCHAR ComputerName[ MAX_COMPUTERNAME_LENGTH + 2 ];
  784. ULONG Length = MAX_COMPUTERNAME_LENGTH + 1;
  785. //
  786. // If we have no account, use the computer name
  787. //
  788. if ( Account == NULL ) {
  789. if ( GetComputerName( ComputerName, &Length ) == FALSE ) {
  790. Win32Err = GetLastError();
  791. } else {
  792. wcscat( ComputerName, SSI_SECRET_PREFIX );
  793. Account = ComputerName;
  794. }
  795. }
  796. //
  797. // Now, do the find
  798. //
  799. if ( Win32Err == ERROR_SUCCESS ) {
  800. DSROLEP_CURRENT_OP2( DSROLEEVT_FIND_DC_FOR_ACCOUNT, Domain, Account );
  801. Win32Err = DsGetDcNameWithAccountW( Server,
  802. Account,
  803. AccountBits,
  804. Domain,
  805. NULL,
  806. NULL,
  807. Flags,
  808. DomainControllerInfo );
  809. if ( ERROR_NO_SUCH_USER == Win32Err ) {
  810. //
  811. // The error should read "no machine account", not "no user"
  812. // since we are searching for a machine account.
  813. //
  814. Win32Err = ERROR_NO_TRUST_SAM_ACCOUNT;
  815. }
  816. if ( Win32Err == ERROR_SUCCESS ) {
  817. DSROLEP_CURRENT_OP2( DSROLEEVT_FOUND_DC,
  818. ( PWSTR ) ( ( *DomainControllerInfo )->DomainControllerName + 2 ),
  819. Domain );
  820. } else {
  821. DsRolepLogPrint(( DEB_ERROR, "Failed to find a DC for domain %ws: %lu\n",
  822. Domain, Win32Err ));
  823. }
  824. }
  825. return( Win32Err );
  826. }
  827. DWORD
  828. DsRolepSetMachineAccountType(
  829. IN LPWSTR Dc,
  830. IN HANDLE ClientToken,
  831. IN LPWSTR User,
  832. IN LPWSTR Password,
  833. IN LPWSTR AccountName,
  834. IN ULONG AccountBits,
  835. IN OUT WCHAR** AccountDn
  836. )
  837. {
  838. DWORD Win32Err = ERROR_SUCCESS, Win32Err2;
  839. USER_INFO_1 *CurrentUI1;
  840. WCHAR ComputerName[ MAX_COMPUTERNAME_LENGTH + 2 ];
  841. ULONG Length = MAX_COMPUTERNAME_LENGTH + 1;
  842. PSEC_WINNT_AUTH_IDENTITY AuthIdent = NULL;
  843. //
  844. // If we have no account, use the computer name
  845. //
  846. if ( AccountName == NULL ) {
  847. if ( GetComputerName( ComputerName, &Length ) == FALSE ) {
  848. Win32Err = GetLastError();
  849. } else {
  850. wcscat( ComputerName, SSI_SECRET_PREFIX );
  851. AccountName = ComputerName;
  852. }
  853. }
  854. if ( Win32Err == ERROR_SUCCESS ) {
  855. Win32Err = DsRolepCreateAuthIdentForCreds( User, Password, &AuthIdent );
  856. }
  857. //
  858. // Call the support dll
  859. //
  860. if ( Win32Err == ERROR_SUCCESS ) {
  861. DsRolepLogPrint(( DEB_TRACE, "Searching for the machine account for %ws on %ws...\n",
  862. AccountName, Dc ));
  863. DSROLEP_CURRENT_OP0( DSROLEEVT_MACHINE_ACCT );
  864. DSROLE_GET_SETUP_FUNC( Win32Err, DsrNtdsSetReplicaMachineAccount );
  865. if ( Win32Err == ERROR_SUCCESS ) {
  866. if ( Dc && *Dc == L'\\' ) {
  867. Dc += 2;
  868. }
  869. Win32Err = (*DsrNtdsSetReplicaMachineAccount)( AuthIdent,
  870. ClientToken,
  871. Dc,
  872. AccountName,
  873. AccountBits,
  874. AccountDn );
  875. }
  876. DsRolepLogPrint(( DEB_TRACE, "NtdsSetReplicaMachineAccount returned %d\n", Win32Err ));
  877. DsRolepFreeAuthIdentForCreds( AuthIdent );
  878. }
  879. return( Win32Err );
  880. }
  881. DWORD
  882. DsRolepForceTimeSync(
  883. IN HANDLE ImpToken,
  884. IN PWSTR TimeSource
  885. )
  886. /*++
  887. Routine Description:
  888. This function forces a time sync with the specified server
  889. Arguments:
  890. TimeSource - Server to use for the time source
  891. Returns:
  892. ERROR_SUCCESS - Success
  893. --*/
  894. {
  895. DWORD Win32Err = ERROR_SUCCESS;
  896. NTSTATUS Status = STATUS_SUCCESS;
  897. PWSTR ServerName = NULL;
  898. PTIME_OF_DAY_INFO TOD;
  899. HANDLE ThreadToken = 0;
  900. TOKEN_PRIVILEGES Enabled, Previous;
  901. DWORD PreviousSize;
  902. TIME_FIELDS TimeFields;
  903. LARGE_INTEGER SystemTime;
  904. BOOL connected=FALSE;
  905. NETRESOURCE NetResource;
  906. WCHAR *remotename=NULL;
  907. BOOL fSuccess = FALSE;
  908. if ( !TimeSource ) {
  909. Win32Err = ERROR_INVALID_PARAMETER;
  910. goto cleanup;
  911. }
  912. //
  913. // Build the server name with preceeding \\'s
  914. //
  915. if ( *TimeSource != L'\\' ) {
  916. ServerName = RtlAllocateHeap( RtlProcessHeap(), 0,
  917. ( wcslen( TimeSource ) + 3 ) * sizeof( WCHAR ) );
  918. if ( ServerName == NULL ) {
  919. Win32Err = ERROR_NOT_ENOUGH_MEMORY;
  920. DsRolepLogPrint(( DEB_ERROR, "Failed to open a NULL session with %ws for time sync. Out of Memory. Failed with %d\n",
  921. TimeSource,
  922. Win32Err ));
  923. goto cleanup;
  924. } else {
  925. swprintf( ServerName, L"\\\\%ws", TimeSource );
  926. }
  927. } else {
  928. ServerName = TimeSource;
  929. }
  930. //
  931. // Enable the systemtime privilege
  932. //
  933. if ( Win32Err == ERROR_SUCCESS ) {
  934. Status = NtOpenThreadToken( NtCurrentThread(),
  935. TOKEN_READ | TOKEN_WRITE,
  936. TRUE,
  937. &ThreadToken );
  938. if ( Status == STATUS_NO_TOKEN ) {
  939. Status = NtOpenProcessToken( NtCurrentProcess(),
  940. TOKEN_WRITE | TOKEN_READ,
  941. &ThreadToken );
  942. }
  943. if ( NT_SUCCESS( Status ) ) {
  944. Enabled.PrivilegeCount = 1;
  945. Enabled.Privileges[0].Luid.LowPart = SE_SYSTEMTIME_PRIVILEGE;
  946. Enabled.Privileges[0].Luid.HighPart = 0;
  947. Enabled.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  948. PreviousSize = sizeof( Previous );
  949. Status = NtAdjustPrivilegesToken( ThreadToken,
  950. FALSE,
  951. &Enabled,
  952. sizeof( Enabled ),
  953. &Previous,
  954. &PreviousSize );
  955. //
  956. // Since we modified the thread token and the thread is shortlived, we won't bother
  957. // restoring it later.
  958. //
  959. }
  960. if ( ThreadToken ) {
  961. NtClose( ThreadToken );
  962. }
  963. Win32Err = RtlNtStatusToDosError( Status );
  964. DsRolepLogOnFailure( Win32Err,
  965. DsRolepLogPrint(( DEB_ERROR,
  966. "Failed to enable the SE_SYSTEMTIME_PRIVILEGE: %lu\n",
  967. Win32Err )) );
  968. }
  969. //
  970. // Get the remote time
  971. //
  972. if ( Win32Err == ERROR_SUCCESS ) {
  973. DSROLEP_CURRENT_OP1( DSROLEEVT_TIMESYNC, TimeSource );
  974. fSuccess = ImpersonateLoggedOnUser( ImpToken );
  975. if ( !fSuccess ) {
  976. DsRolepLogPrint(( DEB_TRACE,
  977. "Failed to impersonate caller, error %lu\n",
  978. GetLastError() ));
  979. //
  980. // We couldn't impersonate?
  981. //
  982. // We will continue anyway
  983. }
  984. }
  985. remotename = RtlAllocateHeap(
  986. RtlProcessHeap(), 0,
  987. sizeof(WCHAR)*(wcslen(L"\\ipc$")+wcslen(ServerName)+1));
  988. if ( remotename == NULL ) {
  989. Win32Err = ERROR_NOT_ENOUGH_MEMORY;
  990. DsRolepLogPrint(( DEB_ERROR, "Failed to open a NULL session with %ws for time sync. Out of Memory. Failed with %d\n",
  991. ServerName,
  992. Win32Err ));
  993. }
  994. wsprintf(remotename,L"%s\\ipc$",ServerName);
  995. NetResource.dwType=RESOURCETYPE_ANY;
  996. NetResource.lpLocalName=NULL;
  997. NetResource.lpRemoteName=remotename;
  998. NetResource.lpProvider=NULL;
  999. //get permission to access the server
  1000. Win32Err=WNetAddConnection2W(&NetResource,
  1001. L"",
  1002. L"",
  1003. 0);
  1004. if ( Win32Err == NO_ERROR ) {
  1005. connected=TRUE;
  1006. }
  1007. else {
  1008. DsRolepLogPrint(( DEB_WARN, "Failed to open a NULL session with %ws for time sync. Failed with %d\n",
  1009. ServerName,
  1010. Win32Err ));
  1011. //We will attempt to Time sync anyway
  1012. }
  1013. Win32Err = NetRemoteTOD( ServerName, ( LPBYTE * )&TOD );
  1014. if ( Win32Err == ERROR_SUCCESS ) {
  1015. TimeFields.Hour = ( WORD )TOD->tod_hours;
  1016. TimeFields.Minute = ( WORD )TOD->tod_mins;
  1017. TimeFields.Second = ( WORD )TOD->tod_secs;
  1018. TimeFields.Milliseconds = ( WORD )TOD->tod_hunds * 10;
  1019. TimeFields.Day = ( WORD )TOD->tod_day;
  1020. TimeFields.Month = ( WORD )TOD->tod_month;
  1021. TimeFields.Year = ( WORD )TOD->tod_year;
  1022. if ( !RtlTimeFieldsToTime( &TimeFields, &SystemTime ) ) {
  1023. Status = STATUS_INVALID_PARAMETER;
  1024. } else {
  1025. if ( connected ) {
  1026. WNetCancelConnection2(remotename,
  1027. 0,
  1028. TRUE);
  1029. }
  1030. if( remotename ) {
  1031. RtlFreeHeap( RtlProcessHeap(), 0, remotename );
  1032. }
  1033. fSuccess = RevertToSelf();
  1034. ASSERT( fSuccess );
  1035. connected=FALSE;
  1036. Status = NtSetSystemTime( &SystemTime, NULL );
  1037. if ( !NT_SUCCESS( Status ) ) {
  1038. DsRolepLogPrint(( DEB_ERROR, "NtSetSystemTime failed with 0x%lx\n", Status ));
  1039. }
  1040. }
  1041. Win32Err = RtlNtStatusToDosError( Status );
  1042. NetApiBufferFree( TOD );
  1043. } else {
  1044. DsRolepLogPrint(( DEB_ERROR, "Failed to get the current time on %ws: %lu\n",
  1045. TimeSource, Win32Err ));
  1046. }
  1047. //
  1048. // For the IDS, consider a failure here non-fatal
  1049. //
  1050. if ( Win32Err != ERROR_SUCCESS ) {
  1051. DsRolepLogPrint(( DEB_ERROR, "NON-FATAL error forcing a time sync (%lu). Ignoring\n",
  1052. Win32Err ));
  1053. Win32Err = ERROR_SUCCESS;
  1054. }
  1055. cleanup:
  1056. if ( connected ) {
  1057. WNetCancelConnection2(remotename,
  1058. 0,
  1059. TRUE);
  1060. if( remotename ) {
  1061. RtlFreeHeap( RtlProcessHeap(), 0, remotename );
  1062. }
  1063. fSuccess = RevertToSelf();
  1064. ASSERT( fSuccess );
  1065. }
  1066. return( Win32Err );
  1067. }
  1068. NTSTATUS
  1069. DsRolepGetMixedModeFlags(
  1070. IN PSID DomainSid,
  1071. OUT PULONG Flags
  1072. )
  1073. /*++
  1074. Routine Description:
  1075. This routine will determine whether the machine is currently in mixed mode or not
  1076. Arguments:
  1077. Flags - Pointer to a flags value to be altered. If the machine is a mixed mode, we simply
  1078. or in the proper value.
  1079. Return Values:
  1080. NTSTATUS
  1081. --*/
  1082. {
  1083. NTSTATUS Status = STATUS_SUCCESS;
  1084. BOOLEAN mixedDomain;
  1085. Status = SamIMixedDomain2( DomainSid, &mixedDomain );
  1086. if ( NT_SUCCESS( Status ) && mixedDomain) {
  1087. *Flags |= DSROLE_PRIMARY_DS_MIXED_MODE;
  1088. }
  1089. return( Status );
  1090. }
  1091. BOOL
  1092. DsRolepShutdownNotification(
  1093. DWORD dwCtrlType
  1094. )
  1095. /*++
  1096. Routine Description:
  1097. This routine is called by the system when system shutdown is occuring.
  1098. It stops a role change if one is in progress.
  1099. Arguments:
  1100. dwCtrlType -- the notification
  1101. Return Value:
  1102. FALSE - to allow any other shutdown routines in this process to
  1103. also be called.
  1104. --*/
  1105. {
  1106. if ( dwCtrlType == CTRL_SHUTDOWN_EVENT ) {
  1107. //
  1108. // Cancel the operation
  1109. //
  1110. (VOID) DsRolepCancel( FALSE ); // Don't block
  1111. }
  1112. return FALSE;
  1113. }
  1114. DWORD
  1115. DsRolepDeregisterNetlogonDnsRecords(
  1116. PNTDS_DNS_RR_INFO pInfo
  1117. )
  1118. /*++
  1119. Routine Description:
  1120. This routine is called during demotion to call netlogon to deregister
  1121. its the service DNS records for this domain controller
  1122. Arguments:
  1123. pInfo -- structure containing the parameters for the deregistration
  1124. Return Value:
  1125. An error from DsDeregisterDnsHostRecordsW
  1126. --*/
  1127. {
  1128. DWORD WinError = ERROR_SUCCESS;
  1129. HKEY hNetlogonParms = NULL;
  1130. BOOL fDoDeregistration = TRUE;
  1131. if ( !pInfo ) {
  1132. return STATUS_SUCCESS;
  1133. }
  1134. #define NETLOGON_PATH L"SYSTEM\\CurrentControlSet\\Services\\Netlogon\\Parameters"
  1135. #define AVOID_DNS_DEREG_KEY L"AvoidDnsDeregOnShutdown"
  1136. WinError = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  1137. NETLOGON_PATH,
  1138. 0,
  1139. KEY_READ,
  1140. &hNetlogonParms );
  1141. if ( ERROR_SUCCESS == WinError ) {
  1142. DWORD val = 0;
  1143. DWORD len = sizeof(DWORD);
  1144. DWORD type;
  1145. WinError = RegQueryValueEx( hNetlogonParms,
  1146. AVOID_DNS_DEREG_KEY,
  1147. 0,
  1148. &type,
  1149. (BYTE*)&val,
  1150. &len );
  1151. if ( (ERROR_SUCCESS == WinError)
  1152. && (type == REG_DWORD)
  1153. && (val == 0) ) {
  1154. //
  1155. // Don't bother; netlogon has already done the deregistration.
  1156. //
  1157. fDoDeregistration = FALSE;
  1158. }
  1159. RegCloseKey( hNetlogonParms );
  1160. }
  1161. if ( fDoDeregistration ) {
  1162. //
  1163. // Ask netlogon to do the deregistration
  1164. //
  1165. WinError = DsDeregisterDnsHostRecordsW( NULL, // go local
  1166. pInfo->DnsDomainName,
  1167. &pInfo->DomainGuid,
  1168. &pInfo->DsaGuid,
  1169. pInfo->DnsHostName );
  1170. } else {
  1171. WinError = ERROR_SUCCESS;
  1172. }
  1173. return WinError;
  1174. }
  1175. NTSTATUS
  1176. ImpLsaDelete(
  1177. IN HANDLE CallerToken,
  1178. IN LSA_HANDLE ObjectHandle
  1179. )
  1180. /*++
  1181. Routine Description:
  1182. This routine is a wrapper for the Lsa call. See The comments for
  1183. ImpOpenLsaPolicy for details.
  1184. --*/
  1185. {
  1186. NTSTATUS Status = STATUS_SUCCESS;
  1187. BOOL fSuccess;
  1188. fSuccess = ImpersonateLoggedOnUser( CallerToken );
  1189. if ( fSuccess ) {
  1190. Status = LsaDelete( ObjectHandle );
  1191. fSuccess = RevertToSelf();
  1192. ASSERT( fSuccess );
  1193. } else {
  1194. DsRolepLogPrint(( DEB_TRACE,
  1195. "Failed to impersonate caller, error %lu\n",
  1196. GetLastError() ));
  1197. //
  1198. // We couldn't impersonate?
  1199. //
  1200. Status = STATUS_ACCESS_DENIED;
  1201. }
  1202. return Status;
  1203. }
  1204. NTSTATUS
  1205. ImpLsaQueryInformationPolicy(
  1206. IN HANDLE CallerToken,
  1207. IN LSA_HANDLE PolicyHandle,
  1208. IN POLICY_INFORMATION_CLASS InformationClass,
  1209. OUT PVOID *Buffer
  1210. )
  1211. /*++
  1212. Routine Description:
  1213. This routine is a wrapper for the Lsa call. See The comments for
  1214. ImpOpenLsaPolicy for details.
  1215. --*/
  1216. {
  1217. NTSTATUS Status = STATUS_SUCCESS;
  1218. BOOL fSuccess;
  1219. fSuccess = ImpersonateLoggedOnUser( CallerToken );
  1220. if ( fSuccess ) {
  1221. Status = LsaQueryInformationPolicy( PolicyHandle,
  1222. InformationClass,
  1223. Buffer );
  1224. fSuccess = RevertToSelf();
  1225. ASSERT( fSuccess );
  1226. } else {
  1227. DsRolepLogPrint(( DEB_TRACE,
  1228. "Failed to impersonate caller, error %lu\n",
  1229. GetLastError() ));
  1230. //
  1231. // We couldn't impersonate?
  1232. //
  1233. Status = STATUS_ACCESS_DENIED;
  1234. }
  1235. return Status;
  1236. }
  1237. NTSTATUS
  1238. ImpLsaOpenTrustedDomainByName(
  1239. IN HANDLE CallerToken,
  1240. IN LSA_HANDLE PolicyHandle,
  1241. IN PLSA_UNICODE_STRING TrustedDomainName,
  1242. IN ACCESS_MASK DesiredAccess,
  1243. OUT PLSA_HANDLE TrustedDomainHandle
  1244. )
  1245. /*++
  1246. Routine Description:
  1247. This routine is a wrapper for the Lsa call. See The comments for
  1248. ImpOpenLsaPolicy for details.
  1249. --*/
  1250. {
  1251. NTSTATUS Status = STATUS_SUCCESS;
  1252. BOOL fSuccess;
  1253. fSuccess = ImpersonateLoggedOnUser( CallerToken );
  1254. if ( fSuccess ) {
  1255. Status = LsaOpenTrustedDomainByName( PolicyHandle,
  1256. TrustedDomainName,
  1257. DesiredAccess,
  1258. TrustedDomainHandle );
  1259. fSuccess = RevertToSelf();
  1260. ASSERT( fSuccess );
  1261. } else {
  1262. DsRolepLogPrint(( DEB_TRACE,
  1263. "Failed to impersonate caller, error %lu\n",
  1264. GetLastError() ));
  1265. //
  1266. // We couldn't impersonate?
  1267. //
  1268. Status = STATUS_ACCESS_DENIED;
  1269. }
  1270. return Status;
  1271. }
  1272. NTSTATUS
  1273. ImpLsaOpenTrustedDomain(
  1274. IN HANDLE CallerToken,
  1275. IN LSA_HANDLE PolicyHandle,
  1276. IN PSID TrustedDomainSid,
  1277. IN ACCESS_MASK DesiredAccess,
  1278. OUT PLSA_HANDLE TrustedDomainHandle
  1279. )
  1280. /*++
  1281. Routine Description:
  1282. This routine is a wrapper for the Lsa call. See The comments for
  1283. ImpOpenLsaPolicy for details.
  1284. --*/
  1285. {
  1286. NTSTATUS Status = STATUS_SUCCESS;
  1287. BOOL fSuccess;
  1288. fSuccess = ImpersonateLoggedOnUser( CallerToken );
  1289. if ( fSuccess ) {
  1290. Status = LsaOpenTrustedDomain( PolicyHandle,
  1291. TrustedDomainSid,
  1292. DesiredAccess,
  1293. TrustedDomainHandle );
  1294. fSuccess = RevertToSelf();
  1295. ASSERT( fSuccess );
  1296. } else {
  1297. DsRolepLogPrint(( DEB_TRACE,
  1298. "Failed to impersonate caller, error %lu\n",
  1299. GetLastError() ));
  1300. //
  1301. // We couldn't impersonate?
  1302. //
  1303. Status = STATUS_ACCESS_DENIED;
  1304. }
  1305. return Status;
  1306. }
  1307. NTSTATUS
  1308. ImpLsaCreateTrustedDomainEx(
  1309. IN HANDLE CallerToken,
  1310. IN LSA_HANDLE PolicyHandle,
  1311. IN PTRUSTED_DOMAIN_INFORMATION_EX TrustedDomainInformation,
  1312. IN PTRUSTED_DOMAIN_AUTH_INFORMATION AuthenticationInformation,
  1313. IN ACCESS_MASK DesiredAccess,
  1314. OUT PLSA_HANDLE TrustedDomainHandle
  1315. )
  1316. /*++
  1317. Routine Description:
  1318. This routine is a wrapper for the Lsa call. See The comments for
  1319. ImpOpenLsaPolicy for details.
  1320. --*/
  1321. {
  1322. NTSTATUS Status = STATUS_SUCCESS;
  1323. BOOL fSuccess;
  1324. fSuccess = ImpersonateLoggedOnUser( CallerToken );
  1325. if ( fSuccess ) {
  1326. Status = LsaCreateTrustedDomainEx( PolicyHandle,
  1327. TrustedDomainInformation,
  1328. AuthenticationInformation,
  1329. DesiredAccess,
  1330. TrustedDomainHandle );
  1331. fSuccess = RevertToSelf();
  1332. ASSERT( fSuccess );
  1333. } else {
  1334. DsRolepLogPrint(( DEB_TRACE,
  1335. "Failed to impersonate caller, error %lu\n",
  1336. GetLastError() ));
  1337. //
  1338. // We couldn't impersonate?
  1339. //
  1340. Status = STATUS_ACCESS_DENIED;
  1341. }
  1342. return Status;
  1343. }
  1344. NTSTATUS
  1345. ImpLsaQueryTrustedDomainInfoByName(
  1346. IN HANDLE CallerToken,
  1347. IN LSA_HANDLE PolicyHandle,
  1348. IN PLSA_UNICODE_STRING TrustedDomainName,
  1349. IN TRUSTED_INFORMATION_CLASS InformationClass,
  1350. OUT PVOID *Buffer
  1351. )
  1352. /*++
  1353. Routine Description:
  1354. This routine is a wrapper for the Lsa call. See The comments for
  1355. ImpOpenLsaPolicy for details.
  1356. --*/
  1357. {
  1358. NTSTATUS Status = STATUS_SUCCESS;
  1359. BOOL fSuccess;
  1360. fSuccess = ImpersonateLoggedOnUser( CallerToken );
  1361. if ( fSuccess ) {
  1362. Status = LsaQueryTrustedDomainInfoByName( PolicyHandle,
  1363. TrustedDomainName,
  1364. InformationClass,
  1365. Buffer );
  1366. fSuccess = RevertToSelf();
  1367. ASSERT( fSuccess );
  1368. } else {
  1369. DsRolepLogPrint(( DEB_TRACE,
  1370. "Failed to impersonate caller, error %lu\n",
  1371. GetLastError() ));
  1372. //
  1373. // We couldn't impersonate?
  1374. //
  1375. Status = STATUS_ACCESS_DENIED;
  1376. }
  1377. return Status;
  1378. }
  1379. NTSTATUS
  1380. ImpLsaQueryDomainInformationPolicy(
  1381. IN HANDLE CallerToken,
  1382. IN LSA_HANDLE PolicyHandle,
  1383. IN POLICY_DOMAIN_INFORMATION_CLASS InformationClass,
  1384. OUT PVOID *Buffer
  1385. )
  1386. /*++
  1387. Routine Description:
  1388. This routine is a wrapper for the Lsa call. See The comments for
  1389. ImpOpenLsaPolicy for details.
  1390. --*/
  1391. {
  1392. NTSTATUS Status = STATUS_SUCCESS;
  1393. BOOL fSuccess;
  1394. fSuccess = ImpersonateLoggedOnUser( CallerToken );
  1395. if ( fSuccess ) {
  1396. Status = LsaQueryDomainInformationPolicy( PolicyHandle,
  1397. InformationClass,
  1398. Buffer );
  1399. fSuccess = RevertToSelf();
  1400. ASSERT( fSuccess );
  1401. } else {
  1402. DsRolepLogPrint(( DEB_TRACE,
  1403. "Failed to impersonate caller, error %lu\n",
  1404. GetLastError() ));
  1405. //
  1406. // We couldn't impersonate?
  1407. //
  1408. Status = STATUS_ACCESS_DENIED;
  1409. }
  1410. return Status;
  1411. }
  1412. NTSTATUS
  1413. ImpLsaClose(
  1414. IN HANDLE CallerToken,
  1415. IN LSA_HANDLE ObjectHandle
  1416. )
  1417. /*++
  1418. Routine Description:
  1419. This routine is a wrapper for the Lsa call. See The comments for
  1420. ImpOpenLsaPolicy for details.
  1421. --*/
  1422. {
  1423. NTSTATUS Status = STATUS_SUCCESS;
  1424. BOOL fSuccess;
  1425. fSuccess = ImpersonateLoggedOnUser( CallerToken );
  1426. if ( fSuccess ) {
  1427. Status = LsaClose( ObjectHandle );
  1428. fSuccess = RevertToSelf();
  1429. ASSERT( fSuccess );
  1430. } else {
  1431. DsRolepLogPrint(( DEB_TRACE,
  1432. "Failed to impersonate caller, error %lu\n",
  1433. GetLastError() ));
  1434. //
  1435. // We couldn't impersonate?
  1436. //
  1437. Status = STATUS_ACCESS_DENIED;
  1438. }
  1439. return Status;
  1440. }