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.

3770 lines
113 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. dstrust.c
  5. Abstract:
  6. Implementation of a variety of TrustedDomain features that interface
  7. soley with the DS
  8. Author:
  9. Mac McLain (MacM) Jan 17, 1997
  10. Environment:
  11. User Mode
  12. Revision History:
  13. --*/
  14. #include <lsapch2.h>
  15. #include <dbp.h>
  16. #include <lmcons.h>
  17. #include <align.h>
  18. #include <rc4.h>
  19. //
  20. // Local function prototypes
  21. //
  22. NTSTATUS
  23. LsapDsUnmarshalAuthInfoHalf(
  24. IN LSAPR_HANDLE ObjectHandle,
  25. IN BOOLEAN ReturnOnlyFirstAuthInfo,
  26. IN BOOLEAN AllowEmptyPreviousInfo,
  27. IN PBYTE Buffer,
  28. IN ULONG Length,
  29. IN OUT PLSAPR_TRUST_DOMAIN_AUTH_INFO_HALF AuthInfo
  30. );
  31. VOID
  32. LsapDsFreeUnmarshaledAuthInfo(
  33. IN ULONG Items,
  34. IN PLSAPR_AUTH_INFORMATION AuthInfo
  35. );
  36. NTSTATUS
  37. LsapDsFindAuthTypeInAuthInfo(
  38. IN ULONG AuthType,
  39. IN PLSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION AuthInfo,
  40. IN BOOLEAN Incoming,
  41. IN BOOLEAN AddIfNotFound,
  42. OUT BOOLEAN *Added,
  43. OUT PULONG AuthTypeIndex
  44. );
  45. //
  46. // Macros to help with copying over the domain information
  47. //
  48. #define LSAPDS_SET_AUTH_INFO( dest, time, type, length, data ) \
  49. RtlCopyMemory( &(dest)->LastUpdateTime, time, sizeof( LARGE_INTEGER ) ); \
  50. (dest)->AuthType = type; \
  51. (dest)->AuthInfoLength = length; \
  52. (dest)->AuthInfo = data;
  53. NTSTATUS
  54. LsapDsGetListOfSystemContainerItems(
  55. IN ULONG ClassId,
  56. OUT PULONG Items,
  57. OUT PDSNAME **DsNames
  58. )
  59. /*++
  60. Routine Description:
  61. This function obtain a list of DsNames of all indicated class types in the system container
  62. in the Ds
  63. NOTE: This function uses a single operation DS transaction only
  64. Arguments:
  65. ClassId - Class types to find
  66. Items - Where the number of items is returned
  67. DsNames - Where the list of DsNames is returned
  68. Returns:
  69. STATUS_SUCCESS - Success
  70. --*/
  71. {
  72. NTSTATUS Status = STATUS_SUCCESS;
  73. PDSNAME CategoryName = NULL;
  74. ATTRVAL AttrVal;
  75. ATTR Attr = {
  76. ATT_OBJECT_CATEGORY, { 1, &AttrVal }
  77. };
  78. LsapEnterFunc( "LsapDsGetListOfSystemContainerItems" );
  79. *Items = 0;
  80. //
  81. // We need to map object class to object category, because apparently object_class is no
  82. // longer indexed.
  83. //
  84. switch ( ClassId ) {
  85. case CLASS_TRUSTED_DOMAIN:
  86. CategoryName = LsaDsStateInfo.SystemContainerItems.TrustedDomainObject;
  87. break;
  88. case CLASS_SECRET:
  89. CategoryName = LsaDsStateInfo.SystemContainerItems.SecretObject;
  90. break;
  91. default:
  92. Status = STATUS_NONE_MAPPED;
  93. break;
  94. }
  95. if ( NT_SUCCESS( Status ) ) {
  96. LSAP_DS_SET_DS_ATTRIBUTE_DSNAME( &Attr, CategoryName );
  97. Status = LsapDsSearchNonUnique( LSAPDS_OP_NO_TRANS,
  98. LsaDsStateInfo.DsSystemContainer,
  99. &Attr,
  100. 1,
  101. DsNames,
  102. Items );
  103. }
  104. LsapExitFunc( "LsapDsGetListOfSystemContainerItems", Status );
  105. return( Status );
  106. }
  107. NTSTATUS
  108. LsapDsEnumerateTrustedDomainsEx(
  109. PLSA_ENUMERATION_HANDLE EnumerationContext,
  110. TRUSTED_INFORMATION_CLASS InformationClass,
  111. PLSAPR_TRUSTED_DOMAIN_INFO *TrustedDomainInformation,
  112. ULONG PreferedMaximumLength,
  113. PULONG CountReturned,
  114. IN ULONG EnumerationFlags
  115. )
  116. /*++
  117. Routine Description:
  118. This function enumerate all of the trusted domains in a Ds, returning the
  119. requested info level of information.
  120. Arguments:
  121. EnumerationContext - Context of new or ongoing enumeration
  122. InformationClass - Level of information being requested
  123. Must be TrustedDomainInformationEx or TrustedDomainInformatinBasic
  124. TrustedDomainInformation - Where the enumerated information is returned
  125. PreferedMaximumLength - Rough upper size limit of buffer to return
  126. CountReturned - Where the count of the number of items in the list is returned
  127. EnumerationFlags -- Controls how the enumeration is done
  128. Returns:
  129. STATUS_SUCCESS - Success
  130. STATUS_INSUFFICIENT_RESOURCES - A memory allocation failed
  131. STATUS_NO_MORE_ENTRIES - All of the appropriate entries have been enumerated
  132. --*/
  133. {
  134. NTSTATUS Status = STATUS_SUCCESS;
  135. PDSNAME *DsNames = NULL;
  136. ULONG Items = 0, BuffSize, Read, Index = 0, Skip, i = 0;
  137. PLSAPR_TRUSTED_DOMAIN_INFO TDInfo = NULL;
  138. LSAPR_TRUSTED_DOMAIN_INFORMATION_EX ExInfo;
  139. PBYTE Buffer = NULL;
  140. ULONG Size = 0;
  141. ULONG Direction = 0, Type = 0, Attributes = 0;
  142. LsapEnterFunc( "LsapDsEnumerateTrustedDomainsEx" );
  143. ASSERT( InformationClass == TrustedDomainInformationEx ||
  144. InformationClass == TrustedDomainInformationBasic ||
  145. InformationClass == TrustedDomainFullInformation ||
  146. InformationClass == TrustedDomainFullInformation2Internal );
  147. switch ( InformationClass ) {
  148. case TrustedDomainInformationBasic:
  149. Size = sizeof( LSAPR_TRUSTED_DOMAIN_INFORMATION_BASIC );
  150. break;
  151. case TrustedDomainInformationEx:
  152. Size = sizeof( LSAPR_TRUSTED_DOMAIN_INFORMATION_EX );
  153. break;
  154. case TrustedDomainFullInformation:
  155. Size = sizeof( LSAPR_TRUSTED_DOMAIN_FULL_INFORMATION );
  156. break;
  157. case TrustedDomainFullInformation2Internal:
  158. Size = sizeof( LSAPR_TRUSTED_DOMAIN_FULL_INFORMATION2 );
  159. break;
  160. default:
  161. return( STATUS_INVALID_PARAMETER );
  162. }
  163. Skip = (ULONG)*EnumerationContext;
  164. LsapDbAcquireLockEx( TrustedDomainObject,
  165. LSAP_DB_READ_ONLY_TRANSACTION );
  166. //
  167. // First, enumerate all of the trusted domains
  168. //
  169. Status = LsapDsGetListOfSystemContainerItems( CLASS_TRUSTED_DOMAIN,
  170. &Items,
  171. &DsNames );
  172. if ( Status == STATUS_OBJECT_NAME_NOT_FOUND ) {
  173. Status = STATUS_NO_MORE_ENTRIES;
  174. *TrustedDomainInformation = NULL;
  175. *CountReturned = 0;
  176. }
  177. if ( NT_SUCCESS( Status ) ) {
  178. //
  179. // See if we've already enumerated all of our items...
  180. //
  181. if ( Items <= (ULONG)*EnumerationContext) {
  182. Status = STATUS_NO_MORE_ENTRIES;
  183. *TrustedDomainInformation = NULL;
  184. *CountReturned = 0;
  185. } else {
  186. TDInfo = MIDL_user_allocate( ( Items - Skip ) * Size );
  187. if( TDInfo == NULL ) {
  188. Status = STATUS_INSUFFICIENT_RESOURCES;
  189. } else {
  190. Buffer = ( PBYTE )TDInfo;
  191. }
  192. }
  193. }
  194. //
  195. // Now, we'll start getting the information from each of the objects
  196. //
  197. if ( NT_SUCCESS( Status ) ) {
  198. BuffSize = 0;
  199. Index = 0;
  200. i = 0;
  201. while ( TRUE ) {
  202. Status = LsapDsGetTrustedDomainInfoEx( DsNames[ Index + Skip ],
  203. LSAPDS_READ_NO_LOCK,
  204. InformationClass,
  205. ( PLSAPR_TRUSTED_DOMAIN_INFO )Buffer,
  206. &Read );
  207. //
  208. // See if we need to do any masking...
  209. //
  210. if ( NT_SUCCESS( Status ) && EnumerationFlags != LSAP_DB_ENUMERATE_NO_OPTIONS ) {
  211. if ( FLAG_ON( EnumerationFlags, LSAP_DB_ENUMERATE_AS_NT4 ) ) {
  212. if ( InformationClass == TrustedDomainInformationEx ||
  213. InformationClass == TrustedDomainFullInformation ) {
  214. Direction =
  215. ( ( PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX )Buffer )->TrustDirection;
  216. Type = ( ( PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX )Buffer )->TrustType;
  217. Attributes =
  218. ( ( PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX )Buffer )->TrustAttributes;
  219. } else {
  220. //
  221. // We'll re-read the full info, and if it doesn't match our criteria,
  222. // we'll ignore it. Our critera state that the it must be outgoing,
  223. // uplevel or downlevel, and not have the UPLEVEL only attribute set
  224. //
  225. Status = LsapDsGetTrustedDomainInfoEx( DsNames[ Index + Skip ],
  226. LSAPDS_READ_NO_LOCK,
  227. TrustedDomainInformationEx,
  228. (PLSAPR_TRUSTED_DOMAIN_INFO)&ExInfo,
  229. NULL );
  230. if ( Status == STATUS_SUCCESS ) {
  231. Direction = ExInfo.TrustDirection;
  232. Type = ExInfo.TrustType;
  233. Attributes = ExInfo.TrustAttributes;
  234. _fgu__LSAPR_TRUSTED_DOMAIN_INFO( (PLSAPR_TRUSTED_DOMAIN_INFO)&ExInfo,
  235. TrustedDomainInformationEx );
  236. }
  237. }
  238. if ( NT_SUCCESS( Status ) ) {
  239. if ( !FLAG_ON( Direction, TRUST_DIRECTION_OUTBOUND ) ||
  240. !( Type == TRUST_TYPE_DOWNLEVEL ||
  241. Type == TRUST_TYPE_UPLEVEL ) ||
  242. FLAG_ON( Attributes, TRUST_ATTRIBUTE_UPLEVEL_ONLY ) ) {
  243. //
  244. // This one doesn't match, so we'll basically drop it on the
  245. // floor
  246. //
  247. _fgu__LSAPR_TRUSTED_DOMAIN_INFO( (PLSAPR_TRUSTED_DOMAIN_INFO)Buffer,
  248. InformationClass );
  249. LsapDsDebugOut(( DEB_TRACE,
  250. "Trust object %ws doesn't match: D:0x%lx T:0x%lx A:0x%lx\n",
  251. LsapDsNameFromDsName( DsNames[ Index + Skip ] ),
  252. Direction,
  253. Type,
  254. Attributes ));
  255. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  256. }
  257. }
  258. }
  259. }
  260. if ( NT_SUCCESS( Status ) ) {
  261. Index++;
  262. i++;
  263. BuffSize += Read;
  264. if ( (Index + Skip) >= Items ) {
  265. break;
  266. }
  267. if ( (BuffSize >= PreferedMaximumLength) ) {
  268. break;
  269. }
  270. Buffer += Size;
  271. } else if ( Status == STATUS_OBJECT_NAME_NOT_FOUND ) {
  272. Index++;
  273. //
  274. // We'll have to pretend this item doesn't exist if we get back no information...
  275. //
  276. Status = STATUS_SUCCESS;
  277. LsapDsDebugOut(( DEB_TRACE,
  278. "Trust object %ws being dropped. %lu current items\n",
  279. LsapDsNameFromDsName( DsNames[ Index + Skip ] ),
  280. Items ));
  281. } else {
  282. break;
  283. }
  284. if ( (Index + Skip) >= Items ) {
  285. break;
  286. }
  287. }
  288. }
  289. //
  290. // Return the information on success
  291. //
  292. if ( NT_SUCCESS( Status ) ) {
  293. *(PULONG)EnumerationContext += Index;
  294. if ( i == 0 ) {
  295. *TrustedDomainInformation = NULL;
  296. *CountReturned = 0;
  297. MIDL_user_free( TDInfo );
  298. } else {
  299. *TrustedDomainInformation = TDInfo;
  300. *CountReturned = i;
  301. }
  302. if( Index + Skip >= Items ) {
  303. if( i == 0 ) {
  304. Status = STATUS_NO_MORE_ENTRIES;
  305. } else {
  306. Status = STATUS_SUCCESS;
  307. }
  308. } else {
  309. ASSERT( i != 0 && "We should be returning something here" );
  310. Status = STATUS_MORE_ENTRIES;
  311. }
  312. }
  313. //
  314. // Free any allocated memory we no longer need
  315. //
  316. if ( DsNames != NULL ) {
  317. LsapFreeLsaHeap( DsNames );
  318. }
  319. if ( !NT_SUCCESS( Status ) && Status != STATUS_NO_MORE_ENTRIES ) {
  320. MIDL_user_free( TDInfo );
  321. }
  322. LsapDbReleaseLockEx( TrustedDomainObject,
  323. LSAP_DB_READ_ONLY_TRANSACTION );
  324. LsapExitFunc( "LsapDsEnumerateTrustedDomainsEx", Status );
  325. return( Status );
  326. }
  327. NTSTATUS
  328. LsapDsGetTrustedDomainInfoEx(
  329. IN PDSNAME ObjectPath,
  330. IN ULONG ReadOptions,
  331. TRUSTED_INFORMATION_CLASS InformationClass,
  332. PLSAPR_TRUSTED_DOMAIN_INFO TrustedDomainInformation,
  333. OUT OPTIONAL PULONG Size
  334. )
  335. /*++
  336. Routine Description:
  337. This function will read the requested level of information off the specified trusted
  338. domain object
  339. Arguments:
  340. ObjectPath - DsName of the trusted domain object
  341. InformationClass - Level of information being requested
  342. TrustedDomainInformation - Where the information is returned
  343. Size - OPTIONAL size of the information buffer is returned here.
  344. Returns:
  345. STATUS_SUCCESS - Success
  346. STATUS_INSUFFICIENT_RESOURCES - A memory allocation failed
  347. STATUS_INVALID_PARAMETER - A bad InformationClass was given
  348. --*/
  349. {
  350. NTSTATUS Status = STATUS_SUCCESS;
  351. ATTRBLOCK ReadBlock, ReturnedBlock;
  352. ULONG Items = 0, i, RetSize = 0;
  353. ATTR DomainOrgTreeAttrVals[] = {
  354. {0, {0, NULL} },
  355. {0, {0, NULL} },
  356. {0, {0, NULL} },
  357. {0, {0, NULL} },
  358. {0, {0, NULL} },
  359. {0, {0, NULL} },
  360. {0, {0, NULL} },
  361. {0, {0, NULL} }
  362. };
  363. //
  364. // List of returned parameters
  365. //
  366. UNICODE_STRING Name, FlatName;
  367. ULONG Offset = 0, Direction = 0, Type = 0, Attributes = 0;
  368. PSID Sid = NULL;
  369. PBYTE Incoming = NULL, Outgoing = NULL;
  370. ULONG IncomingSize = 0, OutgoingSize = 0;
  371. ULONG ForestTrustLength = 0;
  372. PBYTE ForestTrustInfo = NULL;
  373. //
  374. // Different info types
  375. //
  376. // PLSAPR_TRUSTED_DOMAIN_NAME_INFO NameInfo;
  377. // PTRUSTED_POSIX_OFFSET_INFO PosixOffset;
  378. // PLSAPR_TRUSTED_PASSWORD_INFO PasswordInfo;
  379. PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX DomainInfoEx;
  380. PLSAPR_TRUSTED_DOMAIN_INFORMATION_BASIC DomainInfoBasic;
  381. PLSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION AuthInfo;
  382. PLSAPR_TRUSTED_DOMAIN_FULL_INFORMATION FullInfo;
  383. PLSAPR_TRUSTED_DOMAIN_FULL_INFORMATION2 FullInfo2;
  384. LsapEnterFunc( "LsapDsGetTrustedDomainInfoEx" );
  385. RtlZeroMemory( &FlatName, sizeof( UNICODE_STRING ) );
  386. RtlZeroMemory( &Name, sizeof( UNICODE_STRING ) );
  387. switch ( InformationClass ) {
  388. case TrustedDomainAuthInformation: // FALL THROUGH
  389. DomainOrgTreeAttrVals[ 0 ].attrTyp = ATT_TRUST_AUTH_INCOMING;
  390. DomainOrgTreeAttrVals[ 1 ].attrTyp = ATT_TRUST_AUTH_OUTGOING;
  391. Items = 2;
  392. break;
  393. case TrustedDomainInformationBasic:
  394. DomainOrgTreeAttrVals[ 0 ].attrTyp = ATT_FLAT_NAME;
  395. DomainOrgTreeAttrVals[ 1 ].attrTyp = ATT_SECURITY_IDENTIFIER;
  396. Items = 2;
  397. break;
  398. case TrustedDomainInformationEx:
  399. DomainOrgTreeAttrVals[ 0 ].attrTyp = ATT_TRUST_PARTNER;
  400. DomainOrgTreeAttrVals[ 1 ].attrTyp = ATT_FLAT_NAME;
  401. DomainOrgTreeAttrVals[ 2 ].attrTyp = ATT_SECURITY_IDENTIFIER;
  402. DomainOrgTreeAttrVals[ 3 ].attrTyp = ATT_TRUST_DIRECTION;
  403. DomainOrgTreeAttrVals[ 4 ].attrTyp = ATT_TRUST_TYPE;
  404. DomainOrgTreeAttrVals[ 5 ].attrTyp = ATT_TRUST_ATTRIBUTES;
  405. Items = 6;
  406. break;
  407. case TrustedDomainFullInformation:
  408. DomainOrgTreeAttrVals[ 0 ].attrTyp = ATT_TRUST_PARTNER;
  409. DomainOrgTreeAttrVals[ 1 ].attrTyp = ATT_FLAT_NAME;
  410. DomainOrgTreeAttrVals[ 2 ].attrTyp = ATT_SECURITY_IDENTIFIER;
  411. DomainOrgTreeAttrVals[ 3 ].attrTyp = ATT_TRUST_DIRECTION;
  412. DomainOrgTreeAttrVals[ 4 ].attrTyp = ATT_TRUST_TYPE;
  413. DomainOrgTreeAttrVals[ 5 ].attrTyp = ATT_TRUST_ATTRIBUTES;
  414. DomainOrgTreeAttrVals[ 6 ].attrTyp = ATT_TRUST_POSIX_OFFSET;
  415. // No caller currently needs auth information.
  416. // DomainOrgTreeAttrVals[ 7 ].attrTyp = ATT_TRUST_AUTH_INCOMING;
  417. // DomainOrgTreeAttrVals[ 8 ].attrTyp = ATT_TRUST_AUTH_OUTGOING;
  418. // Items = 9;
  419. Items = 7;
  420. break;
  421. case TrustedDomainFullInformation2Internal:
  422. DomainOrgTreeAttrVals[ 0 ].attrTyp = ATT_TRUST_PARTNER;
  423. DomainOrgTreeAttrVals[ 1 ].attrTyp = ATT_FLAT_NAME;
  424. DomainOrgTreeAttrVals[ 2 ].attrTyp = ATT_SECURITY_IDENTIFIER;
  425. DomainOrgTreeAttrVals[ 3 ].attrTyp = ATT_TRUST_DIRECTION;
  426. DomainOrgTreeAttrVals[ 4 ].attrTyp = ATT_TRUST_TYPE;
  427. DomainOrgTreeAttrVals[ 5 ].attrTyp = ATT_TRUST_ATTRIBUTES;
  428. DomainOrgTreeAttrVals[ 6 ].attrTyp = ATT_TRUST_POSIX_OFFSET;
  429. DomainOrgTreeAttrVals[ 7 ].attrTyp = ATT_MS_DS_TRUST_FOREST_TRUST_INFO;
  430. Items = 8;
  431. // No caller currently needs auth information.
  432. // DomainOrgTreeAttrVals[ 8 ].attrTyp = ATT_TRUST_AUTH_INCOMING;
  433. // DomainOrgTreeAttrVals[ 9 ].attrTyp = ATT_TRUST_AUTH_OUTGOING;
  434. // Items = 10;
  435. break;
  436. default:
  437. Status = STATUS_INVALID_PARAMETER;
  438. break;
  439. }
  440. //
  441. // Now, read all of the attributes we care about
  442. //
  443. if ( NT_SUCCESS( Status ) ) {
  444. ReadBlock.attrCount = Items;
  445. ReadBlock.pAttr = DomainOrgTreeAttrVals;
  446. Status = LsapDsReadByDsName( ObjectPath,
  447. ReadOptions,
  448. &ReadBlock,
  449. &ReturnedBlock );
  450. //
  451. // If that succeeded, then return the proper information
  452. //
  453. if ( NT_SUCCESS( Status ) ) {
  454. if ( Items != ReturnedBlock.attrCount ) {
  455. LsapDsDebugOut(( DEB_WARN,
  456. "LsapDsGetTrustedDomainInfoEx: Expected %lu attributes, got %lu\n",
  457. Items,
  458. ReturnedBlock.attrCount ));
  459. }
  460. for ( i = 0; i < ReturnedBlock.attrCount && NT_SUCCESS( Status ); i++) {
  461. switch ( ReturnedBlock.pAttr[i].attrTyp ) {
  462. case ATT_TRUST_PARTNER:
  463. Name.Buffer = MIDL_user_allocate(
  464. ReturnedBlock.pAttr[i].AttrVal.pAVal->valLen + sizeof( WCHAR ) );
  465. if ( Name.Buffer == NULL ) {
  466. Status = STATUS_INSUFFICIENT_RESOURCES;
  467. } else {
  468. RtlZeroMemory( Name.Buffer,
  469. ReturnedBlock.pAttr[i].AttrVal.pAVal->valLen + sizeof(WCHAR) );
  470. RtlCopyMemory( Name.Buffer,
  471. ReturnedBlock.pAttr[i].AttrVal.pAVal->pVal,
  472. ReturnedBlock.pAttr[i].AttrVal.pAVal->valLen );
  473. Name.Length = (USHORT)ReturnedBlock.pAttr[i].AttrVal.pAVal->valLen;
  474. Name.MaximumLength = Name.Length + sizeof( WCHAR );
  475. }
  476. break;
  477. case ATT_FLAT_NAME:
  478. FlatName.Buffer = MIDL_user_allocate(
  479. ReturnedBlock.pAttr[i].AttrVal.pAVal->valLen + sizeof( WCHAR ) );
  480. if ( FlatName.Buffer == NULL ) {
  481. Status = STATUS_INSUFFICIENT_RESOURCES;
  482. } else {
  483. RtlZeroMemory( FlatName.Buffer,
  484. ReturnedBlock.pAttr[i].AttrVal.pAVal->valLen + sizeof(WCHAR) );
  485. RtlCopyMemory( FlatName.Buffer,
  486. ReturnedBlock.pAttr[i].AttrVal.pAVal->pVal,
  487. ReturnedBlock.pAttr[i].AttrVal.pAVal->valLen );
  488. FlatName.Length = (USHORT)ReturnedBlock.pAttr[i].AttrVal.pAVal->valLen;
  489. FlatName.MaximumLength = FlatName.Length + sizeof( WCHAR );
  490. }
  491. break;
  492. case ATT_SECURITY_IDENTIFIER:
  493. Sid = MIDL_user_allocate( ReturnedBlock.pAttr[i].AttrVal.pAVal->valLen );
  494. if ( Sid == NULL ) {
  495. Status = STATUS_INSUFFICIENT_RESOURCES;
  496. } else {
  497. RtlCopyMemory( Sid, ReturnedBlock.pAttr[i].AttrVal.pAVal->pVal,
  498. ReturnedBlock.pAttr[i].AttrVal.pAVal->valLen );
  499. ASSERT( RtlValidSid( Sid ) );
  500. }
  501. break;
  502. case ATT_TRUST_DIRECTION:
  503. Direction = LSAP_DS_GET_DS_ATTRIBUTE_AS_ULONG( &ReturnedBlock.pAttr[i] );
  504. break;
  505. case ATT_TRUST_TYPE:
  506. Type = LSAP_DS_GET_DS_ATTRIBUTE_AS_ULONG( &ReturnedBlock.pAttr[i] );
  507. break;
  508. case ATT_TRUST_ATTRIBUTES:
  509. Attributes = LSAP_DS_GET_DS_ATTRIBUTE_AS_ULONG( &ReturnedBlock.pAttr[i] );
  510. break;
  511. case ATT_TRUST_POSIX_OFFSET:
  512. Offset = LSAP_DS_GET_DS_ATTRIBUTE_AS_ULONG( &ReturnedBlock.pAttr[i] );
  513. break;
  514. case ATT_TRUST_AUTH_INCOMING:
  515. Incoming = ReturnedBlock.pAttr[i].AttrVal.pAVal->pVal;
  516. IncomingSize = ReturnedBlock.pAttr[i].AttrVal.pAVal->valLen;
  517. break;
  518. case ATT_TRUST_AUTH_OUTGOING:
  519. Outgoing = ReturnedBlock.pAttr[i].AttrVal.pAVal->pVal;
  520. OutgoingSize = ReturnedBlock.pAttr[i].AttrVal.pAVal->valLen;
  521. break;
  522. case ATT_MS_DS_TRUST_FOREST_TRUST_INFO:
  523. ForestTrustLength = ReturnedBlock.pAttr[i].AttrVal.pAVal->valLen;
  524. if ( ForestTrustLength > 0 ) {
  525. ForestTrustInfo = ( PBYTE )MIDL_user_allocate( ForestTrustLength );
  526. if ( ForestTrustInfo == NULL ) {
  527. Status = STATUS_INSUFFICIENT_RESOURCES;
  528. } else {
  529. RtlCopyMemory(
  530. ForestTrustInfo,
  531. ReturnedBlock.pAttr[i].AttrVal.pAVal->pVal,
  532. ForestTrustLength
  533. );
  534. }
  535. }
  536. break;
  537. default:
  538. Status = STATUS_INVALID_PARAMETER;
  539. break;
  540. }
  541. }
  542. } else if ( Status == STATUS_NOT_FOUND ) {
  543. //
  544. // We map the NOT_FOUND error code to OBJECT_NAME_NOT_FOUND, so we don't end up
  545. // returning an unexpected error code to the outside world
  546. //
  547. if ( !FLAG_ON( ReadOptions, LSAPDS_READ_RETURN_NOT_FOUND ) ) {
  548. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  549. }
  550. }
  551. //
  552. // Now, simply assemble everything, and return it... Also, compute the size while
  553. // we're at it...
  554. //
  555. if ( NT_SUCCESS( Status ) ) {
  556. RetSize = 0;
  557. switch ( InformationClass ) {
  558. case TrustedDomainAuthInformation:
  559. AuthInfo = (PLSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION)TrustedDomainInformation;
  560. RtlZeroMemory( AuthInfo, sizeof( AuthInfo ) );
  561. Status = LsapDsUnmarshalAuthInfoHalf(
  562. NULL,
  563. FALSE,
  564. FALSE,
  565. Incoming,
  566. IncomingSize,
  567. LsapDsAuthHalfFromAuthInfo( AuthInfo, TRUE ) );
  568. if ( NT_SUCCESS( Status ) ) {
  569. Status = LsapDsUnmarshalAuthInfoHalf(
  570. NULL,
  571. FALSE,
  572. FALSE,
  573. Outgoing,
  574. OutgoingSize,
  575. LsapDsAuthHalfFromAuthInfo( AuthInfo, FALSE ) );
  576. if ( !NT_SUCCESS( Status ) ) {
  577. LsapDsFreeUnmarshalAuthInfoHalf( LsapDsAuthHalfFromAuthInfo( AuthInfo, TRUE ) );
  578. }
  579. }
  580. break;
  581. case TrustedDomainInformationBasic:
  582. DomainInfoBasic =
  583. ( PLSAPR_TRUSTED_DOMAIN_INFORMATION_BASIC )TrustedDomainInformation;
  584. RtlZeroMemory( DomainInfoBasic, sizeof( DomainInfoBasic ) );
  585. RetSize += sizeof( PLSAPR_TRUSTED_DOMAIN_INFORMATION_BASIC );
  586. RetSize += FlatName.MaximumLength;
  587. RtlCopyMemory( &DomainInfoBasic->Name, &FlatName, sizeof( UNICODE_STRING ) );
  588. DomainInfoBasic->Sid = Sid;
  589. if ( Sid ) {
  590. RetSize += RtlLengthSid( Sid );
  591. }
  592. break;
  593. case TrustedDomainFullInformation2Internal:
  594. FullInfo2 = ( PLSAPR_TRUSTED_DOMAIN_FULL_INFORMATION2 )TrustedDomainInformation;
  595. RtlZeroMemory( FullInfo2, sizeof( LSAPR_TRUSTED_DOMAIN_FULL_INFORMATION2 ));
  596. RtlCopyMemory( &FullInfo2->Information.Name, &Name, sizeof( UNICODE_STRING ));
  597. RtlCopyMemory( &FullInfo2->Information.FlatName, &FlatName, sizeof( UNICODE_STRING ));
  598. FullInfo2->Information.Sid = Sid;
  599. FullInfo2->Information.TrustType = Type;
  600. FullInfo2->Information.TrustAttributes = Attributes;
  601. FullInfo2->Information.TrustDirection = Direction;
  602. FullInfo2->Information.ForestTrustInfo = ForestTrustInfo;
  603. FullInfo2->Information.ForestTrustLength = ForestTrustLength;
  604. FullInfo2->PosixOffset.Offset = Offset;
  605. RetSize += Name.MaximumLength +
  606. FlatName.MaximumLength +
  607. ( Sid ? RtlLengthSid( Sid ) : 0 ) +
  608. 6 * sizeof( ULONG ) +
  609. ForestTrustLength;
  610. break;
  611. case TrustedDomainFullInformation:
  612. FullInfo = ( PLSAPR_TRUSTED_DOMAIN_FULL_INFORMATION )TrustedDomainInformation;
  613. RtlZeroMemory( FullInfo, sizeof(FullInfo) );
  614. FullInfo->PosixOffset.Offset = Offset;
  615. RetSize += sizeof(ULONG);
  616. /* Drop through */
  617. case TrustedDomainInformationEx:
  618. DomainInfoEx = ( PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX )TrustedDomainInformation;
  619. RtlZeroMemory( DomainInfoEx, sizeof( DomainInfoEx ) );
  620. RetSize += sizeof( PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX );
  621. RetSize += Name.MaximumLength;
  622. RtlCopyMemory( &DomainInfoEx->Name, &Name, sizeof( UNICODE_STRING ) );
  623. RetSize += FlatName.MaximumLength;
  624. RtlCopyMemory( &DomainInfoEx->FlatName, &FlatName, sizeof( UNICODE_STRING ) );
  625. DomainInfoEx->Sid = Sid;
  626. if ( Sid ) {
  627. RetSize += RtlLengthSid( Sid );
  628. }
  629. DomainInfoEx->TrustType = Type;
  630. DomainInfoEx->TrustAttributes = Attributes;
  631. DomainInfoEx->TrustDirection = Direction;
  632. RetSize += 3 * sizeof( ULONG );
  633. break;
  634. }
  635. }
  636. }
  637. if ( !NT_SUCCESS( Status ) ) {
  638. MIDL_user_free( ForestTrustInfo );
  639. MIDL_user_free( Name.Buffer );
  640. MIDL_user_free( Sid );
  641. } else if ( Size != NULL ) {
  642. *Size = RetSize;
  643. }
  644. LsapExitFunc( "LsapDsGetTrustedDomainInfoEx", Status );
  645. return( Status );
  646. }
  647. NTSTATUS
  648. LsapDsUnMarshalAuthInfoForReturn(
  649. IN ULONG Items,
  650. IN OPTIONAL PBYTE Buffer,
  651. IN ULONG Length,
  652. OUT PLSAPR_AUTH_INFORMATION *RetAuthInfo
  653. )
  654. /*++
  655. Routine Description:
  656. This function will unmarshal an authinfo list
  657. Arguments:
  658. Infos - Number of authinfos in Buffer
  659. Buffer - Buffer to unmarshal from.
  660. Length - Length (in bytes) of Buffer.
  661. RetAuthInfo - AuthenticationInformation to fill in.
  662. Free by calling LsapDsFreeUnmarshaledAuthInfo then MIDL_user_free.
  663. Returns:
  664. STATUS_SUCCESS -- Success
  665. STATUS_INSUFFICIENT_RESOURCES -- A memory allocation failed
  666. STATUS_INTERNAL_DB_CORRUPTION -- Buffer is corrupt
  667. --*/
  668. {
  669. NTSTATUS Status = STATUS_SUCCESS;
  670. ULONG i;
  671. ULONG ArraySize;
  672. PLSAPR_AUTH_INFORMATION AuthInfo;
  673. PBYTE BufferEnd = Buffer + Length;
  674. LsapEnterFunc( "LsapDsUnMarshalAuthInfoForReturn" );
  675. //
  676. // If there is no input auth info,
  677. // we're done.
  678. //
  679. *RetAuthInfo = NULL;
  680. if ( Buffer == NULL || Length == 0 ) {
  681. Status = STATUS_SUCCESS;
  682. goto Cleanup;
  683. }
  684. //
  685. // Determine the size of the authinfo array.
  686. //
  687. if ( Items > 0xFFFFFFFF/sizeof(LSAPR_AUTH_INFORMATION) ) {
  688. Status = STATUS_INTERNAL_DB_CORRUPTION;
  689. LsapExitFunc( "LsapDsUnMarshalAuthInfoForReturn", Status );
  690. return Status;
  691. }
  692. ArraySize = Items * sizeof(LSAPR_AUTH_INFORMATION);
  693. //
  694. // Allocate a buffer for the authinfo array.
  695. //
  696. *RetAuthInfo = MIDL_user_allocate( ArraySize );
  697. if ( *RetAuthInfo == NULL ) {
  698. Status = STATUS_INSUFFICIENT_RESOURCES;
  699. goto Cleanup;
  700. }
  701. AuthInfo = *RetAuthInfo;
  702. RtlZeroMemory( AuthInfo, ArraySize );
  703. //
  704. // Copy each authinfo
  705. //
  706. for (i = 0; i < Items ; i++ ) {
  707. if ( Buffer+sizeof(LARGE_INTEGER)+sizeof(ULONG)+sizeof(ULONG) > BufferEnd ) {
  708. Status = STATUS_INTERNAL_DB_CORRUPTION;
  709. goto Cleanup;
  710. }
  711. RtlCopyMemory( &(AuthInfo[ i ].LastUpdateTime), Buffer, sizeof( LARGE_INTEGER ) );
  712. Buffer += sizeof( LARGE_INTEGER );
  713. AuthInfo[ i ].AuthType = *(PULONG)Buffer;
  714. Buffer += sizeof ( ULONG );
  715. AuthInfo[i].AuthInfoLength = *(PULONG)Buffer;
  716. Buffer += sizeof ( ULONG );
  717. if ( AuthInfo[ i ]. AuthInfoLength == 0 ) {
  718. AuthInfo[i].AuthInfo = NULL;
  719. } else {
  720. if ( AuthInfo[ i ].AuthInfoLength > Length ||
  721. Buffer + AuthInfo[ i ].AuthInfoLength > BufferEnd ) {
  722. Status = STATUS_INTERNAL_DB_CORRUPTION;
  723. goto Cleanup;
  724. }
  725. AuthInfo[i].AuthInfo = MIDL_user_allocate( AuthInfo[i].AuthInfoLength );
  726. if ( AuthInfo[ i ].AuthInfo == NULL ) {
  727. Status = STATUS_INSUFFICIENT_RESOURCES;
  728. goto Cleanup;
  729. }
  730. RtlCopyMemory( AuthInfo[ i ].AuthInfo, Buffer, AuthInfo[i].AuthInfoLength );
  731. Buffer += ROUND_UP_COUNT(AuthInfo[ i ].AuthInfoLength,
  732. ALIGN_DWORD);
  733. }
  734. }
  735. Status = STATUS_SUCCESS;
  736. Cleanup:
  737. if ( !NT_SUCCESS(Status) ) {
  738. if ( *RetAuthInfo != NULL ) {
  739. LsapDsFreeUnmarshaledAuthInfo( Items, *RetAuthInfo );
  740. MIDL_user_free( *RetAuthInfo );
  741. *RetAuthInfo = NULL;
  742. }
  743. }
  744. LsapExitFunc( "LsapDsUnMarshalAuthInfoForReturn", Status );
  745. return( Status );
  746. }
  747. NTSTATUS
  748. LsapDsBuildAuthInfoFromAttribute(
  749. IN LSAPR_HANDLE Handle,
  750. IN PBYTE Buffer,
  751. IN ULONG Len,
  752. OUT PLSAPR_TRUST_DOMAIN_AUTH_INFO_HALF NewAuthInfo
  753. )
  754. /*++
  755. Routine Description:
  756. This function builds an authentication information structure from a marshaled blob
  757. Arguments:
  758. Handle - Handle to the trusted domain object which holds this information
  759. Incoming - Building incoming or outgoing authinfo
  760. Buffer - Marshaled buffer
  761. Len - Length of the buffer
  762. NewAuthInfo - AuthenticationInformation structure to fill in
  763. Free this buffer by calling LsapDsFreeUnmarshalAuthInfoHalf or by letting
  764. the RPC server side stub free it.
  765. Returns:
  766. STATUS_SUCCESS - Success
  767. STATUS_INSUFFICIENT_RESOURCES - A memory allocation failed.
  768. --*/
  769. {
  770. NTSTATUS Status = STATUS_SUCCESS;
  771. ULONG Items = 0;
  772. PBYTE Current, Prev;
  773. PLSAPR_AUTH_INFORMATION CurrentAuth = NULL;
  774. PLSAPR_AUTH_INFORMATION PrevAuth = NULL;
  775. LsapEnterFunc( "LsapDsBuildAuthInfoFromAttribute" );
  776. if ( Buffer == NULL || ( Len == sizeof(ULONG) && *Buffer == 0 ) ) {
  777. NewAuthInfo->AuthInfos = 0;
  778. NewAuthInfo->AuthenticationInformation = NULL;
  779. NewAuthInfo->PreviousAuthenticationInformation = NULL;
  780. } else {
  781. Status = LsapDsUnmarshalAuthInfoHalf( Handle,
  782. TRUE,
  783. FALSE,
  784. Buffer,
  785. Len,
  786. NewAuthInfo );
  787. }
  788. LsapExitFunc( "LsapDsBuildAuthInfoFromAttribute", Status );
  789. return( Status );
  790. }
  791. NTSTATUS
  792. LsapDsUnmarshalAuthInfoHalf(
  793. IN LSAPR_HANDLE ObjectHandle,
  794. IN BOOLEAN ReturnOnlyFirstAuthInfo,
  795. IN BOOLEAN AllowEmptyPreviousInfo,
  796. IN PBYTE Buffer,
  797. IN ULONG Length,
  798. OUT PLSAPR_TRUST_DOMAIN_AUTH_INFO_HALF AuthInfo
  799. )
  800. /*++
  801. Routine Description:
  802. This function will take a marshaled authinfo structure, decrypt it using the Lsa key,
  803. unmarshal it, and optionally reencrypt it with the session key
  804. Arguments:
  805. ObjectHandle - Handle to the trusted domain object which holds this information
  806. ReturnOnlyFirstAuthInfo - Pass TRUE if only the first element of the auth info
  807. array is to be returned.
  808. AllowEmptyPreviousInfo - Pass TRUE if it is OK to return NULL as the previuos
  809. AuthInfo. Otherwise, the current auth info will be duplicated.
  810. Buffer - Marshaled buffer
  811. Length - Length of the buffer
  812. AuthInfo - Unmarshaled AuthInfo goes here.
  813. Free this buffer by calling LsapDsFreeUnmarshalAuthInfoHalf or by letting
  814. the RPC server side stub free it.
  815. Returns:
  816. STATUS_SUCCESS - Success
  817. --*/
  818. {
  819. NTSTATUS Status;
  820. ULONG Items;
  821. PBYTE Auth, Prev;
  822. ULONG AuthLen, PrevLen;
  823. PBYTE Where;
  824. LsapEnterFunc( "LsapDsUnmarshalAuthInfoHalf" );
  825. //
  826. // Make sure we don't have the plug
  827. //
  828. RtlZeroMemory( AuthInfo, sizeof( LSAPR_TRUST_DOMAIN_AUTH_INFO_HALF ) );
  829. if ( ( Length == 0 || Length == sizeof( ULONG ) ) &&
  830. ( Buffer == NULL || *( PULONG )Buffer == 0 ) ) {
  831. Status = STATUS_SUCCESS;
  832. goto Cleanup;
  833. }
  834. //
  835. // The format of the buffer is:
  836. //
  837. // [Info count][OffsetCurrent][OffsetPrevious] and then some number of the following:
  838. // [UpdateTime(LargeInteger)][AuthType][AuthInfoLen][data (sizeis(AuthInfoLen) ]
  839. //
  840. Where = Buffer;
  841. Items = *(PULONG)Where;
  842. Where += sizeof(ULONG );
  843. if ( (*(PULONG)Where) > Length ) {
  844. Status = STATUS_INTERNAL_DB_CORRUPTION;
  845. goto Cleanup;
  846. }
  847. Auth = Buffer + *(PULONG)Where;
  848. Where += sizeof(ULONG );
  849. if ( (*(PULONG)Where) > Length ) {
  850. Status = STATUS_INTERNAL_DB_CORRUPTION;
  851. goto Cleanup;
  852. }
  853. Prev = Buffer + *(PULONG)Where;
  854. AuthLen = (ULONG)(Prev - Auth);
  855. PrevLen = (ULONG)((Buffer + Length) - Prev);
  856. AuthInfo->AuthInfos = Items;
  857. //
  858. // There is a bug in the idl definition of LSAPR_TRUST_DOMAIN_AUTH_INFO_HALF
  859. // At most, one AuthInfo can be returned. So, for out of process clients,
  860. // don't return more than one.
  861. //
  862. if ( ReturnOnlyFirstAuthInfo &&
  863. ObjectHandle &&
  864. !((LSAP_DB_HANDLE)ObjectHandle)->Trusted &&
  865. AuthInfo->AuthInfos > 1 ) {
  866. AuthInfo->AuthInfos = 1;
  867. }
  868. //
  869. // If we have no previous info, return the current info as previous.
  870. //
  871. if ( !AllowEmptyPreviousInfo && PrevLen == 0 && AuthLen > 0 ) {
  872. PrevLen = AuthLen;
  873. Prev = Auth;
  874. if ( ObjectHandle ) {
  875. LsapDsDebugOut(( DEB_ERROR,
  876. "No PREVIOUS auth info. Returning current for %wZ\n",
  877. &( ( LSAP_DB_HANDLE )ObjectHandle )->PhysicalNameDs ));
  878. }
  879. }
  880. //
  881. // Do the actual unmarshalling
  882. //
  883. Status = LsapDsUnMarshalAuthInfoForReturn( AuthInfo->AuthInfos,
  884. Auth,
  885. AuthLen,
  886. &AuthInfo->AuthenticationInformation );
  887. if ( NT_SUCCESS( Status ) ) {
  888. Status = LsapDsUnMarshalAuthInfoForReturn(
  889. AuthInfo->AuthInfos,
  890. Prev,
  891. PrevLen,
  892. &AuthInfo->PreviousAuthenticationInformation );
  893. }
  894. //
  895. // If something failed, clean up after ourselves
  896. //
  897. Cleanup:
  898. if ( !NT_SUCCESS( Status ) ) {
  899. LsapDsFreeUnmarshalAuthInfoHalf( AuthInfo );
  900. AuthInfo->AuthInfos = 0;
  901. AuthInfo->PreviousAuthenticationInformation = NULL;
  902. AuthInfo->AuthenticationInformation = NULL;
  903. }
  904. LsapExitFunc( "LsapDsUnmarshalAuthInfoHalf", Status );
  905. return( Status );
  906. }
  907. VOID
  908. LsapDsFreeUnmarshaledAuthInfo(
  909. IN ULONG Items,
  910. IN PLSAPR_AUTH_INFORMATION AuthInfo
  911. )
  912. /*++
  913. Routine Description:
  914. This function will free an authinfo struct allocated during unmarshalling
  915. Arguments:
  916. Items - Number of items in the list
  917. AuthInfo - AuthenticationInformation to free
  918. Returns:
  919. VOID
  920. --*/
  921. {
  922. ULONG i;
  923. if ( AuthInfo != NULL ) {
  924. for ( i = 0; i < Items; i++) {
  925. MIDL_user_free( AuthInfo[ i ].AuthInfo );
  926. }
  927. }
  928. }
  929. NTSTATUS
  930. LsapDsBuildAuthInfoAttribute(
  931. IN LSAPR_HANDLE Handle,
  932. IN PLSAPR_TRUST_DOMAIN_AUTH_INFO_HALF NewAuthInfo,
  933. IN PLSAPR_TRUST_DOMAIN_AUTH_INFO_HALF PreviousAuthInfo,
  934. OUT PBYTE *Buffer,
  935. OUT PULONG Len
  936. )
  937. /*++
  938. Routine Description:
  939. This function will take an AuthInfo, merge it with the old AuthInfo, convert it into
  940. a writable blob
  941. Arguments:
  942. Handle - Handle to open trusted domain object
  943. NewAuthInfo - AuthInfo to set on the object
  944. PreviousAuthInfo - AuthInfo that currently exists on the object
  945. Buffer - Where to return the allocated buffer
  946. Len - Where to return the buffer length
  947. Returns:
  948. STATUS_SUCCESS - Success
  949. STATUS_UNSUCCESSFUL - Client coming in is trusted.
  950. STATUS_INSUFFICIENT_RESOURCES - A memory allocation failed.
  951. --*/
  952. {
  953. NTSTATUS Status;
  954. PLSAP_CR_CIPHER_VALUE Encrypted;
  955. PLSAPR_AUTH_INFORMATION Prev = NULL;
  956. LSAPR_TRUST_DOMAIN_AUTH_INFO_HALF SetAuthHalf;
  957. ULONG i,j;
  958. LsapEnterFunc( "LsapDsBuildAuthInfoAttribute" );
  959. if ( NewAuthInfo == NULL ) {
  960. *Buffer = NULL;
  961. *Len = 0;
  962. Status = STATUS_SUCCESS;
  963. LsapExitFunc( "LsapDsBuildAuthInfoAttribute", Status );
  964. return Status;
  965. }
  966. //
  967. // Always use the new authentication info passed by the caller
  968. //
  969. SetAuthHalf.AuthInfos = NewAuthInfo->AuthInfos;
  970. SetAuthHalf.AuthenticationInformation = NewAuthInfo->AuthenticationInformation;
  971. //
  972. // If the caller passed in explicit Previous Authentication info,
  973. // use it.
  974. //
  975. if ( NewAuthInfo->PreviousAuthenticationInformation != NULL ) {
  976. SetAuthHalf.PreviousAuthenticationInformation = NewAuthInfo->PreviousAuthenticationInformation;
  977. //
  978. // Verify that the AuthTypes in this array are in the same order as
  979. // the new auth info.
  980. //
  981. for( i = 0; i < SetAuthHalf.AuthInfos; i++ ) {
  982. if ( ( SetAuthHalf.AuthenticationInformation[i].AuthType !=
  983. SetAuthHalf.PreviousAuthenticationInformation[i].AuthType ) &&
  984. ( SetAuthHalf.PreviousAuthenticationInformation[i].AuthType !=
  985. TRUST_AUTH_TYPE_NONE ) &&
  986. ( SetAuthHalf.AuthenticationInformation[i].AuthType !=
  987. TRUST_AUTH_TYPE_NONE ) ) {
  988. Status = STATUS_INVALID_PARAMETER;
  989. goto Cleanup;
  990. }
  991. }
  992. //
  993. // If the caller didn't pass explicit Previous Authentication info,
  994. // compute it.
  995. } else {
  996. //
  997. // Default the Previous Authentication info to the new authentication info
  998. // explicitly passed by the caller.
  999. //
  1000. // This copy of the Authentication info has all of the AuthTypes in the
  1001. // right order.
  1002. //
  1003. // If none of the current auth info can be merged in,
  1004. // we'll simply end up with the previous auth info equaling the
  1005. // new auth info.
  1006. //
  1007. SetAuthHalf.PreviousAuthenticationInformation = SetAuthHalf.AuthenticationInformation;
  1008. //
  1009. // If there was Auth info on the object before,
  1010. // try to use as much auth info from the object as we can.
  1011. //
  1012. // That is, if the caller just passes a new auth info data,
  1013. // the "current" auth info data on the object is now the previuos auth info.
  1014. // The only gotcha is that the new auth info data might have totally
  1015. // different AuthTypes. So, we grab only that portion of the current
  1016. // auth info data that matches the AuthTypes from the new auth info.
  1017. //
  1018. if ( PreviousAuthInfo != NULL ) {
  1019. //
  1020. // Allocate a buffer to do the merge into.
  1021. //
  1022. Prev = LsapAllocateLsaHeap( sizeof( LSAPR_AUTH_INFORMATION) * NewAuthInfo->AuthInfos );
  1023. if ( Prev == NULL ) {
  1024. Status = STATUS_INSUFFICIENT_RESOURCES;
  1025. goto Cleanup;
  1026. }
  1027. //
  1028. // Initialize the buffer to simply be a copy of the new auth info.
  1029. //
  1030. RtlCopyMemory( Prev,
  1031. SetAuthHalf.PreviousAuthenticationInformation,
  1032. SetAuthHalf.AuthInfos * sizeof( LSAPR_AUTH_INFORMATION) );
  1033. SetAuthHalf.PreviousAuthenticationInformation = Prev;
  1034. //
  1035. // Loop through each of these entries ...
  1036. //
  1037. for( i = 0; i < SetAuthHalf.AuthInfos; i++ ) {
  1038. //
  1039. // ... finding the corresponding entry in the old list.
  1040. //
  1041. for ( j = 0; j < PreviousAuthInfo->AuthInfos; j++) {
  1042. if ( SetAuthHalf.PreviousAuthenticationInformation[i].AuthType ==
  1043. PreviousAuthInfo->AuthenticationInformation[j].AuthType ) {
  1044. //
  1045. // If the entry used to exist on the object,
  1046. // use that entry rather than the default.
  1047. //
  1048. // Note, we don't need to copy the actual auth data here.
  1049. // We just copy the structure that points to the data.
  1050. //
  1051. SetAuthHalf.PreviousAuthenticationInformation[i] =
  1052. PreviousAuthInfo->AuthenticationInformation[j];
  1053. break;
  1054. }
  1055. }
  1056. }
  1057. }
  1058. }
  1059. //
  1060. // Marshall the resultant auth info.
  1061. //
  1062. Status = LsapDsMarshalAuthInfoHalf( &SetAuthHalf, Len, Buffer );
  1063. //
  1064. // Free any memory we may have allocated
  1065. //
  1066. Cleanup:
  1067. if ( Prev ) {
  1068. LsapFreeLsaHeap( Prev );
  1069. }
  1070. LsapExitFunc( "LsapDsBuildAuthInfoAttribute", Status );
  1071. return( Status );
  1072. }
  1073. NTSTATUS
  1074. LsapDsFindAuthTypeInAuthInfo(
  1075. IN ULONG AuthType,
  1076. IN PLSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION AuthInfo,
  1077. IN BOOLEAN Incoming,
  1078. IN BOOLEAN AddIfNotFound,
  1079. OUT BOOLEAN *Added,
  1080. OUT PULONG AuthTypeIndex
  1081. )
  1082. /*++
  1083. Routine Description:
  1084. This function will find the index of the first auth blob it finds of the given type.
  1085. Optionally, if the entry is not found, a new node can be allocated and added to the lsit
  1086. Arguments:
  1087. AuthType - AuthType to find
  1088. AuthInfo - Auth info to search
  1089. Incoming - Search incoming or outgoing
  1090. AddIfNotFound - If TRUE, the entry is added to the end of the list
  1091. AutyTypeIndex - Where the index is returned
  1092. Returns:
  1093. STATUS_SUCCESS - Success
  1094. STATUS_INSUFFICIENT_RESOURCES - A memory allocation failed.
  1095. STATUS_NOT_FOUND - The object wasn't found
  1096. --*/
  1097. {
  1098. NTSTATUS Status = STATUS_SUCCESS;
  1099. ULONG Items, Index = 0xFFFFFFFF, i;
  1100. PLSAPR_AUTH_INFORMATION SearchList, SearchPrev;
  1101. PLSAPR_AUTH_INFORMATION Current = NULL, Previous = NULL;
  1102. *Added = FALSE;
  1103. if ( Incoming ) {
  1104. Items = AuthInfo->IncomingAuthInfos;
  1105. SearchList = AuthInfo->IncomingAuthenticationInformation;
  1106. SearchPrev = AuthInfo->IncomingPreviousAuthenticationInformation;
  1107. } else {
  1108. Items = AuthInfo->OutgoingAuthInfos;
  1109. SearchList = AuthInfo->OutgoingAuthenticationInformation;
  1110. SearchPrev = AuthInfo->OutgoingPreviousAuthenticationInformation;
  1111. }
  1112. //
  1113. // Now, find the index of the entry in the auth list
  1114. //
  1115. for ( i = 0; i < Items ; i++ ) {
  1116. if ( SearchList[ i ].AuthType == AuthType) {
  1117. Index = i;
  1118. break;
  1119. }
  1120. }
  1121. if ( Index == 0xFFFFFFFF ) {
  1122. if ( !AddIfNotFound ) {
  1123. Status = STATUS_NOT_FOUND;
  1124. } else {
  1125. //
  1126. // We'll have to add it, since it doesn't currently exist.
  1127. //
  1128. Current = LsapAllocateLsaHeap( sizeof( LSAPR_AUTH_INFORMATION ) * ( Items + 1 ) );
  1129. if ( Current != NULL ) {
  1130. Previous = LsapAllocateLsaHeap( sizeof( LSAPR_AUTH_INFORMATION ) * ( Items + 1 ) );
  1131. }
  1132. if ( Current == NULL || Previous == NULL ) {
  1133. Status = STATUS_INSUFFICIENT_RESOURCES;
  1134. } else {
  1135. Index = Items;
  1136. RtlCopyMemory( Current, SearchList,
  1137. sizeof( LSAPR_AUTH_INFORMATION ) * Items );
  1138. if ( SearchPrev ) {
  1139. RtlCopyMemory( Previous, SearchPrev,
  1140. sizeof( LSAPR_AUTH_INFORMATION ) * Items );
  1141. }
  1142. Items++;
  1143. *Added = TRUE;
  1144. }
  1145. if ( Incoming ) {
  1146. AuthInfo->IncomingAuthInfos = Items;
  1147. AuthInfo->IncomingAuthenticationInformation = Current;
  1148. AuthInfo->IncomingPreviousAuthenticationInformation = Previous;
  1149. } else {
  1150. AuthInfo->OutgoingAuthInfos = Items;
  1151. AuthInfo->OutgoingAuthenticationInformation = Current;
  1152. AuthInfo->OutgoingPreviousAuthenticationInformation = Previous;
  1153. }
  1154. }
  1155. }
  1156. if ( NT_SUCCESS( Status ) ) {
  1157. *AuthTypeIndex = Index;
  1158. }
  1159. if ( !*Added ) {
  1160. LsapFreeLsaHeap( Previous );
  1161. LsapFreeLsaHeap( Current );
  1162. }
  1163. return( Status );
  1164. }
  1165. NTSTATUS
  1166. LsapDsSetSecretOnTrustedDomainObject(
  1167. IN LSAP_DB_HANDLE TrustedDomainHandle,
  1168. IN ULONG AuthDataType,
  1169. IN PLSAP_CR_CLEAR_VALUE ClearCurrent,
  1170. IN PLSAP_CR_CLEAR_VALUE ClearOld,
  1171. IN PLARGE_INTEGER CurrentValueSetTime
  1172. )
  1173. /*++
  1174. Routine Description:
  1175. This function perform the equvialent of setting the values on a secret that corresponds
  1176. to a trusted domain object.
  1177. Arguments:
  1178. TrustedDomainHandle - Handle to trusted domain object
  1179. ClearCurrent - New secret value
  1180. ClearOld - Old secret value
  1181. Returns:
  1182. STATUS_SUCCESS - Success
  1183. STATUS_INSUFFICIENT_RESOURCES - A memory allocation failed.
  1184. --*/
  1185. {
  1186. //
  1187. // Use a common routine that supports both incoming and outgoing trust.
  1188. //
  1189. return LsapDsAuthDataOnTrustedDomainObject(
  1190. TrustedDomainHandle,
  1191. FALSE, // Set the outgoing trust
  1192. AuthDataType,
  1193. ClearCurrent,
  1194. ClearOld,
  1195. CurrentValueSetTime );
  1196. }
  1197. NTSTATUS
  1198. LsapDsAuthDataOnTrustedDomainObject(
  1199. IN LSAP_DB_HANDLE TrustedDomainHandle,
  1200. IN BOOLEAN Incoming,
  1201. IN ULONG AuthDataType,
  1202. IN PLSAP_CR_CLEAR_VALUE ClearCurrent,
  1203. IN PLSAP_CR_CLEAR_VALUE ClearOld,
  1204. IN PLARGE_INTEGER CurrentValueSetTime
  1205. )
  1206. /*++
  1207. Routine Description:
  1208. This function perform the equvialent of setting the values on a secret that corresponds
  1209. to a trusted domain object.
  1210. Arguments:
  1211. TrustedDomainHandle - Handle to trusted domain object
  1212. Incoming -- Whether to set the incoming or going data
  1213. AuthDataType -- Type of the auth data being set
  1214. ClearCurrent - New secret value
  1215. ClearOld - Old secret value
  1216. CurrentValueSetTime -- Time of the set.
  1217. Returns:
  1218. STATUS_SUCCESS - Success
  1219. STATUS_INSUFFICIENT_RESOURCES - A memory allocation failed.
  1220. --*/
  1221. {
  1222. NTSTATUS Status = STATUS_SUCCESS;
  1223. LSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION AuthInfo = { 0 };
  1224. ULONG Index, Options = 0;
  1225. PDSNAME DsName;
  1226. BOOLEAN Added = FALSE ;
  1227. BOOLEAN CloseTransaction;
  1228. PLSA_AUTH_INFORMATION NewIncoming = NULL, NewPrevious = NULL;
  1229. LsapEnterFunc( "LsapDsAuthDataOnTrustedDomainObject" );
  1230. if ( AuthDataType != TRUST_AUTH_TYPE_CLEAR && AuthDataType != TRUST_AUTH_TYPE_NT4OWF ) {
  1231. Status = STATUS_INVALID_PARAMETER;
  1232. LsapExitFunc( "LsapDsAuthDataOnTrustedDomainObject", Status );
  1233. return( Status );
  1234. }
  1235. Status = LsapDsInitAllocAsNeededEx( LSAP_DB_DS_OP_TRANSACTION |
  1236. LSAP_DB_READ_ONLY_TRANSACTION,
  1237. TrustedDomainObject,
  1238. &CloseTransaction );
  1239. if ( !NT_SUCCESS( Status ) ) {
  1240. LsapExitFunc( "LsapDsAuthDataOnTrustedDomainObject", Status );
  1241. return( Status );
  1242. }
  1243. Status = LsapAllocAndInitializeDsNameFromUnicode(
  1244. &TrustedDomainHandle->PhysicalNameDs,
  1245. &DsName
  1246. );
  1247. if ( NT_SUCCESS( Status ) ) {
  1248. RtlZeroMemory( &AuthInfo, sizeof( LSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION ) );
  1249. Status = LsapDsGetTrustedDomainInfoEx( DsName,
  1250. LSAPDS_READ_NO_LOCK,
  1251. TrustedDomainAuthInformation,
  1252. (PLSAPR_TRUSTED_DOMAIN_INFO)&AuthInfo,
  1253. NULL );
  1254. if ( NT_SUCCESS( Status ) ||
  1255. Status == STATUS_NOT_FOUND ||
  1256. Status == STATUS_OBJECT_NAME_NOT_FOUND ) {
  1257. BOOLEAN MustFreeClearOld = FALSE;
  1258. //
  1259. // Now, find the index of the CLEAR entry in the correct auth list
  1260. //
  1261. Status = LsapDsFindAuthTypeInAuthInfo( AuthDataType,
  1262. &AuthInfo,
  1263. Incoming,
  1264. TRUE,
  1265. &Added,
  1266. &Index );
  1267. if ( NT_SUCCESS( Status ) ) {
  1268. if ( ClearCurrent == NULL ) {
  1269. if ( Incoming ) {
  1270. RtlZeroMemory( &AuthInfo.IncomingAuthenticationInformation[ Index ],
  1271. sizeof( LSAPR_AUTH_INFORMATION ) );
  1272. } else {
  1273. RtlZeroMemory( &AuthInfo.OutgoingAuthenticationInformation[ Index ],
  1274. sizeof( LSAPR_AUTH_INFORMATION ) );
  1275. }
  1276. } else {
  1277. LSAPDS_SET_AUTH_INFO(
  1278. Incoming ?
  1279. &AuthInfo.IncomingAuthenticationInformation[ Index ] :
  1280. &AuthInfo.OutgoingAuthenticationInformation[ Index ],
  1281. CurrentValueSetTime,
  1282. AuthDataType,
  1283. ClearCurrent->Length,
  1284. ClearCurrent->Buffer );
  1285. }
  1286. //
  1287. // LsaDbSetSecret expects the old password
  1288. // to be set to the previous current password
  1289. //
  1290. if ( ClearOld == NULL ) {
  1291. BOOLEAN SavedTrusted;
  1292. //
  1293. // We may not have access, so go as trusted.
  1294. // Password comes back in the clear.
  1295. //
  1296. SavedTrusted = TrustedDomainHandle->Trusted;
  1297. TrustedDomainHandle->Trusted = TRUE;
  1298. Status = LsarQuerySecret(
  1299. TrustedDomainHandle,
  1300. &(PLSAPR_CR_CIPHER_VALUE)ClearOld,
  1301. NULL,
  1302. NULL,
  1303. NULL);
  1304. TrustedDomainHandle->Trusted = SavedTrusted;
  1305. if ( !NT_SUCCESS( Status ) && ClearOld) {
  1306. LsapCrFreeMemoryValue( ClearOld );
  1307. ClearOld = NULL;
  1308. } else {
  1309. MustFreeClearOld = TRUE;
  1310. }
  1311. Status = STATUS_SUCCESS;
  1312. //
  1313. // Failure to obtain old value should not stop us, as the worst
  1314. // thing that could happen is it won't be set, and that's not fatal
  1315. //
  1316. }
  1317. if ( ClearOld == NULL ) {
  1318. if ( Incoming ) {
  1319. RtlZeroMemory( &AuthInfo.IncomingPreviousAuthenticationInformation[ Index ],
  1320. sizeof( LSAPR_AUTH_INFORMATION ) );
  1321. } else {
  1322. RtlZeroMemory( &AuthInfo.OutgoingPreviousAuthenticationInformation[ Index ],
  1323. sizeof( LSAPR_AUTH_INFORMATION ) );
  1324. }
  1325. } else {
  1326. LSAPDS_SET_AUTH_INFO(
  1327. Incoming ?
  1328. &AuthInfo.IncomingPreviousAuthenticationInformation[ Index ] :
  1329. &AuthInfo.OutgoingPreviousAuthenticationInformation[ Index ],
  1330. CurrentValueSetTime,
  1331. AuthDataType,
  1332. ClearOld->Length,
  1333. ClearOld->Buffer );
  1334. }
  1335. }
  1336. //
  1337. // Finally, set it
  1338. //
  1339. if ( NT_SUCCESS (Status ) ) {
  1340. //
  1341. // Since we already have the db locked, we'll fool the set routine into
  1342. // thinking we're a trusted client and have therefore locked the database
  1343. //
  1344. if ( !Incoming ) {
  1345. Options = TrustedDomainHandle->Options;
  1346. TrustedDomainHandle->Options |= LSAP_DB_DS_TRUSTED_DOMAIN_AS_SECRET;
  1347. }
  1348. Status = LsarSetInformationTrustedDomain( TrustedDomainHandle,
  1349. TrustedDomainAuthInformation,
  1350. (PLSAPR_TRUSTED_DOMAIN_INFO)&AuthInfo );
  1351. if ( !Incoming ) {
  1352. TrustedDomainHandle->Options = Options;
  1353. }
  1354. }
  1355. if ( MustFreeClearOld ) {
  1356. LsapCrFreeMemoryValue( ClearOld );
  1357. ClearOld = NULL;
  1358. }
  1359. }
  1360. LsapDsFree( DsName );
  1361. }
  1362. if ( Added ) {
  1363. if ( Incoming ) {
  1364. LsapFreeLsaHeap( AuthInfo.IncomingAuthenticationInformation );
  1365. LsapFreeLsaHeap( AuthInfo.IncomingPreviousAuthenticationInformation );
  1366. } else {
  1367. LsapFreeLsaHeap( AuthInfo.OutgoingAuthenticationInformation );
  1368. LsapFreeLsaHeap( AuthInfo.OutgoingPreviousAuthenticationInformation );
  1369. }
  1370. }
  1371. //
  1372. // Destruction of the thread state will delete any allocated Ds memory
  1373. //
  1374. LsapDsDeleteAllocAsNeededEx( LSAP_DB_DS_OP_TRANSACTION |
  1375. LSAP_DB_READ_ONLY_TRANSACTION,
  1376. TrustedDomainObject,
  1377. CloseTransaction );
  1378. LsapExitFunc( "LsapDsAuthDataOnTrustedDomainObject", Status );
  1379. return( Status );
  1380. }
  1381. NTSTATUS
  1382. LsapDsGetSecretOnTrustedDomainObject(
  1383. IN LSAP_DB_HANDLE TrustedDomainHandle,
  1384. IN OPTIONAL PLSAP_CR_CIPHER_KEY SessionKey,
  1385. OUT OPTIONAL PLSAP_CR_CIPHER_VALUE *CipherCurrent,
  1386. OUT OPTIONAL PLSAP_CR_CIPHER_VALUE *CipherOld,
  1387. OUT OPTIONAL PLARGE_INTEGER CurrentValueSetTime,
  1388. OUT OPTIONAL PLARGE_INTEGER OldValueSetTime
  1389. )
  1390. /*++
  1391. Routine Description:
  1392. This function perform the equvialent of getting the values on a secret that corresponds
  1393. to a trusted domain object.
  1394. Arguments:
  1395. TrustedDomainHandle - Handle to trusted domain object
  1396. SessionKey - Optional SessionKey to use for encrypting the values
  1397. CipherCurrent - Where to return the current value
  1398. CipherOld - Where to return previous current value
  1399. CurrValueSetTime - Where to return the current set time
  1400. OldValueSetTime - Where to return the old set time
  1401. Returns:
  1402. STATUS_SUCCESS - Success
  1403. STATUS_INSUFFICIENT_RESOURCES - A memory allocation failed.
  1404. STATUS_NOT_FOUND - No such auth data exists
  1405. STATUS_INVALID_PARAMETER - No information was requested
  1406. --*/
  1407. {
  1408. NTSTATUS Status = STATUS_SUCCESS;
  1409. LSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION AuthInfo;
  1410. ULONG Index;
  1411. PDSNAME DsName;
  1412. BOOLEAN Added;
  1413. BOOLEAN CloseTransaction;
  1414. LSAP_CR_CLEAR_VALUE ClearValue;
  1415. if ( !ARGUMENT_PRESENT( CipherCurrent ) && !ARGUMENT_PRESENT( CipherOld ) &&
  1416. !ARGUMENT_PRESENT( CurrentValueSetTime) && !ARGUMENT_PRESENT( OldValueSetTime ) ) {
  1417. return( STATUS_INVALID_PARAMETER );
  1418. }
  1419. LsapEnterFunc( "LsapDsGetSecretOnTrustedDomainObject" );
  1420. //
  1421. // See if we already have a transaction going
  1422. //
  1423. Status = LsapDsInitAllocAsNeededEx( LSAP_DB_DS_OP_TRANSACTION |
  1424. LSAP_DB_READ_ONLY_TRANSACTION,
  1425. TrustedDomainObject,
  1426. &CloseTransaction );
  1427. if ( !NT_SUCCESS( Status ) ) {
  1428. LsapExitFunc( "LsapDsGetSecretOnTrustedDomainObject", Status );
  1429. return( Status );
  1430. }
  1431. Status = LsapAllocAndInitializeDsNameFromUnicode(
  1432. &TrustedDomainHandle->PhysicalNameDs,
  1433. &DsName
  1434. );
  1435. if ( NT_SUCCESS( Status ) ) {
  1436. Status = LsapDsGetTrustedDomainInfoEx( DsName,
  1437. LSAPDS_READ_RETURN_NOT_FOUND,
  1438. TrustedDomainAuthInformation,
  1439. (PLSAPR_TRUSTED_DOMAIN_INFO)&AuthInfo,
  1440. NULL );
  1441. if ( NT_SUCCESS( Status ) ) {
  1442. //
  1443. // Now, find the index of the CLEAR entry in the outgoing auth list
  1444. //
  1445. Status = LsapDsFindAuthTypeInAuthInfo( TRUST_AUTH_TYPE_CLEAR,
  1446. &AuthInfo,
  1447. FALSE,
  1448. FALSE,
  1449. &Added,
  1450. &Index );
  1451. if ( NT_SUCCESS( Status ) ) {
  1452. if ( ARGUMENT_PRESENT( CipherCurrent ) ) {
  1453. ClearValue.Length =
  1454. AuthInfo.OutgoingAuthenticationInformation[ Index ].AuthInfoLength;
  1455. ClearValue.MaximumLength = ClearValue.Length;
  1456. ClearValue.Buffer = AuthInfo.OutgoingAuthenticationInformation[ Index ].AuthInfo;
  1457. if ( !LsapValidateLsaCipherValue( &ClearValue ) ) {
  1458. Status = STATUS_INVALID_PARAMETER;
  1459. } else if ( SessionKey != NULL ) {
  1460. Status = LsapCrEncryptValue ( &ClearValue, SessionKey, CipherCurrent );
  1461. } else {
  1462. *CipherCurrent = MIDL_user_allocate( sizeof( LSAP_CR_CIPHER_VALUE ) +
  1463. ClearValue.Length );
  1464. if ( *CipherCurrent == NULL ) {
  1465. Status = STATUS_INSUFFICIENT_RESOURCES;
  1466. } else {
  1467. (*CipherCurrent)->Length = ClearValue.Length;
  1468. (*CipherCurrent)->MaximumLength = ClearValue.Length;
  1469. (*CipherCurrent)->Buffer = (PBYTE)(*CipherCurrent) +
  1470. sizeof( LSAP_CR_CIPHER_VALUE );
  1471. RtlCopyMemory( (*CipherCurrent)->Buffer,
  1472. ClearValue.Buffer,
  1473. ClearValue.Length );
  1474. }
  1475. }
  1476. }
  1477. if ( NT_SUCCESS( Status ) &&
  1478. ARGUMENT_PRESENT( CipherOld ) ) {
  1479. ClearValue.Length =
  1480. AuthInfo.OutgoingPreviousAuthenticationInformation[ Index ].AuthInfoLength;
  1481. ClearValue.MaximumLength = ClearValue.Length;
  1482. ClearValue.Buffer =
  1483. AuthInfo.OutgoingPreviousAuthenticationInformation[ Index ].AuthInfo;
  1484. if ( !LsapValidateLsaCipherValue( &ClearValue ) ) {
  1485. Status = STATUS_INVALID_PARAMETER;
  1486. } else if ( SessionKey != NULL ) {
  1487. Status = LsapCrEncryptValue ( &ClearValue, SessionKey, CipherOld );
  1488. } else {
  1489. *CipherOld = MIDL_user_allocate( sizeof( LSAP_CR_CIPHER_VALUE ) +
  1490. ClearValue.Length );
  1491. if ( *CipherOld == NULL ) {
  1492. Status = STATUS_INSUFFICIENT_RESOURCES;
  1493. } else {
  1494. (*CipherOld)->Length = ClearValue.Length;
  1495. (*CipherOld)->MaximumLength = ClearValue.Length;
  1496. (*CipherOld)->Buffer = (PBYTE)(*CipherOld) +
  1497. sizeof( LSAP_CR_CIPHER_VALUE );
  1498. RtlCopyMemory( (*CipherOld)->Buffer,
  1499. ClearValue.Buffer,
  1500. ClearValue.Length );
  1501. }
  1502. }
  1503. if ( !NT_SUCCESS( Status ) && ARGUMENT_PRESENT( CipherCurrent ) ) {
  1504. LsapCrFreeMemoryValue( CipherCurrent );
  1505. }
  1506. }
  1507. if ( NT_SUCCESS( Status ) && ARGUMENT_PRESENT( CurrentValueSetTime ) ) {
  1508. RtlCopyMemory( CurrentValueSetTime,
  1509. &AuthInfo.OutgoingAuthenticationInformation[ Index ].
  1510. LastUpdateTime,
  1511. sizeof( LARGE_INTEGER ) );
  1512. }
  1513. if ( NT_SUCCESS( Status ) &&
  1514. ARGUMENT_PRESENT( OldValueSetTime ) ) {
  1515. RtlCopyMemory( OldValueSetTime,
  1516. &AuthInfo.OutgoingPreviousAuthenticationInformation[ Index ].
  1517. LastUpdateTime,
  1518. sizeof( LARGE_INTEGER ) );
  1519. }
  1520. }
  1521. LsapDsFreeUnmarshalAuthInfoHalf( LsapDsAuthHalfFromAuthInfo( &AuthInfo, TRUE ) );
  1522. LsapDsFreeUnmarshalAuthInfoHalf( LsapDsAuthHalfFromAuthInfo( &AuthInfo, FALSE ) );
  1523. }
  1524. if ( Status == STATUS_NOT_FOUND ) {
  1525. if ( ARGUMENT_PRESENT( CipherCurrent ) ) {
  1526. *CipherCurrent = NULL;
  1527. }
  1528. if ( ARGUMENT_PRESENT( CipherOld ) ) {
  1529. *CipherOld = NULL;
  1530. }
  1531. if ( ARGUMENT_PRESENT( CurrentValueSetTime ) ) {
  1532. RtlZeroMemory( CurrentValueSetTime, sizeof( LARGE_INTEGER ) );
  1533. }
  1534. if ( ARGUMENT_PRESENT( OldValueSetTime ) ) {
  1535. RtlZeroMemory( CurrentValueSetTime, sizeof( LARGE_INTEGER ) );
  1536. }
  1537. Status = STATUS_SUCCESS;
  1538. }
  1539. LsapDsFree( DsName );
  1540. }
  1541. //
  1542. // Destruction of the thread state will delete any allocated Ds memory
  1543. //
  1544. LsapDsDeleteAllocAsNeededEx( LSAP_DB_DS_OP_TRANSACTION |
  1545. LSAP_DB_READ_ONLY_TRANSACTION,
  1546. TrustedDomainObject,
  1547. CloseTransaction );
  1548. LsapExitFunc( "LsapDsGetSecretOnTrustedDomainObject", Status );
  1549. return( Status );
  1550. }
  1551. NTSTATUS
  1552. LsapDsEnumerateTrustedDomainsAsSecrets(
  1553. IN OUT PLSAP_DB_NAME_ENUMERATION_BUFFER EnumerationBuffer
  1554. )
  1555. /*++
  1556. Routine Description:
  1557. This function returns a list of trusted domain objects as if they were secret objects
  1558. Arguments:
  1559. EnumerationBuffer - Where the enumerated information is returned
  1560. Returns:
  1561. STATUS_SUCCESS - Success
  1562. STATUS_INSUFFICIENT_RESOURCES - A memory allocation failed.
  1563. --*/
  1564. {
  1565. NTSTATUS Status = STATUS_SUCCESS;
  1566. LSA_ENUMERATION_HANDLE EnumContext = 0;
  1567. LSAPR_TRUSTED_ENUM_BUFFER EnumBuffer;
  1568. PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX TDInfoEx;
  1569. LSAPR_HANDLE TDHandle;
  1570. PUNICODE_STRING Names = NULL;
  1571. PBYTE Buffer;
  1572. ULONG i;
  1573. //
  1574. // Just return if the Ds isn't running
  1575. //
  1576. if (!LsapDsWriteDs ) {
  1577. RtlZeroMemory( EnumerationBuffer, sizeof( LSAP_DB_NAME_ENUMERATION_BUFFER ) );
  1578. return( Status );
  1579. }
  1580. Status = LsarEnumerateTrustedDomains( LsapPolicyHandle,
  1581. &EnumContext,
  1582. &EnumBuffer,
  1583. TENMEG );
  1584. if ( NT_SUCCESS( Status ) ) {
  1585. Names = MIDL_user_allocate( EnumBuffer.EntriesRead * sizeof( UNICODE_STRING ) );
  1586. if( Names == NULL ) {
  1587. Status = STATUS_INSUFFICIENT_RESOURCES;
  1588. } else {
  1589. for ( i = 0; i < EnumBuffer.EntriesRead; i++ ) {
  1590. Status = LsapDbOpenTrustedDomain( LsapPolicyHandle,
  1591. EnumBuffer.Information[ i ].Sid,
  1592. MAXIMUM_ALLOWED,
  1593. &TDHandle,
  1594. LSAP_DB_TRUSTED );
  1595. if ( NT_SUCCESS( Status ) ) {
  1596. Status = LsarQueryInfoTrustedDomain( TDHandle,
  1597. TrustedDomainInformationEx,
  1598. (PLSAPR_TRUSTED_DOMAIN_INFO *)&TDInfoEx );
  1599. LsapCloseHandle( &TDHandle, Status );
  1600. //
  1601. // Allocate a buffer to hold the name. The sizeof below accounts for our
  1602. // terminating NULL
  1603. //
  1604. if ( NT_SUCCESS( Status ) ) {
  1605. if ( FLAG_ON( TDInfoEx->TrustDirection, TRUST_DIRECTION_OUTBOUND ) ) {
  1606. Buffer = MIDL_user_allocate( TDInfoEx->FlatName.Length +
  1607. sizeof( LSAP_DS_TRUSTED_DOMAIN_SECRET_PREFIX ) );
  1608. if ( Buffer == NULL ) {
  1609. Status = STATUS_INSUFFICIENT_RESOURCES;
  1610. LsaIFree_LSAPR_TRUSTED_DOMAIN_INFO( TrustedDomainInformationEx,
  1611. (PLSAPR_TRUSTED_DOMAIN_INFO)TDInfoEx );
  1612. break;
  1613. } else {
  1614. RtlCopyMemory( Buffer, LSAP_DS_TRUSTED_DOMAIN_SECRET_PREFIX,
  1615. sizeof( LSAP_DS_TRUSTED_DOMAIN_SECRET_PREFIX ) );
  1616. RtlCopyMemory( Buffer +
  1617. sizeof( LSAP_DS_TRUSTED_DOMAIN_SECRET_PREFIX ) -
  1618. sizeof(WCHAR),
  1619. TDInfoEx->FlatName.Buffer,
  1620. TDInfoEx->FlatName.Length + sizeof( WCHAR ) );
  1621. RtlInitUnicodeString( &Names[ i ], (PWSTR)Buffer );
  1622. }
  1623. }
  1624. LsaIFree_LSAPR_TRUSTED_DOMAIN_INFO( TrustedDomainInformationEx,
  1625. (PLSAPR_TRUSTED_DOMAIN_INFO)TDInfoEx );
  1626. }
  1627. }
  1628. }
  1629. }
  1630. LsaIFree_LSAPR_TRUSTED_ENUM_BUFFER ( &EnumBuffer );
  1631. EnumerationBuffer->Names = Names;
  1632. EnumerationBuffer->EntriesRead = EnumBuffer.EntriesRead;
  1633. } else if ( Status == STATUS_OBJECT_NAME_NOT_FOUND ) {
  1634. RtlZeroMemory( EnumerationBuffer, sizeof( LSAP_DB_NAME_ENUMERATION_BUFFER ) );
  1635. Status = STATUS_SUCCESS;
  1636. }
  1637. LsapExitFunc( "LsapDsEnumerateTrustedDomainsAsSecrets", Status );
  1638. return( Status );
  1639. }
  1640. BOOLEAN
  1641. LsapDsIsNtStatusResourceError(
  1642. NTSTATUS NtStatus
  1643. )
  1644. {
  1645. switch ( NtStatus )
  1646. {
  1647. case STATUS_NO_MEMORY:
  1648. case STATUS_INSUFFICIENT_RESOURCES:
  1649. case STATUS_DISK_FULL:
  1650. return TRUE;
  1651. default:
  1652. return FALSE;
  1653. }
  1654. }
  1655. NTSTATUS
  1656. LsapDeleteUpgradedTrustedDomain(
  1657. IN HANDLE LsaPolicyHandle,
  1658. IN PSID DomainSid
  1659. )
  1660. /*++
  1661. Routine Description:
  1662. This routine deletes the trusted domain pointed to by DomainSid.
  1663. This routine is only meant to be called during an upgrade from nt4 to nt5
  1664. Arguments:
  1665. LsaPolicyHandle - a valid policy handle
  1666. DomainSid -- domain to delete
  1667. Return Values:
  1668. STATUS_SUCCESS -- Success
  1669. --*/
  1670. {
  1671. NTSTATUS Status = STATUS_SUCCESS;
  1672. LSAPR_HANDLE TDHandle = 0;
  1673. Status = LsapDbOpenTrustedDomain( LsaPolicyHandle,
  1674. DomainSid,
  1675. MAXIMUM_ALLOWED,
  1676. &TDHandle,
  1677. LSAP_DB_TRUSTED );
  1678. if ( NT_SUCCESS( Status ) ) {
  1679. Status = LsapRegOpenTransaction();
  1680. if ( NT_SUCCESS( Status ) ) {
  1681. Status = LsapDbDeleteObject( TDHandle );
  1682. if ( NT_SUCCESS( Status ) ) {
  1683. Status = LsapRegApplyTransaction();
  1684. } else {
  1685. NTSTATUS IgnoreStatus;
  1686. IgnoreStatus = LsapRegAbortTransaction();
  1687. }
  1688. } else {
  1689. LsapDbCloseHandle(TDHandle);
  1690. }
  1691. }
  1692. return Status;
  1693. }
  1694. NTSTATUS
  1695. LsapDsDomainUpgradeRegistryToDs(
  1696. IN BOOLEAN DeleteOnly
  1697. )
  1698. /*++
  1699. Routine Description:
  1700. This routine will move the remaining registry based trusted domains into the Ds
  1701. NOTE: It is assumed that the database is locked before calling this routine
  1702. Arguments:
  1703. DeleteOldValues -- If TRUE, the registry values are deleted following the upgade.
  1704. Return Values:
  1705. STATUS_SUCCESS -- Success
  1706. --*/
  1707. {
  1708. NTSTATUS Status = STATUS_SUCCESS;
  1709. LSA_ENUMERATION_HANDLE EnumContext = 0;
  1710. LSAPR_TRUSTED_ENUM_BUFFER EnumBuffer;
  1711. PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX TDInfoEx = { 0 };
  1712. LSAPR_HANDLE TDHandle;
  1713. BOOLEAN UseDsOld = LsaDsStateInfo.UseDs;
  1714. ULONG i;
  1715. if ( !LsapDsWriteDs
  1716. && !DeleteOnly ) {
  1717. return( STATUS_SUCCESS );
  1718. }
  1719. LsapEnterFunc( "LsapDsDomainUpgradeRegistryToDs" );
  1720. ( ( LSAP_DB_HANDLE )LsapPolicyHandle )->Options |= LSAP_DB_HANDLE_UPGRADE;
  1721. //
  1722. // First, enumerate all of the registry based trusted domains
  1723. //
  1724. while ( NT_SUCCESS( Status ) ) {
  1725. LsaDsStateInfo.UseDs = FALSE;
  1726. LsapDbMakeCacheInvalid( TrustedDomainObject );
  1727. Status = LsarEnumerateTrustedDomains( LsapPolicyHandle,
  1728. &EnumContext,
  1729. &EnumBuffer,
  1730. TENMEG );
  1731. LsaDsStateInfo.UseDs = UseDsOld;
  1732. LsapDbMakeCacheValid( TrustedDomainObject );
  1733. if ( Status == STATUS_SUCCESS || Status == STATUS_MORE_ENTRIES ) {
  1734. for ( i = 0; i < EnumBuffer.EntriesRead && NT_SUCCESS( Status ) ; i++ ) {
  1735. //
  1736. // Get the information from the registry for this sid...
  1737. //
  1738. LsaDsStateInfo.UseDs = FALSE;
  1739. if ( DeleteOnly ) {
  1740. Status = LsapDeleteUpgradedTrustedDomain( LsapPolicyHandle,
  1741. EnumBuffer.Information[ i ].Sid );
  1742. if ( !NT_SUCCESS( Status ) ) {
  1743. LsapDsDebugOut(( DEB_UPGRADE,
  1744. "Failed to delete trust object (0x%x)\n",
  1745. Status ));
  1746. Status = STATUS_SUCCESS;
  1747. }
  1748. LsaDsStateInfo.UseDs = UseDsOld;
  1749. continue;
  1750. }
  1751. Status = LsapDbOpenTrustedDomain( LsapPolicyHandle,
  1752. EnumBuffer.Information[ i ].Sid,
  1753. MAXIMUM_ALLOWED,
  1754. &TDHandle,
  1755. LSAP_DB_TRUSTED );
  1756. if ( NT_SUCCESS( Status ) ) {
  1757. Status = LsarQueryInfoTrustedDomain( TDHandle,
  1758. TrustedDomainInformationEx,
  1759. (PLSAPR_TRUSTED_DOMAIN_INFO *)&TDInfoEx );
  1760. LsapCloseHandle( &TDHandle, Status);
  1761. }
  1762. LsaDsStateInfo.UseDs = UseDsOld;
  1763. //
  1764. // Now, if that worked, write it out to the Ds
  1765. //
  1766. if ( NT_SUCCESS( Status ) ) {
  1767. Status = LsapCreateTrustedDomain2(
  1768. LsapPolicyHandle,
  1769. ( PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX )TDInfoEx,
  1770. NULL,
  1771. MAXIMUM_ALLOWED,
  1772. &TDHandle );
  1773. if ( NT_SUCCESS( Status ) ) {
  1774. LsapCloseHandle( &TDHandle, STATUS_SUCCESS );
  1775. LsapDsDebugOut(( DEB_UPGRADE,
  1776. "Moved trusted domain %wZ to Ds\n",
  1777. &TDInfoEx->Name ));
  1778. }
  1779. if ( Status == STATUS_OBJECT_NAME_COLLISION ) {
  1780. Status = STATUS_SUCCESS;
  1781. }
  1782. LsaIFree_LSAPR_TRUSTED_DOMAIN_INFO( TrustedDomainInformationEx,
  1783. (PLSAPR_TRUSTED_DOMAIN_INFO)TDInfoEx );
  1784. }
  1785. if (!NT_SUCCESS(Status))
  1786. {
  1787. if (!LsapDsIsNtStatusResourceError(Status))
  1788. {
  1789. SpmpReportEventU(
  1790. EVENTLOG_ERROR_TYPE,
  1791. LSA_TRUST_UPGRADE_ERROR,
  1792. 0,
  1793. sizeof( ULONG ),
  1794. &Status,
  1795. 1,
  1796. &EnumBuffer.Information[i].Name
  1797. );
  1798. //
  1799. // Continue on all errors excepting resource errors
  1800. //
  1801. Status = STATUS_SUCCESS;
  1802. }
  1803. else
  1804. {
  1805. //
  1806. // Break out of the loop and terminate the status
  1807. //
  1808. break;
  1809. }
  1810. }
  1811. }
  1812. LsaIFree_LSAPR_TRUSTED_ENUM_BUFFER ( &EnumBuffer );
  1813. }
  1814. }
  1815. if ( Status == STATUS_NO_MORE_ENTRIES ) {
  1816. Status = STATUS_SUCCESS;
  1817. }
  1818. ( ( LSAP_DB_HANDLE )LsapPolicyHandle )->Options &= ~LSAP_DB_HANDLE_UPGRADE;
  1819. LsapExitFunc( "LsapDsDomainUpgradeRegistryToDs", Status );
  1820. return( Status );
  1821. }
  1822. NTSTATUS
  1823. LsapDsCreateSetITAForTrustInfo(
  1824. IN PUNICODE_STRING AccountName,
  1825. IN PTRUSTED_DOMAIN_AUTH_INFORMATION AuthInfo
  1826. )
  1827. /*++
  1828. Routine Description:
  1829. This function creates/sets a SAM interdomain trust account for an NT5 style trust object,
  1830. given the trust information
  1831. Arguments:
  1832. AccountName - Name of the account to create/set
  1833. AuthInfo - AuthInfo for the trust object
  1834. Return Values:
  1835. STATUS_SUCCESS -- Success
  1836. STATUS_UNSUCCESSFUL -- The Sam domain handle has not been opened.
  1837. --*/
  1838. {
  1839. NTSTATUS Status = STATUS_SUCCESS;
  1840. SAM_HANDLE AccountHandle = NULL ;
  1841. ULONG Access, Rid, i;
  1842. USER_ALL_INFORMATION UserAllInfo;
  1843. SAMPR_USER_INTERNAL1_INFORMATION UserInternalInfo1;
  1844. PVOID SamData = NULL;
  1845. ULONG SamInfoLevel = 0;
  1846. BOOLEAN SetPassword = FALSE;
  1847. UNICODE_STRING Account;
  1848. WCHAR AccountNameBuffer[ UNLEN + 2 ];
  1849. LsapEnterFunc( "LsapDsCreateSetITAForTrustInfo" );
  1850. if ( AccountName->Length > UNLEN * sizeof( WCHAR ) ) {
  1851. LsapDsDebugOut(( DEB_ERROR,
  1852. "LsapDsCreateSetITAForTrustInfo: Name too long: %wZ\n",
  1853. AccountName ));
  1854. Status = STATUS_OBJECT_NAME_INVALID;
  1855. LsapExitFunc( "LsapDsCreateSetITAForTrustInfo", Status );
  1856. }
  1857. Status = LsapOpenSam();
  1858. if ( !NT_SUCCESS( Status ) ) {
  1859. LsapDsDebugOut(( DEB_ERROR,
  1860. "LsapDsCreateSetITAForTrustInfo: Sam not opened\n"));
  1861. LsapExitFunc( "LsapDsCreateSetITAForTrustInfo", Status );
  1862. return( Status );
  1863. }
  1864. if ( NT_SUCCESS( Status ) ) {
  1865. //
  1866. // Find the clear password, if it exists
  1867. //
  1868. for ( i = 0; i < AuthInfo->IncomingAuthInfos; i++ ) {
  1869. if ( AuthInfo->IncomingAuthenticationInformation[ i ].AuthType == TRUST_AUTH_TYPE_CLEAR) {
  1870. RtlZeroMemory( &UserAllInfo, sizeof( USER_ALL_INFORMATION ) );
  1871. UserAllInfo.NtPassword.Buffer =
  1872. (PUSHORT)( AuthInfo-> IncomingAuthenticationInformation[ i ].AuthInfo );
  1873. UserAllInfo.NtPassword.Length =
  1874. (USHORT)( AuthInfo-> IncomingAuthenticationInformation[ i ].AuthInfoLength );
  1875. UserAllInfo.NtPassword.MaximumLength = UserAllInfo.NtPassword.Length;
  1876. UserAllInfo.NtPasswordPresent = TRUE;
  1877. UserAllInfo.WhichFields = USER_ALL_NTPASSWORDPRESENT | USER_ALL_USERACCOUNTCONTROL;
  1878. UserAllInfo.UserAccountControl = USER_INTERDOMAIN_TRUST_ACCOUNT | USER_PASSWORD_NOT_REQUIRED;
  1879. SetPassword = TRUE;
  1880. SamData = &UserAllInfo;
  1881. SamInfoLevel = UserAllInformation;
  1882. break;
  1883. }
  1884. }
  1885. //
  1886. // Find the OWF password, if we are supposed to use it,
  1887. // and we haven't already used the cleartext one
  1888. //
  1889. if ( SetPassword == FALSE ) {
  1890. for ( i = 0; i < AuthInfo->IncomingAuthInfos; i++ ) {
  1891. if ( AuthInfo->IncomingAuthenticationInformation[ i ].AuthType == TRUST_AUTH_TYPE_NT4OWF ) {
  1892. RtlZeroMemory( &UserInternalInfo1, sizeof( SAMPR_USER_INTERNAL1_INFORMATION ) );
  1893. RtlCopyMemory( &UserInternalInfo1.EncryptedNtOwfPassword,
  1894. AuthInfo->IncomingAuthenticationInformation[ i ].AuthInfo,
  1895. ENCRYPTED_LM_OWF_PASSWORD_LENGTH );
  1896. UserInternalInfo1.NtPasswordPresent = TRUE;
  1897. SamData = &UserInternalInfo1;
  1898. SamInfoLevel = UserInternal1Information;
  1899. SetPassword = TRUE;
  1900. break;
  1901. }
  1902. }
  1903. }
  1904. }
  1905. LsapSaveDsThreadState();
  1906. //
  1907. // Create the user
  1908. //
  1909. if ( NT_SUCCESS( Status ) ) {
  1910. RtlZeroMemory( &AccountNameBuffer, sizeof( AccountNameBuffer ) );
  1911. RtlCopyMemory( AccountNameBuffer, AccountName->Buffer, AccountName->Length );
  1912. *( PWSTR )( ( ( PBYTE )AccountNameBuffer ) + AccountName->Length ) = L'$';
  1913. RtlInitUnicodeString( &Account, AccountNameBuffer );
  1914. Status = LsaOpenSamUser( ( PSECURITY_STRING )&Account,
  1915. SecNameSamCompatible,
  1916. NULL,
  1917. FALSE,
  1918. 0,
  1919. &AccountHandle );
  1920. if ( NT_SUCCESS( Status )) {
  1921. //
  1922. // Account already exists? This might be a stale machine account.
  1923. // Check it out before proceeding.
  1924. //
  1925. SID_AND_ATTRIBUTES_LIST GroupMembership = {0};
  1926. PSAMPR_USER_INFO_BUFFER UserAllInfoLocal = NULL;
  1927. SAMPR_HANDLE UserHandle = NULL;
  1928. Status = SamIGetUserLogonInformationEx(
  1929. LsapAccountDomainHandle,
  1930. SAM_OPEN_BY_UPN_OR_ACCOUNTNAME |
  1931. SAM_NO_MEMBERSHIPS,
  1932. &Account,
  1933. USER_ALL_USERACCOUNTCONTROL,
  1934. &UserAllInfoLocal,
  1935. &GroupMembership,
  1936. &UserHandle
  1937. );
  1938. if ( NT_SUCCESS( Status )) {
  1939. if (( UserAllInfoLocal->All.UserAccountControl & USER_INTERDOMAIN_TRUST_ACCOUNT ) == 0 ) {
  1940. //
  1941. // The existing account is not an ITA. Fail TDO creation.
  1942. //
  1943. Status = STATUS_USER_EXISTS;
  1944. }
  1945. if ( GroupMembership.SidAndAttributes != NULL ) {
  1946. SamIFreeSidAndAttributesList(&GroupMembership);
  1947. }
  1948. if ( UserAllInfoLocal != NULL ) {
  1949. SamIFree_SAMPR_USER_INFO_BUFFER( UserAllInfoLocal, UserAllInformation );
  1950. }
  1951. if ( UserHandle != NULL ) {
  1952. SamrCloseHandle( &UserHandle );
  1953. }
  1954. }
  1955. } else if ( Status == STATUS_NO_SUCH_USER ||
  1956. Status == STATUS_NONE_MAPPED ) {
  1957. Status = SamrCreateUser2InDomain( LsapAccountDomainHandle,
  1958. ( PRPC_UNICODE_STRING )&Account,
  1959. USER_INTERDOMAIN_TRUST_ACCOUNT,
  1960. MAXIMUM_ALLOWED,
  1961. &AccountHandle,
  1962. &Access,
  1963. &Rid );
  1964. if ( !NT_SUCCESS( Status )) {
  1965. LsapDsDebugOut(( DEB_ERROR,
  1966. "SamrCreateUser2InDomain on %wZ failed with 0x%lx\n",
  1967. &Account,
  1968. Status));
  1969. }
  1970. } else if ( !NT_SUCCESS( Status ) ) {
  1971. LsapDsDebugOut(( DEB_ERROR,
  1972. "LsaOpenSamUser on %wZ failed with 0x%lx\n",
  1973. &Account,
  1974. Status));
  1975. }
  1976. //
  1977. // Set the password
  1978. //
  1979. if ( NT_SUCCESS( Status ) ) {
  1980. DsysAssert( AccountHandle );
  1981. if ( SetPassword )
  1982. {
  1983. Status = SamrSetInformationUser( AccountHandle,
  1984. SamInfoLevel,
  1985. SamData );
  1986. }
  1987. SamrCloseHandle( &AccountHandle );
  1988. }
  1989. }
  1990. LsapRestoreDsThreadState( );
  1991. LsapExitFunc( "LsapDsCreateSetITAForTrustInfo", Status );
  1992. return( Status );
  1993. }
  1994. NTSTATUS
  1995. LsapDsCreateInterdomainTrustAccount(
  1996. IN LSAPR_HANDLE TrustedDomain
  1997. )
  1998. /*++
  1999. Routine Description:
  2000. This function creates a SAM interdomain trust account for an NT5 style trust object
  2001. Arguments:
  2002. TrustedDomain - Handle to the newly created trusted domain object
  2003. Return Values:
  2004. STATUS_SUCCESS -- Success
  2005. STATUS_UNSUCCESSFUL -- The Sam domain handle has not been opened.
  2006. --*/
  2007. {
  2008. NTSTATUS Status = STATUS_SUCCESS;
  2009. PTRUSTED_DOMAIN_FULL_INFORMATION FullInfo = NULL;
  2010. BOOLEAN SavedTrusted;
  2011. LSAP_DB_HANDLE InternalTdoHandle = (LSAP_DB_HANDLE) TrustedDomain;
  2012. LsapEnterFunc( "LsapDsCreateInterdomainTrustAccount" );
  2013. //
  2014. // If this is the case of an NT4 upgrade in progress then bail
  2015. //
  2016. if (LsaDsStateInfo.Nt4UpgradeInProgress)
  2017. {
  2018. return (STATUS_SUCCESS);
  2019. }
  2020. if (LsapProductSuiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED)
  2021. {
  2022. return STATUS_NOT_SUPPORTED_ON_SBS;
  2023. }
  2024. Status = LsapOpenSam();
  2025. if ( !NT_SUCCESS( Status ) ) {
  2026. LsapDsDebugOut(( DEB_ERROR,
  2027. "CreateInterdomainTrustAccount: Sam not opened\n"));
  2028. LsapExitFunc( "LsapDsCreateInterdomainTrustAccount", Status );
  2029. return( Status );
  2030. }
  2031. //
  2032. // First, find the domain. We'll need to get the full info on it
  2033. //
  2034. // Do this operation as trusted since it is an internal operation and the
  2035. // handle might not grant access to do this operation.
  2036. //
  2037. SavedTrusted = InternalTdoHandle->Trusted;
  2038. InternalTdoHandle->Trusted = TRUE;
  2039. Status = LsarQueryInfoTrustedDomain( TrustedDomain,
  2040. TrustedDomainFullInformation,
  2041. (PLSAPR_TRUSTED_DOMAIN_INFO *)&FullInfo );
  2042. InternalTdoHandle->Trusted = SavedTrusted;
  2043. if ( NT_SUCCESS( Status ) ) {
  2044. Status = LsapDsCreateSetITAForTrustInfo( &FullInfo->Information.FlatName,
  2045. &FullInfo->AuthInformation );
  2046. }
  2047. //
  2048. // Free our info
  2049. //
  2050. if ( FullInfo != NULL ) {
  2051. LsaIFree_LSAPR_TRUSTED_DOMAIN_INFO( TrustedDomainFullInformation,
  2052. ( PLSAPR_TRUSTED_DOMAIN_INFO )FullInfo );
  2053. }
  2054. LsapExitFunc( "LsapDsCreateInterdomainTrustAccount", Status );
  2055. return( Status );
  2056. }
  2057. NTSTATUS
  2058. LsapDsCreateInterdomainTrustAccountByDsName(
  2059. IN PDSNAME TrustedDomainPath,
  2060. IN PUNICODE_STRING FlatName
  2061. )
  2062. /*++
  2063. Routine Description:
  2064. This function creates a SAM interdomain trust account for an NT5 style trust object
  2065. Arguments:
  2066. DomainName -- Name of the newly added domain
  2067. AccountPassword -- Auth data set on the trust account
  2068. Return Values:
  2069. STATUS_SUCCESS -- Success
  2070. STATUS_UNSUCCESSFUL -- The Sam domain handle has not been opened.
  2071. --*/
  2072. {
  2073. NTSTATUS Status = STATUS_SUCCESS;
  2074. TRUSTED_DOMAIN_AUTH_INFORMATION AuthInfo;
  2075. LsapEnterFunc( "LsapDsCreateInterdomainTrustAccountByDsName" );
  2076. Status = LsapOpenSam();
  2077. if ( !NT_SUCCESS( Status ) ) {
  2078. LsapDsDebugOut(( DEB_ERROR,
  2079. "CreateInterdomainTrustAccount: Sam not opened\n"));
  2080. LsapExitFunc( "LsapDsCreateInterdomainTrustAccountByDsName", Status );
  2081. return( Status );
  2082. }
  2083. //
  2084. // Get the auth data
  2085. //
  2086. RtlZeroMemory( &AuthInfo, sizeof( AuthInfo ) );
  2087. Status = LsapDsGetTrustedDomainInfoEx( TrustedDomainPath,
  2088. 0,
  2089. TrustedDomainAuthInformation,
  2090. ( PLSAPR_TRUSTED_DOMAIN_INFO )&AuthInfo,
  2091. NULL );
  2092. if ( NT_SUCCESS( Status ) ) {
  2093. Status = LsapDsCreateSetITAForTrustInfo( FlatName,
  2094. ( PTRUSTED_DOMAIN_AUTH_INFORMATION )&AuthInfo );
  2095. }
  2096. //
  2097. // Free our info
  2098. //
  2099. LsapDsFreeUnmarshalAuthInfoHalf( LsapDsAuthHalfFromAuthInfo( &AuthInfo, TRUE ) );
  2100. LsapDsFreeUnmarshalAuthInfoHalf( LsapDsAuthHalfFromAuthInfo( &AuthInfo, FALSE ) );
  2101. LsapExitFunc( "LsapDsCreateInterdomainTrustAccountByDsName", Status );
  2102. return( Status );
  2103. }
  2104. NTSTATUS
  2105. LsapDsDeleteInterdomainTrustAccount(
  2106. IN LSAPR_HANDLE TrustedDomainObject
  2107. )
  2108. /*++
  2109. Routine Description:
  2110. This function deletes a SAM interdomain trust account for an NT5 style trust object
  2111. Arguments:
  2112. TrustedDomainObject -- Handle to the trusted domain object
  2113. Return Values:
  2114. STATUS_SUCCESS -- Success
  2115. STATUS_UNSUCCESSFUL -- The Sam domain handle has not been opened.
  2116. --*/
  2117. {
  2118. NTSTATUS Status = STATUS_SUCCESS;
  2119. SAM_HANDLE AccountHandle;
  2120. LSAP_DB_HANDLE InternalTdoHandle = (LSAP_DB_HANDLE) TrustedDomainObject;
  2121. PTRUSTED_DOMAIN_INFORMATION_EX ExInfo = NULL;
  2122. UNICODE_STRING Account;
  2123. WCHAR AccountName[ UNLEN + 2 ], *Accnt = AccountName;
  2124. BOOLEAN SavedTrusted;
  2125. LsapEnterFunc( "LsapDsDeleteInterdomainTrustAccount" );
  2126. Status = LsapOpenSam();
  2127. if ( !NT_SUCCESS( Status ) ) {
  2128. LsapDsDebugOut(( DEB_ERROR,
  2129. "LsapDsDeleteInterdomainTrustAccount: Sam not opened\n"));
  2130. LsapExitFunc( "LsapDsDeleteInterdomainTrustAccount", Status );
  2131. return( Status );
  2132. }
  2133. //
  2134. // First, find the domain. We'll need to get the full info on it
  2135. //
  2136. // Do this operation as trusted since it is an internal operation and the
  2137. // handle might not grant access to do this operation.
  2138. //
  2139. SavedTrusted = InternalTdoHandle->Trusted;
  2140. InternalTdoHandle->Trusted = TRUE;
  2141. Status = LsarQueryInfoTrustedDomain( TrustedDomainObject,
  2142. TrustedDomainInformationEx,
  2143. (PLSAPR_TRUSTED_DOMAIN_INFO *)&ExInfo );
  2144. InternalTdoHandle->Trusted = SavedTrusted;
  2145. //
  2146. // Delete the user
  2147. //
  2148. // First, create the name to look for
  2149. //
  2150. if ( NT_SUCCESS( Status ) ) {
  2151. RtlZeroMemory( &AccountName, sizeof( AccountName ) );
  2152. if ( ExInfo->FlatName.MaximumLength >= sizeof( AccountName ) - sizeof( WCHAR ) ) {
  2153. Accnt = LsapAllocateLsaHeap( ExInfo->FlatName.MaximumLength +
  2154. sizeof( WCHAR ) + sizeof( WCHAR ) );
  2155. if ( Accnt == NULL ) {
  2156. Status = STATUS_INSUFFICIENT_RESOURCES;
  2157. }
  2158. }
  2159. if ( NT_SUCCESS( Status ) ) {
  2160. RtlCopyMemory( Accnt, ExInfo->FlatName.Buffer, ExInfo->FlatName.MaximumLength );
  2161. *( PWSTR )( ( ( PBYTE) Accnt ) + ExInfo->FlatName.Length ) = L'$';
  2162. RtlInitUnicodeString( &Account, Accnt );
  2163. //
  2164. // We can't call into sam with an active thread state
  2165. //
  2166. LsapSaveDsThreadState();
  2167. //
  2168. // Open the user. If the user doesn't exist, it's not an error
  2169. //
  2170. Status = LsaOpenSamUser( ( PSECURITY_STRING )&Account,
  2171. SecNameSamCompatible,
  2172. NULL,
  2173. FALSE,
  2174. 0,
  2175. &AccountHandle );
  2176. if ( NT_SUCCESS( Status ) ) {
  2177. //
  2178. // Now, delete it
  2179. //
  2180. Status = SamrDeleteUser( &AccountHandle );
  2181. if ( !NT_SUCCESS( Status ) ) {
  2182. LsapDsDebugOut(( DEB_ERROR,
  2183. "Failed to delete user %wZ: 0x%lx\n",
  2184. &Account,
  2185. Status ));
  2186. SpmpReportEventU(
  2187. EVENTLOG_WARNING_TYPE,
  2188. LSAEVENT_ITA_NOT_DELETED,
  2189. 0,
  2190. sizeof( ULONG ),
  2191. &Status,
  2192. 1,
  2193. &ExInfo->Name
  2194. );
  2195. SamrCloseHandle( &AccountHandle );
  2196. }
  2197. } else if ( Status == STATUS_NONE_MAPPED ) {
  2198. Status = STATUS_SUCCESS;
  2199. }
  2200. if ( Accnt != AccountName ) {
  2201. LsapFreeLsaHeap( Accnt );
  2202. }
  2203. LsapRestoreDsThreadState();
  2204. }
  2205. }
  2206. //
  2207. // Free our info
  2208. //
  2209. if ( ExInfo != NULL ) {
  2210. LsaIFree_LSAPR_TRUSTED_DOMAIN_INFO( TrustedDomainInformationEx,
  2211. ( PLSAPR_TRUSTED_DOMAIN_INFO )ExInfo );
  2212. }
  2213. LsapExitFunc( "LsapDsDeleteInterdomainTrustAccount", Status );
  2214. return( Status );
  2215. }
  2216. NTSTATUS
  2217. LsapDsDomainUpgradeInterdomainTrustAccountsToDs(
  2218. VOID
  2219. )
  2220. /*++
  2221. Routine Description:
  2222. This routine will create the appropriate part of the trust object if an interdomain
  2223. trust account by that name is found
  2224. NOTE: It is assumed that the database is locked before calling this routine
  2225. Arguments:
  2226. VOID
  2227. Return Values:
  2228. STATUS_SUCCESS -- Success
  2229. --*/
  2230. {
  2231. NTSTATUS Status = STATUS_SUCCESS;
  2232. SAM_ENUMERATE_HANDLE SamEnum = 0;
  2233. SAMPR_HANDLE UserHandle;
  2234. PSAMPR_ENUMERATION_BUFFER RidEnum = NULL;
  2235. PSAMPR_USER_INTERNAL1_INFORMATION UserInfo1 = NULL;
  2236. PLSAPR_TRUSTED_DOMAIN_FULL_INFORMATION FullInfo = NULL;
  2237. LSAPR_TRUSTED_DOMAIN_FULL_INFORMATION NewFullInfo;
  2238. LSAPR_AUTH_INFORMATION NewIncomingAuthInfo;
  2239. LSAPR_HANDLE TrustedDomain = NULL;
  2240. NT_OWF_PASSWORD EmptyPassword;
  2241. UNICODE_STRING EmptyString;
  2242. ULONG SamCount = 0;
  2243. PVOID CurrentState;
  2244. ULONG i;
  2245. if ( !LsapDsWriteDs ) {
  2246. return( STATUS_SUCCESS );
  2247. }
  2248. LsapEnterFunc( "LsapDsDomainUpgradeInterdomainTrustAccountsToDs" );
  2249. ( ( LSAP_DB_HANDLE )LsapPolicyHandle )->Options |= LSAP_DB_HANDLE_UPGRADE;
  2250. LsapSaveDsThreadState();
  2251. Status = LsapOpenSam();
  2252. if ( !NT_SUCCESS( Status ) ) {
  2253. LsapDsDebugOut(( DEB_ERROR,
  2254. "LsapDsDomainUpgradeInterdomainTrustAccountsToDs: Sam not opened\n"));
  2255. } else {
  2256. Status = SamIEnumerateInterdomainTrustAccountsForUpgrade(
  2257. &SamEnum,
  2258. &RidEnum,
  2259. 0xFFFFFFFF,
  2260. &SamCount );
  2261. if ( !NT_SUCCESS( Status ) ) {
  2262. LsapDsDebugOut(( DEB_FIXUP,
  2263. "SamEnumerateUsersInDomain failed with 0x%lx\n",
  2264. Status ));
  2265. } else {
  2266. LsapDsDebugOut(( DEB_FIXUP,
  2267. "SamEnumerateUsersInDomain returned %lu accounts\n",
  2268. SamCount ));
  2269. }
  2270. }
  2271. LsapRestoreDsThreadState();
  2272. //
  2273. // Now, we'll process them all. If the domain already exists, we'll simply set it's
  2274. // information appropriately. Otherwise, we'll create it.
  2275. //
  2276. for ( i = 0; NT_SUCCESS( Status ) && i < RidEnum->EntriesRead; i++ ) {
  2277. UCHAR NtOwfPassword[NT_OWF_PASSWORD_LENGTH];
  2278. UCHAR LmOwfPassword[LM_OWF_PASSWORD_LENGTH];
  2279. BOOLEAN NtPasswordPresent = FALSE;
  2280. BOOLEAN LmPasswordPresent = FALSE;
  2281. //
  2282. // Burn the trailing '$' from the account name
  2283. //
  2284. RidEnum->Buffer[ i ].Name.Length -= sizeof( WCHAR );
  2285. //
  2286. // Save Thread state before calling into SAM
  2287. //
  2288. LsapSaveDsThreadState();
  2289. //
  2290. // Next, we'll need to read the current nt4 owf from the account
  2291. //
  2292. Status = SamIGetInterdomainTrustAccountPasswordsForUpgrade(
  2293. RidEnum->Buffer[ i ].RelativeId, // RID of the account
  2294. NtOwfPassword,
  2295. &NtPasswordPresent,
  2296. LmOwfPassword,
  2297. &LmPasswordPresent
  2298. );
  2299. //
  2300. // Restore the thread state after the SAM call
  2301. //
  2302. LsapRestoreDsThreadState();
  2303. //
  2304. // Now, we've got the user info. We'll get the domain information, and
  2305. // set it on the trust object (or alternately create it if it doesn't exist)
  2306. //
  2307. if ( NT_SUCCESS( Status ) ) {
  2308. //
  2309. // Build the new AUTHINFO
  2310. //
  2311. GetSystemTimeAsFileTime( (LPFILETIME) &NewIncomingAuthInfo.LastUpdateTime );
  2312. NewIncomingAuthInfo.AuthType = TRUST_AUTH_TYPE_NT4OWF;
  2313. NewIncomingAuthInfo.AuthInfoLength = NT_OWF_PASSWORD_LENGTH;
  2314. if ( NtPasswordPresent ) {
  2315. NewIncomingAuthInfo.AuthInfo = NtOwfPassword;
  2316. } else {
  2317. RtlInitUnicodeString( &EmptyString, L"" );
  2318. Status = RtlCalculateNtOwfPassword( ( PNT_PASSWORD )&EmptyString,
  2319. &EmptyPassword );
  2320. if ( NT_SUCCESS( Status ) ) {
  2321. NewIncomingAuthInfo.AuthInfo = ( PUCHAR )&EmptyPassword;
  2322. }
  2323. }
  2324. Status = LsapDbOpenTrustedDomainByName(
  2325. NULL, // use global policy handle
  2326. ( PUNICODE_STRING )&RidEnum->Buffer[ i ].Name,
  2327. &TrustedDomain,
  2328. MAXIMUM_ALLOWED,
  2329. LSAP_DB_START_TRANSACTION,
  2330. TRUE ); // Trusted
  2331. if ( NT_SUCCESS( Status ) ) {
  2332. Status = LsarQueryInfoTrustedDomain( TrustedDomain,
  2333. TrustedDomainFullInformation,
  2334. (PLSAPR_TRUSTED_DOMAIN_INFO *) &FullInfo );
  2335. if ( NT_SUCCESS( Status ) ) {
  2336. //
  2337. // Add our new information in
  2338. //
  2339. if ( !FLAG_ON( FullInfo->Information.TrustDirection, TRUST_DIRECTION_INBOUND ) ) {
  2340. FullInfo->Information.TrustDirection |= TRUST_DIRECTION_INBOUND;
  2341. FullInfo->AuthInformation.IncomingAuthInfos = 1;
  2342. FullInfo->AuthInformation.IncomingAuthenticationInformation =
  2343. &NewIncomingAuthInfo;
  2344. FullInfo->AuthInformation.IncomingPreviousAuthenticationInformation = NULL;
  2345. Status = LsarSetInformationTrustedDomain(
  2346. TrustedDomain,
  2347. TrustedDomainFullInformation,
  2348. ( PLSAPR_TRUSTED_DOMAIN_INFO ) FullInfo );
  2349. //
  2350. // NULL out the IncomingAuthenticationInformation variable, as that
  2351. // is a stack buffer and we do not want to free it.
  2352. //
  2353. FullInfo->AuthInformation.IncomingAuthInfos = 0;
  2354. FullInfo->AuthInformation.IncomingAuthenticationInformation = NULL;
  2355. LsaIFree_LSAPR_TRUSTED_DOMAIN_INFO(
  2356. TrustedDomainFullInformation,
  2357. (PLSAPR_TRUSTED_DOMAIN_INFO) FullInfo );
  2358. }
  2359. }
  2360. } else if ( Status == STATUS_OBJECT_NAME_NOT_FOUND ) {
  2361. //
  2362. // We'll have to create it...
  2363. //
  2364. RtlZeroMemory( &NewFullInfo, sizeof( NewFullInfo ) );
  2365. RtlCopyMemory( &NewFullInfo.Information.Name,
  2366. &RidEnum->Buffer[ i ].Name,
  2367. sizeof( LSAPR_UNICODE_STRING ) );
  2368. RtlCopyMemory( &NewFullInfo.Information.FlatName,
  2369. &RidEnum->Buffer[ i ].Name,
  2370. sizeof( LSAPR_UNICODE_STRING ) );
  2371. NewFullInfo.Information.TrustDirection = TRUST_DIRECTION_INBOUND;
  2372. NewFullInfo.Information.TrustType = TRUST_TYPE_DOWNLEVEL;
  2373. NewFullInfo.AuthInformation.IncomingAuthInfos = 1;
  2374. NewFullInfo.AuthInformation.IncomingAuthenticationInformation =
  2375. &NewIncomingAuthInfo;
  2376. NewFullInfo.AuthInformation.IncomingPreviousAuthenticationInformation = NULL;
  2377. Status = LsapCreateTrustedDomain2( LsapPolicyHandle,
  2378. &NewFullInfo.Information,
  2379. &NewFullInfo.AuthInformation,
  2380. MAXIMUM_ALLOWED,
  2381. &TrustedDomain );
  2382. }
  2383. }
  2384. if ( TrustedDomain != NULL ) {
  2385. LsapCloseHandle( &TrustedDomain, Status );
  2386. }
  2387. if ( UserInfo1 ) {
  2388. SamIFree_SAMPR_USER_INFO_BUFFER( ( PSAMPR_USER_INFO_BUFFER )UserInfo1,
  2389. UserInternal1Information );
  2390. UserInfo1 = NULL;
  2391. }
  2392. if (!NT_SUCCESS(Status))
  2393. {
  2394. if (!LsapDsIsNtStatusResourceError(Status))
  2395. {
  2396. //
  2397. // Log an event log message indicating the failure
  2398. //
  2399. SpmpReportEventU(
  2400. EVENTLOG_ERROR_TYPE,
  2401. LSA_ITA_UPGRADE_ERROR,
  2402. 0,
  2403. sizeof( ULONG ),
  2404. &Status,
  2405. 1,
  2406. &RidEnum->Buffer[i].Name
  2407. );
  2408. //
  2409. // Continue on all errors excepting resource errors
  2410. //
  2411. Status = STATUS_SUCCESS;
  2412. }
  2413. else
  2414. {
  2415. //
  2416. // Break out of the loop and terminate the upgrade
  2417. //
  2418. break;
  2419. }
  2420. }
  2421. }
  2422. //
  2423. // We're done with the sam enumeration
  2424. //
  2425. if ( RidEnum ) {
  2426. SamFreeMemory( RidEnum );
  2427. }
  2428. ( ( LSAP_DB_HANDLE )LsapPolicyHandle )->Options &= ~LSAP_DB_HANDLE_UPGRADE;
  2429. LsapExitFunc( "LsapDsDomainUpgradeInterdomainTrustAccountsToDs", Status );
  2430. return( Status );
  2431. }
  2432. VOID
  2433. LsapDsFreeUnmarshalAuthInfoHalf(
  2434. IN PLSAPR_TRUST_DOMAIN_AUTH_INFO_HALF AuthInfo
  2435. )
  2436. /*++
  2437. Routine Description:
  2438. This routine will free the memory allocated by LsapDsUnMarshalAuthInfoForReturn
  2439. Arguments:
  2440. VOID
  2441. Return Values:
  2442. VOID
  2443. --*/
  2444. {
  2445. if ( !AuthInfo ) {
  2446. return;
  2447. }
  2448. LsapDsFreeUnmarshaledAuthInfo( AuthInfo->AuthInfos,
  2449. AuthInfo->AuthenticationInformation );
  2450. LsapDsFreeUnmarshaledAuthInfo( AuthInfo->AuthInfos,
  2451. AuthInfo->PreviousAuthenticationInformation );
  2452. MIDL_user_free( AuthInfo->AuthenticationInformation );
  2453. AuthInfo->AuthenticationInformation = NULL;
  2454. MIDL_user_free( AuthInfo->PreviousAuthenticationInformation );
  2455. AuthInfo->PreviousAuthenticationInformation = NULL;
  2456. return;
  2457. }
  2458. NTSTATUS
  2459. LsapDecryptAuthDataWithSessionKey(
  2460. IN PLSAP_CR_CIPHER_KEY SessionKey,
  2461. IN PLSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION_INTERNAL AuthInformationInternal,
  2462. IN PTRUSTED_DOMAIN_AUTH_INFORMATION AuthInfo
  2463. )
  2464. /*++
  2465. Routine Description:
  2466. This routine decrypts the auth info as passed to us on an RPC call.
  2467. Arguments:
  2468. SessionKey - Session key to decrypt with.
  2469. AuthInformationInternal - Pointer to the encrypted auth info.
  2470. AuthInfo - Buffer to return the authentication information into.
  2471. Free the buffer using:
  2472. LsapDsFreeUnmarshalAuthInfoHalf( LsapDsAuthHalfFromAuthInfo( AuthInfo, TRUE ) );
  2473. LsapDsFreeUnmarshalAuthInfoHalf( LsapDsAuthHalfFromAuthInfo( AuthInfo, FALSE ) );
  2474. Return Value:
  2475. --*/
  2476. {
  2477. NTSTATUS Status;
  2478. struct RC4_KEYSTRUCT Rc4Key;
  2479. ULONG OverheadSize = LSAP_ENCRYPTED_AUTH_DATA_FILL + sizeof(ULONG) + sizeof(ULONG);
  2480. ULONG MessageSize;
  2481. PUCHAR Where;
  2482. ULONG IncomingAuthInfoSize = 0;
  2483. PUCHAR IncomingAuthInfo = NULL;
  2484. ULONG OutgoingAuthInfoSize = 0;
  2485. PUCHAR OutgoingAuthInfo = NULL;
  2486. //
  2487. // Initialization.
  2488. //
  2489. RtlZeroMemory( AuthInfo, sizeof(*AuthInfo) );
  2490. if ( SessionKey == NULL ) {
  2491. Status = STATUS_INVALID_PARAMETER;
  2492. goto Cleanup;
  2493. }
  2494. //
  2495. // Ensure the auth data is big enough.
  2496. //
  2497. // Here's the format of the decrypted buffer:
  2498. // 512 random bytes
  2499. // The Outgoing auth info buffer.
  2500. // The Incoming auth info buffer.
  2501. // The length of the outgoing auth info buffer.
  2502. // The length of the incoming auth info buffer.
  2503. //
  2504. MessageSize = AuthInformationInternal->AuthBlob.AuthSize;
  2505. if ( MessageSize < OverheadSize ) {
  2506. Status = STATUS_INVALID_PARAMETER;
  2507. goto Cleanup;
  2508. }
  2509. MessageSize -= OverheadSize;
  2510. //
  2511. // Decrypt the auth info
  2512. //
  2513. rc4_key(
  2514. &Rc4Key,
  2515. SessionKey->Length,
  2516. SessionKey->Buffer );
  2517. rc4( &Rc4Key,
  2518. AuthInformationInternal->AuthBlob.AuthSize,
  2519. AuthInformationInternal->AuthBlob.AuthBlob );
  2520. //
  2521. // Sanity check the decrypted data.
  2522. //
  2523. Where = AuthInformationInternal->AuthBlob.AuthBlob +
  2524. AuthInformationInternal->AuthBlob.AuthSize -
  2525. sizeof(ULONG);
  2526. RtlCopyMemory( &IncomingAuthInfoSize, Where, sizeof(ULONG));
  2527. Where -= sizeof(ULONG);
  2528. if ( IncomingAuthInfoSize > MessageSize ) {
  2529. Status = STATUS_INVALID_PARAMETER;
  2530. goto Cleanup;
  2531. }
  2532. MessageSize -= IncomingAuthInfoSize;
  2533. RtlCopyMemory( &OutgoingAuthInfoSize, Where, sizeof(ULONG));
  2534. if ( OutgoingAuthInfoSize != MessageSize ) {
  2535. Status = STATUS_INVALID_PARAMETER;
  2536. goto Cleanup;
  2537. }
  2538. Where -= IncomingAuthInfoSize;
  2539. IncomingAuthInfo = Where;
  2540. Where -= OutgoingAuthInfoSize;
  2541. OutgoingAuthInfo = Where;
  2542. //
  2543. // Unmarshal the auth info.
  2544. //
  2545. Status = LsapDsUnmarshalAuthInfoHalf(
  2546. NULL,
  2547. FALSE,
  2548. TRUE,
  2549. IncomingAuthInfo,
  2550. IncomingAuthInfoSize,
  2551. LsapDsAuthHalfFromAuthInfo( AuthInfo, TRUE ) );
  2552. if ( !NT_SUCCESS(Status)) {
  2553. Status = STATUS_INVALID_PARAMETER;
  2554. goto Cleanup;
  2555. }
  2556. Status = LsapDsUnmarshalAuthInfoHalf(
  2557. NULL,
  2558. FALSE,
  2559. TRUE,
  2560. OutgoingAuthInfo,
  2561. OutgoingAuthInfoSize,
  2562. LsapDsAuthHalfFromAuthInfo( AuthInfo, FALSE ) );
  2563. if ( !NT_SUCCESS(Status)) {
  2564. Status = STATUS_INVALID_PARAMETER;
  2565. goto Cleanup;
  2566. }
  2567. Cleanup:
  2568. if ( !NT_SUCCESS(Status)) {
  2569. LsapDsFreeUnmarshalAuthInfoHalf( LsapDsAuthHalfFromAuthInfo( AuthInfo, TRUE ) );
  2570. LsapDsFreeUnmarshalAuthInfoHalf( LsapDsAuthHalfFromAuthInfo( AuthInfo, FALSE ) );
  2571. }
  2572. return Status;
  2573. }
  2574. UUID LsapNullUuidValue = {0,0,0,{0,0,0,0,0,0,0,0}};
  2575. // Return TRUE if the ptr to the UUID is NULL, or the uuid is all zeroes
  2576. BOOLEAN LsapNullUuid (const UUID *pUuid)
  2577. {
  2578. if (!pUuid) {
  2579. return TRUE;
  2580. }
  2581. if (memcmp (pUuid, &LsapNullUuidValue, sizeof (UUID))) {
  2582. return FALSE;
  2583. }
  2584. return TRUE;
  2585. }
  2586. NTSTATUS
  2587. LsapDsTrustedDomainObjectNameForDomain(
  2588. IN PUNICODE_STRING TrustedDomainName,
  2589. IN BOOLEAN NameAsFlatName,
  2590. OUT PDSNAME *DsObjectName
  2591. )
  2592. /*++
  2593. Routine Description:
  2594. This routine will find the DS object name associated with the given domain name. The
  2595. domain name can be either the flat name or the dns name, depending on the given flags
  2596. Arguments:
  2597. TrustedDomainName - Name of the domain to find the object name for
  2598. NameAsFlatName - If TRUE, assume that the input name is the flat name. Otherwise, it's
  2599. the Dns domain name
  2600. DsObjectName - Where the path to the object is returned. Freed via LsapFreeLsaHeap
  2601. Return Values:
  2602. STATUS_SUCCESS - Success
  2603. STATUS_INSUFFICIENT_RESOURCES - A memory allocation failed
  2604. --*/
  2605. {
  2606. NTSTATUS Status = STATUS_SUCCESS;
  2607. ATTRVAL AttrVal;
  2608. LSAPR_TRUST_INFORMATION InputTrustInformation;
  2609. PLSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY TrustEntry;
  2610. LsapEnterFunc( "LsapDsTrustedDomainObjectNameForDomain" );
  2611. //
  2612. // Lookup the object in the trusted domain cache. Currently this is
  2613. // for duplicate detection and reconciliation. Later we can extend
  2614. // the cache to always keep the guid of the object in the DS. This way
  2615. // this will be a useful performance optimization
  2616. //
  2617. //
  2618. // Acquire the Read Lock for the Trusted Domain List
  2619. //
  2620. Status = LsapDbAcquireReadLockTrustedDomainList();
  2621. if (!NT_SUCCESS(Status)) {
  2622. goto Cleanup;
  2623. }
  2624. RtlCopyMemory(&InputTrustInformation.Name,TrustedDomainName,sizeof(UNICODE_STRING));
  2625. InputTrustInformation.Sid = NULL;
  2626. Status = LsapDbLookupEntryTrustedDomainList(
  2627. &InputTrustInformation,
  2628. &TrustEntry
  2629. );
  2630. if ((STATUS_SUCCESS==Status) && (!LsapNullUuid(&TrustEntry->ObjectGuidInDs)))
  2631. {
  2632. GUID ObjectGuid;
  2633. //
  2634. // Duplicate detection filled in a GUID. use that
  2635. //
  2636. RtlCopyMemory(&ObjectGuid, &TrustEntry->ObjectGuidInDs,sizeof(GUID));
  2637. AttrVal.valLen = sizeof(GUID);
  2638. AttrVal.pVal = ( PUCHAR )&ObjectGuid;
  2639. LsapDbReleaseLockTrustedDomainList();
  2640. Status = LsapDsFindUnique( 0,
  2641. NULL, // Default naming context
  2642. TrustedDomainObject,
  2643. &AttrVal,
  2644. ATT_OBJECT_GUID,
  2645. DsObjectName );
  2646. }
  2647. else
  2648. {
  2649. LsapDbReleaseLockTrustedDomainList();
  2650. AttrVal.valLen = TrustedDomainName->Length;
  2651. AttrVal.pVal = ( PUCHAR )TrustedDomainName->Buffer;
  2652. Status = LsapDsFindUnique( 0,
  2653. NULL, // Default naming context
  2654. TrustedDomainObject,
  2655. &AttrVal,
  2656. NameAsFlatName ?
  2657. LsapDsAttributeIds[ LsapDsAttrTrustPartnerFlat ] :
  2658. LsapDsAttributeIds[ LsapDsAttrTrustPartner ],
  2659. DsObjectName );
  2660. }
  2661. Cleanup:
  2662. LsapExitFunc( "LsapDsTrustedDomainObjectNameForDomain", Status );
  2663. return( Status );
  2664. }