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.

4407 lines
108 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. lsads.c
  5. Abstract:
  6. Implemntation of the LSA/Ds interface and support routines
  7. Author:
  8. Mac McLain (MacM) Jan 17, 1997
  9. Environment:
  10. User Mode
  11. Revision History:
  12. --*/
  13. #include <lsapch2.h>
  14. #include <dbp.h>
  15. #include <sertlp.h>
  16. #ifdef DS_LOOKUP
  17. #include <dslookup.h>
  18. #endif
  19. #include <align.h>
  20. #include <windns.h>
  21. #include <alloca.h>
  22. #if DBG
  23. DEFINE_DEBUG2(LsaDs);
  24. DEBUG_KEY LsaDsDebugKeys[] = {{DEB_ERROR, "Error"},
  25. {DEB_WARN, "Warn"},
  26. {DEB_TRACE, "Trace"},
  27. {DEB_UPGRADE, "Upgrade"},
  28. {DEB_POLICY, "Policy"},
  29. {DEB_FIXUP, "Fixup"},
  30. {DEB_NOTIFY, "Notify"},
  31. {DEB_DSNOTIFY, "DsNotify"},
  32. {DEB_FTRACE, "FTrace"},
  33. {DEB_LOOKUP, "Lookup"},
  34. {DEB_HANDLE, "Handle"},
  35. {DEB_FTINFO, "FtInfo"},
  36. {DEB_SIDFILTER, "SidFilter"},
  37. {0, NULL}};
  38. HANDLE g_hDebugWait = NULL;
  39. HANDLE g_hDebugParamEvent = NULL;
  40. HKEY g_hDebugParamKey = NULL;
  41. extern DWORD LsaDsInfoLevel;
  42. void
  43. LsaDsGetDebugRegParams(
  44. IN HKEY ParamKey
  45. )
  46. /*++
  47. Routine Description:
  48. Gets the debug paramaters from the registry
  49. Sets LsaDsInfolevel for debug spew
  50. Arguments: HKEY to HKLM/System/CCS/Control/LSA
  51. --*/
  52. {
  53. DWORD cbType, tmpInfoLevel = LsaDsInfoLevel, cbSize = sizeof(DWORD);
  54. DWORD dwErr;
  55. dwErr = RegQueryValueExW(
  56. ParamKey,
  57. L"LsaDsInfoLevel",
  58. NULL,
  59. &cbType,
  60. (LPBYTE)&tmpInfoLevel,
  61. &cbSize
  62. );
  63. if (dwErr != ERROR_SUCCESS) {
  64. if (dwErr == ERROR_FILE_NOT_FOUND) {
  65. // no registry value is present, don't want info
  66. // so reset to defaults
  67. tmpInfoLevel = DEB_ERROR;
  68. } else {
  69. DebugLog((DEB_WARN, "Failed to query DebugLevel: 0x%x\n", dwErr));
  70. tmpInfoLevel = 0;
  71. }
  72. } else if ( cbType != REG_DWORD ) {
  73. DebugLog((DEB_WARN, "DebugLevel is of the wrong type, DEB_ERROR assumed"));
  74. tmpInfoLevel = DEB_ERROR;
  75. }
  76. LsaDsInfoLevel = tmpInfoLevel;
  77. dwErr = RegQueryValueExW(
  78. ParamKey,
  79. L"LogToFile",
  80. NULL,
  81. &cbType,
  82. (LPBYTE)&tmpInfoLevel,
  83. &cbSize
  84. );
  85. if (dwErr == ERROR_SUCCESS && cbType == REG_DWORD) {
  86. LsaDsSetLoggingOption((BOOL) tmpInfoLevel);
  87. } else {
  88. LsaDsSetLoggingOption(FALSE);
  89. }
  90. return;
  91. }
  92. VOID
  93. LsaDsWatchDebugParamKey(
  94. PVOID pCtxt,
  95. BOOLEAN fWaitStatus
  96. )
  97. /*++
  98. Routine Description:
  99. Sets RegNotifyChangeKeyValue() on param key, initializes
  100. debug level, then utilizes thread pool to wait on
  101. changes to this registry key. Enables dynamic debug
  102. level changes, as this function will also be callback
  103. if registry key modified.
  104. Arguments: pCtxt is actually a HANDLE to an event. This event
  105. will be triggered when key is modified.
  106. --*/
  107. {
  108. NTSTATUS Status;
  109. LONG lRes = ERROR_SUCCESS;
  110. if (NULL == g_hDebugParamKey) { // first time we've been called.
  111. lRes = RegOpenKeyExW(
  112. HKEY_LOCAL_MACHINE,
  113. L"System\\CurrentControlSet\\Control\\Lsa",
  114. 0,
  115. KEY_READ,
  116. &g_hDebugParamKey
  117. );
  118. if (ERROR_SUCCESS != lRes) {
  119. DebugLog((DEB_WARN,"Failed to open LSA debug parameters key: 0x%x\n", lRes));
  120. goto Reregister;
  121. }
  122. }
  123. if (NULL != g_hDebugWait) {
  124. Status = RtlDeregisterWait(g_hDebugWait);
  125. if (!NT_SUCCESS(Status)) {
  126. DebugLog((DEB_WARN, "Failed to Deregister wait on registry key: 0x%x\n", Status));
  127. goto Reregister;
  128. }
  129. }
  130. lRes = RegNotifyChangeKeyValue(
  131. g_hDebugParamKey,
  132. FALSE,
  133. REG_NOTIFY_CHANGE_LAST_SET,
  134. (HANDLE) pCtxt,
  135. TRUE
  136. );
  137. if (ERROR_SUCCESS != lRes) {
  138. DebugLog((DEB_ERROR,"Debug RegNotify setup failed: 0x%x\n", lRes));
  139. // we're tanked now. No further notifications, so get this one
  140. }
  141. LsaDsGetDebugRegParams(g_hDebugParamKey);
  142. Reregister:
  143. Status = RtlRegisterWait(
  144. &g_hDebugWait,
  145. (HANDLE) pCtxt,
  146. LsaDsWatchDebugParamKey,
  147. (HANDLE) pCtxt,
  148. INFINITE,
  149. WT_EXECUTEINPERSISTENTIOTHREAD |
  150. WT_EXECUTEONLYONCE
  151. );
  152. }
  153. VOID
  154. LsapDsDebugInitialize()
  155. {
  156. LsaDsInitDebug( LsaDsDebugKeys );
  157. g_hDebugParamEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
  158. if ( NULL == g_hDebugParamEvent ) {
  159. DebugLog((DEB_WARN, "CreateEvent for g_hDebugParamEvent failed - 0x%x\n", GetLastError()));
  160. } else {
  161. LsaDsWatchDebugParamKey( g_hDebugParamEvent, FALSE );
  162. }
  163. }
  164. #else // !DBG
  165. VOID
  166. LsapDsDebugInitialize()
  167. {
  168. }
  169. #endif
  170. //
  171. // extern definitions.
  172. //
  173. DWORD LsapDsThreadState; // Defined in lsads.h, referenced in spinit.c
  174. ULONG
  175. LsapClassIdFromObjType(
  176. IN LSAP_DB_OBJECT_TYPE_ID DsObjType
  177. );
  178. PVOID
  179. LsapDsAlloc(
  180. IN DWORD dwLen
  181. )
  182. /*++
  183. Routine Description:
  184. This function is the allocator for the LSA DS functions
  185. Arguments:
  186. dwLen - Number of bytes to allocate
  187. Return Value:
  188. Pointer to allocated memory on success or NULL on failure
  189. --*/
  190. {
  191. PLSADS_PER_THREAD_INFO CurrentThreadInfo;
  192. //
  193. // If there's no DS thread state,
  194. // we shouldn't be here.
  195. //
  196. if ( !THQuery()) {
  197. ASSERT( THQuery() );
  198. return NULL;
  199. }
  200. //
  201. // Otherwise simply allocate from the DS thread state.
  202. //
  203. return( THAlloc( dwLen ) );
  204. }
  205. VOID
  206. LsapDsFree(
  207. IN PVOID pvMemory
  208. )
  209. /*++
  210. Routine Description:
  211. This function frees memory allocated by LsapDsAlloc
  212. Arguments:
  213. pvMemory -- memory to free
  214. Return Value:
  215. VOID
  216. --*/
  217. {
  218. ASSERT( THQuery() );
  219. if ( THQuery() ) {
  220. THFree( pvMemory );
  221. }
  222. }
  223. NTSTATUS
  224. LsapDsInitializeDsStateInfo(
  225. IN LSADS_INIT_STATE DsInitState
  226. )
  227. /*++
  228. Routine Description:
  229. This routine will initialize the global DS State information that is used
  230. to contol the behavior of all of the lsa operations
  231. Arguments:
  232. DsInitState -- State the DS booted off of
  233. Return Value:
  234. STATUS_SUCCES -- Success
  235. STATUS_NO_MEMORY -- A memory allocation failed
  236. --*/
  237. {
  238. NTSTATUS Status = STATUS_SUCCESS;
  239. LSADS_INIT_STATE CalledInitState = DsInitState;
  240. if ( LsapDsDsSetup == DsInitState ) {
  241. //
  242. // At the time of modification, it is difficult to tell what
  243. // ramifications running with an init state of LsapDsDsSetup
  244. // will have since it is untested. So, let's be safe and translate
  245. // LsapDsDsSetup to LsapDsDs, which is a known state to
  246. // be in.
  247. //
  248. DsInitState = LsapDsDs;
  249. }
  250. LsaDsInitState = DsInitState ;
  251. if ( DsInitState != LsapDsDs ) {
  252. //
  253. // Use the dummy functions
  254. //
  255. LsaDsStateInfo.DsFuncTable.pOpenTransaction = LsapDsOpenTransactionDummy;
  256. LsaDsStateInfo.DsFuncTable.pApplyTransaction = LsapDsApplyTransactionDummy;
  257. LsaDsStateInfo.DsFuncTable.pAbortTransaction = LsapDsAbortTransactionDummy;
  258. } else if ( !LsaDsStateInfo.DsInitializedAndRunning ) {
  259. Status = LsaISamIndicatedDsStarted( FALSE );
  260. }
  261. //
  262. // Initialize the domain and default policy object references
  263. //
  264. if ( NT_SUCCESS( Status ) &&
  265. LsapDsWriteDs &&
  266. CalledInitState != LsapDsDsSetup ) {
  267. //
  268. // Fixup our trusted domain objects, if necessary
  269. //
  270. Status = LsapDsFixupTrustedDomainObjectOnRestart();
  271. }
  272. #if DBG
  273. if ( NT_SUCCESS( Status ) ) {
  274. LsapDsDebugOut(( 0, "LsapDsInitializeDsStateInfo succeeded\n", Status ));
  275. } else if ( LsapProductType == NtProductLanManNt ) {
  276. LsapDsDebugOut(( DEB_ERROR, "LsapDsInitializeDsStateInfo failed: 0x%lx\n", Status ));
  277. }
  278. #endif
  279. return( Status );
  280. }
  281. NTSTATUS
  282. LsapDsUnitializeDsStateInfo(
  283. VOID
  284. )
  285. /*++
  286. Routine Description:
  287. This routine will undo what the initialization did. Only valid for the setup case
  288. Arguments:
  289. None
  290. Return Value:
  291. STATUS_SUCCES -- Success
  292. --*/
  293. {
  294. LsaDsStateInfo.UseDs = FALSE;
  295. LsapDsIsRunning = FALSE;
  296. LsaDsStateInfo.WriteLocal = TRUE;
  297. //
  298. // Go back to using the dummy functions
  299. //
  300. LsaDsStateInfo.DsFuncTable.pOpenTransaction = LsapDsOpenTransactionDummy;
  301. LsaDsStateInfo.DsFuncTable.pApplyTransaction = LsapDsApplyTransactionDummy;
  302. LsaDsStateInfo.DsFuncTable.pAbortTransaction = LsapDsAbortTransactionDummy;
  303. LsaDsStateInfo.DsInitializedAndRunning = FALSE;
  304. return( STATUS_SUCCESS );
  305. }
  306. NTSTATUS
  307. LsapDsMapDsReturnToStatus (
  308. ULONG DsStatus
  309. )
  310. /*++
  311. Routine Description:
  312. Maps a DS error to NTSTATUS
  313. Arguments:
  314. DsStatus - DsStatus to map
  315. Return Values:
  316. STATUS_SUCCESS - Ds call succeeded
  317. STATUS_UNSUCCESSFUL - Ds call failed
  318. --*/
  319. {
  320. NTSTATUS Status;
  321. switch ( DsStatus )
  322. {
  323. case 0L:
  324. Status = STATUS_SUCCESS;
  325. break;
  326. default:
  327. Status = STATUS_UNSUCCESSFUL;
  328. LsapDsDebugOut(( DEB_TRACE, "DS Error %lu mapped to NT Status 0x%lx\n",
  329. DsStatus, Status ));
  330. break;
  331. }
  332. return( Status );
  333. }
  334. NTSTATUS
  335. LsapDsMapDsReturnToStatusEx (
  336. IN COMMRES *pComRes
  337. )
  338. /*++
  339. Routine Description:
  340. Maps a DS error to NTSTATUS
  341. Arguments:
  342. DsStatus - DsStatus to map
  343. Return Values:
  344. STATUS_SUCCESS - Ds call succeeded
  345. STATUS_UNSUCCESSFUL - Ds call failed
  346. --*/
  347. {
  348. NTSTATUS Status = STATUS_UNSUCCESSFUL;
  349. switch ( pComRes->errCode ) {
  350. case 0:
  351. Status = STATUS_SUCCESS;
  352. break;
  353. case attributeError:
  354. switch ( pComRes->pErrInfo->AtrErr.FirstProblem.intprob.problem ) {
  355. case PR_PROBLEM_NO_ATTRIBUTE_OR_VAL:
  356. Status = STATUS_NOT_FOUND;
  357. break;
  358. case PR_PROBLEM_INVALID_ATT_SYNTAX:
  359. case PR_PROBLEM_UNDEFINED_ATT_TYPE:
  360. case PR_PROBLEM_CONSTRAINT_ATT_TYPE:
  361. Status = STATUS_DATA_ERROR;
  362. break;
  363. case PR_PROBLEM_ATT_OR_VALUE_EXISTS:
  364. Status = STATUS_OBJECT_NAME_COLLISION;
  365. break;
  366. }
  367. break;
  368. case nameError:
  369. switch ( pComRes->pErrInfo->NamErr.problem ) {
  370. case NA_PROBLEM_NO_OBJECT:
  371. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  372. break;
  373. case NA_PROBLEM_BAD_ATT_SYNTAX:
  374. case NA_PROBLEM_BAD_NAME:
  375. Status = STATUS_OBJECT_NAME_INVALID;
  376. break;
  377. }
  378. break;
  379. case updError:
  380. switch ( pComRes->pErrInfo->UpdErr.problem ) {
  381. case UP_PROBLEM_ENTRY_EXISTS:
  382. Status = STATUS_OBJECT_NAME_COLLISION;
  383. break;
  384. case UP_PROBLEM_NAME_VIOLATION:
  385. Status = STATUS_OBJECT_NAME_INVALID;
  386. break;
  387. }
  388. break;
  389. case securityError:
  390. switch ( pComRes->pErrInfo->SecErr.problem ) {
  391. case SE_PROBLEM_INSUFF_ACCESS_RIGHTS:
  392. Status = STATUS_ACCESS_DENIED;
  393. break;
  394. }
  395. break;
  396. case serviceError:
  397. switch ( pComRes->pErrInfo->SvcErr.problem ) {
  398. case SV_PROBLEM_BUSY:
  399. Status = STATUS_DEVICE_BUSY;
  400. break;
  401. }
  402. }
  403. THClearErrors();
  404. return( Status );
  405. }
  406. VOID
  407. LsapDsInitializeStdCommArg (
  408. IN COMMARG *pCommArg,
  409. IN ULONG Flags
  410. )
  411. /*++
  412. Routine Description:
  413. Initialized a COMMARG structue with a standard set of options used by LsapDs routines
  414. Arguments:
  415. pCommArg - Pointer to the COMMARG structure to be initialized
  416. Return Values:
  417. None
  418. --*/
  419. {
  420. /* Get the default values... */
  421. InitCommarg(pCommArg);
  422. /* ...and override some of them */
  423. pCommArg->Svccntl.DerefAliasFlag = DA_NEVER;
  424. pCommArg->Svccntl.localScope = TRUE;
  425. pCommArg->Svccntl.SecurityDescriptorFlags = 0;
  426. pCommArg->ulSizeLimit = 0x20000;
  427. if ( FLAG_ON( Flags, LSAPDS_USE_PERMISSIVE_WRITE ) ) {
  428. pCommArg->Svccntl.fPermissiveModify = TRUE;
  429. }
  430. if ( FLAG_ON( Flags, LSAPDS_READ_DELETED ) ) {
  431. pCommArg->Svccntl.makeDeletionsAvail = TRUE;
  432. }
  433. }
  434. ULONG
  435. LsapClassIdFromObjType(
  436. IN LSAP_DB_OBJECT_TYPE_ID ObjType
  437. )
  438. /*++
  439. Routine Description:
  440. Maps from an LSA object type to a DS Class ID
  441. Arguments:
  442. DsObjType - Type of the object
  443. Return Values:
  444. ClassID of object type on success
  445. 0xFFFFFFFF on failure
  446. --*/
  447. {
  448. ULONG ClassId = 0xFFFFFFFF;
  449. switch ( ObjType ) {
  450. case TrustedDomainObject:
  451. ClassId = LsapDsClassIds[ LsapDsClassTrustedDomain ];
  452. break;
  453. case SecretObject:
  454. ClassId = LsapDsClassIds[ LsapDsClassSecret ];
  455. break;
  456. }
  457. return( ClassId );
  458. }
  459. NTSTATUS
  460. LsapAllocAndInitializeDsNameFromUnicode(
  461. IN PLSA_UNICODE_STRING pObjectName,
  462. OUT PDSNAME *pDsName
  463. )
  464. /*++
  465. Routine Description:
  466. This function constructs a DSNAME structure and optional RDN for the
  467. stated object.
  468. Arguments:
  469. DsObjType -- Type of the object to be created.
  470. pObjectName -- Name of the object to be created.
  471. pObjectPath -- Root path under which to create the object
  472. pDsName -- Where the DS Name structure is returned. Free via LsapDsFree
  473. Return Value:
  474. STATUS_SUCCESS -- Success
  475. --*/
  476. {
  477. NTSTATUS Status = STATUS_SUCCESS;
  478. DWORD dwLen;
  479. DWORD dwNameLen = 0;
  480. if (pObjectName == NULL || pObjectName->Length == 0) {
  481. return( STATUS_INVALID_PARAMETER );
  482. }
  483. //
  484. // Determine our length...
  485. //
  486. dwNameLen = LsapDsGetUnicodeStringLenNoNull( pObjectName ) / sizeof(WCHAR);
  487. dwLen = DSNameSizeFromLen( dwNameLen );
  488. //
  489. // Now, allocate it...
  490. //
  491. *pDsName = LsapDsAlloc( dwLen );
  492. if ( *pDsName == NULL ) {
  493. Status = STATUS_NO_MEMORY;
  494. } else {
  495. (*pDsName)->structLen = dwLen;
  496. //
  497. // Length doesn't include trailing NULL
  498. //
  499. (*pDsName)->NameLen = dwNameLen;
  500. RtlCopyMemory( (*pDsName)->StringName, pObjectName->Buffer, pObjectName->Length );
  501. }
  502. return(Status);
  503. }
  504. NTSTATUS
  505. LsapDsCopyDsNameLsa(
  506. OUT PDSNAME *Dest,
  507. IN PDSNAME Source
  508. )
  509. /*++
  510. Routine Description:
  511. This function copies one
  512. Arguments:
  513. DsObjType -- Type of the object to be created.
  514. pObjectName -- Name of the object to be created.
  515. Flags -- Flags to control the various actions of the create
  516. cItems -- Number of attributes to set
  517. pAttrTypeList -- List of attribute types
  518. pAttrValList -- List of attribute values
  519. Return Value:
  520. STATUS_SUCCESS -- Success
  521. --*/
  522. {
  523. NTSTATUS Status = STATUS_SUCCESS;
  524. if ( Source == NULL ) {
  525. *Dest = NULL;
  526. } else {
  527. *Dest = LsapAllocateLsaHeap( Source->structLen );
  528. if ( *Dest == NULL ) {
  529. Status = STATUS_INSUFFICIENT_RESOURCES;
  530. } else {
  531. RtlCopyMemory( *Dest, Source, Source->structLen );
  532. }
  533. }
  534. return( Status );
  535. }
  536. NTSTATUS
  537. LsapDsCreateAndSetObject(
  538. IN PLSA_UNICODE_STRING pObjectName,
  539. IN ULONG Flags,
  540. IN ULONG cItems,
  541. IN ATTRTYP *pAttrTypeList,
  542. IN ATTRVAL *pAttrValList
  543. )
  544. /*++
  545. Routine Description:
  546. This function creates the specified DS object and sets the given
  547. attributes on the object
  548. Arguments:
  549. pObjectName -- Name of the object to be created.
  550. Flags -- Flags to control the various actions of the create
  551. cItems -- Number of attributes to set
  552. pAttrTypeList -- List of attribute types
  553. pAttrValList -- List of attribute values
  554. Return Value:
  555. STATUS_SUCCESS -- Success
  556. --*/
  557. {
  558. NTSTATUS Status = STATUS_SUCCESS;
  559. PDSNAME pDSName;
  560. ADDARG AddArg;
  561. ADDRES *AddRes = NULL;
  562. ATTR *pAddResAttributes;
  563. ATTRBLOCK AddResAttrBlock;
  564. ULONG i;
  565. LsapEnterFunc( "LsapDsCreateAndSetObject" );
  566. ASSERT( pObjectName != NULL );
  567. RtlZeroMemory( &AddArg, sizeof( ADDARG ) );
  568. //
  569. // Build the DSName
  570. //
  571. Status = LsapAllocAndInitializeDsNameFromUnicode( pObjectName, &pDSName );
  572. if ( NT_SUCCESS( Status ) ) {
  573. //
  574. // Initialize our memory for our structures.
  575. //
  576. pAddResAttributes = LsapDsAlloc( sizeof(ATTR) * cItems );
  577. if ( pAddResAttributes == NULL ) {
  578. Status = STATUS_NO_MEMORY;
  579. } else {
  580. for ( i = 0 ; i < cItems ; i++ ) {
  581. LSAP_DS_INIT_ATTR( pAddResAttributes[i], pAttrTypeList[i], 1, &(pAttrValList[i]) );
  582. }
  583. AddResAttrBlock.attrCount = cItems;
  584. AddResAttrBlock.pAttr = pAddResAttributes;
  585. AddArg.pObject = pDSName;
  586. AddArg.AttrBlock = AddResAttrBlock;
  587. LsapDsInitializeStdCommArg( &(AddArg.CommArg), 0 );
  588. }
  589. //
  590. // Now, do the create
  591. //
  592. if ( NT_SUCCESS( Status ) ) {
  593. //
  594. // Turn off fDSA flag. This is to force the core DS to perform
  595. // the access ck. Only the core DS has the knowledge to consider
  596. // the security descriptor on the logical parent in the DS. Do
  597. // not turn of the fDSA flag if this is an upgrade ( theoritically
  598. // for trusted clients too ). fDSA for Ds is analogous to trusted
  599. // client in LSA.
  600. //
  601. if ( !FLAG_ON( Flags, LSAPDS_CREATE_TRUSTED ) ) {
  602. LsapDsSetDsaFlags( FALSE );
  603. }
  604. DirAddEntry( &AddArg, &AddRes );
  605. if ( AddRes ) {
  606. Status = LsapDsMapDsReturnToStatusEx( &AddRes->CommRes );
  607. } else {
  608. Status = STATUS_INSUFFICIENT_RESOURCES;
  609. }
  610. LsapDsContinueTransaction();
  611. if ( !FLAG_ON( Flags, LSAPDS_CREATE_TRUSTED ) ) {
  612. LsapDsSetDsaFlags( TRUE );
  613. }
  614. LsapDsDebugOut(( DEB_TRACE, "DirAddEntry on %wZ returned 0x%lx\n",
  615. pObjectName, Status ));
  616. }
  617. LsapDsFree(pDSName);
  618. } else {
  619. LsapDsDebugOut(( DEB_TRACE,
  620. "LsapAllocAndInitializeDsNameFromUnicode on %wZ returned 0x%lx\n",
  621. pObjectName, Status ));
  622. }
  623. LsapExitFunc( "LsapDsCreateAndSetObject", Status );
  624. return( Status );
  625. }
  626. NTSTATUS
  627. LsapDsCreateObjectDs(
  628. IN PDSNAME ObjectName,
  629. IN ULONG Flags,
  630. IN ATTRBLOCK *AttrBlock
  631. )
  632. /*++
  633. Routine Description:
  634. This function creates the specified DS object and sets the given
  635. attributes on the object
  636. Arguments:
  637. ObjectName -- Dsname of the object to be created.
  638. Flags -- Flags to control the various actions of the create
  639. Attrs -- Optional list of attributes to set on the object
  640. Return Value:
  641. STATUS_SUCCESS -- Success
  642. --*/
  643. {
  644. NTSTATUS Status = STATUS_SUCCESS;
  645. ADDARG AddArg;
  646. ADDRES *AddRes = NULL;
  647. LsapEnterFunc( "LsapDsCreateObjectDs" );
  648. RtlZeroMemory( &AddArg, sizeof (ADDARG ) );
  649. AddArg.pObject = ObjectName;
  650. RtlCopyMemory( &AddArg.AttrBlock, AttrBlock, sizeof( ATTRBLOCK ) );
  651. LsapDsInitializeStdCommArg( &AddArg.CommArg, 0 );
  652. if ( !FLAG_ON( Flags, LSAPDS_CREATE_TRUSTED ) ) {
  653. LsapDsSetDsaFlags( FALSE );
  654. }
  655. //
  656. // Do the add
  657. //
  658. DirAddEntry( &AddArg, &AddRes );
  659. if ( AddRes ) {
  660. Status = LsapDsMapDsReturnToStatusEx( &AddRes->CommRes );
  661. } else {
  662. Status = STATUS_INSUFFICIENT_RESOURCES;
  663. }
  664. LsapDsContinueTransaction();
  665. if ( !FLAG_ON( Flags, LSAPDS_CREATE_TRUSTED ) ) {
  666. LsapDsSetDsaFlags( TRUE );
  667. }
  668. LsapDsDebugOut(( DEB_TRACE, "DirAddEntry on %ws returned 0x%lx\n",
  669. LsapDsNameFromDsName( ObjectName ), Status ));
  670. LsapExitFunc( "LsapDsCreateObjectDs", Status );
  671. return( Status );
  672. }
  673. NTSTATUS
  674. LsapDsRemove (
  675. IN PDSNAME pObject
  676. )
  677. {
  678. NTSTATUS Status = STATUS_SUCCESS;
  679. REMOVEARG Remove;
  680. REMOVERES *RemoveRes = NULL;
  681. RtlZeroMemory( &Remove, sizeof( REMOVEARG ) );
  682. //
  683. // Initialize the commarg struct
  684. //
  685. LsapDsInitializeStdCommArg( &Remove.CommArg, 0 );
  686. Remove.pObject = pObject;
  687. //
  688. // Do the call
  689. //
  690. DirRemoveEntry( &Remove, &RemoveRes );
  691. if ( RemoveRes ) {
  692. Status = LsapDsMapDsReturnToStatusEx( &RemoveRes->CommRes );
  693. } else {
  694. Status = STATUS_INSUFFICIENT_RESOURCES;
  695. }
  696. LsapDsContinueTransaction();
  697. return( Status );
  698. }
  699. NTSTATUS
  700. LsapDsRead (
  701. IN PUNICODE_STRING pObject,
  702. IN ULONG fFlags,
  703. IN ATTRBLOCK *pAttributesToRead,
  704. OUT ATTRBLOCK *pAttributeValues
  705. )
  706. /*++
  707. Routine Description:
  708. This function reads the specified attributes from the given object of the
  709. specified type. It servers as the primary interface between the LSA and the
  710. DS for reading a property/object
  711. Arguments:
  712. pObject - DSNAME of the object
  713. fFlags - Read flags
  714. ObjType - Type of LSA object to be read
  715. pReadAttributes - Attributes to be read
  716. pAttributeValues - Value of the attributes that were read.
  717. Return Value:
  718. STATUS_SUCCESS - Success
  719. --*/
  720. {
  721. NTSTATUS Status;
  722. PDSNAME DsName = NULL;
  723. Status = STATUS_SUCCESS;
  724. //
  725. // By the time we get here, everything should be valid...
  726. //
  727. ASSERT( pObject != NULL );
  728. ASSERT( pAttributesToRead != NULL && pAttributesToRead->attrCount > 0 );
  729. ASSERT( pAttributeValues != NULL );
  730. //
  731. // Build the DSName
  732. //
  733. Status = LsapAllocAndInitializeDsNameFromUnicode(
  734. pObject,
  735. &DsName
  736. );
  737. if ( NT_SUCCESS( Status ) ) {
  738. Status = LsapDsReadByDsName( DsName,
  739. fFlags,
  740. pAttributesToRead,
  741. pAttributeValues );
  742. LsapDsFree( DsName );
  743. }
  744. return( Status );
  745. }
  746. NTSTATUS
  747. LsapDsReadByDsName(
  748. IN PDSNAME DsName,
  749. IN ULONG Flags,
  750. IN ATTRBLOCK *pAttributesToRead,
  751. OUT ATTRBLOCK *pAttributeValues
  752. )
  753. /*++
  754. Routine Description:
  755. This function reads the specified attributes from the given object of the
  756. specified type. It servers as the primary interface between the LSA and the
  757. DS for reading a property/object
  758. Arguments:
  759. DsName - DSNAME of the object
  760. Flags - Read flags
  761. ObjType - Type of LSA object to be read
  762. pReadAttributes - Attributes to be read
  763. pAttributeValues - Value of the attributes that were read.
  764. Return Value:
  765. STATUS_SUCCESS - Success
  766. --*/
  767. {
  768. NTSTATUS Status = STATUS_SUCCESS, Status2;
  769. ENTINFSEL EntryInf;
  770. READARG ReadArg;
  771. READRES *ReadRes = NULL;
  772. ULONG i;
  773. //
  774. // By the time we get here, everything should be valid...
  775. //
  776. ASSERT( DsName != NULL );
  777. ASSERT( pAttributesToRead != NULL && pAttributesToRead->attrCount > 0 );
  778. ASSERT( pAttributeValues != NULL );
  779. ASSERT( THQuery() );
  780. if ( !THQuery() ) {
  781. return( STATUS_RXACT_INVALID_STATE );
  782. }
  783. //
  784. // Initialize the ENTINFSEL structure
  785. //
  786. EntryInf.attSel = EN_ATTSET_LIST;
  787. EntryInf.infoTypes = EN_INFOTYPES_TYPES_VALS;
  788. //
  789. // Initialize the READARG structure
  790. //
  791. RtlZeroMemory(&ReadArg, sizeof(READARG));
  792. ReadArg.pObject = DsName;
  793. ReadArg.pSel = &EntryInf;
  794. //
  795. // Initialize the commarg struct
  796. //
  797. LsapDsInitializeStdCommArg( &ReadArg.CommArg, Flags );
  798. EntryInf.AttrTypBlock.pAttr = LsapDsAlloc( pAttributesToRead->attrCount * sizeof(ATTR ) );
  799. if ( EntryInf.AttrTypBlock.pAttr == NULL ) {
  800. Status = STATUS_NO_MEMORY;
  801. } else {
  802. EntryInf.AttrTypBlock.attrCount = pAttributesToRead->attrCount;
  803. for ( i = 0 ; i < pAttributesToRead->attrCount ; i++ ) {
  804. EntryInf.AttrTypBlock.pAttr[i].attrTyp = pAttributesToRead->pAttr[i].attrTyp;
  805. EntryInf.AttrTypBlock.pAttr[i].AttrVal.valCount =
  806. pAttributesToRead->pAttr[i].AttrVal.valCount;
  807. EntryInf.AttrTypBlock.pAttr[i].AttrVal.pAVal =
  808. pAttributesToRead->pAttr[i].AttrVal.pAVal;
  809. EntryInf.attSel = EN_ATTSET_LIST;
  810. EntryInf.infoTypes = EN_INFOTYPES_TYPES_VALS;
  811. }
  812. }
  813. //
  814. // Do the call
  815. //
  816. if ( NT_SUCCESS( Status ) ) {
  817. DirRead( &ReadArg, &ReadRes );
  818. if ( ReadRes ) {
  819. Status = LsapDsMapDsReturnToStatusEx( &ReadRes->CommRes );
  820. } else {
  821. Status = STATUS_INSUFFICIENT_RESOURCES;
  822. }
  823. LsapDsContinueTransaction();
  824. }
  825. //
  826. // Now, build the attr block going back
  827. //
  828. if ( NT_SUCCESS( Status ) ) {
  829. pAttributeValues->attrCount = ReadRes->entry.AttrBlock.attrCount;
  830. pAttributeValues->pAttr = ReadRes->entry.AttrBlock.pAttr;
  831. }
  832. return( Status );
  833. }
  834. NTSTATUS
  835. LsapDsWrite(
  836. IN PUNICODE_STRING pObject,
  837. IN ULONG Flags,
  838. IN ATTRBLOCK *Attributes
  839. )
  840. {
  841. NTSTATUS Status = STATUS_SUCCESS;
  842. MODIFYARG Modify;
  843. MODIFYRES *ModifyRes;
  844. ATTRMODLIST *AttrMod = NULL;
  845. INT i;
  846. PDSNAME DsName;
  847. ASSERT( pObject );
  848. ASSERT( Attributes->pAttr );
  849. ASSERT( Flags != 0 );
  850. RtlZeroMemory( &Modify, sizeof( MODIFYARG ) );
  851. //
  852. // Build the DSName
  853. //
  854. Status = LsapAllocAndInitializeDsNameFromUnicode(
  855. pObject,
  856. &DsName
  857. );
  858. if ( NT_SUCCESS( Status ) ) {
  859. Status = LsapDsWriteByDsName( DsName,
  860. Flags,
  861. Attributes
  862. );
  863. LsapDsFree( DsName );
  864. }
  865. return( Status );
  866. }
  867. NTSTATUS
  868. LsapDsWriteByDsName(
  869. IN PDSNAME DsName,
  870. IN ULONG Flags,
  871. IN ATTRBLOCK *Attributes
  872. )
  873. {
  874. NTSTATUS Status = STATUS_SUCCESS;
  875. MODIFYARG Modify;
  876. MODIFYRES *ModifyRes = NULL;
  877. ATTRMODLIST *AttrMod = NULL;
  878. INT i, AttrModIndex = 0;
  879. ASSERT( DsName );
  880. ASSERT( Attributes );
  881. ASSERT( Attributes->pAttr );
  882. RtlZeroMemory( &Modify, sizeof( MODIFYARG ) );
  883. //
  884. // If there are no attributes, simply return success. Otherwise, DirModifyEntry will
  885. // av.
  886. //
  887. if ( Attributes->attrCount == 0 ) {
  888. return( Status );
  889. }
  890. //
  891. // Initialize the AttrMod structure
  892. //
  893. if ( Attributes->attrCount > 1 ) {
  894. AttrMod = LsapDsAlloc( sizeof(ATTRMODLIST) * ( Attributes->attrCount - 1 ) );
  895. if ( AttrMod == NULL ) {
  896. Status = STATUS_NO_MEMORY;
  897. } else {
  898. //
  899. // Copy the attrs into the ATTRMODLIST
  900. //
  901. for ( i = 0; i < (INT)Attributes->attrCount - 1 ; i++) {
  902. AttrMod[i].pNextMod = &AttrMod[i + 1];
  903. AttrMod[i].choice = (USHORT)( Flags & LSAPDS_WRITE_TYPES );
  904. RtlCopyMemory( &AttrMod[i].AttrInf,
  905. &Attributes->pAttr[i + 1],
  906. sizeof( ATTR ) );
  907. }
  908. AttrMod[i - 1].pNextMod = NULL;
  909. }
  910. }
  911. if ( NT_SUCCESS( Status ) ) {
  912. //
  913. // Set the root node...
  914. //
  915. Modify.FirstMod.pNextMod = AttrMod;
  916. Modify.FirstMod.choice = (USHORT)( Flags & LSAPDS_WRITE_TYPES );
  917. RtlCopyMemory( &Modify.FirstMod.AttrInf,
  918. &Attributes->pAttr[0],
  919. sizeof( ATTR ) );
  920. //
  921. // Setup the MODIFYARG structure
  922. //
  923. Modify.pObject = DsName;
  924. Modify.count = (USHORT)Attributes->attrCount;
  925. LsapDsInitializeStdCommArg( &Modify.CommArg, Flags );
  926. if ( FlagOn( Flags, LSAPDS_REPL_CHANGE_URGENTLY ) ) {
  927. Modify.CommArg.Svccntl.fUrgentReplication = TRUE;
  928. }
  929. //
  930. // Make the call
  931. //
  932. DirModifyEntry( &Modify, &ModifyRes );
  933. if ( ModifyRes ) {
  934. Status = LsapDsMapDsReturnToStatusEx( &ModifyRes->CommRes );
  935. } else {
  936. Status = STATUS_INSUFFICIENT_RESOURCES;
  937. }
  938. LsapDsContinueTransaction();
  939. LsapDsFree( AttrMod );
  940. }
  941. return( Status );
  942. }
  943. NTSTATUS
  944. LsapDsLsaAttributeToDsAttribute(
  945. IN PLSAP_DB_ATTRIBUTE LsaAttribute,
  946. OUT PATTR Attr
  947. )
  948. {
  949. NTSTATUS Status = STATUS_SUCCESS;
  950. ULONG Length = 0, Value;
  951. PDSNAME DsName;
  952. PLARGE_INTEGER LargeInt;
  953. if ( LsaAttribute->AttribType == LsapDbAttribDsNameAsUnicode ) {
  954. if ( LsaAttribute->AttributeValue != NULL &&
  955. ( ( PUNICODE_STRING )LsaAttribute->AttributeValue )->Length != 0 ) {
  956. Length = DSNameSizeFromLen( LsapDsGetUnicodeStringLenNoNull(
  957. (PUNICODE_STRING)LsaAttribute->AttributeValue) / sizeof( WCHAR ) );
  958. } else {
  959. return( STATUS_INVALID_PARAMETER );
  960. }
  961. } else if ( LsaAttribute->AttribType == LsapDbAttribIntervalAsULong ) {
  962. Length = sizeof( LARGE_INTEGER );
  963. } else if ( LsaAttribute->AttribType == LsapDbAttribUShortAsULong ) {
  964. Length = sizeof( ULONG );
  965. }
  966. Attr->attrTyp = LsaAttribute->DsAttId;
  967. Attr->AttrVal.valCount = 1;
  968. Attr->AttrVal.pAVal = LsapDsAlloc( Length + sizeof( ATTRVAL ) );
  969. if ( Attr->AttrVal.pAVal == NULL ) {
  970. Status = STATUS_NO_MEMORY;
  971. } else {
  972. switch ( LsaAttribute->AttribType ) {
  973. case LsapDbAttribUnicode:
  974. //
  975. // These unicode strings are self relative. Note that we have to write them out
  976. // without a trailing NULL!
  977. //
  978. Attr->AttrVal.pAVal->valLen =
  979. LsapDsGetSelfRelativeUnicodeStringLenNoNull(
  980. (PUNICODE_STRING_SR)LsaAttribute->AttributeValue);
  981. Attr->AttrVal.pAVal->pVal = LsaAttribute->AttributeValue;
  982. Attr->AttrVal.pAVal->pVal += sizeof(UNICODE_STRING_SR);
  983. break;
  984. case LsapDbAttribMultiUnicode:
  985. Status = STATUS_NOT_IMPLEMENTED;
  986. break;
  987. case LsapDbAttribGuid: // Fall through
  988. case LsapDbAttribTime: // Fall through
  989. case LsapDbAttribSid: // Fall through
  990. case LsapDbAttribDsName:// Fall through
  991. case LsapDbAttribPByte: // Fall through
  992. case LsapDbAttribSecDesc: // Fall through
  993. Attr->AttrVal.pAVal->valLen = LsaAttribute->AttributeValueLength;
  994. Attr->AttrVal.pAVal->pVal = LsaAttribute->AttributeValue;
  995. break;
  996. case LsapDbAttribULong:
  997. Attr->AttrVal.pAVal->valLen = sizeof(ULONG);
  998. Attr->AttrVal.pAVal->pVal = LsaAttribute->AttributeValue;
  999. break;
  1000. case LsapDbAttribUShortAsULong:
  1001. Attr->AttrVal.pAVal->valLen = sizeof(ULONG);
  1002. Attr->AttrVal.pAVal->pVal = ( ( PBYTE ) Attr->AttrVal.pAVal ) + sizeof( ATTRVAL );
  1003. Value = *( PULONG )LsaAttribute->AttributeValue;
  1004. Value &= 0xFFFF;
  1005. RtlCopyMemory( Attr->AttrVal.pAVal->pVal,
  1006. &Value,
  1007. sizeof( ULONG ) );
  1008. break;
  1009. case LsapDbAttribDsNameAsUnicode:
  1010. DsName = (PDSNAME)( ( ( PBYTE ) Attr->AttrVal.pAVal ) + sizeof( ATTRVAL ) );
  1011. DsName->structLen = Length;
  1012. DsName->NameLen = LsapDsGetUnicodeStringLenNoNull(
  1013. (PUNICODE_STRING)LsaAttribute->AttributeValue) / sizeof( WCHAR );
  1014. RtlCopyMemory( DsName->StringName,
  1015. ((PUNICODE_STRING)LsaAttribute->AttributeValue)->Buffer,
  1016. (DsName->NameLen + 1 ) * sizeof ( WCHAR ) );
  1017. Attr->AttrVal.pAVal->pVal = (PUCHAR)DsName;
  1018. Attr->AttrVal.pAVal->valLen = DsName->structLen;
  1019. break;
  1020. case LsapDbAttribIntervalAsULong:
  1021. LargeInt = ( PLARGE_INTEGER )( ( ( PBYTE ) Attr->AttrVal.pAVal ) + sizeof( ATTRVAL ) );
  1022. *LargeInt = RtlConvertUlongToLargeInteger( *( PULONG )LsaAttribute->AttributeValue );
  1023. Attr->AttrVal.pAVal->pVal = (PUCHAR)LargeInt;
  1024. Attr->AttrVal.pAVal->valLen = sizeof( LARGE_INTEGER );
  1025. break;
  1026. default:
  1027. ASSERT(FALSE);
  1028. break;
  1029. }
  1030. }
  1031. return( Status );
  1032. }
  1033. NTSTATUS
  1034. LsapDsDsAttributeToLsaAttribute(
  1035. IN ATTRVAL *AttVal,
  1036. OUT PLSAP_DB_ATTRIBUTE LsaAttribute
  1037. )
  1038. {
  1039. NTSTATUS Status = STATUS_SUCCESS;
  1040. ULONG Len, CopyLen;
  1041. PUNICODE_STRING_SR UnicodeStringSr;
  1042. PBYTE Buff, DsBuff;
  1043. //
  1044. // If we were supplied a buffer in the LSA attribute, copy it over
  1045. //
  1046. if ( LsaAttribute->AttributeValue != NULL && LsaAttribute->AttributeValueLength != 0 ) {
  1047. if ( AttVal->valLen > LsaAttribute->AttributeValueLength ) {
  1048. Status = STATUS_BUFFER_OVERFLOW;
  1049. } else {
  1050. RtlCopyMemory( LsaAttribute->AttributeValue, AttVal->pVal,
  1051. AttVal->valLen );
  1052. LsaAttribute->AttributeValueLength = AttVal->valLen;
  1053. }
  1054. LsaAttribute->MemoryAllocated = FALSE;
  1055. return( Status ) ;
  1056. }
  1057. //
  1058. // Allocate a new buffer using LSA heap, and then copy it over...
  1059. //
  1060. Len = AttVal->valLen;
  1061. CopyLen = AttVal->valLen;
  1062. DsBuff = AttVal->pVal;
  1063. if ( LsaAttribute->AttribType == LsapDbAttribUnicode ) {
  1064. Len += sizeof( UNICODE_STRING_SR ) + sizeof( WCHAR );
  1065. } else if ( LsaAttribute->AttribType == LsapDbAttribDsNameAsUnicode ) {
  1066. Len = ( LsapDsNameLenFromDsName( (PDSNAME)(AttVal->pVal) ) + 1 ) * sizeof( WCHAR ) +
  1067. sizeof( UNICODE_STRING );
  1068. CopyLen = 0;
  1069. DsBuff = (PBYTE)((PDSNAME)AttVal->pVal)->StringName;
  1070. } else if ( LsaAttribute->AttribType == LsapDbAttribIntervalAsULong ) {
  1071. Len = sizeof( ULONG );
  1072. CopyLen = sizeof( ULONG );
  1073. DsBuff = DsBuff;
  1074. } else if ( Len == 0 ) {
  1075. Buff = NULL;
  1076. Status = STATUS_INVALID_PARAMETER;
  1077. goto Exit;
  1078. }
  1079. Buff = MIDL_user_allocate( Len );
  1080. if ( Buff == NULL ) {
  1081. Status = STATUS_NO_MEMORY;
  1082. goto Exit;
  1083. } else if (LsaAttribute->AttribType != LsapDbAttribUnicode &&
  1084. LsaAttribute->AttribType != LsapDbAttribDsNameAsUnicode) {
  1085. RtlCopyMemory( Buff, DsBuff, CopyLen );
  1086. }
  1087. switch ( LsaAttribute->AttribType ) {
  1088. case LsapDbAttribUnicode:
  1089. //
  1090. // Make the string self relative
  1091. //
  1092. UnicodeStringSr = (PUNICODE_STRING_SR)Buff;
  1093. RtlCopyMemory( Buff + sizeof(UNICODE_STRING_SR), DsBuff, AttVal->valLen );
  1094. UnicodeStringSr->Length = (USHORT)AttVal->valLen;
  1095. UnicodeStringSr->MaximumLength = UnicodeStringSr->Length + sizeof( WCHAR );
  1096. UnicodeStringSr->Offset = sizeof(UNICODE_STRING_SR);
  1097. ((PWSTR)(Buff+sizeof(UNICODE_STRING_SR)))[UnicodeStringSr->Length / sizeof(WCHAR)] = UNICODE_NULL;
  1098. LsaAttribute->AttributeValue = Buff;
  1099. LsaAttribute->AttributeValueLength = AttVal->valLen + sizeof( UNICODE_STRING_SR );
  1100. break;
  1101. case LsapDbAttribDsNameAsUnicode:
  1102. //
  1103. // Make the string self relative
  1104. //
  1105. UnicodeStringSr = (PUNICODE_STRING_SR)Buff;
  1106. RtlCopyMemory( Buff + sizeof(UNICODE_STRING_SR), DsBuff,
  1107. LsapDsNameLenFromDsName( (PDSNAME)(AttVal->pVal) ) * sizeof( WCHAR ) );
  1108. UnicodeStringSr->Length =
  1109. (USHORT)LsapDsNameLenFromDsName( (PDSNAME)(AttVal->pVal) ) * sizeof( WCHAR );
  1110. UnicodeStringSr->MaximumLength = UnicodeStringSr->Length + sizeof( WCHAR );
  1111. UnicodeStringSr->Offset = sizeof(UNICODE_STRING_SR);
  1112. ((PWSTR)(Buff+sizeof(UNICODE_STRING_SR)))[UnicodeStringSr->Length / sizeof(WCHAR)] = UNICODE_NULL;
  1113. LsaAttribute->AttributeValue = Buff;
  1114. LsaAttribute->AttributeValueLength =
  1115. UnicodeStringSr->MaximumLength + sizeof( UNICODE_STRING_SR );
  1116. break;
  1117. case LsapDbAttribMultiUnicode:
  1118. Status = STATUS_NOT_IMPLEMENTED;
  1119. break;
  1120. case LsapDbAttribSecDesc:
  1121. LsaAttribute->AttributeValue = Buff;
  1122. LsaAttribute->AttributeValueLength = AttVal->valLen;
  1123. break;
  1124. case LsapDbAttribGuid:
  1125. Status = LsapDbMakeGuidAttribute( (GUID *)Buff,
  1126. LsaAttribute->AttributeName,
  1127. LsaAttribute );
  1128. break;
  1129. case LsapDbAttribSid:
  1130. Status = LsapDbMakeSidAttribute( (PSID)Buff,
  1131. LsaAttribute->AttributeName,
  1132. LsaAttribute );
  1133. break;
  1134. case LsapDbAttribPByte: // FALL THROUGH
  1135. case LsapDbAttribULong: // FALL THROUGH
  1136. case LsapDbAttribUShortAsULong: // FALL THROUGH
  1137. case LsapDbAttribTime:
  1138. Status = LsapDbMakePByteAttributeDs( Buff,
  1139. AttVal->valLen,
  1140. LsaAttribute->AttribType,
  1141. LsaAttribute->AttributeName,
  1142. LsaAttribute );
  1143. break;
  1144. case LsapDbAttribIntervalAsULong:
  1145. LsaAttribute->AttributeValue = Buff;
  1146. LsaAttribute->AttributeValueLength = sizeof( ULONG );
  1147. break;
  1148. default:
  1149. LsapDsDebugOut(( DEB_ERROR,
  1150. "Unexpected attribute type: %lu\n",
  1151. LsaAttribute->AttribType ));
  1152. Status = STATUS_INVALID_PARAMETER;
  1153. break;
  1154. }
  1155. Exit:
  1156. if ( NT_SUCCESS(Status) ) {
  1157. LsaAttribute->MemoryAllocated = TRUE;
  1158. } else {
  1159. MIDL_user_free( Buff );
  1160. LsaAttribute->AttributeValue = NULL;
  1161. LsaAttribute->AttributeValueLength = 0;
  1162. LsaAttribute->MemoryAllocated = FALSE;
  1163. }
  1164. return( Status );
  1165. }
  1166. NTSTATUS
  1167. LsapDsSearchMultiple(
  1168. IN ULONG Flags,
  1169. IN PDSNAME pContainer,
  1170. IN PATTR pAttrsToMatch,
  1171. IN ULONG cAttrs,
  1172. OUT SEARCHRES **SearchRes
  1173. )
  1174. {
  1175. NTSTATUS Status = STATUS_SUCCESS;
  1176. SEARCHARG SearchArg;
  1177. FILTER *Filters, RootFilter;
  1178. ENTINFSEL EntInfSel;
  1179. ULONG i;
  1180. RtlZeroMemory( &SearchArg, sizeof( SEARCHARG ) );
  1181. //
  1182. // Make sure we already have a transaction going
  1183. //
  1184. ASSERT( THQuery() );
  1185. //
  1186. // Build the filters
  1187. //
  1188. Filters = LsapDsAlloc(cAttrs * sizeof(FILTER) );
  1189. if ( Filters == NULL ) {
  1190. Status = STATUS_NO_MEMORY;
  1191. } else {
  1192. for ( i = 0; i < cAttrs; i++ ) {
  1193. Filters[i].pNextFilter = &Filters[i + 1];
  1194. Filters[i].choice = FILTER_CHOICE_ITEM;
  1195. Filters[i].FilterTypes.Item.choice = FI_CHOICE_EQUALITY;
  1196. Filters[i].FilterTypes.Item.FilTypes.ava.type = pAttrsToMatch[i].attrTyp;
  1197. Filters[i].FilterTypes.Item.FilTypes.ava.Value.valLen =
  1198. pAttrsToMatch[i].AttrVal.pAVal->valLen;
  1199. Filters[i].FilterTypes.Item.FilTypes.ava.Value.pVal =
  1200. pAttrsToMatch[i].AttrVal.pAVal->pVal;
  1201. }
  1202. if ( NT_SUCCESS( Status ) ) {
  1203. //
  1204. // Fill in the filter
  1205. //
  1206. Filters[cAttrs - 1].pNextFilter = NULL;
  1207. if ( cAttrs > 1 ) {
  1208. RtlZeroMemory( &RootFilter, sizeof (RootFilter));
  1209. RootFilter.pNextFilter = NULL;
  1210. if ( FLAG_ON( Flags, LSAPDS_SEARCH_OR ) ) {
  1211. RootFilter.choice = FILTER_CHOICE_OR;
  1212. RootFilter.FilterTypes.Or.count = (USHORT)cAttrs;
  1213. RootFilter.FilterTypes.Or.pFirstFilter = Filters;
  1214. } else {
  1215. RootFilter.choice = FILTER_CHOICE_AND;
  1216. RootFilter.FilterTypes.And.count = (USHORT)cAttrs;
  1217. RootFilter.FilterTypes.And.pFirstFilter = Filters;
  1218. }
  1219. SearchArg.pFilter = &RootFilter;
  1220. } else {
  1221. SearchArg.pFilter = Filters;
  1222. }
  1223. //
  1224. // Fill in the search argument
  1225. //
  1226. SearchArg.pObject = pContainer;
  1227. if ( ( Flags & LSAPDS_SEARCH_FLAGS ) == 0 || FLAG_ON( Flags, LSAPDS_SEARCH_TREE ) ) {
  1228. SearchArg.choice = SE_CHOICE_WHOLE_SUBTREE;
  1229. } else if ( FLAG_ON( Flags, LSAPDS_SEARCH_LEVEL ) ) {
  1230. SearchArg.choice = SE_CHOICE_IMMED_CHLDRN;
  1231. } else if ( FLAG_ON( Flags, LSAPDS_SEARCH_ROOT ) ) {
  1232. SearchArg.choice = SE_CHOICE_BASE_ONLY;
  1233. } else {
  1234. Status = STATUS_INVALID_PARAMETER;
  1235. }
  1236. if ( NT_SUCCESS( Status ) ) {
  1237. SearchArg.searchAliases = FALSE;
  1238. SearchArg.pSelection = &EntInfSel;
  1239. SearchArg.bOneNC = FLAG_ON(Flags, LSAPDS_SEARCH_ALL_NCS) ?
  1240. FALSE : TRUE;
  1241. EntInfSel.attSel = EN_ATTSET_LIST;
  1242. EntInfSel.AttrTypBlock.attrCount = 0;
  1243. EntInfSel.AttrTypBlock.pAttr = NULL;
  1244. EntInfSel.infoTypes = EN_INFOTYPES_TYPES_ONLY;
  1245. //
  1246. // Build the Commarg structure
  1247. //
  1248. LsapDsInitializeStdCommArg( &( SearchArg.CommArg ), 0 );
  1249. //
  1250. // Make the call
  1251. //
  1252. *SearchRes = NULL;
  1253. DirSearch( &SearchArg, SearchRes );
  1254. if ( *SearchRes ) {
  1255. Status = LsapDsMapDsReturnToStatusEx( &(*SearchRes)->CommRes );
  1256. } else {
  1257. Status = STATUS_INSUFFICIENT_RESOURCES;
  1258. }
  1259. LsapDsContinueTransaction();
  1260. }
  1261. }
  1262. }
  1263. return( Status ) ;
  1264. }
  1265. NTSTATUS
  1266. LsapDsSearchUnique(
  1267. IN ULONG Flags,
  1268. IN PDSNAME pContainer,
  1269. IN PATTR pAttrsToMatch,
  1270. IN ULONG cAttrs,
  1271. OUT PDSNAME *ppFoundName
  1272. )
  1273. {
  1274. NTSTATUS Status = STATUS_SUCCESS;
  1275. BOOLEAN CloseTransaction;
  1276. SEARCHRES *SearchRes;
  1277. ULONG i;
  1278. //
  1279. // Check the parameters for validity
  1280. //
  1281. ASSERT( pAttrsToMatch );
  1282. ASSERT( pAttrsToMatch->AttrVal.pAVal );
  1283. ASSERT( pContainer );
  1284. ASSERT( ppFoundName );
  1285. //
  1286. // See if we already have a transaction going
  1287. //
  1288. Status = LsapDsInitAllocAsNeededEx( LSAP_DB_READ_ONLY_TRANSACTION |
  1289. LSAP_DB_NO_LOCK |
  1290. LSAP_DB_DS_OP_TRANSACTION,
  1291. NullObject,
  1292. &CloseTransaction );
  1293. if ( !NT_SUCCESS( Status ) ) {
  1294. return( Status );
  1295. }
  1296. //
  1297. // Do the search
  1298. //
  1299. Status = LsapDsSearchMultiple( Flags,
  1300. pContainer,
  1301. pAttrsToMatch,
  1302. cAttrs,
  1303. &SearchRes );
  1304. if ( NT_SUCCESS( Status ) ) {
  1305. //
  1306. // See if we found the object
  1307. //
  1308. if ( SearchRes->count == 0 ) {
  1309. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  1310. } else if ( SearchRes->count == 1 ) {
  1311. //
  1312. // Copy the name
  1313. //
  1314. *ppFoundName = LsapAllocateLsaHeap(
  1315. SearchRes->FirstEntInf.Entinf.pName->structLen );
  1316. if ( *ppFoundName == NULL ) {
  1317. Status = STATUS_NO_MEMORY;
  1318. } else {
  1319. RtlCopyMemory( *ppFoundName,
  1320. SearchRes->FirstEntInf.Entinf.pName,
  1321. SearchRes->FirstEntInf.Entinf.pName->structLen );
  1322. }
  1323. } else {
  1324. //
  1325. // More than one object was found!
  1326. //
  1327. Status = STATUS_OBJECT_NAME_COLLISION;
  1328. }
  1329. }
  1330. //
  1331. // Destruction of the thread state will delete any memory allocated via the DS
  1332. //
  1333. LsapDsDeleteAllocAsNeededEx( LSAP_DB_READ_ONLY_TRANSACTION |
  1334. LSAP_DB_NO_LOCK |
  1335. LSAP_DB_DS_OP_TRANSACTION,
  1336. NullObject,
  1337. CloseTransaction );
  1338. return( Status );
  1339. }
  1340. NTSTATUS
  1341. LsapDsFindUnique(
  1342. IN ULONG Flags,
  1343. IN PDSNAME NCName OPTIONAL,
  1344. IN LSAP_DB_OBJECT_TYPE_ID ObjectTypeId,
  1345. IN ATTRVAL *Attribute,
  1346. IN ATTRTYP AttId,
  1347. OUT PDSNAME *FoundObject
  1348. )
  1349. /*++
  1350. Routine Description:
  1351. This function will find the object with the given attribute. The attribute must be indexed.
  1352. Arguments:
  1353. Flags - Flags to control the operation of the find
  1354. NCName - DSNAME of the naming context under which to look
  1355. If not specified, the default NCNAME is used.
  1356. ObjectTypeId - ObjectType represented by DSNAME.
  1357. The corresponding lock will be locked.
  1358. If the ObjectType isn't known, pass AllObject to grab all locks.
  1359. Attribute - Attribute to be matched
  1360. AttrTyp - Attribute id of the attribute
  1361. FoundObject - Where the object's dsname is returned, if it is found
  1362. Return Value:
  1363. STATUS_SUCCESS - Success
  1364. --*/
  1365. {
  1366. NTSTATUS Status = STATUS_SUCCESS;
  1367. FINDARG FindArg;
  1368. FINDRES *FindRes;
  1369. BOOLEAN CloseTransaction = FALSE;
  1370. LsapEnterFunc( "LsapDsFindUnique ");
  1371. //
  1372. // See if we already have a transaction going
  1373. //
  1374. Status = LsapDsInitAllocAsNeededEx( LSAP_DB_READ_ONLY_TRANSACTION |
  1375. LSAP_DB_DS_OP_TRANSACTION,
  1376. ObjectTypeId,
  1377. &CloseTransaction );
  1378. if ( !NT_SUCCESS( Status ) ) {
  1379. LsapExitFunc( "LsapDsFindUnique", Status );
  1380. return( Status );
  1381. }
  1382. //
  1383. // Do the initialization
  1384. //
  1385. RtlZeroMemory(&FindArg,sizeof(FINDARG));
  1386. if ( NCName == NULL ) {
  1387. FindArg.hDomain = LsaDsStateInfo.DsDomainHandle;
  1388. } else {
  1389. FindArg.hDomain = DirGetDomainHandle( NCName );
  1390. if (0==FindArg.hDomain)
  1391. {
  1392. Status = STATUS_INSUFFICIENT_RESOURCES;
  1393. goto Error;
  1394. }
  1395. LsapDsContinueTransaction();
  1396. }
  1397. FindArg.AttId = AttId;
  1398. RtlCopyMemory( &FindArg.AttrVal,
  1399. Attribute,
  1400. sizeof( ATTRVAL ) );
  1401. LsapDsInitializeStdCommArg( &( FindArg.CommArg ), 0 );
  1402. DirFindEntry( &FindArg, &FindRes );
  1403. if ( FindRes ) {
  1404. Status = LsapDsMapDsReturnToStatusEx( &(FindRes->CommRes ) );
  1405. } else {
  1406. Status = STATUS_INSUFFICIENT_RESOURCES;
  1407. }
  1408. if ( NT_SUCCESS( Status ) ) {
  1409. //
  1410. // Copy the return value using the lsa allocator
  1411. //
  1412. Status = LsapDsCopyDsNameLsa( FoundObject,
  1413. FindRes->pObject );
  1414. }
  1415. LsapDsContinueTransaction();
  1416. Error:
  1417. //
  1418. // Destruction of the thread state will delete any memory allocated via the DS
  1419. //
  1420. LsapDsDeleteAllocAsNeededEx( LSAP_DB_READ_ONLY_TRANSACTION |
  1421. LSAP_DB_DS_OP_TRANSACTION,
  1422. ObjectTypeId,
  1423. CloseTransaction );
  1424. LsapExitFunc( "LsapDsFindUnqiue", Status );
  1425. return( Status );
  1426. }
  1427. NTSTATUS
  1428. LsapDsIsSecretDsTrustedDomain(
  1429. IN PUNICODE_STRING SecretName,
  1430. IN PLSAP_DB_OBJECT_INFORMATION ObjectInformation OPTIONAL,
  1431. IN ULONG Options,
  1432. IN ACCESS_MASK DesiredAccess,
  1433. OUT PLSAPR_HANDLE TDObjHandle OPTIONAL,
  1434. OUT BOOLEAN *IsTrustedDomainSecret
  1435. )
  1436. /*++
  1437. Routine Description:
  1438. This function will determine if the indicated secret is the global secret for a trust object.
  1439. Arguments:
  1440. SecretName - Name of secret to check
  1441. ObjectInformation - LsaDb information on the object
  1442. Need not be specified if no TDObjHandle is to be returned.
  1443. Options - Options to use for the access
  1444. Need not be specified if no TDObjHandle is to be returned.
  1445. DesiredAccess - Access to open the object with
  1446. Need not be specified if no TDObjHandle is to be returned.
  1447. TDObjHandle - Where the object handle is returned
  1448. If not specified, no handle is returned.
  1449. IsTrustedDomainSecret - A TRUE is returned here if this secret is indeed a trusted domain
  1450. secret.
  1451. Return Value:
  1452. STATUS_SUCCESS - Success
  1453. STATUS_INSUFFICIENT_RESOURCES - A memory allocation failed
  1454. --*/
  1455. {
  1456. NTSTATUS Status = STATUS_SUCCESS;
  1457. PWSTR pwszSecretName;
  1458. UNICODE_STRING TdoName;
  1459. PLSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY TrustedDomainListEntry;
  1460. BOOLEAN AcquiredTrustedDomainListReadLock = FALSE;
  1461. LsapEnterFunc( "LsapDsIsSecretDsTrustedDomain" );
  1462. *IsTrustedDomainSecret = FALSE;
  1463. LsapDsReturnSuccessIfNoDs
  1464. if ( LsaDsStateInfo.DsInitializedAndRunning == FALSE ) {
  1465. LsapDsDebugOut((DEB_ERROR,
  1466. "LsapDsIsSecretDsTrustedDomain: Object %wZ, Ds is not started\n ",
  1467. SecretName ));
  1468. goto Cleanup;
  1469. }
  1470. //
  1471. // Convert the secret name to a TDO name.
  1472. //
  1473. if ( SecretName->Length <= (LSAP_DS_TRUSTED_DOMAIN_SECRET_PREFIX_LENGTH * sizeof(WCHAR)) ) {
  1474. goto Cleanup;
  1475. }
  1476. pwszSecretName = SecretName->Buffer + LSAP_DS_TRUSTED_DOMAIN_SECRET_PREFIX_LENGTH;
  1477. LsapDsDebugOut((DEB_TRACE, "Matching secret %ws to trusted domain\n ", pwszSecretName ));
  1478. RtlInitUnicodeString( &TdoName, pwszSecretName );
  1479. //
  1480. // Acquire the Read Lock for the Trusted Domain List
  1481. //
  1482. Status = LsapDbAcquireReadLockTrustedDomainList();
  1483. if (!NT_SUCCESS(Status)) {
  1484. goto Cleanup;
  1485. }
  1486. AcquiredTrustedDomainListReadLock = TRUE;
  1487. //
  1488. // Verify that the Trusted Domain List is marked as valid.
  1489. //
  1490. if (!LsapDbIsValidTrustedDomainList()) {
  1491. Status = STATUS_INVALID_SERVER_STATE;
  1492. goto Cleanup;
  1493. }
  1494. //
  1495. // Lookup the name in the TDL
  1496. //
  1497. Status = LsapDbLookupNameTrustedDomainListEx(
  1498. (PLSAPR_UNICODE_STRING)&TdoName,
  1499. &TrustedDomainListEntry );
  1500. if ( !NT_SUCCESS(Status)) {
  1501. //
  1502. // Not a trusted domain.
  1503. //
  1504. if ( Status == STATUS_NO_SUCH_DOMAIN ) {
  1505. Status = STATUS_SUCCESS;
  1506. }
  1507. goto Cleanup;
  1508. }
  1509. //
  1510. // See if this TDO is also a secret.
  1511. //
  1512. if ( FLAG_ON( TrustedDomainListEntry->TrustInfoEx.TrustDirection, TRUST_DIRECTION_OUTBOUND ) ) {
  1513. *IsTrustedDomainSecret = TRUE;
  1514. }
  1515. //
  1516. // If the caller wants a handle,
  1517. // return one.
  1518. //
  1519. if ( TDObjHandle ) {
  1520. LSAP_DB_OBJECT_INFORMATION NewObjInfo;
  1521. RtlCopyMemory( &NewObjInfo, ObjectInformation, sizeof( LSAP_DB_OBJECT_INFORMATION ) );
  1522. NewObjInfo.ObjectTypeId = TrustedDomainObject;
  1523. NewObjInfo.ObjectAttributes.ObjectName = &TdoName;
  1524. Status = LsapDbOpenObject( &NewObjInfo,
  1525. DesiredAccess,
  1526. Options | LSAP_DB_DS_TRUSTED_DOMAIN_AS_SECRET,
  1527. TDObjHandle );
  1528. }
  1529. Cleanup:
  1530. if ( AcquiredTrustedDomainListReadLock ) {
  1531. LsapDbReleaseLockTrustedDomainList();
  1532. }
  1533. LsapExitFunc( "LsapDsIsSecretDsTrustedDomain", Status );
  1534. return( Status );
  1535. }
  1536. NTSTATUS
  1537. LsapDsIsHandleDsObjectTypeHandle(
  1538. IN LSAP_DB_HANDLE Handle,
  1539. IN LSAP_DB_OBJECT_TYPE_ID ObjectType,
  1540. OUT BOOLEAN *IsObjectHandle
  1541. )
  1542. /*++
  1543. Routine Description:
  1544. Determines if the object handle refers to an object of the specified type or not
  1545. Arguments:
  1546. Handle - Handle to verify
  1547. ObjectType - Type of object to verify
  1548. IsObjectHandle - If TRUE, the handle refers to an object of that type
  1549. Return Value:
  1550. NTSTATUS - Standard Nt Result Code
  1551. --*/
  1552. {
  1553. NTSTATUS Status = STATUS_SUCCESS;
  1554. ATTR NameAttr;
  1555. ATTRVAL NameVal;
  1556. ATTRBLOCK NameBlock, ReturnBlock;
  1557. PDSNAME SearchName = NULL;
  1558. BOOLEAN CloseTransaction = FALSE;
  1559. ULONG ReadVal, Class;
  1560. BOOLEAN TsAllocated = FALSE;
  1561. *IsObjectHandle = FALSE;
  1562. LsapDsReturnSuccessIfNoDs;
  1563. if ( !LsapDsIsHandleDsHandle( Handle ) ) {
  1564. return( STATUS_SUCCESS );
  1565. }
  1566. if ( LsaDsStateInfo.DsInitializedAndRunning == FALSE ) {
  1567. LsapDsDebugOut((DEB_TRACE,
  1568. "LsapDsIsHandleDsObjectTypeHandle: Object %wZ, Ds is not started\n ",
  1569. &Handle->LogicalNameU ));
  1570. return( Status );
  1571. }
  1572. Class = LsapClassIdFromObjType( ObjectType );
  1573. if ( Class == 0xFFFFFFFF ) {
  1574. Status = STATUS_INVALID_PARAMETER;
  1575. }
  1576. //
  1577. // Special case the situation where we're looking for a secret object but we were given a
  1578. // trusted domain object handle
  1579. //
  1580. if ( ObjectType == TrustedDomainObject &&
  1581. ((LSAP_DB_HANDLE)Handle)->ObjectTypeId == TrustedDomainObject &&
  1582. FLAG_ON( ((LSAP_DB_HANDLE)Handle)->Options, LSAP_DB_DS_TRUSTED_DOMAIN_AS_SECRET ) ) {
  1583. *IsObjectHandle = TRUE;
  1584. return( STATUS_SUCCESS );
  1585. }
  1586. if ( ObjectType == TrustedDomainObject &&
  1587. ((LSAP_DB_HANDLE)Handle)->ObjectTypeId == SecretObject &&
  1588. FLAG_ON( ((LSAP_DB_HANDLE)Handle)->Options, LSAP_DB_DS_TRUSTED_DOMAIN_AS_SECRET ) ) {
  1589. *IsObjectHandle = FALSE;
  1590. return( STATUS_SUCCESS );
  1591. }
  1592. if ( NT_SUCCESS( Status ) ) {
  1593. //
  1594. // We can't lock any locks because the caller already has some locks locked.
  1595. // So locking an object type specific lock might violate the locking order.
  1596. //
  1597. // Locking any lock doesn't help anyway. An object can disappear out
  1598. // from under us due to replication or immediately after we drop the lock.
  1599. //
  1600. Status = LsapDsInitAllocAsNeededEx( LSAP_DB_READ_ONLY_TRANSACTION |
  1601. LSAP_DB_NO_LOCK |
  1602. LSAP_DB_DS_OP_TRANSACTION,
  1603. ObjectType,
  1604. &CloseTransaction );
  1605. if ( NT_SUCCESS( Status ) ) {
  1606. TsAllocated = TRUE;
  1607. Status = LsapAllocAndInitializeDsNameFromUnicode(
  1608. (PLSA_UNICODE_STRING)&Handle->PhysicalNameDs,
  1609. &SearchName );
  1610. }
  1611. }
  1612. if ( NT_SUCCESS( Status ) ) {
  1613. //
  1614. // Check for the existence of the object
  1615. //
  1616. NameAttr.attrTyp = ATT_OBJECT_CLASS;
  1617. NameAttr.AttrVal.valCount = 1;
  1618. NameAttr.AttrVal.pAVal = &NameVal;
  1619. NameVal.valLen = SearchName->structLen;
  1620. NameVal.pVal = (PBYTE)SearchName;
  1621. NameBlock.attrCount = 1;
  1622. NameBlock.pAttr = &NameAttr;
  1623. Status = LsapDsRead( &Handle->PhysicalNameDs,
  1624. LSAPDS_READ_NO_LOCK,
  1625. &NameBlock,
  1626. &ReturnBlock);
  1627. if ( NT_SUCCESS( Status ) ) {
  1628. ReadVal = LSAP_DS_GET_DS_ATTRIBUTE_AS_ULONG( ReturnBlock.pAttr );
  1629. if ( ReadVal == Class ) {
  1630. *IsObjectHandle = TRUE;
  1631. }
  1632. }
  1633. LsapDsFree( SearchName );
  1634. }
  1635. //
  1636. // If the object exists and we're looking for a global secret of the same name, then
  1637. //
  1638. if ( TsAllocated ) {
  1639. LsapDsDeleteAllocAsNeededEx( LSAP_DB_READ_ONLY_TRANSACTION |
  1640. LSAP_DB_NO_LOCK |
  1641. LSAP_DB_DS_OP_TRANSACTION,
  1642. ObjectType,
  1643. CloseTransaction );
  1644. }
  1645. return( Status );
  1646. }
  1647. NTSTATUS
  1648. LsapDsCauseTransactionToCommitOrAbort (
  1649. IN BOOLEAN Commit
  1650. )
  1651. /*++
  1652. Routine Description:
  1653. Arguments:
  1654. Return Value:
  1655. STATUS_SUCCESS - Success
  1656. --*/
  1657. {
  1658. NTSTATUS Status;
  1659. ATTR Attr;
  1660. ENTINFSEL EntryInf;
  1661. READARG ReadArg;
  1662. READRES *ReadRes = NULL;
  1663. //
  1664. // Initialize the structures
  1665. //
  1666. RtlZeroMemory(&Attr, sizeof(ATTR));
  1667. Attr.attrTyp = ATT_OBJECT_CLASS;
  1668. RtlZeroMemory(&EntryInf, sizeof(ENTINFSEL));
  1669. EntryInf.attSel = EN_ATTSET_LIST;
  1670. EntryInf.AttrTypBlock.attrCount = 1;
  1671. EntryInf.AttrTypBlock.pAttr = &Attr;
  1672. EntryInf.infoTypes = EN_INFOTYPES_TYPES_VALS;
  1673. RtlZeroMemory(&ReadArg, sizeof(READARG));
  1674. ReadArg.pSel = &EntryInf;
  1675. //
  1676. // Initialize the commarg struct
  1677. //
  1678. LsapDsInitializeStdCommArg( &ReadArg.CommArg, 0 );
  1679. //
  1680. // If there is no transaction, just exit
  1681. //
  1682. if ( !THQuery() ) {
  1683. return( STATUS_SUCCESS );
  1684. }
  1685. if ( !SampExistsDsTransaction() ) {
  1686. LsapDsDebugOut(( DEB_ERROR,
  1687. "LsapDsCauseTransactionToCommitOrAbort invoked with no active DS "
  1688. "transaction\n" ));
  1689. return( STATUS_SUCCESS );
  1690. }
  1691. //
  1692. // Clear any errors in the thread state
  1693. //
  1694. THClearErrors();
  1695. DirTransactControl( TRANSACT_DONT_BEGIN_END );
  1696. ReadArg.pObject = LsaDsStateInfo.DsRoot;
  1697. if ( Commit == FALSE ) {
  1698. Attr.attrTyp = 0xFFFFFFFF;
  1699. } else {
  1700. Attr.attrTyp = ATT_OBJECT_CLASS;
  1701. }
  1702. DirRead( &ReadArg, &ReadRes );
  1703. if ( ReadRes ) {
  1704. Status = LsapDsMapDsReturnToStatusEx( &ReadRes->CommRes );
  1705. } else {
  1706. Status = STATUS_INSUFFICIENT_RESOURCES;
  1707. }
  1708. DirTransactControl( TRANSACT_BEGIN_END );
  1709. return( Status );
  1710. }
  1711. NTSTATUS
  1712. LsapDsSearchNonUnique(
  1713. IN ULONG Flags,
  1714. IN PDSNAME pContainer,
  1715. IN PATTR pAttrsToMatch,
  1716. IN ULONG Attrs,
  1717. OUT PDSNAME **pppFoundNames,
  1718. OUT PULONG pcNames
  1719. )
  1720. /*++
  1721. Routine Description:
  1722. This routine will search the specified container(s) in the DS for the object
  1723. whose attributes are matched with pAttrToMatch. The returned DSNAME structures are allocated
  1724. via LSA memory allocators. The returned list should be freed via a single call to
  1725. LsapFreeLsaHeap
  1726. Arguments:
  1727. DsInitState -- State the DS booted off of
  1728. Return Value:
  1729. STATUS_SUCCES -- Success
  1730. STATUS_NO_MEMORY -- A memory allocation failed
  1731. STATUS_OBJECT_NAME_NOT_FOUND -- The object did not exist
  1732. --*/
  1733. {
  1734. NTSTATUS Status = STATUS_SUCCESS;
  1735. BOOLEAN CloseTransaction;
  1736. ULONG OutputLen, i;
  1737. PBYTE Buff;
  1738. SEARCHRES *SearchRes;
  1739. ENTINFLIST *EntInfList;
  1740. //
  1741. // Check the parameters for validity
  1742. //
  1743. ASSERT( pAttrsToMatch );
  1744. ASSERT( pContainer );
  1745. ASSERT( pppFoundNames );
  1746. ASSERT( pcNames );
  1747. //
  1748. // See if we already have a transaction going
  1749. //
  1750. Status = LsapDsInitAllocAsNeededEx( LSAP_DB_READ_ONLY_TRANSACTION |
  1751. LSAP_DB_DS_OP_TRANSACTION |
  1752. LSAP_DB_NO_LOCK,
  1753. PolicyObject,
  1754. &CloseTransaction );
  1755. if ( !NT_SUCCESS( Status ) ) {
  1756. return( Status );
  1757. }
  1758. Status = LsapDsSearchMultiple( Flags,
  1759. pContainer,
  1760. pAttrsToMatch,
  1761. Attrs,
  1762. &SearchRes );
  1763. if ( NT_SUCCESS( Status ) ) {
  1764. //
  1765. // See if we found the object
  1766. //
  1767. if ( SearchRes->count == 0 ) {
  1768. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  1769. } else if ( SearchRes->count >= 1 ) {
  1770. //
  1771. // See how big a buffer we need to allocate
  1772. //
  1773. OutputLen = sizeof( PDSNAME ) * SearchRes->count;
  1774. EntInfList = &(SearchRes->FirstEntInf);
  1775. for ( i = 0; i < SearchRes->count ; i++) {
  1776. OutputLen += ROUND_UP_COUNT( EntInfList->Entinf.pName->structLen, ALIGN_WORST );
  1777. EntInfList = EntInfList->pNextEntInf;
  1778. }
  1779. //
  1780. // Allocate it
  1781. //
  1782. *pppFoundNames = LsapAllocateLsaHeap( OutputLen );
  1783. //
  1784. // Copy the names
  1785. //
  1786. if ( *pppFoundNames == NULL ) {
  1787. Status = STATUS_NO_MEMORY;
  1788. } else {
  1789. Buff = ((PBYTE)*pppFoundNames) + (sizeof( PDSNAME ) * SearchRes->count);
  1790. EntInfList = &SearchRes->FirstEntInf;
  1791. for (i = 0; i < SearchRes->count ; i++ ) {
  1792. (*pppFoundNames)[i] = (PDSNAME)Buff;
  1793. RtlCopyMemory( Buff,
  1794. EntInfList->Entinf.pName,
  1795. EntInfList->Entinf.pName->structLen );
  1796. Buff += ROUND_UP_COUNT( EntInfList->Entinf.pName->structLen, ALIGN_WORST );
  1797. EntInfList = EntInfList->pNextEntInf;
  1798. }
  1799. *pcNames = SearchRes->count;
  1800. }
  1801. }
  1802. }
  1803. //
  1804. // Destruction of the thread state will delete the memory for pVal
  1805. //
  1806. LsapDsDeleteAllocAsNeededEx( LSAP_DB_READ_ONLY_TRANSACTION |
  1807. LSAP_DB_DS_OP_TRANSACTION |
  1808. LSAP_DB_NO_LOCK,
  1809. PolicyObject,
  1810. CloseTransaction );
  1811. return( Status );
  1812. }
  1813. NTSTATUS
  1814. LsapDsFixupTrustForXrefChange(
  1815. IN PDSNAME ObjectPath,
  1816. IN BOOLEAN TransactionActive
  1817. );
  1818. NTSTATUS
  1819. LsapDsMorphTrustsToUplevel(
  1820. VOID
  1821. )
  1822. /*++
  1823. Routine Description
  1824. This function will first enumerate all the cross ref's in the partitions container and for
  1825. each Xref will try patching up the corresponding TDO
  1826. --*/
  1827. {
  1828. NTSTATUS Status = STATUS_SUCCESS;
  1829. ULONG ClassId = CLASS_CROSS_REF;
  1830. SEARCHRES *pSearchRes;
  1831. ENTINFLIST *CurrentEntInf = NULL;
  1832. BOOLEAN CloseTransaction = FALSE;
  1833. BOOLEAN ActiveThreadState = FALSE;
  1834. ATTRVAL XRefAttVals[] = {
  1835. { sizeof(ULONG), (PUCHAR)&ClassId} };
  1836. ATTR XRefAttrs[] = {
  1837. { ATT_OBJECT_CLASS, {1, &XRefAttVals[0] } },
  1838. };
  1839. ULONG CountOfDomains=0;
  1840. PDSNAME *ListOfDomains = NULL;
  1841. ULONG i;
  1842. //
  1843. // Acquire the Trusted domain lock
  1844. //
  1845. LsapDbAcquireLockEx( TrustedDomainObject,
  1846. 0);
  1847. //
  1848. // Begin a Transaction
  1849. //
  1850. Status = LsapDsInitAllocAsNeededEx(
  1851. LSAP_DB_NO_LOCK,
  1852. TrustedDomainObject,
  1853. &CloseTransaction
  1854. );
  1855. if (!NT_SUCCESS(Status))
  1856. goto Error;
  1857. ActiveThreadState = TRUE;
  1858. Status = LsapDsSearchMultiple(
  1859. 0,
  1860. LsaDsStateInfo.DsPartitionsContainer,
  1861. XRefAttrs,
  1862. 1,
  1863. &pSearchRes
  1864. );
  1865. if (!NT_SUCCESS(Status))
  1866. {
  1867. //
  1868. // Bail, most likely resource failure
  1869. //
  1870. goto Error;
  1871. }
  1872. ASSERT(NULL!=pSearchRes);
  1873. //
  1874. // At least 1 Xref should be present otherwise there is something odd
  1875. // going on in here
  1876. //
  1877. ASSERT((pSearchRes->count>=1) && "No Xrefs In Partitions Container !!!");
  1878. CountOfDomains = pSearchRes->count;
  1879. ListOfDomains = LsapAllocateLsaHeap(CountOfDomains * sizeof(PDSNAME));
  1880. if (NULL==ListOfDomains)
  1881. {
  1882. Status = STATUS_INSUFFICIENT_RESOURCES;
  1883. goto Error;
  1884. }
  1885. RtlZeroMemory(ListOfDomains,CountOfDomains * sizeof(PDSNAME));
  1886. //
  1887. // Walk through the linked list of entries returned by the DS
  1888. // and perform and copy the dsnames for each of the domains that were returned. Copying is
  1889. // required as once the DS thread state is deleted all the memory allocated by it is lost
  1890. //
  1891. for (CurrentEntInf = &(pSearchRes->FirstEntInf),i=0;
  1892. CurrentEntInf!=NULL;
  1893. CurrentEntInf=CurrentEntInf->pNextEntInf,i++)
  1894. {
  1895. ListOfDomains[i] = LsapAllocateLsaHeap(CurrentEntInf->Entinf.pName->structLen);
  1896. if (NULL==ListOfDomains[i])
  1897. {
  1898. Status = STATUS_INSUFFICIENT_RESOURCES;
  1899. goto Error;
  1900. }
  1901. RtlCopyMemory(
  1902. ListOfDomains[i],
  1903. CurrentEntInf->Entinf.pName,
  1904. CurrentEntInf->Entinf.pName->structLen
  1905. );
  1906. }
  1907. //
  1908. // Close the transaction now so that we may free up resources
  1909. // Closing the transaction and thread state now and opening up a new
  1910. // transaction/thread state per object keeps the memory consumption much
  1911. // lower and also curtails the transaction length. Remember the DS does
  1912. // not free any memory till the thread state is destroyed. If we have to
  1913. // scale to 2000 trust objects, doing it this way provides for better
  1914. // performance
  1915. //
  1916. LsapDsDeleteAllocAsNeededEx2(
  1917. LSAP_DB_NO_LOCK,
  1918. TrustedDomainObject,
  1919. CloseTransaction,
  1920. FALSE // Rollback Transaction
  1921. );
  1922. ASSERT(!SampExistsDsTransaction());
  1923. ASSERT(THVerifyCount(0));
  1924. ActiveThreadState = FALSE;
  1925. //
  1926. // For each DS NAME in the list check cross ref and update
  1927. // TDO if necessary
  1928. //
  1929. for (i=0;i<CountOfDomains;i++)
  1930. {
  1931. Status = LsapDsFixupTrustForXrefChange(
  1932. ListOfDomains[i],
  1933. FALSE
  1934. );
  1935. if (!NT_SUCCESS(Status))
  1936. {
  1937. //
  1938. // Continue on all errors excepting resource errors
  1939. // The caller logs any errors to the event log
  1940. //
  1941. if (!LsapDsIsNtStatusResourceError(Status))
  1942. {
  1943. Status = STATUS_SUCCESS;
  1944. }
  1945. else
  1946. {
  1947. //
  1948. // Break out of the loop and terminate the upgrade
  1949. //
  1950. goto Error;
  1951. }
  1952. }
  1953. }
  1954. Error:
  1955. //
  1956. // Free up resources
  1957. //
  1958. if (ListOfDomains)
  1959. {
  1960. for (i=0;i<CountOfDomains;i++)
  1961. {
  1962. if (ListOfDomains[i])
  1963. {
  1964. LsapFreeLsaHeap(ListOfDomains[i]);
  1965. }
  1966. }
  1967. LsapFreeLsaHeap(ListOfDomains);
  1968. }
  1969. if (ActiveThreadState)
  1970. {
  1971. BOOLEAN RollbackTransaction = (NT_SUCCESS(Status))?FALSE:TRUE;
  1972. LsapDsDeleteAllocAsNeededEx2(
  1973. LSAP_DB_NO_LOCK,
  1974. TrustedDomainObject,
  1975. CloseTransaction,
  1976. RollbackTransaction // Rollback Transaction
  1977. );
  1978. }
  1979. ASSERT(!SampExistsDsTransaction());
  1980. ASSERT(THVerifyCount(0));
  1981. LsapDbReleaseLockEx( TrustedDomainObject,
  1982. 0);
  1983. return Status;
  1984. }
  1985. NTSTATUS
  1986. LsaIUpgradeRegistryToDs(
  1987. BOOLEAN DeleteOnly
  1988. )
  1989. /*++
  1990. Routine Description:
  1991. This function will upgrade the policy/trusted domain/secret objects in the registry
  1992. and move them to the Ds.
  1993. Arguments:
  1994. VOID
  1995. Return Value:
  1996. STATUS_SUCCESS -- Success
  1997. --*/
  1998. {
  1999. NTSTATUS Status = STATUS_SUCCESS;
  2000. BOOLEAN ReplicatorState = LsapDbState.ReplicatorNotificationEnabled;
  2001. //
  2002. // Lock the database
  2003. //
  2004. LsapDbAcquireLockEx( AllObject,
  2005. 0 );
  2006. //
  2007. // Set the upgrade flag
  2008. //
  2009. LsaDsStateInfo.Nt4UpgradeInProgress = TRUE;
  2010. //
  2011. // Ok, move the accounts...
  2012. //
  2013. LsapDbDisableReplicatorNotification();
  2014. //
  2015. // Upgrade TDO's in registry to DS.
  2016. //
  2017. Status = LsapDsDomainUpgradeRegistryToDs( DeleteOnly );
  2018. if ( !NT_SUCCESS( Status ) ) {
  2019. LsapDsDebugOut(( DEB_ERROR,
  2020. "Trusted Domain upgrade failed: 0x%lx\n", Status ));
  2021. }
  2022. //
  2023. // Upgrade secrets in registry to DS
  2024. //
  2025. if ( NT_SUCCESS( Status ) ) {
  2026. Status = LsapDsSecretUpgradeRegistryToDs( DeleteOnly );
  2027. if ( !NT_SUCCESS( Status ) ) {
  2028. LsapDsDebugOut(( DEB_ERROR,
  2029. "Secret upgrade failed: 0x%lx\n", Status ));
  2030. }
  2031. }
  2032. //
  2033. // Upgrade interdomain trust accounts in SAM to DS.
  2034. //
  2035. if ( !DeleteOnly ) {
  2036. if (NT_SUCCESS(Status)) {
  2037. Status = LsapDsDomainUpgradeInterdomainTrustAccountsToDs( );
  2038. if ( !NT_SUCCESS( Status ) ) {
  2039. LsapDsDebugOut(( DEB_ERROR,
  2040. "InterdomainTrustAccount upgrade failed with 0x%lx\n",
  2041. Status ));
  2042. }
  2043. }
  2044. if (NT_SUCCESS(Status))
  2045. {
  2046. Status = LsapDsMorphTrustsToUplevel();
  2047. if (!NT_SUCCESS(Status)) {
  2048. LsapDsDebugOut(( DEB_ERROR,
  2049. "Morphing Trusts to NT5 failed 0x%lx\n", Status ));
  2050. }
  2051. }
  2052. }
  2053. if ( ReplicatorState ) {
  2054. LsapDbEnableReplicatorNotification();
  2055. }
  2056. LsapDbReleaseLockEx( AllObject,
  2057. 0 );
  2058. LsaDsStateInfo.Nt4UpgradeInProgress = FALSE;
  2059. ASSERT(!SampExistsDsTransaction());
  2060. ASSERT(THVerifyCount(0));
  2061. return( Status );
  2062. }
  2063. NTSTATUS
  2064. LsapDsRenameObject(
  2065. IN PDSNAME OldObject,
  2066. IN PDSNAME NewParent,
  2067. IN ULONG AttrType,
  2068. IN PUNICODE_STRING NewObject
  2069. )
  2070. /*++
  2071. Routine Description:
  2072. This function will change the rdn of an object
  2073. Arguments:
  2074. OldObject -- Current object name
  2075. Return Value:
  2076. STATUS_SUCCESS -- Success
  2077. --*/
  2078. {
  2079. NTSTATUS Status = STATUS_SUCCESS;
  2080. BOOLEAN CloseTransaction;
  2081. MODIFYDNARG ModifyDnArg;
  2082. MODIFYDNRES *ModifyRes = NULL;
  2083. ATTR NewDn;
  2084. ATTRVAL NewDnVal;
  2085. ASSERT( OldObject );
  2086. ASSERT( NewObject );
  2087. Status = LsapDsInitAllocAsNeededEx( LSAP_DB_NO_LOCK,
  2088. AllObject,
  2089. &CloseTransaction );
  2090. if ( !NT_SUCCESS( Status ) ) {
  2091. return( Status );
  2092. }
  2093. RtlZeroMemory( &ModifyDnArg, sizeof( ModifyDnArg ) );
  2094. NewDnVal.valLen = NewObject->Length;
  2095. NewDnVal.pVal = ( PUCHAR )NewObject->Buffer;
  2096. NewDn.attrTyp = AttrType;
  2097. NewDn.AttrVal.valCount = 1;
  2098. NewDn.AttrVal.pAVal = &NewDnVal;
  2099. ModifyDnArg.pObject = OldObject;
  2100. ModifyDnArg.pNewParent = NewParent;
  2101. ModifyDnArg.pNewRDN = &NewDn;
  2102. LsapDsInitializeStdCommArg( &(ModifyDnArg.CommArg), 0 );
  2103. DirModifyDN( &ModifyDnArg, &ModifyRes );
  2104. if ( ModifyRes ) {
  2105. Status = LsapDsMapDsReturnToStatusEx( &ModifyRes->CommRes );
  2106. } else {
  2107. Status = STATUS_INSUFFICIENT_RESOURCES;
  2108. }
  2109. LsapDsContinueTransaction();
  2110. LsapDsDeleteAllocAsNeededEx( LSAP_DB_NO_LOCK,
  2111. AllObject,
  2112. CloseTransaction );
  2113. return( Status );
  2114. }
  2115. NTSTATUS NetpApiStatusToNtStatus( NET_API_STATUS );
  2116. NTSTATUS
  2117. LsapDbDomainRenameHandler(
  2118. OUT BOOLEAN * Renamed
  2119. )
  2120. /*++
  2121. Routine Description:
  2122. Checks the domain name values stored in the registry against those reported
  2123. by the DS. DS values are treated as master copies and registry is updated
  2124. accordingly.
  2125. Parameters:
  2126. None
  2127. Returns:
  2128. STATUS_SUCCESS - success
  2129. STATUS_ error code on failure
  2130. --*/
  2131. {
  2132. NTSTATUS Status;
  2133. LSAP_DB_ATTRIBUTE AttributesReadReg[4]; // attrs read from registry
  2134. LSAP_DB_ATTRIBUTE AttributesReadDsDom[2]; // attrs read from domain XRef
  2135. LSAP_DB_ATTRIBUTE AttributesReadDsRoot[1]; // attrs read from root XRef
  2136. LSAP_DB_ATTRIBUTE AttributesWriteReg[4]; // attrs written to registry
  2137. PLSAP_DB_ATTRIBUTE NextAttribute;
  2138. ULONG AttributeCountReadReg = 0;
  2139. ULONG AttributeCountReadDsDom = 0;
  2140. ULONG AttributeCountReadDsRoot = 0;
  2141. ULONG AttributeCountWriteReg = 0;
  2142. ULONG AttributeNumber;
  2143. ULONG DomainLen = 0, RootDomainLen = 0;
  2144. PDSNAME DomainXRef = NULL;
  2145. PDSNAME RootDomainXRef = NULL;
  2146. UNICODE_STRING PrimaryDomainNameReg,
  2147. AccountDomainNameReg,
  2148. DnsDomainNameReg,
  2149. RootDnsDomainNameReg,
  2150. DnsDomainNameDs,
  2151. NetbiosDomainNameDs,
  2152. RootDnsDomainNameDs;
  2153. ULONG iPolDnDDN, iPolDnTrN, iPolPrDmN, iPolAcDmN;
  2154. ULONG iXRefDnsRoot, iXRefNetbiosName, iXRefDnsRoot2;
  2155. WCHAR NameBuffer[DNS_MAX_NAME_LENGTH + 1];
  2156. DWORD NameBufferSize = DNS_MAX_NAME_LENGTH + 1;
  2157. WCHAR ErrorCode[16];
  2158. LPWSTR pErrorCode;
  2159. DWORD Reason = LSA_DOMAIN_RENAME_ERROR1;
  2160. LsarpReturnCheckSetup();
  2161. ASSERT( Renamed );
  2162. *Renamed = FALSE;
  2163. //
  2164. // Read the attributes of interest out of the registry
  2165. //
  2166. ASSERT( AttributeCountReadReg == 0 );
  2167. NextAttribute = AttributesReadReg;
  2168. //
  2169. // Request read of the DNS domain name attribute
  2170. //
  2171. LsapDbInitializeAttributeDs(
  2172. NextAttribute,
  2173. PolDnDDN,
  2174. NULL,
  2175. 0,
  2176. FALSE
  2177. );
  2178. iPolDnDDN = AttributeCountReadReg;
  2179. NextAttribute++;
  2180. AttributeCountReadReg++;
  2181. //
  2182. // Request read of the Dns Tree Name attribute
  2183. //
  2184. LsapDbInitializeAttributeDs(
  2185. NextAttribute,
  2186. PolDnTrN,
  2187. NULL,
  2188. 0,
  2189. FALSE
  2190. );
  2191. iPolDnTrN = AttributeCountReadReg;
  2192. NextAttribute++;
  2193. AttributeCountReadReg++;
  2194. //
  2195. // Request read of the primary domain name attribute
  2196. //
  2197. LsapDbInitializeAttributeDs(
  2198. NextAttribute,
  2199. PolPrDmN,
  2200. NULL,
  2201. 0,
  2202. FALSE
  2203. );
  2204. iPolPrDmN = AttributeCountReadReg;
  2205. NextAttribute++;
  2206. AttributeCountReadReg++;
  2207. //
  2208. // Request read of the account domain name attribute
  2209. //
  2210. LsapDbInitializeAttributeDs(
  2211. NextAttribute,
  2212. PolAcDmN,
  2213. NULL,
  2214. 0,
  2215. FALSE
  2216. );
  2217. iPolAcDmN = AttributeCountReadReg;
  2218. NextAttribute++;
  2219. AttributeCountReadReg++;
  2220. Status = LsapDbReadAttributesObject(
  2221. LsapPolicyHandle,
  2222. 0,
  2223. AttributesReadReg,
  2224. AttributeCountReadReg
  2225. );
  2226. if ( !NT_SUCCESS( Status )) {
  2227. goto Error;
  2228. }
  2229. LsapDbCopyUnicodeAttributeNoAlloc(
  2230. &PrimaryDomainNameReg,
  2231. &AttributesReadReg[iPolPrDmN],
  2232. TRUE
  2233. );
  2234. LsapDbCopyUnicodeAttributeNoAlloc(
  2235. &AccountDomainNameReg,
  2236. &AttributesReadReg[iPolAcDmN],
  2237. TRUE
  2238. );
  2239. LsapDbCopyUnicodeAttributeNoAlloc(
  2240. &DnsDomainNameReg,
  2241. &AttributesReadReg[iPolDnDDN],
  2242. TRUE
  2243. );
  2244. LsapDbCopyUnicodeAttributeNoAlloc(
  2245. &RootDnsDomainNameReg,
  2246. &AttributesReadReg[iPolDnTrN],
  2247. TRUE
  2248. );
  2249. //
  2250. // Now read the DS to get the values to compare against
  2251. // Start by reading the names of domain and root domain cross-ref objects
  2252. //
  2253. Status = GetConfigurationName(
  2254. DSCONFIGNAME_DOMAIN_CR,
  2255. &DomainLen,
  2256. NULL
  2257. );
  2258. ASSERT( Status == STATUS_BUFFER_TOO_SMALL );
  2259. DomainXRef = ( PDSNAME )LsapAllocateLsaHeap( DomainLen );
  2260. if ( DomainXRef == NULL ) {
  2261. Status = STATUS_INSUFFICIENT_RESOURCES;
  2262. goto Error;
  2263. }
  2264. Status = GetConfigurationName(
  2265. DSCONFIGNAME_DOMAIN_CR,
  2266. &DomainLen,
  2267. DomainXRef
  2268. );
  2269. if ( !NT_SUCCESS( Status )) {
  2270. goto Error;
  2271. }
  2272. Status = GetConfigurationName(
  2273. DSCONFIGNAME_ROOT_DOMAIN_CR,
  2274. &RootDomainLen,
  2275. NULL
  2276. );
  2277. ASSERT( Status == STATUS_BUFFER_TOO_SMALL );
  2278. RootDomainXRef = ( PDSNAME )LsapAllocateLsaHeap( RootDomainLen );
  2279. if ( RootDomainXRef == NULL ) {
  2280. Status = STATUS_INSUFFICIENT_RESOURCES;
  2281. goto Error;
  2282. }
  2283. Status = GetConfigurationName(
  2284. DSCONFIGNAME_ROOT_DOMAIN_CR,
  2285. &RootDomainLen,
  2286. RootDomainXRef
  2287. );
  2288. if ( !NT_SUCCESS( Status )) {
  2289. goto Error;
  2290. }
  2291. //
  2292. // From the domain cross-ref object,
  2293. // read the "NetbiosName" and "DnsRoot" attributes
  2294. //
  2295. ASSERT( AttributeCountReadDsDom == 0 );
  2296. NextAttribute = AttributesReadDsDom;
  2297. LsapDbInitializeAttributeDs(
  2298. NextAttribute,
  2299. XRefDnsRoot,
  2300. NULL,
  2301. 0,
  2302. FALSE
  2303. );
  2304. iXRefDnsRoot = AttributeCountReadDsDom;
  2305. NextAttribute++;
  2306. AttributeCountReadDsDom++;
  2307. LsapDbInitializeAttributeDs(
  2308. NextAttribute,
  2309. XRefNetbiosName,
  2310. NULL,
  2311. 0,
  2312. FALSE
  2313. );
  2314. iXRefNetbiosName = AttributeCountReadDsDom;
  2315. NextAttribute++;
  2316. AttributeCountReadDsDom++;
  2317. Status = LsapDsReadAttributesByDsName(
  2318. DomainXRef,
  2319. 0,
  2320. AttributesReadDsDom,
  2321. AttributeCountReadDsDom
  2322. );
  2323. if ( !NT_SUCCESS( Status )) {
  2324. goto Error;
  2325. }
  2326. LsapDbCopyUnicodeAttributeNoAlloc(
  2327. &DnsDomainNameDs,
  2328. &AttributesReadDsDom[iXRefDnsRoot],
  2329. TRUE
  2330. );
  2331. LsapDbCopyUnicodeAttributeNoAlloc(
  2332. &NetbiosDomainNameDs,
  2333. &AttributesReadDsDom[iXRefNetbiosName],
  2334. TRUE
  2335. );
  2336. //
  2337. // From the root domain cross-ref object,
  2338. // read the "DnsRoot" attribute
  2339. //
  2340. ASSERT( AttributeCountReadDsRoot == 0 );
  2341. NextAttribute = AttributesReadDsRoot;
  2342. LsapDbInitializeAttributeDs(
  2343. NextAttribute,
  2344. XRefDnsRoot,
  2345. NULL,
  2346. 0,
  2347. FALSE
  2348. );
  2349. iXRefDnsRoot2 = AttributeCountReadDsRoot;
  2350. NextAttribute++;
  2351. AttributeCountReadDsRoot++;
  2352. Status = LsapDsReadAttributesByDsName(
  2353. RootDomainXRef,
  2354. 0,
  2355. AttributesReadDsRoot,
  2356. AttributeCountReadDsRoot
  2357. );
  2358. if ( !NT_SUCCESS( Status )) {
  2359. goto Error;
  2360. }
  2361. LsapDbCopyUnicodeAttributeNoAlloc(
  2362. &RootDnsDomainNameDs,
  2363. &AttributesReadDsRoot[iXRefDnsRoot2],
  2364. TRUE
  2365. );
  2366. //
  2367. // See if the values in the registry match what's in the DS,
  2368. // and if they don't, update the registry
  2369. //
  2370. ASSERT( AttributeCountWriteReg == 0 );
  2371. NextAttribute = AttributesWriteReg;
  2372. //
  2373. // Match the netbios name in the domain object XRef against
  2374. // the primary domain name in the registry
  2375. //
  2376. if ( !RtlEqualUnicodeString(
  2377. &PrimaryDomainNameReg,
  2378. &NetbiosDomainNameDs,
  2379. TRUE )) {
  2380. Status = LsapDbMakeUnicodeAttributeDs(
  2381. &NetbiosDomainNameDs,
  2382. PolPrDmN,
  2383. NextAttribute
  2384. );
  2385. if ( !NT_SUCCESS( Status )) {
  2386. goto Error;
  2387. }
  2388. NextAttribute++;
  2389. AttributeCountWriteReg++;
  2390. }
  2391. //
  2392. // Match the netbios name in the domain object XRef against
  2393. // the account domain name in the registry
  2394. //
  2395. if ( !RtlEqualUnicodeString(
  2396. &AccountDomainNameReg,
  2397. &NetbiosDomainNameDs,
  2398. TRUE )) {
  2399. Status = LsapDbMakeUnicodeAttributeDs(
  2400. &NetbiosDomainNameDs,
  2401. PolAcDmN,
  2402. NextAttribute
  2403. );
  2404. if ( !NT_SUCCESS( Status )) {
  2405. goto Error;
  2406. }
  2407. NextAttribute++;
  2408. AttributeCountWriteReg++;
  2409. }
  2410. //
  2411. // Match the DNS name in the domain object XRef against
  2412. // the DNS domain name in the registry
  2413. //
  2414. if ( !RtlEqualUnicodeString(
  2415. &DnsDomainNameReg,
  2416. &DnsDomainNameDs,
  2417. TRUE )) {
  2418. Status = LsapDbMakeUnicodeAttributeDs(
  2419. &DnsDomainNameDs,
  2420. PolDnDDN,
  2421. NextAttribute
  2422. );
  2423. if ( !NT_SUCCESS( Status )) {
  2424. goto Error;
  2425. }
  2426. NextAttribute++;
  2427. AttributeCountWriteReg++;
  2428. }
  2429. //
  2430. // Match the DNS name in the root domain object XRef against
  2431. // the root DNS domain name in the registry
  2432. //
  2433. if ( !RtlEqualUnicodeString(
  2434. &RootDnsDomainNameReg,
  2435. &RootDnsDomainNameDs,
  2436. TRUE )) {
  2437. Status = LsapDbMakeUnicodeAttributeDs(
  2438. &RootDnsDomainNameDs,
  2439. PolDnTrN,
  2440. NextAttribute
  2441. );
  2442. if ( !NT_SUCCESS( Status )) {
  2443. goto Error;
  2444. }
  2445. NextAttribute++;
  2446. AttributeCountWriteReg++;
  2447. }
  2448. //
  2449. // See if anything in the registry has got to change
  2450. // and if so, update it
  2451. //
  2452. if ( AttributeCountWriteReg > 0 ) {
  2453. Status = LsapDbReferenceObject(
  2454. LsapPolicyHandle,
  2455. 0,
  2456. PolicyObject,
  2457. PolicyObject,
  2458. LSAP_DB_LOCK |
  2459. LSAP_DB_START_TRANSACTION
  2460. );
  2461. if ( NT_SUCCESS( Status )) {
  2462. Status = LsapDbWriteAttributesObject(
  2463. LsapPolicyHandle,
  2464. AttributesWriteReg,
  2465. AttributeCountWriteReg
  2466. );
  2467. Status = LsapDbDereferenceObject(
  2468. &LsapPolicyHandle,
  2469. PolicyObject,
  2470. PolicyObject,
  2471. LSAP_DB_LOCK |
  2472. LSAP_DB_FINISH_TRANSACTION |
  2473. LSAP_DB_OMIT_REPLICATOR_NOTIFICATION,
  2474. SecurityDbChange,
  2475. Status
  2476. );
  2477. if ( NT_SUCCESS( Status )) {
  2478. *Renamed = TRUE;
  2479. }
  2480. }
  2481. if ( NT_SUCCESS( Status )) {
  2482. //
  2483. // Currently existing logon sessions must be modified with the new
  2484. // domain name
  2485. //
  2486. Status = LsapDomainRenameHandlerForLogonSessions(
  2487. &PrimaryDomainNameReg,
  2488. &DnsDomainNameReg,
  2489. &NetbiosDomainNameDs,
  2490. &DnsDomainNameDs
  2491. );
  2492. }
  2493. if ( !NT_SUCCESS( Status )) {
  2494. goto Error;
  2495. }
  2496. }
  2497. //
  2498. // Bug #380437: Since the DC can have a setting that allows it to keep
  2499. // its DNS suffix across membership changes, this check
  2500. // may cause the machine to fail to boot.
  2501. //
  2502. // Thus the following segment of code has been pulled
  2503. //
  2504. #if 0
  2505. //
  2506. // One final check: call GetComputerNameEx() and see if what it returns
  2507. // matches what we believe the DNS domain name to be
  2508. //
  2509. // Note that we do NOT ask for the physical DNS domain name,
  2510. // this is done so that the code does not have to be changed for Blackcomb,
  2511. // which is expected to be able to host multiple domains on clusters
  2512. //
  2513. if ( FALSE == GetComputerNameExW(
  2514. ComputerNameDnsDomain,
  2515. NameBuffer,
  2516. &NameBufferSize )) {
  2517. //
  2518. // Must return an NT status code, so map the error code back
  2519. //
  2520. Status = NetpApiStatusToNtStatus( GetLastError());
  2521. //
  2522. // Guard against return values that are not of type 'error'
  2523. //
  2524. if ( NT_SUCCESS( Status )) {
  2525. Status = STATUS_UNSUCCESSFUL;
  2526. }
  2527. goto Error;
  2528. } else {
  2529. WCHAR * Buffer;
  2530. BOOLEAN BufferAllocated = FALSE;
  2531. ASSERT( DnsDomainNameDs.Length <= DNS_MAX_NAME_LENGTH );
  2532. if ( DnsDomainNameDs.MaximumLength > DnsDomainNameDs.Length ) {
  2533. Buffer = DnsDomainNameDs.Buffer;
  2534. } else {
  2535. SafeAllocaAllocate( Buffer, DnsDomainNameDs.Length + sizeof( WCHAR ));
  2536. if ( Buffer == NULL ) {
  2537. Status = STATUS_INSUFFICIENT_RESOURCES;
  2538. goto Error;
  2539. }
  2540. BufferAllocated = TRUE;
  2541. wcsncpy( Buffer, DnsDomainNameDs.Buffer, DnsDomainNameDs.Length );
  2542. }
  2543. Buffer[DnsDomainNameDs.Length / sizeof( WCHAR )] = L'\0';
  2544. if ( !DnsNameCompare_W( NameBuffer, Buffer )) {
  2545. //
  2546. // Can not proceed.
  2547. // The boot sequence must be aborted, and the computer name
  2548. // in the registry corrected manually from the recovery console
  2549. //
  2550. Status = STATUS_INTERNAL_ERROR;
  2551. Reason = LSA_DOMAIN_RENAME_ERROR2;
  2552. if ( BufferAllocated ) {
  2553. SafeAllocaFree( Buffer );
  2554. }
  2555. goto Error;
  2556. }
  2557. if ( BufferAllocated ) {
  2558. SafeAllocaFree( Buffer );
  2559. }
  2560. }
  2561. #endif // #if 0
  2562. Cleanup:
  2563. LsapDbFreeAttributes( AttributeCountReadReg, AttributesReadReg );
  2564. LsapDbFreeAttributes( AttributeCountReadDsDom, AttributesReadDsDom );
  2565. LsapDbFreeAttributes( AttributeCountReadDsRoot, AttributesReadDsRoot );
  2566. LsapDbFreeAttributes( AttributeCountWriteReg, AttributesWriteReg );
  2567. LsapFreeLsaHeap( DomainXRef );
  2568. LsapFreeLsaHeap( RootDomainXRef );
  2569. LsarpReturnPrologue();
  2570. return Status;
  2571. Error:
  2572. ASSERT( !NT_SUCCESS( Status ));
  2573. //
  2574. // log an explanatory event
  2575. //
  2576. _ltow( Status, ErrorCode, 16 );
  2577. pErrorCode = &ErrorCode[0];
  2578. SpmpReportEvent(
  2579. TRUE,
  2580. EVENTLOG_ERROR_TYPE,
  2581. Reason,
  2582. 0,
  2583. 0,
  2584. NULL,
  2585. 1,
  2586. pErrorCode
  2587. );
  2588. goto Cleanup;
  2589. }
  2590. NTSTATUS
  2591. LsaISamIndicatedDsStarted(
  2592. IN BOOLEAN PerformDomainRenameCheck
  2593. )
  2594. /*++
  2595. Routine Description:
  2596. This function is a sort of callback from SampInitialize, which is used to tell Lsa that
  2597. the Ds has started. It is supplied so that the Lsa can initialize enough of its state
  2598. to allow access to Ds stored Lsa information so that Sam can complete initialization
  2599. This function only gets called if the Ds is running
  2600. This function must NOT call any APIs that invoke any SAM calls, since this function gets
  2601. called from SampInitialize, and it causes problems.
  2602. Arguments:
  2603. PerformDomainRenameCheck perform the domain rename check in this iteration?
  2604. Return Value:
  2605. STATUS_SUCCESS -- Success
  2606. --*/
  2607. {
  2608. NTSTATUS Status = STATUS_SUCCESS;
  2609. ULONG Len, i, j;
  2610. BOOLEAN DbLocked = FALSE, CloseTransaction = FALSE;
  2611. ATTRBLOCK SystemContainerRead, SystemContainerResults;
  2612. ATTRVAL AttrVal;
  2613. ATTR SearchAttr;
  2614. PDSNAME SchemaPath = NULL;
  2615. SYNTAX_DISTNAME_STRING *DistnameString;
  2616. SYNTAX_ADDRESS *SyntaxAddress;
  2617. GUID KnownSystemContainerGuid = {
  2618. 0xf3301dab, 0x8876, 0xd111, 0xad, 0xed, 0x00, 0xc0, 0x4f, 0xd8, 0xd5, 0xcd
  2619. };
  2620. BOOLEAN DomainRenamed = FALSE;
  2621. LsaDsStateInfo.WriteLocal = FALSE;
  2622. LsaDsStateInfo.DsRoot = NULL;
  2623. LsaDsStateInfo.FunctionTableInitialized = FALSE;
  2624. LsaDsStateInfo.UseDs = TRUE;
  2625. LsaDsStateInfo.Nt4UpgradeInProgress = FALSE;
  2626. LsapDsIsRunning = TRUE;
  2627. //
  2628. // Initialize the function table
  2629. //
  2630. LsaDsStateInfo.DsFuncTable.pOpenTransaction = LsapDsOpenTransaction;
  2631. LsaDsStateInfo.DsFuncTable.pApplyTransaction = LsapDsApplyTransaction;
  2632. LsaDsStateInfo.DsFuncTable.pAbortTransaction = LsapDsAbortTransaction;
  2633. LsaDsStateInfo.FunctionTableInitialized = TRUE;
  2634. //
  2635. // Determine our write state. At init time, the write is only allowed if
  2636. // we are a DC. The client write state will be set after we examine the
  2637. // machine object.
  2638. //
  2639. if ( LsapProductType == NtProductLanManNt ) {
  2640. LsaDsStateInfo.WriteLocal = TRUE;
  2641. }
  2642. //
  2643. // Now, build the DS name for the root of the domain. We do this using the
  2644. // Lsa memory allocations and deallocations, since this structure will outlive
  2645. // any thread state
  2646. //
  2647. Len = 0;
  2648. Status = GetConfigurationName( DSCONFIGNAME_DOMAIN, &Len, NULL );
  2649. ASSERT( Status == STATUS_BUFFER_TOO_SMALL );
  2650. LsaDsStateInfo.DsRoot = LsapAllocateLsaHeap( Len );
  2651. if ( LsaDsStateInfo.DsRoot == NULL ) {
  2652. Status = STATUS_INSUFFICIENT_RESOURCES;
  2653. } else {
  2654. Status = GetConfigurationName( DSCONFIGNAME_DOMAIN, &Len, LsaDsStateInfo.DsRoot );
  2655. //
  2656. // Get the handle to the domain
  2657. //
  2658. if ( NT_SUCCESS( Status ) ) {
  2659. Status = LsapDsInitAllocAsNeededEx( LSAP_DB_NO_LOCK,
  2660. PolicyObject,
  2661. &CloseTransaction );
  2662. if ( NT_SUCCESS( Status ) ) {
  2663. LsaDsStateInfo.DsDomainHandle = DirGetDomainHandle( LsaDsStateInfo.DsRoot );
  2664. LsapDsDeleteAllocAsNeededEx( LSAP_DB_NO_LOCK,
  2665. PolicyObject,
  2666. CloseTransaction );
  2667. }
  2668. } else {
  2669. LsapDsDebugOut(( DEB_ERROR,
  2670. "GetConfigurationName for DOMAIN returned 0x%lx\n", Status ));
  2671. }
  2672. }
  2673. //
  2674. // Now, the Configuration container
  2675. //
  2676. if ( NT_SUCCESS( Status ) ) {
  2677. Len = 0;
  2678. Status = GetConfigurationName( DSCONFIGNAME_CONFIGURATION, &Len, NULL );
  2679. ASSERT( Status == STATUS_BUFFER_TOO_SMALL );
  2680. LsaDsStateInfo.DsConfigurationContainer = LsapAllocateLsaHeap( Len );
  2681. if ( LsaDsStateInfo.DsConfigurationContainer == NULL ) {
  2682. Status = STATUS_INSUFFICIENT_RESOURCES;
  2683. } else {
  2684. Status = GetConfigurationName( DSCONFIGNAME_CONFIGURATION, &Len,
  2685. LsaDsStateInfo.DsConfigurationContainer );
  2686. }
  2687. }
  2688. //
  2689. // Now, the Partitions container
  2690. //
  2691. if ( NT_SUCCESS( Status ) ) {
  2692. Len = 0;
  2693. Status = GetConfigurationName( DSCONFIGNAME_PARTITIONS, &Len, NULL );
  2694. ASSERT( Status == STATUS_BUFFER_TOO_SMALL );
  2695. LsaDsStateInfo.DsPartitionsContainer = LsapAllocateLsaHeap( Len );
  2696. if ( LsaDsStateInfo.DsPartitionsContainer == NULL ) {
  2697. Status = STATUS_INSUFFICIENT_RESOURCES;
  2698. } else {
  2699. Status = GetConfigurationName( DSCONFIGNAME_PARTITIONS, &Len,
  2700. LsaDsStateInfo.DsPartitionsContainer );
  2701. }
  2702. }
  2703. //
  2704. // Build the path to the system container. We read the wellKnownObjects from the root
  2705. // container and use that to determine which one of these objects is the system
  2706. //
  2707. if ( NT_SUCCESS( Status ) ) {
  2708. //
  2709. // Make sure we have an open transaction
  2710. //
  2711. Status = LsapDsInitAllocAsNeededEx( LSAP_DB_NO_LOCK,
  2712. PolicyObject,
  2713. &CloseTransaction );
  2714. if ( NT_SUCCESS( Status ) ) {
  2715. SystemContainerRead.attrCount = LsapDsDnsRootWellKnownObjectCount;
  2716. SystemContainerRead.pAttr = LsapDsDnsRootWellKnownObject;
  2717. Status = LsapDsReadByDsName( LsaDsStateInfo.DsRoot,
  2718. LSAPDS_READ_NO_LOCK,
  2719. &SystemContainerRead,
  2720. &SystemContainerResults );
  2721. if ( NT_SUCCESS( Status ) ) {
  2722. //
  2723. // Process all returned information until we find the one that corresponds to
  2724. // the system container
  2725. //
  2726. Status = STATUS_NOT_FOUND;
  2727. for ( i = 0; i < SystemContainerResults.attrCount; i++ ) {
  2728. for ( j = 0; j < SystemContainerResults.pAttr->AttrVal.valCount; j++ ) {
  2729. DistnameString = ( SYNTAX_DISTNAME_STRING * )
  2730. SystemContainerResults.pAttr->AttrVal.pAVal[ j ].pVal;
  2731. SyntaxAddress = DATAPTR( DistnameString );
  2732. if ( RtlCompareMemory( &KnownSystemContainerGuid,
  2733. SyntaxAddress->byteVal,
  2734. sizeof( GUID ) ) == sizeof( GUID ) ) {
  2735. Status = LsapDsCopyDsNameLsa( &LsaDsStateInfo.DsSystemContainer,
  2736. NAMEPTR( DistnameString ) );
  2737. break;
  2738. }
  2739. }
  2740. }
  2741. }
  2742. LsapDsDeleteAllocAsNeededEx( LSAP_DB_NO_LOCK,
  2743. PolicyObject,
  2744. CloseTransaction );
  2745. }
  2746. }
  2747. //
  2748. // Now, build the DS name for the schema container
  2749. //
  2750. Len = 0;
  2751. Status = GetConfigurationName( DSCONFIGNAME_DMD, &Len, NULL );
  2752. ASSERT( Status == STATUS_BUFFER_TOO_SMALL );
  2753. SchemaPath = LsapAllocateLsaHeap( Len );
  2754. if ( SchemaPath == NULL ) {
  2755. Status = STATUS_INSUFFICIENT_RESOURCES;
  2756. } else {
  2757. Status = GetConfigurationName( DSCONFIGNAME_DMD, &Len, SchemaPath );
  2758. //
  2759. // Query for the info we need to be able to look up items in the system container
  2760. //
  2761. if ( NT_SUCCESS( Status ) ) {
  2762. AttrVal.valLen = sizeof( LSAP_DS_TRUSTED_DOMAIN ) - sizeof( WCHAR );
  2763. AttrVal.pVal = ( PUCHAR )LSAP_DS_TRUSTED_DOMAIN;
  2764. Status = LsapDsFindUnique( 0,
  2765. SchemaPath,
  2766. AllObject,
  2767. &AttrVal,
  2768. ATT_LDAP_DISPLAY_NAME,
  2769. &LsaDsStateInfo.SystemContainerItems.TrustedDomainObject );
  2770. //
  2771. // If we didn't find it via the DirFind, it could be because the indicies haven't
  2772. // been created yet. So, we're forced to try it again with an old fashioned search.
  2773. //
  2774. if ( Status == STATUS_NOT_FOUND ) {
  2775. SearchAttr.attrTyp = ATT_LDAP_DISPLAY_NAME;
  2776. SearchAttr.AttrVal.valCount = 1;
  2777. SearchAttr.AttrVal.pAVal = &AttrVal;
  2778. Status = LsapDsSearchUnique(
  2779. 0,
  2780. SchemaPath,
  2781. &SearchAttr,
  2782. 1,
  2783. &LsaDsStateInfo.SystemContainerItems.TrustedDomainObject );
  2784. }
  2785. }
  2786. if ( NT_SUCCESS( Status ) ) {
  2787. AttrVal.valLen = sizeof( LSAP_DS_SECRET ) - sizeof( WCHAR );
  2788. AttrVal.pVal = ( PUCHAR )LSAP_DS_SECRET;
  2789. Status = LsapDsFindUnique( 0,
  2790. SchemaPath,
  2791. AllObject,
  2792. &AttrVal,
  2793. ATT_LDAP_DISPLAY_NAME,
  2794. &LsaDsStateInfo.SystemContainerItems.SecretObject );
  2795. //
  2796. // If we didn't find it via the DirFind, it could be because the indicies haven't
  2797. // been created yet. So, we're forced to try it again with an old fashioned search.
  2798. //
  2799. if ( Status == STATUS_NOT_FOUND ) {
  2800. SearchAttr.attrTyp = ATT_LDAP_DISPLAY_NAME;
  2801. SearchAttr.AttrVal.valCount = 1;
  2802. SearchAttr.AttrVal.pAVal = &AttrVal;
  2803. Status = LsapDsSearchUnique(
  2804. 0,
  2805. SchemaPath,
  2806. &SearchAttr,
  2807. 1,
  2808. &LsaDsStateInfo.SystemContainerItems.SecretObject );
  2809. }
  2810. }
  2811. if ( SchemaPath ) {
  2812. LsapFreeLsaHeap( SchemaPath );
  2813. }
  2814. }
  2815. if ( NT_SUCCESS( Status )) {
  2816. LsaDsStateInfo.DsInitializedAndRunning = TRUE;
  2817. //
  2818. // Domain rename support -- synchronize domain name in the DS with what's
  2819. // in the registry
  2820. //
  2821. if ( PerformDomainRenameCheck ) {
  2822. Status = LsapDbDomainRenameHandler( &DomainRenamed );
  2823. }
  2824. }
  2825. if ( NT_SUCCESS (Status ) ) {
  2826. LsapDbAcquireLockEx( AllObject,
  2827. 0 );
  2828. //
  2829. // Rebuild all the caches after setting up the ds and the registry
  2830. //
  2831. Status = LsapDbBuildObjectCaches();
  2832. LsapDbReleaseLockEx( AllObject,
  2833. 0 );
  2834. }
  2835. if ( NT_SUCCESS( Status ) &&
  2836. LsapProductType == NtProductLanManNt &&
  2837. SamIIsRebootAfterPromotion()) {
  2838. //
  2839. // Bug 222800: if this a reboot after promotion, notify the parent
  2840. // of the trust relationship so netlogon.chg gets updated
  2841. //
  2842. Status = LsapNotifyNetlogonOfTrustWithParent();
  2843. }
  2844. if ( !NT_SUCCESS( Status ) ) {
  2845. LsapDsIsRunning = FALSE;
  2846. LsaDsStateInfo.UseDs = TRUE;
  2847. LsaDsStateInfo.DsInitializedAndRunning = FALSE;
  2848. } else if ( DomainRenamed ) {
  2849. LsaINotifyChangeNotification(
  2850. PolicyNotifyAccountDomainInformation
  2851. );
  2852. LsaINotifyChangeNotification(
  2853. PolicyNotifyDnsDomainInformation
  2854. );
  2855. }
  2856. return( Status ) ;
  2857. }
  2858. BOOLEAN
  2859. LsapDsIsValidSid(
  2860. IN PSID Sid,
  2861. IN BOOLEAN DsSid
  2862. )
  2863. /*++
  2864. Routine Description:
  2865. This function determines whether the SID is valid for the Ds or registry based LSA
  2866. Arguments:
  2867. Sid - Sid to validate
  2868. DsSid - If TRUE, this is a SID for a DS function
  2869. Return Value:
  2870. TRUE - Valid SID
  2871. FALSE - Invalid SID
  2872. --*/
  2873. {
  2874. BOOLEAN ValidSid;
  2875. ValidSid = RtlValidSid( Sid );
  2876. if ( ValidSid && DsSid ) {
  2877. if ( RtlLengthSid( Sid ) > sizeof( NT4SID ) ) {
  2878. ValidSid = FALSE;
  2879. }
  2880. }
  2881. return( ValidSid );
  2882. }
  2883. NTSTATUS
  2884. LsapRetrieveDnsDomainNameFromHive(
  2885. IN HKEY Hive,
  2886. IN OUT DWORD * Length,
  2887. OUT WCHAR * Buffer
  2888. )
  2889. {
  2890. DWORD Status;
  2891. DWORD Win32Err;
  2892. HKEY Hkey;
  2893. DWORD Type;
  2894. DWORD Size = DNS_MAX_NAME_LENGTH * sizeof( WCHAR ) + 8;
  2895. BYTE Value[DNS_MAX_NAME_LENGTH * sizeof( WCHAR ) + 8];
  2896. ASSERT( Hive );
  2897. ASSERT( Length );
  2898. ASSERT( *Length );
  2899. ASSERT( Buffer );
  2900. Win32Err = RegOpenKeyW(
  2901. Hive,
  2902. L"Policy\\PolDnDDN",
  2903. &Hkey
  2904. );
  2905. if ( Win32Err != ERROR_SUCCESS) {
  2906. return STATUS_NOT_FOUND;
  2907. }
  2908. Win32Err = RegQueryValueExW(
  2909. Hkey,
  2910. NULL,
  2911. NULL,
  2912. &Type,
  2913. Value,
  2914. &Size
  2915. );
  2916. RegCloseKey( Hkey );
  2917. if ( Win32Err != ERROR_SUCCESS) {
  2918. return STATUS_NOT_FOUND;
  2919. }
  2920. if ( Type != REG_BINARY && Type != REG_NONE ) {
  2921. return STATUS_DATA_ERROR; // should never happen, sanity check only
  2922. }
  2923. if ( Size <= 8 ) {
  2924. return STATUS_DATA_ERROR; // should never happen, sanity check only
  2925. }
  2926. if ( Size - 8 > *Length ) {
  2927. return STATUS_BUFFER_TOO_SMALL;
  2928. }
  2929. RtlCopyMemory( Buffer, Value + 8, Size - 8 );
  2930. *Length = Size - 8;
  2931. return STATUS_SUCCESS;
  2932. }
  2933. NTSTATUS
  2934. LsapDsReadObjectSDByDsName(
  2935. IN DSNAME* Object,
  2936. OUT PSECURITY_DESCRIPTOR *pSD
  2937. )
  2938. /*++
  2939. Routine Description:
  2940. This routine reads the security descriptor for an object in the DS.
  2941. Note that this is primary used when Object does not represent an
  2942. LSA object. For example, the domain object.
  2943. Arguments:
  2944. Object -- the object in the DS
  2945. pSD -- the security descriptor. Caller must free with LsapFreeLsaHeap
  2946. Return Values:
  2947. STATUS_SUCCESS
  2948. STATUS_NO_SECURITY_ON_OBJECT
  2949. a resource error otherwise.
  2950. --*/
  2951. {
  2952. NTSTATUS NtStatus = STATUS_SUCCESS;
  2953. BOOLEAN ReleaseState = FALSE;
  2954. //
  2955. // Setup the attrs to read
  2956. //
  2957. ATTR SDReadAttr = {ATT_NT_SECURITY_DESCRIPTOR, {0, NULL}};
  2958. ATTRBLOCK SDReadAttrBlock = {1,&SDReadAttr};
  2959. ATTRBLOCK SDReadResAttrBlock = {0, NULL};
  2960. PSECURITY_DESCRIPTOR LocalSD = NULL;
  2961. ULONG Size = 0;
  2962. ULONG i;
  2963. NtStatus = LsapDsInitAllocAsNeededEx( LSAP_DB_READ_ONLY_TRANSACTION |
  2964. LSAP_DB_DS_OP_TRANSACTION,
  2965. NullObject,
  2966. &ReleaseState );
  2967. if ( !NT_SUCCESS( NtStatus ) ) {
  2968. goto DsReadObjectSDError;
  2969. }
  2970. //
  2971. // Read the SD
  2972. //
  2973. NtStatus = LsapDsReadByDsName(Object,
  2974. LSAPDS_READ_NO_LOCK,
  2975. &SDReadAttrBlock,
  2976. &SDReadResAttrBlock);
  2977. if (!NT_SUCCESS(NtStatus)) {
  2978. goto DsReadObjectSDError;
  2979. }
  2980. //
  2981. // Extract the attribute
  2982. //
  2983. for (i = 0; i < SDReadResAttrBlock.attrCount; i++) {
  2984. if (SDReadResAttrBlock.pAttr[i].attrTyp == ATT_NT_SECURITY_DESCRIPTOR) {
  2985. if (SDReadResAttrBlock.pAttr[i].AttrVal.valCount > 0
  2986. && SDReadResAttrBlock.pAttr[i].AttrVal.pAVal[0].valLen > 0) {
  2987. Size = SDReadResAttrBlock.pAttr[i].AttrVal.pAVal[0].valLen;
  2988. LocalSD = (PSECURITY_DESCRIPTOR) SDReadResAttrBlock.pAttr[i].AttrVal.pAVal[0].pVal;
  2989. ASSERT(IsValidSecurityDescriptor(LocalSD));
  2990. }
  2991. }
  2992. }
  2993. //
  2994. // Copy it to local memory
  2995. //
  2996. if (NULL == LocalSD) {
  2997. //
  2998. // No security descriptor is an error
  2999. //
  3000. NtStatus = STATUS_NO_SECURITY_ON_OBJECT;
  3001. goto DsReadObjectSDError;
  3002. }
  3003. (*pSD) = LsapAllocateLsaHeap(Size);
  3004. if (NULL == (*pSD)) {
  3005. NtStatus = STATUS_NO_MEMORY;
  3006. goto DsReadObjectSDError;
  3007. }
  3008. RtlCopyMemory((*pSD), LocalSD, Size);
  3009. DsReadObjectSDError:
  3010. if (ReleaseState) {
  3011. LsapDsDeleteAllocAsNeededEx( LSAP_DB_READ_ONLY_TRANSACTION |
  3012. LSAP_DB_DS_OP_TRANSACTION,
  3013. NullObject,
  3014. ReleaseState );
  3015. }
  3016. return NtStatus;
  3017. }
  3018. PACL LsapGetDacl(
  3019. IN PSECURITY_DESCRIPTOR Sd
  3020. )
  3021. {
  3022. BOOL Status;
  3023. PACL Dacl = NULL;
  3024. PACL DaclToReturn = NULL;
  3025. BOOL DaclPresent;
  3026. BOOL DaclDefaulted;
  3027. Status = GetSecurityDescriptorDacl(
  3028. Sd,
  3029. &DaclPresent,
  3030. &Dacl,
  3031. &DaclDefaulted
  3032. );
  3033. if ((Status)
  3034. && DaclPresent
  3035. && !DaclDefaulted)
  3036. {
  3037. DaclToReturn = Dacl;
  3038. }
  3039. return DaclToReturn;
  3040. }
  3041. PACL LsapGetSacl(
  3042. IN PSECURITY_DESCRIPTOR Sd
  3043. )
  3044. {
  3045. BOOL Status;
  3046. PACL Sacl = NULL;
  3047. PACL SaclToReturn = NULL;
  3048. BOOL SaclPresent;
  3049. BOOL SaclDefaulted;
  3050. Status = GetSecurityDescriptorSacl(
  3051. Sd,
  3052. &SaclPresent,
  3053. &Sacl,
  3054. &SaclDefaulted
  3055. );
  3056. if ((Status)
  3057. && SaclPresent
  3058. && !SaclDefaulted)
  3059. {
  3060. SaclToReturn = Sacl;
  3061. }
  3062. return SaclToReturn;
  3063. }
  3064. NTSTATUS
  3065. LsapDsGetDefaultSecurityDescriptor(
  3066. IN ULONG ClassId,
  3067. OUT PSECURITY_DESCRIPTOR *ppSD,
  3068. OUT ULONG *cbSD
  3069. )
  3070. /*++
  3071. Routine Description:
  3072. This routine obtains the default security descriptor for ClassId
  3073. and sets the Owner as the owner of the current's called token.
  3074. Arguments:
  3075. ClassId -- the class to get the security descriptor for
  3076. ppSD -- the security descriptor
  3077. cbSD -- the number of bytes pointed to by ppSD
  3078. Return Values:
  3079. STATUS_SUCCESS, a resource error otherwise
  3080. --*/
  3081. {
  3082. NTSTATUS Status = STATUS_SUCCESS;
  3083. ULONG cbLocalSD = 0;
  3084. PSECURITY_DESCRIPTOR pLocalSD = NULL;
  3085. PTOKEN_OWNER Owner = NULL;
  3086. PTOKEN_PRIMARY_GROUP PrimaryGroup = NULL;
  3087. //
  3088. // Get the default security descriptor
  3089. //
  3090. Status = SampGetClassAttribute(ClassId,
  3091. ATT_DEFAULT_SECURITY_DESCRIPTOR,
  3092. &cbLocalSD,
  3093. pLocalSD);
  3094. if (STATUS_BUFFER_TOO_SMALL == Status) {
  3095. SafeAllocaAllocate(pLocalSD, cbLocalSD);
  3096. if (NULL == pLocalSD) {
  3097. goto Exit;
  3098. }
  3099. Status = SampGetClassAttribute(ClassId,
  3100. ATT_DEFAULT_SECURITY_DESCRIPTOR,
  3101. &cbLocalSD,
  3102. pLocalSD
  3103. );
  3104. }
  3105. if (!NT_SUCCESS(Status)) {
  3106. goto Exit;
  3107. }
  3108. //
  3109. // Get the current owner and primary group of the token
  3110. //
  3111. Status = LsapGetCurrentOwnerAndPrimaryGroup(
  3112. &Owner,
  3113. &PrimaryGroup
  3114. );
  3115. if (!NT_SUCCESS(Status)) {
  3116. goto Exit;
  3117. }
  3118. //
  3119. // Make a new security descriptor , setting the owner and the group
  3120. // to that of
  3121. //
  3122. Status = LsapMakeNewSelfRelativeSecurityDescriptor(
  3123. (Owner)?Owner->Owner:LsapAliasAdminsSid,
  3124. (PrimaryGroup)?PrimaryGroup->PrimaryGroup:LsapAliasAdminsSid,
  3125. LsapGetDacl(pLocalSD),
  3126. LsapGetSacl(pLocalSD),
  3127. cbSD,
  3128. ppSD
  3129. );
  3130. //
  3131. // Fall through to exit
  3132. //
  3133. Exit:
  3134. if (pLocalSD) {
  3135. SafeAllocaFree(pLocalSD);
  3136. }
  3137. if (Owner) {
  3138. LsapFreeLsaHeap(Owner);
  3139. }
  3140. if (PrimaryGroup) {
  3141. LsapFreeLsaHeap(PrimaryGroup);
  3142. }
  3143. return Status;
  3144. }