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

731 lines
15 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1997.
  5. //
  6. // File: mgroup.c
  7. //
  8. // Contents: LSA Mode Context API
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 2-24-97 RichardW Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include "xtcbpkg.h"
  18. #include <cryptdll.h>
  19. LIST_ENTRY MachineGroupList ;
  20. CRITICAL_SECTION MachineGroupLock ;
  21. WCHAR MachineLocalName[ MAX_PATH ];
  22. #define LOOPBACK_KEY L"Loopback"
  23. #define GROUPKEY_VALUE L"$$GroupKey"
  24. PXTCB_MACHINE_GROUP_ENTRY
  25. MGpCreateGroupEntry(
  26. PWSTR MachineName,
  27. PUCHAR Key
  28. )
  29. {
  30. PXTCB_MACHINE_GROUP_ENTRY Entry ;
  31. ULONG Length ;
  32. Length = wcslen( MachineName ) + 1;
  33. Entry = LocalAlloc( LMEM_FIXED,
  34. sizeof( XTCB_MACHINE_GROUP_ENTRY ) + (Length * sizeof(WCHAR) ) );
  35. if ( Entry )
  36. {
  37. Entry->MachineName = (PWSTR) (Entry + 1);
  38. CopyMemory( Entry->UniqueKey,
  39. Key,
  40. SEED_KEY_SIZE );
  41. CopyMemory( Entry->MachineName,
  42. MachineName,
  43. Length * sizeof(WCHAR) );
  44. if ( _wcsicmp( MachineName, MachineLocalName ) == 0 )
  45. {
  46. Entry->Flags = MGROUP_ENTRY_SELF ;
  47. }
  48. else
  49. {
  50. Entry->Flags = 0;
  51. }
  52. }
  53. return Entry ;
  54. }
  55. VOID
  56. MGpFreeGroup(
  57. PXTCB_MACHINE_GROUP Group
  58. )
  59. {
  60. ULONG i ;
  61. for ( i = 0 ; i < Group->Count ; i++ )
  62. {
  63. LocalFree( Group->GroupList[ i ] );
  64. }
  65. LocalFree( Group );
  66. }
  67. PXTCB_MACHINE_GROUP
  68. MGpCreateMachineGroup(
  69. HKEY Root,
  70. PWSTR KeyName
  71. )
  72. {
  73. ULONG Count ;
  74. ULONG Size ;
  75. ULONG Type ;
  76. UCHAR Key[ SEED_KEY_SIZE ];
  77. PWSTR Name ;
  78. ULONG MaxName ;
  79. ULONG NameSize ;
  80. ULONG Index ;
  81. PXTCB_MACHINE_GROUP Group ;
  82. int err ;
  83. err = RegQueryInfoKey(
  84. Root,
  85. NULL,
  86. NULL,
  87. NULL,
  88. NULL,
  89. NULL,
  90. NULL,
  91. &Count,
  92. &MaxName,
  93. NULL,
  94. NULL,
  95. NULL );
  96. if ( err )
  97. {
  98. return NULL ;
  99. }
  100. MaxName++;
  101. Name = LocalAlloc( LMEM_FIXED, (MaxName) * sizeof( WCHAR ) );
  102. if ( !Name )
  103. {
  104. return NULL ;
  105. }
  106. Group = LocalAlloc( LMEM_FIXED,
  107. sizeof( XTCB_MACHINE_GROUP ) +
  108. ( Count ) * sizeof( PXTCB_MACHINE_GROUP_ENTRY ) +
  109. ( wcslen( KeyName ) + 1 ) * sizeof( WCHAR ) );
  110. if ( !Group )
  111. {
  112. LocalFree( Name );
  113. return NULL ;
  114. }
  115. //
  116. // We've got all the base structures. Let's load it in:
  117. //
  118. Group->List.Flink = NULL ;
  119. Group->List.Blink = NULL ;
  120. Group->Count = 0 ;
  121. Group->GroupList = (PXTCB_MACHINE_GROUP_ENTRY *) (Group + 1);
  122. Group->Group.Buffer = (PWSTR) ((PUCHAR) Group->GroupList +
  123. (Count * sizeof( PXTCB_MACHINE_GROUP_ENTRY ) ) );
  124. wcscpy( Group->Group.Buffer, KeyName );
  125. Group->Group.Length = wcslen( Group->Group.Buffer ) * sizeof( WCHAR );
  126. Group->Group.MaximumLength = Group->Group.Length + sizeof( WCHAR );
  127. for ( Index = 0 ; Index < Count ; Index++ )
  128. {
  129. NameSize = MaxName ;
  130. Size = SEED_KEY_SIZE ;
  131. err = RegEnumValue(
  132. Root,
  133. Index,
  134. Name,
  135. &NameSize,
  136. NULL,
  137. &Type,
  138. Key,
  139. &Size );
  140. if ( (err == 0) && (Type == REG_BINARY) )
  141. {
  142. if ( _wcsicmp( Name, GROUPKEY_VALUE ) == 0 )
  143. {
  144. CopyMemory(
  145. Group->SeedKey,
  146. Key,
  147. Size );
  148. continue;
  149. }
  150. Group->GroupList[ Group->Count ] = MGpCreateGroupEntry( Name, Key );
  151. if ( Group->GroupList[ Group->Count ] )
  152. {
  153. Group->Count++ ;
  154. }
  155. }
  156. }
  157. LocalFree( Name );
  158. if ( Group->Count == 0 )
  159. {
  160. DebugLog(( DEB_ERROR, "No machines found in group %ws\n", KeyName ));
  161. LocalFree( Group );
  162. Group = NULL ;
  163. }
  164. if ( Group )
  165. {
  166. for ( Index = 0 ; Index < Group->Count ; Index++ )
  167. {
  168. if ( Group->GroupList[ Index ]->Flags & MGROUP_ENTRY_SELF )
  169. {
  170. break;
  171. }
  172. }
  173. if ( Index == Group->Count )
  174. {
  175. DebugLog(( DEB_ERROR, "No entry for self found in group %ws\n", KeyName ));
  176. MGpFreeGroup( Group );
  177. Group = NULL ;
  178. }
  179. }
  180. return Group ;
  181. }
  182. VOID
  183. MGpCreateLoopback(
  184. HKEY RootKey
  185. )
  186. {
  187. int err ;
  188. DWORD Disp ;
  189. HKEY LoopbackKey ;
  190. UCHAR Random1[ XTCB_SEED_LENGTH ];
  191. UCHAR Random2[ XTCB_SEED_LENGTH ];
  192. err = RegCreateKeyEx(
  193. RootKey,
  194. LOOPBACK_KEY,
  195. 0,
  196. NULL,
  197. REG_OPTION_VOLATILE,
  198. KEY_READ | KEY_WRITE,
  199. NULL,
  200. &LoopbackKey,
  201. &Disp );
  202. if ( err == 0 )
  203. {
  204. if ( Disp == REG_OPENED_EXISTING_KEY )
  205. {
  206. RegCloseKey( LoopbackKey );
  207. return;
  208. }
  209. CDGenerateRandomBits( Random1, XTCB_SEED_LENGTH );
  210. CDGenerateRandomBits( Random2, XTCB_SEED_LENGTH );
  211. (VOID) RegSetValueEx(
  212. LoopbackKey,
  213. GROUPKEY_VALUE,
  214. 0,
  215. REG_BINARY,
  216. Random2,
  217. XTCB_SEED_LENGTH );
  218. (VOID) RegSetValueEx(
  219. LoopbackKey,
  220. L"LocalHost",
  221. 0,
  222. REG_BINARY,
  223. Random1,
  224. XTCB_SEED_LENGTH );
  225. (VOID) RegSetValueEx(
  226. LoopbackKey,
  227. XtcbUnicodeDnsName.Buffer,
  228. 0,
  229. REG_BINARY,
  230. Random1,
  231. XTCB_SEED_LENGTH );
  232. //
  233. // Enumerate and stick aliases for this machine in the key here.
  234. //
  235. RegCloseKey( LoopbackKey );
  236. }
  237. }
  238. BOOL
  239. MGpLoadGroups(
  240. VOID
  241. )
  242. {
  243. HKEY RootKey = NULL ;
  244. HKEY Enum ;
  245. int err ;
  246. DWORD Index ;
  247. DWORD Disp ;
  248. PXTCB_MACHINE_GROUP Group ;
  249. DWORD MaxLen ;
  250. PWSTR KeyName = NULL ;
  251. WCHAR Buffer[ 32 ];
  252. DWORD Len ;
  253. BOOL Success = FALSE ;
  254. ULONG KeyCount ;
  255. err = RegCreateKeyEx(
  256. HKEY_LOCAL_MACHINE,
  257. L"System\\CurrentControlSet\\Control\\LSA\\XTCB\\Groups",
  258. 0,
  259. NULL,
  260. REG_OPTION_NON_VOLATILE,
  261. KEY_READ | KEY_WRITE,
  262. NULL,
  263. &RootKey,
  264. &Disp );
  265. if ( err )
  266. {
  267. return FALSE ;
  268. }
  269. MGpCreateLoopback( RootKey );
  270. err = RegQueryInfoKey(
  271. RootKey,
  272. NULL,
  273. NULL,
  274. NULL,
  275. &KeyCount,
  276. &MaxLen,
  277. NULL,
  278. NULL,
  279. NULL,
  280. NULL,
  281. NULL,
  282. NULL );
  283. if ( err )
  284. {
  285. goto Cleanup ;
  286. }
  287. DebugLog(( DEB_TRACE, "Found %d groups\n", KeyCount ));
  288. if ( MaxLen < 32 )
  289. {
  290. KeyName = Buffer ;
  291. MaxLen = 32 ;
  292. }
  293. else
  294. {
  295. KeyName = LocalAlloc( LMEM_FIXED, (MaxLen + 1) * sizeof( WCHAR ) );
  296. if ( KeyName == NULL )
  297. {
  298. goto Cleanup ;
  299. }
  300. }
  301. Index = 0 ;
  302. while ( Index < KeyCount )
  303. {
  304. Len = MaxLen ;
  305. err = RegEnumKeyEx(
  306. RootKey,
  307. Index,
  308. KeyName,
  309. &Len,
  310. NULL,
  311. NULL,
  312. NULL,
  313. NULL );
  314. if ( err )
  315. {
  316. Index++ ;
  317. continue;
  318. }
  319. err = RegOpenKeyEx(
  320. RootKey,
  321. KeyName,
  322. REG_OPTION_NON_VOLATILE,
  323. KEY_READ,
  324. &Enum );
  325. if ( err )
  326. {
  327. err = RegOpenKeyEx(
  328. RootKey,
  329. KeyName,
  330. REG_OPTION_VOLATILE,
  331. KEY_READ,
  332. &Enum );
  333. }
  334. if ( err == 0 )
  335. {
  336. DebugLog(( DEB_TRACE, "Processing group %d:%ws\n", Index, KeyName ));
  337. Group = MGpCreateMachineGroup( Enum, KeyName );
  338. RegCloseKey( Enum );
  339. if ( Group )
  340. {
  341. InsertTailList( &MachineGroupList, &Group->List );
  342. }
  343. }
  344. else
  345. {
  346. DebugLog(( DEB_TRACE, "Unable to open key %ws\n", KeyName ));
  347. }
  348. Index++ ;
  349. }
  350. Success = TRUE ;
  351. Cleanup:
  352. if ( RootKey )
  353. {
  354. RegCloseKey( RootKey );
  355. }
  356. if ( KeyName )
  357. {
  358. if ( KeyName != Buffer )
  359. {
  360. LocalFree( KeyName );
  361. }
  362. }
  363. return Success ;
  364. }
  365. BOOL
  366. MGroupReload(
  367. VOID
  368. )
  369. {
  370. PLIST_ENTRY List ;
  371. PXTCB_MACHINE_GROUP Group ;
  372. BOOL Success ;
  373. DWORD Size = MAX_PATH ;
  374. EnterCriticalSection( &MachineGroupLock );
  375. while ( !IsListEmpty( &MachineGroupList ) )
  376. {
  377. List = RemoveHeadList( &MachineGroupList );
  378. Group = CONTAINING_RECORD( List, XTCB_MACHINE_GROUP, List );
  379. MGpFreeGroup( Group );
  380. }
  381. GetComputerNameEx( ComputerNamePhysicalDnsFullyQualified,
  382. MachineLocalName,
  383. &Size );
  384. Success = MGpLoadGroups();
  385. LeaveCriticalSection( &MachineGroupLock );
  386. return Success ;
  387. }
  388. BOOL
  389. MGroupInitialize(
  390. VOID
  391. )
  392. {
  393. BOOL Success = TRUE ;
  394. try {
  395. InitializeCriticalSection( &MachineGroupLock );
  396. }
  397. except ( EXCEPTION_EXECUTE_HANDLER )
  398. {
  399. Success = FALSE ;
  400. }
  401. InitializeListHead( &MachineGroupList );
  402. if ( Success )
  403. {
  404. Success = MGroupReload();
  405. }
  406. return Success ;
  407. }
  408. BOOL
  409. MGroupLocateInboundKey(
  410. IN PSECURITY_STRING GroupName,
  411. IN PSECURITY_STRING Origin,
  412. OUT PUCHAR TargetKey,
  413. OUT PUCHAR GroupKey,
  414. OUT PUCHAR MyKey
  415. )
  416. {
  417. PLIST_ENTRY Scan ;
  418. PXTCB_MACHINE_GROUP Group ;
  419. PXTCB_MACHINE_GROUP_ENTRY Entry ;
  420. PXTCB_MACHINE_GROUP_ENTRY Self = NULL ;
  421. ULONG i ;
  422. BOOL Success = FALSE ;
  423. EnterCriticalSection( &MachineGroupLock );
  424. Scan = MachineGroupList.Flink ;
  425. while ( Scan != &MachineGroupList )
  426. {
  427. Group = CONTAINING_RECORD( Scan, XTCB_MACHINE_GROUP, List );
  428. if ( RtlEqualUnicodeString( GroupName,
  429. &Group->Group,
  430. TRUE ) )
  431. {
  432. for ( i = 0 ; i < Group->Count ; i++ )
  433. {
  434. Entry = Group->GroupList[ i ];
  435. if ( Entry->Flags & MGROUP_ENTRY_SELF )
  436. {
  437. Self = Entry ;
  438. }
  439. if ( _wcsicmp( Origin->Buffer, Entry->MachineName ) == 0 )
  440. {
  441. //
  442. // We have a hit:
  443. //
  444. Success = TRUE ;
  445. CopyMemory( TargetKey, Entry->UniqueKey, SEED_KEY_SIZE );
  446. CopyMemory( GroupKey, Group->SeedKey, SEED_KEY_SIZE );
  447. break;
  448. }
  449. }
  450. }
  451. if ( Success )
  452. {
  453. break;
  454. }
  455. Scan = Scan->Flink ;
  456. Self = NULL ;
  457. }
  458. if ( Success && ( Self == NULL ) )
  459. {
  460. //
  461. // Continue through the group, looking for the
  462. // self entry
  463. //
  464. for ( ; i < Group->Count ; i++ )
  465. {
  466. if ( Group->GroupList[ i ]->Flags & MGROUP_ENTRY_SELF )
  467. {
  468. Self = Group->GroupList[ i ];
  469. break;
  470. }
  471. }
  472. }
  473. if ( Success )
  474. {
  475. CopyMemory( MyKey, Self->UniqueKey, SEED_KEY_SIZE );
  476. }
  477. LeaveCriticalSection( &MachineGroupLock );
  478. return Success ;
  479. }
  480. BOOL
  481. MGroupLocateKeys(
  482. IN PWSTR Target,
  483. OUT PSECURITY_STRING * GroupName,
  484. OUT PUCHAR TargetKey,
  485. OUT PUCHAR GroupKey,
  486. OUT PUCHAR MyKey
  487. )
  488. {
  489. PLIST_ENTRY Scan ;
  490. PXTCB_MACHINE_GROUP Group ;
  491. PXTCB_MACHINE_GROUP_ENTRY Entry ;
  492. PXTCB_MACHINE_GROUP_ENTRY Self = NULL ;
  493. ULONG i ;
  494. BOOL Success = FALSE ;
  495. EnterCriticalSection( &MachineGroupLock );
  496. Scan = MachineGroupList.Flink ;
  497. while ( Scan != &MachineGroupList )
  498. {
  499. Group = CONTAINING_RECORD( Scan, XTCB_MACHINE_GROUP, List );
  500. for ( i = 0 ; i < Group->Count ; i++ )
  501. {
  502. Entry = Group->GroupList[ i ];
  503. if ( Entry->Flags & MGROUP_ENTRY_SELF )
  504. {
  505. Self = Entry ;
  506. }
  507. if ( _wcsicmp( Target, Entry->MachineName ) == 0 )
  508. {
  509. //
  510. // We have a hit:
  511. //
  512. Success = TRUE ;
  513. CopyMemory( TargetKey, Entry->UniqueKey, SEED_KEY_SIZE );
  514. CopyMemory( GroupKey, Group->SeedKey, SEED_KEY_SIZE );
  515. *GroupName = &Group->Group ;
  516. break;
  517. }
  518. }
  519. if ( Success )
  520. {
  521. break;
  522. }
  523. Scan = Scan->Flink ;
  524. Self = NULL ;
  525. }
  526. if ( Success && ( Self == NULL ) )
  527. {
  528. //
  529. // Continue through the group, looking for the
  530. // self entry
  531. //
  532. for ( ; i < Group->Count ; i++ )
  533. {
  534. if ( Group->GroupList[ i ]->Flags & MGROUP_ENTRY_SELF )
  535. {
  536. Self = Group->GroupList[ i ];
  537. break;
  538. }
  539. }
  540. }
  541. if ( Success )
  542. {
  543. CopyMemory( MyKey, Self->UniqueKey, SEED_KEY_SIZE );
  544. }
  545. LeaveCriticalSection( &MachineGroupLock );
  546. return Success ;
  547. }
  548. BOOL
  549. MGroupParseTarget(
  550. PWSTR TargetSpn,
  551. PWSTR * MachineName
  552. )
  553. {
  554. PWSTR Scan ;
  555. PWSTR Tail ;
  556. PWSTR Copy ;
  557. ULONG Length ;
  558. *MachineName = NULL ;
  559. Scan = wcschr( TargetSpn, L'/' );
  560. if ( !Scan )
  561. {
  562. return FALSE ;
  563. }
  564. Scan++ ;
  565. Tail = wcschr( Scan, L'/' );
  566. if ( Tail != NULL )
  567. {
  568. //
  569. // three-part SPN (e.g. HOST/hostname.domain.com).
  570. // null out this slash for now
  571. //
  572. *Tail = L'\0';
  573. }
  574. Length = wcslen( Scan );
  575. Copy = LocalAlloc( LMEM_FIXED, (Length + 1) * sizeof( WCHAR ) );
  576. if ( Copy )
  577. {
  578. CopyMemory( Copy, Scan, (Length + 1) * sizeof( WCHAR ) );
  579. }
  580. if ( Tail )
  581. {
  582. *Tail = L'/' ;
  583. }
  584. *MachineName = Copy ;
  585. return ( Copy != NULL );
  586. }