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.

954 lines
21 KiB

  1. //+-----------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) Microsoft Corporation 1992 - 1997
  6. //
  7. // File: sidcache.cxx
  8. //
  9. // Contents: routines to cache username->sid translations to speed up
  10. // logon performance
  11. //
  12. //
  13. // History: 27-May-1998 MikeSw Created
  14. //
  15. //------------------------------------------------------------------------
  16. #include <kerb.hxx>
  17. #include <kerbp.h>
  18. #define KERB_LOGON_SID_CACHE_KEY L"SidCache"
  19. #define KERB_LOGON_SID_CACHE_ENTRIES L"CacheEntries"
  20. #define KERB_LOGON_SID_CACHE_ENTRY_NAME L"Entry%d"
  21. #define KERB_MACHINE_SID_CACHE_NAME L"MachineSid"
  22. #define KERB_LOGON_SID_CACHE_MAX_ENTRIES 1000
  23. #define KERB_LOGON_SID_CACHE_DEFAULT_ENTRIES 10
  24. #define KERB_LOGON_SID_CACHE_ENTRY_NAME_SIZE (sizeof(L"Entry") * 4*sizeof(WCHAR))
  25. #define KERB_LOGON_SID_CACHE_VERSION 0
  26. KERBEROS_LIST KerbSidCache;
  27. HKEY KerbSidCacheKey;
  28. ULONG KerbSidCacheMaxEntries = KERB_LOGON_SID_CACHE_DEFAULT_ENTRIES;
  29. ULONG KerbSidCacheEntries;
  30. #define VALIDATE_POINTER(Ptr,Size,Base,Bound,NewBase,Type) \
  31. if (((PUCHAR)(Ptr) < (PUCHAR)(Base)) || (((PUCHAR)(Ptr) + (Size)) > (PUCHAR)(Bound))) \
  32. { \
  33. Status = STATUS_INVALID_PARAMETER; \
  34. goto Cleanup; \
  35. } \
  36. else \
  37. { \
  38. (Ptr) = (Type) ((PUCHAR) (Ptr) - (ULONG_PTR) Base + (ULONG_PTR) NewBase); \
  39. } \
  40. //+-------------------------------------------------------------------------
  41. //
  42. // Function: KerbVerifyUnpackAndLinkSidCacheEntry
  43. //
  44. // Synopsis: Unmarshalls the entry & verifies that the pointers all
  45. // match up within the buffer. If this is the case, it
  46. // inserts the entry into the list & zeroes out the pointer
  47. // so the caller won't free it.
  48. //
  49. // Effects:
  50. //
  51. // Arguments:
  52. //
  53. // Requires:
  54. //
  55. // Returns:
  56. //
  57. // Notes:
  58. //
  59. //
  60. //--------------------------------------------------------------------------
  61. NTSTATUS
  62. KerbVerifyUnpackAndLinkSidCacheEntry(
  63. IN PKERB_SID_CACHE_ENTRY * SidCacheEntry,
  64. IN ULONG CacheEntrySize
  65. )
  66. {
  67. NTSTATUS Status = STATUS_SUCCESS;
  68. PKERB_SID_CACHE_ENTRY CacheEntry = *SidCacheEntry;
  69. PUCHAR Bound;
  70. //
  71. // First check the base structure size
  72. //
  73. if (CacheEntrySize < sizeof(KERB_SID_CACHE_ENTRY))
  74. {
  75. Status = STATUS_INVALID_PARAMETER;
  76. goto Cleanup;
  77. }
  78. //
  79. // Now check the version
  80. //
  81. if (CacheEntry->Version != KERB_LOGON_SID_CACHE_VERSION)
  82. {
  83. Status = STATUS_INVALID_PARAMETER;
  84. goto Cleanup;
  85. }
  86. if (CacheEntry->Size != CacheEntrySize)
  87. {
  88. Status = STATUS_INVALID_PARAMETER;
  89. goto Cleanup;
  90. }
  91. //
  92. // Now check all the pointers
  93. //
  94. Bound = (PUCHAR) CacheEntry->Base + CacheEntrySize;
  95. VALIDATE_POINTER(
  96. CacheEntry->Sid,
  97. RtlLengthRequiredSid(5), // space for 5 sub authorities
  98. CacheEntry->Base,
  99. Bound,
  100. CacheEntry,
  101. PSID
  102. );
  103. VALIDATE_POINTER(
  104. CacheEntry->LogonUserName.Buffer,
  105. CacheEntry->LogonUserName.MaximumLength,
  106. CacheEntry->Base,
  107. Bound,
  108. CacheEntry,
  109. PWSTR
  110. );
  111. VALIDATE_POINTER(
  112. CacheEntry->LogonDomainName.Buffer,
  113. CacheEntry->LogonDomainName.MaximumLength,
  114. CacheEntry->Base,
  115. Bound,
  116. CacheEntry,
  117. PWSTR
  118. );
  119. VALIDATE_POINTER(
  120. CacheEntry->LogonRealm.Buffer,
  121. CacheEntry->LogonRealm.MaximumLength,
  122. CacheEntry->Base,
  123. Bound,
  124. CacheEntry,
  125. PWSTR
  126. );
  127. KerbInitializeListEntry(
  128. &CacheEntry->Next
  129. );
  130. //
  131. // This inserts at the head, not the tail
  132. //
  133. KerbInsertListEntryTail(
  134. &CacheEntry->Next,
  135. &KerbSidCache
  136. );
  137. *SidCacheEntry = NULL;
  138. Cleanup:
  139. return(Status);
  140. }
  141. //+-------------------------------------------------------------------------
  142. //
  143. // Function: KerbInitializeLogonSidCache
  144. //
  145. // Synopsis: Initializes the list of cached logon sids
  146. //
  147. // Effects: Reads data from the registry
  148. //
  149. // Arguments:
  150. //
  151. // Requires:
  152. //
  153. // Returns:
  154. //
  155. // Notes:
  156. //
  157. //
  158. //--------------------------------------------------------------------------
  159. NTSTATUS
  160. KerbInitializeLogonSidCache(
  161. VOID
  162. )
  163. {
  164. NTSTATUS Status = STATUS_SUCCESS;
  165. DWORD RegErr = ERROR_SUCCESS;
  166. DWORD Disposition = 0;
  167. PKERB_SID_CACHE_ENTRY NextEntry = NULL;
  168. ULONG NextEntrySize = 0;
  169. ULONG ValueType;
  170. ULONG Index;
  171. HKEY KerbParamKey = NULL;
  172. WCHAR EntryName[KERB_LOGON_SID_CACHE_ENTRY_NAME_SIZE];
  173. //
  174. // Initialize the list
  175. //
  176. Status = KerbInitializeList(&KerbSidCache);
  177. if (!NT_SUCCESS(Status))
  178. {
  179. goto Cleanup;
  180. }
  181. //
  182. // Create the sid cache key
  183. //
  184. RegErr = RegCreateKeyEx(
  185. HKEY_LOCAL_MACHINE,
  186. KERB_PARAMETER_PATH,
  187. 0,
  188. NULL,
  189. 0,
  190. KEY_ALL_ACCESS,
  191. 0,
  192. &KerbParamKey,
  193. &Disposition
  194. );
  195. if (RegErr != ERROR_SUCCESS)
  196. {
  197. DebugLog((DEB_ERROR,"Failed to create %ws key: %d\n",KERB_PARAMETER_PATH, RegErr));
  198. Status = STATUS_UNSUCCESSFUL;
  199. goto Cleanup;
  200. }
  201. RegErr = RegCreateKeyEx(
  202. KerbParamKey,
  203. KERB_LOGON_SID_CACHE_KEY,
  204. 0, // reserved
  205. NULL, // no class
  206. 0, // no options
  207. KEY_ALL_ACCESS,
  208. NULL, // no security attributes
  209. &KerbSidCacheKey,
  210. &Disposition
  211. );
  212. if (RegErr != ERROR_SUCCESS)
  213. {
  214. DebugLog((DEB_ERROR,"Failed to create key %ws: %d\n",KERB_LOGON_SID_CACHE_KEY, RegErr));
  215. Status = STATUS_UNSUCCESSFUL;
  216. goto Cleanup;
  217. }
  218. //
  219. // Read out the size of the cache
  220. //
  221. NextEntrySize = sizeof(ULONG);
  222. RegErr = RegQueryValueEx(
  223. KerbSidCacheKey,
  224. KERB_LOGON_SID_CACHE_ENTRIES,
  225. NULL, // reserved,
  226. &ValueType,
  227. (PUCHAR) &KerbSidCacheMaxEntries,
  228. &NextEntrySize
  229. );
  230. if (RegErr == ERROR_SUCCESS)
  231. {
  232. //
  233. // Make sure the value is within the range & is of the correc type
  234. //
  235. if ( (ValueType != REG_DWORD) ||
  236. (KerbSidCacheMaxEntries > KERB_LOGON_SID_CACHE_MAX_ENTRIES) ||
  237. (KerbSidCacheMaxEntries == 0) )
  238. {
  239. KerbSidCacheMaxEntries = KERB_LOGON_SID_CACHE_DEFAULT_ENTRIES;
  240. }
  241. }
  242. //
  243. // Now read in all the entries. Loop through up to the max number of
  244. // entries, reading the entry, and inserting at the tail of the list.
  245. //
  246. for (Index = 0; Index < KerbSidCacheMaxEntries ; Index++ )
  247. {
  248. swprintf(EntryName,KERB_LOGON_SID_CACHE_ENTRY_NAME, Index);
  249. //
  250. // Query the size of the entry
  251. //
  252. NextEntrySize = NULL;
  253. RegErr = RegQueryValueEx(
  254. KerbSidCacheKey,
  255. EntryName,
  256. NULL,
  257. &ValueType,
  258. (PUCHAR) NextEntry,
  259. &NextEntrySize
  260. );
  261. if ((RegErr == ERROR_SUCCESS) && (ValueType == REG_BINARY))
  262. {
  263. //
  264. // Allocate space for the entry and re-query to get the real
  265. // value.
  266. //
  267. NextEntry = (PKERB_SID_CACHE_ENTRY) KerbAllocate(NextEntrySize);
  268. if (NextEntry == NULL)
  269. {
  270. Status = STATUS_INSUFFICIENT_RESOURCES;
  271. goto Cleanup;
  272. }
  273. RegErr = RegQueryValueEx(
  274. KerbSidCacheKey,
  275. EntryName,
  276. NULL,
  277. &ValueType,
  278. (PUCHAR) NextEntry,
  279. &NextEntrySize
  280. );
  281. if (RegErr != ERROR_SUCCESS)
  282. {
  283. DebugLog((DEB_ERROR,"Failed to query for sid cache value: %d\n",
  284. RegErr ));
  285. Status = STATUS_UNSUCCESSFUL;
  286. goto Cleanup;
  287. }
  288. //
  289. // Call a helper routine to unpack,verify, and insert
  290. Status = KerbVerifyUnpackAndLinkSidCacheEntry(
  291. &NextEntry,
  292. NextEntrySize
  293. );
  294. //
  295. // If the entry was invalid, remove it now
  296. //
  297. if (!NT_SUCCESS(Status))
  298. {
  299. (VOID) RegDeleteValue(
  300. KerbSidCacheKey,
  301. EntryName
  302. );
  303. Status = STATUS_SUCCESS;
  304. }
  305. if (NextEntry != NULL)
  306. {
  307. KerbFree(NextEntry);
  308. NextEntry = NULL;
  309. }
  310. NextEntrySize = 0;
  311. }
  312. }
  313. Cleanup:
  314. if (KerbParamKey != NULL)
  315. {
  316. RegCloseKey(KerbParamKey);
  317. }
  318. if (NextEntry != NULL)
  319. {
  320. KerbFree(NextEntry);
  321. }
  322. if (!NT_SUCCESS(Status))
  323. {
  324. if (KerbSidCacheKey != NULL)
  325. {
  326. RegCloseKey(KerbSidCacheKey);
  327. KerbSidCacheKey = NULL;
  328. }
  329. }
  330. return(Status);
  331. }
  332. //+-------------------------------------------------------------------------
  333. //
  334. // Function: KerbScavengeSidCache
  335. //
  336. // Synopsis: removes any stale entries from the sid cache to make it fit
  337. // within bounds
  338. //
  339. // Effects:
  340. //
  341. // Arguments:
  342. //
  343. // Requires:
  344. //
  345. // Returns:
  346. //
  347. // Notes:
  348. //
  349. //
  350. //--------------------------------------------------------------------------
  351. VOID
  352. KerbScavengeSidCache(
  353. VOID
  354. )
  355. {
  356. PKERB_SID_CACHE_ENTRY CacheEntry;
  357. while (KerbSidCacheEntries > KerbSidCacheMaxEntries)
  358. {
  359. //
  360. // Pickup the last entry and remove it
  361. //
  362. CacheEntry = CONTAINING_RECORD(KerbSidCache.List.Blink, KERB_SID_CACHE_ENTRY, Next.Next);
  363. KerbReferenceListEntry(
  364. &KerbSidCache,
  365. &CacheEntry->Next,
  366. TRUE
  367. );
  368. KerbDereferenceSidCacheEntry(
  369. CacheEntry
  370. );
  371. KerbSidCacheEntries--;
  372. }
  373. }
  374. //+-------------------------------------------------------------------------
  375. //
  376. // Function: KerbWriteSidCache
  377. //
  378. // Synopsis: Writes the sid cache back to the registry
  379. //
  380. // Effects:
  381. //
  382. // Arguments:
  383. //
  384. // Requires:
  385. //
  386. // Returns:
  387. //
  388. // Notes:
  389. //
  390. //
  391. //--------------------------------------------------------------------------
  392. NTSTATUS
  393. KerbWriteSidCache(
  394. VOID
  395. )
  396. {
  397. ULONG Index = 0;
  398. WCHAR EntryName[KERB_LOGON_SID_CACHE_ENTRY_NAME_SIZE];
  399. PLIST_ENTRY ListEntry;
  400. PKERB_SID_CACHE_ENTRY CacheEntry;
  401. for (ListEntry = KerbSidCache.List.Flink ;
  402. ListEntry != &KerbSidCache.List ;
  403. ListEntry = ListEntry->Flink )
  404. {
  405. CacheEntry = CONTAINING_RECORD(ListEntry, KERB_SID_CACHE_ENTRY, Next.Next);
  406. swprintf(EntryName,KERB_LOGON_SID_CACHE_ENTRY_NAME, Index++);
  407. (VOID) RegSetValueEx(
  408. KerbSidCacheKey,
  409. EntryName,
  410. 0, // reserved
  411. REG_BINARY,
  412. (PUCHAR) CacheEntry,
  413. CacheEntry->Size
  414. );
  415. }
  416. return(STATUS_SUCCESS);
  417. }
  418. //+-------------------------------------------------------------------------
  419. //
  420. // Function: KerbPromoteSidCacheEntry
  421. //
  422. // Synopsis: Moves a cache entry to the front of the list
  423. //
  424. // Effects:
  425. //
  426. // Arguments:
  427. //
  428. // Requires:
  429. //
  430. // Returns:
  431. //
  432. // Notes:
  433. //
  434. //
  435. //--------------------------------------------------------------------------
  436. VOID
  437. KerbPromoteSidCacheEntry(
  438. IN PKERB_SID_CACHE_ENTRY CacheEntry
  439. )
  440. {
  441. KerbLockList(&KerbSidCache);
  442. RemoveEntryList(&CacheEntry->Next.Next);
  443. InsertHeadList(&KerbSidCache.List, &CacheEntry->Next.Next);
  444. KerbUnlockList(&KerbSidCache);
  445. }
  446. //+-------------------------------------------------------------------------
  447. //
  448. // Function: KerbLocateLogonSidCacheEntry
  449. //
  450. // Synopsis: Locates a logon sid cache entry by user name and domain name
  451. //
  452. // Effects:
  453. //
  454. // Arguments:
  455. //
  456. // Requires:
  457. //
  458. // Returns: returns a referenced cache entry, if available
  459. //
  460. // Notes:
  461. //
  462. //
  463. //--------------------------------------------------------------------------
  464. PKERB_SID_CACHE_ENTRY
  465. KerbLocateLogonSidCacheEntry(
  466. IN PUNICODE_STRING LogonUserName,
  467. IN PUNICODE_STRING LogonDomainName
  468. )
  469. {
  470. PKERB_SID_CACHE_ENTRY CacheEntry = NULL;
  471. PLIST_ENTRY ListEntry;
  472. if (!KerbGlobalUseSidCache)
  473. {
  474. return(NULL);
  475. }
  476. KerbLockList(&KerbSidCache);
  477. for (ListEntry = KerbSidCache.List.Flink ;
  478. ListEntry != &KerbSidCache.List ;
  479. ListEntry = ListEntry->Flink )
  480. {
  481. CacheEntry = CONTAINING_RECORD(ListEntry, KERB_SID_CACHE_ENTRY, Next.Next);
  482. if (RtlEqualUnicodeString(
  483. &CacheEntry->LogonUserName,
  484. LogonUserName,
  485. TRUE
  486. ) &&
  487. RtlEqualUnicodeString(
  488. &CacheEntry->LogonDomainName,
  489. LogonDomainName,
  490. TRUE
  491. ) )
  492. {
  493. //
  494. // We found it
  495. //
  496. KerbReferenceListEntry(
  497. &KerbSidCache,
  498. &CacheEntry->Next,
  499. FALSE // don't remove
  500. );
  501. break;
  502. }
  503. CacheEntry = NULL;
  504. }
  505. KerbUnlockList(&KerbSidCache);
  506. return(CacheEntry);
  507. }
  508. //+-------------------------------------------------------------------------
  509. //
  510. // Function: KerbDereferenceSidCacheEntry
  511. //
  512. // Synopsis: Dereferences the entry, possibly freeing it
  513. //
  514. // Effects:
  515. //
  516. // Arguments:
  517. //
  518. // Requires:
  519. //
  520. // Returns:
  521. //
  522. // Notes:
  523. //
  524. //
  525. //--------------------------------------------------------------------------
  526. VOID
  527. KerbDereferenceSidCacheEntry(
  528. IN PKERB_SID_CACHE_ENTRY CacheEntry
  529. )
  530. {
  531. KerbLockList(&KerbSidCache);
  532. if (KerbDereferenceListEntry(
  533. &CacheEntry->Next,
  534. &KerbSidCache
  535. ))
  536. {
  537. KerbFree(CacheEntry);
  538. }
  539. KerbUnlockList(&KerbSidCache);
  540. }
  541. //+-------------------------------------------------------------------------
  542. //
  543. // Function: KerbCacheLogonSid
  544. //
  545. // Synopsis: Caches a username/domainname & Sid combination for logon
  546. //
  547. // Effects: caches the user name/domainname/sid in the registry
  548. //
  549. // Arguments: LogonUserName - user name supplied to LogonUser
  550. // LogonDomainName - domain name supplied to LogonUser
  551. // LogonRealm - Realm actually containing the account
  552. // UserSid - Sid of user who just logged on
  553. //
  554. // Requires:
  555. //
  556. // Returns: none - this is just a cache
  557. //
  558. // Notes:
  559. //
  560. //
  561. //--------------------------------------------------------------------------
  562. VOID
  563. KerbCacheLogonSid(
  564. IN PUNICODE_STRING LogonUserName,
  565. IN PUNICODE_STRING LogonDomainName,
  566. IN PUNICODE_STRING LogonRealm,
  567. IN PSID UserSid
  568. )
  569. {
  570. NTSTATUS Status = STATUS_SUCCESS;
  571. PKERB_SID_CACHE_ENTRY CacheEntry;
  572. ULONG CacheEntrySize = 0;
  573. PUCHAR Where;
  574. if (!KerbGlobalUseSidCache)
  575. {
  576. return;
  577. }
  578. CacheEntry = KerbLocateLogonSidCacheEntry(
  579. LogonUserName,
  580. LogonDomainName
  581. );
  582. //
  583. // If we found the entry & it is the same as this one, move it up in
  584. // the list
  585. //
  586. if (CacheEntry != NULL)
  587. {
  588. if (RtlEqualUnicodeString(
  589. &CacheEntry->LogonRealm,
  590. LogonRealm,
  591. TRUE
  592. ) &&
  593. RtlEqualSid(
  594. CacheEntry->Sid,
  595. UserSid
  596. ) )
  597. {
  598. KerbPromoteSidCacheEntry(
  599. CacheEntry
  600. );
  601. goto Cleanup;
  602. }
  603. else
  604. {
  605. //
  606. // Remove it from the list
  607. //
  608. KerbLockList(&KerbSidCache);
  609. KerbReferenceListEntry(
  610. &KerbSidCache,
  611. &CacheEntry->Next,
  612. TRUE // remove
  613. );
  614. KerbDereferenceSidCacheEntry(
  615. CacheEntry
  616. );
  617. KerbDereferenceSidCacheEntry(
  618. CacheEntry
  619. );
  620. KerbUnlockList(&KerbSidCache);
  621. CacheEntry = NULL;
  622. }
  623. }
  624. //
  625. // Now build a new entry
  626. //
  627. CacheEntrySize = sizeof(KERB_SID_CACHE_ENTRY) +
  628. RtlLengthSid(UserSid) +
  629. LogonUserName->Length + sizeof(WCHAR) +
  630. LogonDomainName->Length + sizeof(WCHAR) +
  631. LogonRealm->Length + sizeof(WCHAR);
  632. CacheEntry = (PKERB_SID_CACHE_ENTRY) KerbAllocate(CacheEntrySize);
  633. if (CacheEntry == NULL)
  634. {
  635. Status = STATUS_INSUFFICIENT_RESOURCES;
  636. goto Cleanup;
  637. }
  638. //
  639. // Fill in all the fixed fields.
  640. //
  641. KerbInitializeListEntry(
  642. &CacheEntry->Next
  643. );
  644. CacheEntry->Base = (ULONG_PTR) CacheEntry;
  645. CacheEntry->Version = KERB_LOGON_SID_CACHE_VERSION;
  646. CacheEntry->Size = CacheEntrySize;
  647. Where = (PUCHAR) (CacheEntry + 1);
  648. //
  649. // Copy in the sid
  650. //
  651. CacheEntry->Sid = (PSID) Where;
  652. Where += RtlLengthSid( UserSid );
  653. RtlCopyMemory(
  654. CacheEntry->Sid,
  655. UserSid,
  656. Where - (PUCHAR) CacheEntry->Sid
  657. );
  658. //
  659. // Put the various strings
  660. //
  661. KerbPutString(
  662. LogonUserName,
  663. &CacheEntry->LogonUserName,
  664. 0, // no offset
  665. &Where
  666. );
  667. KerbPutString(
  668. LogonDomainName,
  669. &CacheEntry->LogonDomainName,
  670. 0, // no offset
  671. &Where
  672. );
  673. KerbPutString(
  674. LogonRealm,
  675. &CacheEntry->LogonRealm,
  676. 0, // no offset
  677. &Where
  678. );
  679. //
  680. // Insert it into the list
  681. //
  682. KerbLockList( &KerbSidCache );
  683. KerbInsertListEntry(
  684. &CacheEntry->Next,
  685. &KerbSidCache
  686. );
  687. //
  688. // Dereference it because we aren't returning the cache entry
  689. //
  690. KerbDereferenceListEntry(
  691. &CacheEntry->Next,
  692. &KerbSidCache
  693. );
  694. KerbSidCacheEntries++;
  695. //
  696. // Remove any extra entries
  697. //
  698. KerbScavengeSidCache();
  699. KerbUnlockList ( &KerbSidCache );
  700. Cleanup:
  701. if (NT_SUCCESS(Status))
  702. {
  703. KerbWriteSidCache();
  704. }
  705. }
  706. //+-------------------------------------------------------------------------
  707. //
  708. // Function: KerbWriteMachineSid
  709. //
  710. // Synopsis: Writes the machine account sid to the registry
  711. //
  712. // Effects:
  713. //
  714. // Arguments: MachineSid - If present, is stored. If not present,
  715. // is deleted from registry
  716. //
  717. // Requires:
  718. //
  719. // Returns:
  720. //
  721. // Notes:
  722. //
  723. //
  724. //--------------------------------------------------------------------------
  725. VOID
  726. KerbWriteMachineSid(
  727. IN OPTIONAL PSID MachineSid
  728. )
  729. {
  730. if (ARGUMENT_PRESENT(MachineSid))
  731. {
  732. (VOID) RegSetValueEx(
  733. KerbSidCacheKey,
  734. KERB_MACHINE_SID_CACHE_NAME,
  735. 0, // reserved
  736. REG_BINARY,
  737. (PUCHAR) MachineSid,
  738. RtlLengthSid(MachineSid)
  739. );
  740. }
  741. else
  742. {
  743. (VOID) RegDeleteValue(
  744. KerbSidCacheKey,
  745. KERB_MACHINE_SID_CACHE_NAME
  746. );
  747. }
  748. }
  749. //+-------------------------------------------------------------------------
  750. //
  751. // Function: Reads the machine sid from the registry
  752. //
  753. // Synopsis:
  754. //
  755. // Effects:
  756. //
  757. // Arguments:
  758. //
  759. // Requires:
  760. //
  761. // Returns:
  762. //
  763. // Notes:
  764. //
  765. //
  766. //--------------------------------------------------------------------------
  767. NTSTATUS
  768. KerbGetMachineSid(
  769. OUT PSID * MachineSid
  770. )
  771. {
  772. BYTE Buffer[sizeof(SID) + SID_MAX_SUB_AUTHORITIES * sizeof(ULONG)];
  773. ULONG BufferSize = sizeof(Buffer);
  774. PSID Sid = (PSID) Buffer;
  775. DWORD RegErr;
  776. NTSTATUS Status = STATUS_SUCCESS;
  777. ULONG ValueType;
  778. *MachineSid = NULL;
  779. RegErr = RegQueryValueEx(
  780. KerbSidCacheKey,
  781. KERB_MACHINE_SID_CACHE_NAME,
  782. NULL,
  783. &ValueType,
  784. Buffer,
  785. &BufferSize
  786. );
  787. if (RegErr != ERROR_SUCCESS)
  788. {
  789. DebugLog((DEB_ERROR,"Failed to query for machine sid value: %d\n",
  790. RegErr ));
  791. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  792. goto Cleanup;
  793. }
  794. //
  795. // If it isn't valid, delete it now
  796. //
  797. if (!RtlValidSid(Sid))
  798. {
  799. (VOID) RegDeleteValue(
  800. KerbSidCacheKey,
  801. KERB_MACHINE_SID_CACHE_NAME
  802. );
  803. }
  804. *MachineSid = (PSID) KerbAllocate(RtlLengthSid(Buffer));
  805. if (*MachineSid == NULL)
  806. {
  807. Status = STATUS_INSUFFICIENT_RESOURCES;
  808. goto Cleanup;
  809. }
  810. RtlCopyMemory(
  811. *MachineSid,
  812. Sid,
  813. RtlLengthSid(Sid)
  814. );
  815. Cleanup:
  816. return(Status);
  817. }