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.

1181 lines
30 KiB

  1. //+-----------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) Microsoft Corporation 1992 - 1996
  6. //
  7. // File: kerberos.cxx
  8. //
  9. // Contents: main entrypoints for the Kerberos security package
  10. //
  11. //
  12. // History: 16-April-1996 Created MikeSw
  13. // 26-Sep-1998 ChandanS
  14. // Added more debugging support etc.
  15. //
  16. //------------------------------------------------------------------------
  17. #include <kerb.hxx>
  18. #define KERBP_ALLOCATE
  19. #include <kerbp.h>
  20. #include <userapi.h>
  21. #include <safeboot.h>
  22. #include <spncache.h>
  23. #include <wow64t.h>
  24. #ifdef RETAIL_LOG_SUPPORT
  25. static TCHAR THIS_FILE[]=TEXT(__FILE__);
  26. HANDLE g_hParamEvent = NULL;
  27. HKEY g_hKeyParams = NULL;
  28. #endif
  29. #ifndef WIN32_CHICAGO
  30. #ifdef RETAIL_LOG_SUPPORT
  31. DEFINE_DEBUG2(Kerb);
  32. extern DWORD KSuppInfoLevel; // needed to adjust values for common2 dir
  33. HANDLE g_hWait = NULL;
  34. DEBUG_KEY KerbDebugKeys[] = { {DEB_ERROR, "Error"},
  35. {DEB_WARN, "Warn"},
  36. {DEB_TRACE, "Trace"},
  37. {DEB_TRACE_API, "API"},
  38. {DEB_TRACE_CRED, "Cred"},
  39. {DEB_TRACE_CTXT, "Ctxt"},
  40. {DEB_TRACE_LSESS, "LSess"},
  41. {DEB_TRACE_LOGON, "Logon"},
  42. {DEB_TRACE_KDC, "KDC"},
  43. {DEB_TRACE_CTXT2, "Ctxt2"},
  44. {DEB_TRACE_TIME, "Time"},
  45. {DEB_TRACE_LOCKS, "Locks"},
  46. {DEB_TRACE_LEAKS, "Leaks"},
  47. {DEB_TRACE_SPN_CACHE, "SPN"},
  48. {DEB_TRACE_LOOPBACK, "LoopBack"},
  49. {DEB_TRACE_U2U, "U2U"},
  50. {0, NULL},
  51. };
  52. VOID
  53. KerbInitializeDebugging(
  54. VOID
  55. )
  56. {
  57. KerbInitDebug(KerbDebugKeys);
  58. }
  59. ////////////////////////////////////////////////////////////////////
  60. //
  61. // Name: KerbGetKerbRegParams
  62. //
  63. // Synopsis: Gets the debug paramaters from the registry
  64. //
  65. // Arguments: HKEY to HKLM/System/CCS/LSA/Kerberos
  66. //
  67. // Notes: Sets KerbInfolevel for debug spew
  68. //
  69. void
  70. KerbGetKerbRegParams(HKEY ParamKey)
  71. {
  72. DWORD cbType, tmpInfoLevel = KerbInfoLevel, cbSize;
  73. DWORD dwErr;
  74. cbSize = sizeof(tmpInfoLevel);
  75. dwErr = RegQueryValueExW(
  76. ParamKey,
  77. WSZ_KERBDEBUGLEVEL,
  78. NULL,
  79. &cbType,
  80. (LPBYTE)&tmpInfoLevel,
  81. &cbSize
  82. );
  83. if (dwErr != ERROR_SUCCESS)
  84. {
  85. if (dwErr == ERROR_FILE_NOT_FOUND)
  86. {
  87. // no registry value is present, don't want info
  88. // so reset to defaults
  89. #if DBG
  90. KSuppInfoLevel = KerbInfoLevel = DEB_ERROR;
  91. #else // fre
  92. KSuppInfoLevel = KerbInfoLevel = 0;
  93. #endif
  94. }else{
  95. D_DebugLog((DEB_WARN, "Failed to query DebugLevel: 0x%x\n", dwErr));
  96. }
  97. }
  98. // TBD: Validate flags?
  99. KSuppInfoLevel = KerbInfoLevel = tmpInfoLevel;
  100. cbSize = sizeof(tmpInfoLevel);
  101. dwErr = RegQueryValueExW(
  102. ParamKey,
  103. WSZ_FILELOG,
  104. NULL,
  105. &cbType,
  106. (LPBYTE)&tmpInfoLevel,
  107. &cbSize
  108. );
  109. if (dwErr == ERROR_SUCCESS)
  110. {
  111. KerbSetLoggingOption((BOOL) tmpInfoLevel);
  112. }
  113. else if (dwErr == ERROR_FILE_NOT_FOUND)
  114. {
  115. KerbSetLoggingOption(FALSE);
  116. }
  117. cbSize = sizeof(tmpInfoLevel);
  118. dwErr = RegQueryValueExW(
  119. ParamKey,
  120. KERB_PARAMETER_RETRY_PDC,
  121. NULL,
  122. &cbType,
  123. (LPBYTE)&tmpInfoLevel,
  124. &cbSize
  125. );
  126. if (dwErr == ERROR_SUCCESS)
  127. {
  128. if( tmpInfoLevel != 0 )
  129. {
  130. KerbGlobalRetryPdc = TRUE;
  131. } else {
  132. KerbGlobalRetryPdc = FALSE;
  133. }
  134. }
  135. else if (dwErr == ERROR_FILE_NOT_FOUND)
  136. {
  137. KerbGlobalRetryPdc = FALSE;
  138. }
  139. return;
  140. }
  141. ////////////////////////////////////////////////////////////////////
  142. //
  143. // Name: KerbWaitCleanup
  144. //
  145. // Synopsis: Cleans up wait from KerbWatchParamKey()
  146. //
  147. // Arguments: <none>
  148. //
  149. // Notes: .
  150. //
  151. void
  152. KerbWaitCleanup()
  153. {
  154. NTSTATUS Status = STATUS_SUCCESS;
  155. if (NULL != g_hWait) {
  156. Status = RtlDeregisterWait(g_hWait);
  157. if (NT_SUCCESS(Status) && NULL != g_hParamEvent ) {
  158. CloseHandle(g_hParamEvent);
  159. }
  160. }
  161. }
  162. ////////////////////////////////////////////////////////////////////
  163. //
  164. // Name: KerbWatchParamKey
  165. //
  166. // Synopsis: Sets RegNotifyChangeKeyValue() on param key, initializes
  167. // debug level, then utilizes thread pool to wait on
  168. // changes to this registry key. Enables dynamic debug
  169. // level changes, as this function will also be callback
  170. // if registry key modified.
  171. //
  172. // Arguments: pCtxt is actually a HANDLE to an event. This event
  173. // will be triggered when key is modified.
  174. //
  175. // Notes: .
  176. //
  177. VOID
  178. KerbWatchKerbParamKey(PVOID pCtxt,
  179. BOOLEAN fWaitStatus)
  180. {
  181. NTSTATUS Status;
  182. LONG lRes = ERROR_SUCCESS;
  183. if (NULL == g_hKeyParams) // first time we've been called.
  184. {
  185. lRes = RegOpenKeyExW(
  186. HKEY_LOCAL_MACHINE,
  187. KERB_PARAMETER_PATH,
  188. 0,
  189. KEY_READ,
  190. &g_hKeyParams);
  191. if (ERROR_SUCCESS != lRes)
  192. {
  193. D_DebugLog((DEB_WARN,"Failed to open kerberos key: 0x%x\n", lRes));
  194. goto Reregister;
  195. }
  196. }
  197. if (NULL != g_hWait)
  198. {
  199. Status = RtlDeregisterWait(g_hWait);
  200. if (!NT_SUCCESS(Status))
  201. {
  202. D_DebugLog((DEB_WARN, "Failed to Deregister wait on registry key: 0x%x\n", Status));
  203. goto Reregister;
  204. }
  205. }
  206. lRes = RegNotifyChangeKeyValue(
  207. g_hKeyParams,
  208. FALSE,
  209. REG_NOTIFY_CHANGE_LAST_SET,
  210. (HANDLE) pCtxt,
  211. TRUE);
  212. if (ERROR_SUCCESS != lRes)
  213. {
  214. D_DebugLog((DEB_ERROR,"Debug RegNotify setup failed: 0x%x\n", lRes));
  215. // we're tanked now. No further notifications, so get this one
  216. }
  217. KerbGetKerbRegParams(g_hKeyParams);
  218. Reregister:
  219. Status = RtlRegisterWait(&g_hWait,
  220. (HANDLE) pCtxt,
  221. KerbWatchKerbParamKey,
  222. (HANDLE) pCtxt,
  223. INFINITE,
  224. WT_EXECUTEINPERSISTENTIOTHREAD|
  225. WT_EXECUTEONLYONCE);
  226. }
  227. #endif // RETAIL_LOG_SUPPORT
  228. NTSTATUS NTAPI
  229. SpCleanup(
  230. VOID
  231. );
  232. BOOL
  233. DllMain(
  234. HINSTANCE Module,
  235. ULONG Reason,
  236. PVOID Context
  237. )
  238. {
  239. if ( Reason == DLL_PROCESS_ATTACH )
  240. {
  241. DisableThreadLibraryCalls( Module );
  242. }
  243. else if ( Reason == DLL_PROCESS_DETACH )
  244. {
  245. #if RETAIL_LOG_SUPPORT
  246. KerbUnloadDebug();
  247. KerbWaitCleanup();
  248. #endif
  249. }
  250. return TRUE ;
  251. }
  252. //+-------------------------------------------------------------------------
  253. //
  254. // Function: SpLsaModeInitialize
  255. //
  256. // Synopsis: This function is called by the LSA when this DLL is loaded.
  257. // It returns security package function tables for all
  258. // security packages in the DLL.
  259. //
  260. // Effects:
  261. //
  262. // Arguments: LsaVersion - Version number of the LSA
  263. // PackageVersion - Returns version number of the package
  264. // Tables - Returns array of function tables for the package
  265. // TableCount - Returns number of entries in array of
  266. // function tables.
  267. //
  268. // Requires:
  269. //
  270. // Returns:
  271. //
  272. // Notes:
  273. //
  274. //
  275. //--------------------------------------------------------------------------
  276. NTSTATUS NTAPI
  277. SpLsaModeInitialize(
  278. IN ULONG LsaVersion,
  279. OUT PULONG PackageVersion,
  280. OUT PSECPKG_FUNCTION_TABLE * Tables,
  281. OUT PULONG TableCount
  282. )
  283. {
  284. KerbInitializeDebugging();
  285. #ifdef RETAIL_LOG_SUPPORT
  286. g_hParamEvent = CreateEvent(NULL,
  287. FALSE,
  288. FALSE,
  289. NULL);
  290. if (NULL == g_hParamEvent)
  291. {
  292. D_DebugLog((DEB_WARN, "CreateEvent for ParamEvent failed - 0x%x\n", GetLastError()));
  293. } else {
  294. KerbWatchKerbParamKey(g_hParamEvent, FALSE);
  295. }
  296. #endif // RETAIL_LOG_SUPPORT
  297. if (LsaVersion != SECPKG_INTERFACE_VERSION)
  298. {
  299. D_DebugLog((DEB_ERROR,"Invalid LSA version: %d. %ws, line %d\n",LsaVersion, THIS_FILE, __LINE__));
  300. return(STATUS_INVALID_PARAMETER);
  301. }
  302. KerberosFunctionTable.InitializePackage = NULL;;
  303. KerberosFunctionTable.LogonUser = NULL;
  304. KerberosFunctionTable.CallPackage = LsaApCallPackage;
  305. KerberosFunctionTable.LogonTerminated = LsaApLogonTerminated;
  306. KerberosFunctionTable.CallPackageUntrusted = LsaApCallPackageUntrusted;
  307. KerberosFunctionTable.LogonUserEx2 = LsaApLogonUserEx2;
  308. KerberosFunctionTable.Initialize = SpInitialize;
  309. KerberosFunctionTable.Shutdown = SpShutdown;
  310. KerberosFunctionTable.GetInfo = SpGetInfo;
  311. KerberosFunctionTable.AcceptCredentials = SpAcceptCredentials;
  312. KerberosFunctionTable.AcquireCredentialsHandle = SpAcquireCredentialsHandle;
  313. KerberosFunctionTable.FreeCredentialsHandle = SpFreeCredentialsHandle;
  314. KerberosFunctionTable.QueryCredentialsAttributes = SpQueryCredentialsAttributes;
  315. KerberosFunctionTable.SaveCredentials = SpSaveCredentials;
  316. KerberosFunctionTable.GetCredentials = SpGetCredentials;
  317. KerberosFunctionTable.DeleteCredentials = SpDeleteCredentials;
  318. KerberosFunctionTable.InitLsaModeContext = SpInitLsaModeContext;
  319. KerberosFunctionTable.AcceptLsaModeContext = SpAcceptLsaModeContext;
  320. KerberosFunctionTable.DeleteContext = SpDeleteContext;
  321. KerberosFunctionTable.ApplyControlToken = SpApplyControlToken;
  322. KerberosFunctionTable.GetUserInfo = SpGetUserInfo;
  323. KerberosFunctionTable.GetExtendedInformation = SpGetExtendedInformation;
  324. KerberosFunctionTable.QueryContextAttributes = SpQueryLsaModeContextAttributes;
  325. KerberosFunctionTable.CallPackagePassthrough = LsaApCallPackagePassthrough;
  326. *PackageVersion = SECPKG_INTERFACE_VERSION;
  327. *TableCount = 1;
  328. *Tables = &KerberosFunctionTable;
  329. // initialize event tracing (a/k/a WMI tracing, software tracing)
  330. KerbInitializeTrace();
  331. return(STATUS_SUCCESS);
  332. }
  333. #endif // WIN32_CHICAGO
  334. //+-------------------------------------------------------------------------
  335. //
  336. // Function: SpInitialize
  337. //
  338. // Synopsis: Initializes the Kerberos package
  339. //
  340. // Effects:
  341. //
  342. // Arguments: PackageId - Contains ID for this package assigned by LSA
  343. // Parameters - Contains machine-specific information
  344. // FunctionTable - Contains table of LSA helper routines
  345. //
  346. // Requires:
  347. //
  348. // Returns:
  349. //
  350. // Notes:
  351. //
  352. //
  353. //--------------------------------------------------------------------------
  354. NTSTATUS NTAPI
  355. SpInitialize(
  356. IN ULONG_PTR PackageId,
  357. IN PSECPKG_PARAMETERS Parameters,
  358. IN PLSA_SECPKG_FUNCTION_TABLE FunctionTable
  359. )
  360. {
  361. NTSTATUS Status;
  362. UNICODE_STRING TempUnicodeString;
  363. #ifndef WIN32_CHICAGO
  364. WCHAR SafeBootEnvVar[sizeof(SAFEBOOT_MINIMAL_STR_W) + sizeof(WCHAR)];
  365. #endif // WIN32_CHICAGO
  366. UNICODE_STRING DnsString = {0};;
  367. #ifdef WIN32_CHICAGO
  368. PKERB_LOGON_SESSION LogonSession = NULL;
  369. #endif // WIN32_CHICAGO
  370. #ifndef WIN32_CHICAGO
  371. RtlInitializeResource(&KerberosGlobalResource);
  372. #endif // WIN32_CHICAGO
  373. KerberosPackageId = PackageId;
  374. LsaFunctions = FunctionTable;
  375. #ifndef WIN32_CHICAGO
  376. KerberosState = KerberosLsaMode;
  377. #else // WIN32_CHICAGO
  378. KerberosState = KerberosUserMode;
  379. #endif // WIN32_CHICAGO
  380. RtlInitUnicodeString(
  381. &KerbPackageName,
  382. MICROSOFT_KERBEROS_NAME_W
  383. );
  384. #ifndef WIN32_CHICAGO
  385. // Check is we are in safe boot.
  386. //
  387. // Does environment variable exist
  388. //
  389. RtlZeroMemory( SafeBootEnvVar, sizeof( SafeBootEnvVar ) );
  390. KerbGlobalSafeModeBootOptionPresent = FALSE;
  391. if ( GetEnvironmentVariable(L"SAFEBOOT_OPTION", SafeBootEnvVar, sizeof(SafeBootEnvVar)/sizeof(SafeBootEnvVar[0]) ) )
  392. {
  393. if ( !wcscmp( SafeBootEnvVar, SAFEBOOT_MINIMAL_STR_W ) )
  394. {
  395. KerbGlobalSafeModeBootOptionPresent = TRUE;
  396. }
  397. }
  398. #endif // WIN32_CHICAGO
  399. Status = KerbInitializeEvents();
  400. if (!NT_SUCCESS(Status))
  401. {
  402. goto Cleanup;
  403. }
  404. //
  405. // Init data for the kdc calling routine
  406. //
  407. #ifndef WIN32_CHICAGO
  408. Status = KerbInitKdcData();
  409. if (!NT_SUCCESS(Status))
  410. {
  411. goto Cleanup;
  412. }
  413. //
  414. // init global LSA policy handle.
  415. //
  416. Status = LsaIOpenPolicyTrusted(
  417. &KerbGlobalPolicyHandle
  418. );
  419. if(!NT_SUCCESS(Status))
  420. {
  421. goto Cleanup;
  422. }
  423. #endif // WIN32_CHICAGO
  424. //
  425. // Get information about encryption
  426. //
  427. if ((Parameters->MachineState & SECPKG_STATE_ENCRYPTION_PERMITTED) != 0)
  428. {
  429. KerbGlobalEncryptionPermitted = TRUE;
  430. }
  431. if ((Parameters->MachineState & SECPKG_STATE_STRONG_ENCRYPTION_PERMITTED) != 0)
  432. {
  433. KerbGlobalStrongEncryptionPermitted = TRUE;
  434. }
  435. //
  436. // Get our global role
  437. //
  438. if ((Parameters->MachineState & SECPKG_STATE_DOMAIN_CONTROLLER) != 0)
  439. {
  440. //
  441. // We will behave like a member workstation/server until the DS
  442. // says we are ready to act as a DC
  443. //
  444. KerbGlobalRole = KerbRoleWorkstation;
  445. }
  446. else if ((Parameters->MachineState & SECPKG_STATE_WORKSTATION) != 0)
  447. {
  448. KerbGlobalRole = KerbRoleWorkstation;
  449. }
  450. else
  451. {
  452. KerbGlobalRole = KerbRoleStandalone;
  453. }
  454. //
  455. // Fill in various useful constants
  456. //
  457. KerbSetTime(&KerbGlobalWillNeverTime, MAXTIMEQUADPART);
  458. KerbSetTime(&KerbGlobalHasNeverTime, 0);
  459. //
  460. // compute blank password hashes.
  461. //
  462. Status = RtlCalculateLmOwfPassword( "", &KerbGlobalNullLmOwfPassword );
  463. ASSERT( NT_SUCCESS(Status) );
  464. RtlInitUnicodeString(&TempUnicodeString, NULL);
  465. Status = RtlCalculateNtOwfPassword(&TempUnicodeString,
  466. &KerbGlobalNullNtOwfPassword);
  467. ASSERT( NT_SUCCESS(Status) );
  468. RtlInitUnicodeString(
  469. &KerbGlobalKdcServiceName,
  470. KDC_PRINCIPAL_NAME
  471. );
  472. //
  473. // At some point we may want to read the registry here to
  474. // find out whether we need to enforce times, currently times
  475. // are always enforced.
  476. //
  477. KerbGlobalEnforceTime = FALSE;
  478. //
  479. // Get the machine Name
  480. //
  481. Status = KerbSetComputerName();
  482. if( !NT_SUCCESS(Status) )
  483. {
  484. D_DebugLog((DEB_ERROR,"KerbSetComputerName failed\n"));
  485. goto Cleanup;
  486. }
  487. //
  488. // Initialize the logon session list. This has to be done because
  489. // KerbSetDomainName will try to acess the logon session list
  490. //
  491. Status = KerbInitLogonSessionList();
  492. if (!NT_SUCCESS(Status))
  493. {
  494. D_DebugLog((DEB_ERROR,"Failed to initialize logon session list: 0x%x. %ws, line %d\n",
  495. Status, THIS_FILE, __LINE__ ));
  496. goto Cleanup;
  497. }
  498. Status = KerbInitNetworkServiceLoopbackDetection();
  499. if (!NT_SUCCESS(Status))
  500. {
  501. D_DebugLog((DEB_ERROR, "Failed to initialize network service loopback detection: 0x%x. %ws, line %d\n",
  502. Status, THIS_FILE, __LINE__ ));
  503. goto Cleanup;
  504. }
  505. Status = KerbCreateSKeyTimer();
  506. if (!NT_SUCCESS(Status))
  507. {
  508. D_DebugLog((DEB_ERROR, "Failed to initialize network service session key list timer: 0x%x. %ws, line %d\n",
  509. Status, THIS_FILE, __LINE__ ));
  510. goto Cleanup;
  511. }
  512. Status = KerbInitTicketHandling();
  513. if (!NT_SUCCESS(Status))
  514. {
  515. D_DebugLog((DEB_ERROR,"Failed to initialize ticket handling: 0x%x. %ws, line %d\n",
  516. Status, THIS_FILE, __LINE__));
  517. goto Cleanup;
  518. }
  519. #ifndef WIN32_CHICAGO
  520. Status = KerbInitializeLogonSidCache();
  521. if (!NT_SUCCESS(Status))
  522. {
  523. D_DebugLog((DEB_ERROR,"Failed to initialize sid cache: 0x%x. %ws, line %d\n",Status, THIS_FILE, __LINE__));
  524. goto Cleanup;
  525. }
  526. #endif
  527. //
  528. // Update all global structures referencing the domain name
  529. //
  530. Status = KerbSetDomainName(
  531. &Parameters->DomainName,
  532. &Parameters->DnsDomainName,
  533. Parameters->DomainSid,
  534. Parameters->DomainGuid
  535. );
  536. if (!NT_SUCCESS(Status))
  537. {
  538. goto Cleanup;
  539. }
  540. //
  541. // Initialize the internal Kerberos lists
  542. //
  543. Status = KerbInitCredentialList();
  544. if (!NT_SUCCESS(Status))
  545. {
  546. D_DebugLog((DEB_ERROR,"Failed to initialize credential list: 0x%x. %ws, line %d\n",
  547. Status, THIS_FILE, __LINE__ ));
  548. goto Cleanup;
  549. }
  550. Status = KerbInitContextList();
  551. if (!NT_SUCCESS(Status))
  552. {
  553. D_DebugLog((DEB_ERROR,"Failed to initialize context list: 0x%x. %ws, line %d\n",
  554. Status, THIS_FILE, __LINE__ ));
  555. goto Cleanup;
  556. }
  557. Status = KerbInitTicketCaching();
  558. if (!NT_SUCCESS(Status))
  559. {
  560. D_DebugLog((DEB_ERROR,"Failed to initialize ticket cache: 0x%x. %ws, line %d\n",
  561. Status, THIS_FILE, __LINE__));
  562. goto Cleanup;
  563. }
  564. Status = KerbInitBindingCache();
  565. if (!NT_SUCCESS(Status))
  566. {
  567. D_DebugLog((DEB_ERROR,"Failed to initialize binding cache: 0x%x. %ws, line %d\n",
  568. Status, THIS_FILE, __LINE__));
  569. goto Cleanup;
  570. }
  571. Status = KerbInitSpnCache();
  572. if (!NT_SUCCESS(Status))
  573. {
  574. D_DebugLog((DEB_ERROR,"Failed to initialize SPN cache: 0x%x. %ws, line %d\n",
  575. Status, THIS_FILE, __LINE__));
  576. goto Cleanup;
  577. }
  578. Status = KerbInitializeMitRealmList();
  579. if (!NT_SUCCESS(Status))
  580. {
  581. D_DebugLog((DEB_ERROR,"Failed to initialize MIT realm list: 0x%x. %ws, line %d\n",
  582. Status, THIS_FILE, __LINE__ ));
  583. goto Cleanup;
  584. }
  585. #ifndef WIN32_CHICAGO
  586. Status = KerbInitializePkinit();
  587. if (!NT_SUCCESS(Status))
  588. {
  589. D_DebugLog((DEB_ERROR,"Failed to initialize PKINT: 0x%x. %ws, line %d\n",Status, THIS_FILE, __LINE__));
  590. goto Cleanup;
  591. }
  592. #endif // WIN32_CHICAGO
  593. Status = KerbInitializeSockets(
  594. MAKEWORD(1,1), // we want version 1.1
  595. 1, // we need at least 1 socket
  596. &KerbGlobalNoTcpUdp
  597. );
  598. if (!NT_SUCCESS(Status))
  599. {
  600. D_DebugLog((DEB_ERROR,"Failed to initialize sockets: 0x%x. %ws, line %d\n",Status, THIS_FILE, __LINE__));
  601. goto Cleanup;
  602. }
  603. #ifndef WIN32_CHICAGO
  604. Status = KerbRegisterForDomainChange();
  605. if (!NT_SUCCESS(Status))
  606. {
  607. D_DebugLog((DEB_ERROR, "Failed to register for domain change notification: 0x%x. %ws, line %d\n",Status, THIS_FILE, __LINE__));
  608. goto Cleanup;
  609. }
  610. //
  611. // Check to see if there is a CSP registered for replacing the StringToKey calculation
  612. //
  613. CheckForOutsideStringToKey();
  614. //
  615. // Register to update the machine sid cache
  616. //
  617. KerbWaitGetMachineSid();
  618. //
  619. // See if there are any "join hints" to process
  620. //
  621. ReadInitialDcRecord(
  622. &KerbGlobalInitialDcRecord,
  623. &KerbGlobalInitialDcAddressType,
  624. &KerbGlobalInitialDcFlags
  625. );
  626. #endif // WIN32_CHICAGO
  627. KerbGlobalSocketsInitialized = TRUE;
  628. KerbGlobalInitialized = TRUE;
  629. Cleanup:
  630. KerbFreeString(
  631. &DnsString
  632. );
  633. //
  634. // If we failed to initialize, shutdown
  635. //
  636. if (!NT_SUCCESS(Status))
  637. {
  638. SpCleanup();
  639. }
  640. return(Status);
  641. }
  642. //+-------------------------------------------------------------------------
  643. //
  644. // Function: SpCleanup
  645. //
  646. // Synopsis: Function to shutdown the Kerberos package.
  647. //
  648. // Effects: Forces the freeing of all credentials, contexts and
  649. // logon sessions and frees all global data
  650. //
  651. // Arguments: none
  652. //
  653. // Requires:
  654. //
  655. // Returns:
  656. //
  657. // Notes: STATUS_SUCCESS in all cases
  658. //
  659. //
  660. //--------------------------------------------------------------------------
  661. NTSTATUS NTAPI
  662. SpCleanup(
  663. VOID
  664. )
  665. {
  666. KerbGlobalInitialized = FALSE;
  667. #ifndef WIN32_CHICAGO
  668. KerbUnregisterForDomainChange();
  669. #endif // WIN32_CHICAGO
  670. KerbFreeLogonSessionList();
  671. KerbFreeContextList();
  672. KerbFreeTicketCache();
  673. // KerbFreeCredentialList();
  674. KerbFreeNetworkServiceSKeyListAndLock();
  675. KerbFreeSKeyTimer();
  676. KerbFreeString(&KerbGlobalDomainName);
  677. KerbFreeString(&KerbGlobalDnsDomainName);
  678. KerbFreeString(&KerbGlobalMachineName);
  679. KerbFreeString((PUNICODE_STRING) &KerbGlobalKerbMachineName);
  680. KerbFreeString(&KerbGlobalMachineServiceName);
  681. KerbFreeKdcName(&KerbGlobalInternalMachineServiceName);
  682. KerbFreeKdcName(&KerbGlobalMitMachineServiceName);
  683. KerbCleanupTicketHandling();
  684. #ifndef WIN32_CHICAGO
  685. if( KerbGlobalPolicyHandle != NULL )
  686. {
  687. LsarClose( &KerbGlobalPolicyHandle );
  688. KerbGlobalPolicyHandle = NULL;
  689. }
  690. if (KerbGlobalDomainSid != NULL)
  691. {
  692. KerbFree(KerbGlobalDomainSid);
  693. }
  694. #endif // WIN32_CHICAGO
  695. if (KerbGlobalSocketsInitialized)
  696. {
  697. KerbCleanupSockets();
  698. }
  699. KerbCleanupBindingCache(FALSE);
  700. KerbUninitializeMitRealmList();
  701. #ifndef WIN32_CHICAGO
  702. KerbFreeKdcData();
  703. // RtlDeleteResource(&KerberosGlobalResource);
  704. #endif // WIN32_CHICGAO
  705. KerbShutdownEvents();
  706. return(STATUS_SUCCESS);
  707. }
  708. //+-------------------------------------------------------------------------
  709. //
  710. // Function: SpShutdown
  711. //
  712. // Synopsis: Exported function to shutdown the Kerberos package.
  713. //
  714. // Effects: Forces the freeing of all credentials, contexts and
  715. // logon sessions and frees all global data
  716. //
  717. // Arguments: none
  718. //
  719. // Requires:
  720. //
  721. // Returns:
  722. //
  723. // Notes: STATUS_SUCCESS in all cases
  724. //
  725. //
  726. //--------------------------------------------------------------------------
  727. NTSTATUS NTAPI
  728. SpShutdown(
  729. VOID
  730. )
  731. {
  732. #if 0
  733. SpCleanup();
  734. #endif
  735. return(STATUS_SUCCESS);
  736. }
  737. #ifndef WIN32_CHICAGO
  738. //+-------------------------------------------------------------------------
  739. //
  740. // Function: SpGetInfo
  741. //
  742. // Synopsis: Returns information about the package
  743. //
  744. // Effects: returns pointers to global data
  745. //
  746. // Arguments: PackageInfo - Receives kerberos package information
  747. //
  748. // Requires:
  749. //
  750. // Returns: STATUS_SUCCESS in all cases
  751. //
  752. // Notes:
  753. //
  754. //
  755. //--------------------------------------------------------------------------
  756. NTSTATUS NTAPI
  757. SpGetInfo(
  758. OUT PSecPkgInfo PackageInfo
  759. )
  760. {
  761. PackageInfo->wVersion = SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION;
  762. PackageInfo->wRPCID = RPC_C_AUTHN_GSS_KERBEROS;
  763. PackageInfo->fCapabilities = KERBEROS_CAPABILITIES;
  764. PackageInfo->cbMaxToken = KerbGlobalMaxTokenSize;
  765. PackageInfo->Name = KERBEROS_PACKAGE_NAME;
  766. PackageInfo->Comment = KERBEROS_PACKAGE_COMMENT;
  767. return(STATUS_SUCCESS);
  768. }
  769. //+-------------------------------------------------------------------------
  770. //
  771. // Function: SpGetExtendedInformation
  772. //
  773. // Synopsis: returns additional information about the package
  774. //
  775. // Effects:
  776. //
  777. // Arguments:
  778. //
  779. // Requires:
  780. //
  781. // Returns:
  782. //
  783. // Notes:
  784. //
  785. //
  786. //--------------------------------------------------------------------------
  787. NTSTATUS
  788. SpGetExtendedInformation(
  789. IN SECPKG_EXTENDED_INFORMATION_CLASS Class,
  790. OUT PSECPKG_EXTENDED_INFORMATION * ppInformation
  791. )
  792. {
  793. NTSTATUS Status = STATUS_SUCCESS;
  794. PSECPKG_EXTENDED_INFORMATION Information = NULL ;
  795. PSECPKG_SERIALIZED_OID SerializedOid;
  796. ULONG Size ;
  797. switch(Class) {
  798. case SecpkgGssInfo:
  799. DsysAssert(gss_mech_krb5_new->length >= 2);
  800. DsysAssert(gss_mech_krb5_new->length < 127);
  801. //
  802. // We need to leave space for the oid and the BER header, which is
  803. // 0x6 and then the length of the oid.
  804. //
  805. Information = (PSECPKG_EXTENDED_INFORMATION)
  806. KerbAllocate(sizeof(SECPKG_EXTENDED_INFORMATION) +
  807. gss_mech_krb5_new->length - 2);
  808. if (Information == NULL)
  809. {
  810. Status = STATUS_INSUFFICIENT_RESOURCES;
  811. goto Cleanup;
  812. }
  813. Information->Class = SecpkgGssInfo;
  814. Information->Info.GssInfo.EncodedIdLength = gss_mech_krb5_new->length + 2;
  815. Information->Info.GssInfo.EncodedId[0] = 0x6; // BER OID type
  816. Information->Info.GssInfo.EncodedId[1] = (UCHAR) gss_mech_krb5_new->length;
  817. RtlCopyMemory(
  818. &Information->Info.GssInfo.EncodedId[2],
  819. gss_mech_krb5_new->elements,
  820. gss_mech_krb5_new->length
  821. );
  822. *ppInformation = Information;
  823. Information = NULL;
  824. break;
  825. case SecpkgContextThunks:
  826. //
  827. // Note - we don't need to add any space for the thunks as there
  828. // is only one, and the structure has space for one. If any more
  829. // thunks are added, we will need to add space for those.
  830. //
  831. Information = (PSECPKG_EXTENDED_INFORMATION)
  832. KerbAllocate(sizeof(SECPKG_EXTENDED_INFORMATION));
  833. if (Information == NULL)
  834. {
  835. Status = STATUS_INSUFFICIENT_RESOURCES;
  836. goto Cleanup;
  837. }
  838. Information->Class = SecpkgContextThunks;
  839. Information->Info.ContextThunks.InfoLevelCount = 1;
  840. Information->Info.ContextThunks.Levels[0] = SECPKG_ATTR_NATIVE_NAMES;
  841. *ppInformation = Information;
  842. Information = NULL;
  843. break;
  844. case SecpkgWowClientDll:
  845. //
  846. // This indicates that we're smart enough to handle wow client processes
  847. //
  848. Information = (PSECPKG_EXTENDED_INFORMATION)
  849. KerbAllocate( sizeof( SECPKG_EXTENDED_INFORMATION ) +
  850. (MAX_PATH * sizeof(WCHAR) ) );
  851. if ( Information == NULL )
  852. {
  853. Status = STATUS_INSUFFICIENT_RESOURCES ;
  854. goto Cleanup ;
  855. }
  856. Information->Class = SecpkgWowClientDll ;
  857. Information->Info.WowClientDll.WowClientDllPath.Buffer = (PWSTR) (Information + 1);
  858. Size = ExpandEnvironmentStrings(
  859. L"%SystemRoot%\\" WOW64_SYSTEM_DIRECTORY_U L"\\Kerberos.DLL",
  860. Information->Info.WowClientDll.WowClientDllPath.Buffer,
  861. MAX_PATH );
  862. Information->Info.WowClientDll.WowClientDllPath.Length = (USHORT) (Size * sizeof(WCHAR));
  863. Information->Info.WowClientDll.WowClientDllPath.MaximumLength = (USHORT) ((Size + 1) * sizeof(WCHAR) );
  864. *ppInformation = Information ;
  865. Information = NULL ;
  866. break;
  867. case SecpkgExtraOids:
  868. Size = sizeof( SECPKG_EXTENDED_INFORMATION ) +
  869. 2 * sizeof( SECPKG_SERIALIZED_OID ) ;
  870. Information = (PSECPKG_EXTENDED_INFORMATION)
  871. KerbAllocate( Size );
  872. if ( Information == NULL )
  873. {
  874. Status = STATUS_INSUFFICIENT_RESOURCES ;
  875. goto Cleanup ;
  876. }
  877. Information->Class = SecpkgExtraOids ;
  878. Information->Info.ExtraOids.OidCount = 2 ;
  879. SerializedOid = Information->Info.ExtraOids.Oids;
  880. SerializedOid->OidLength = gss_mech_krb5_spnego->length + 2;
  881. SerializedOid->OidAttributes = SECPKG_CRED_BOTH ;
  882. SerializedOid->OidValue[ 0 ] = 0x06 ; // BER OID type
  883. SerializedOid->OidValue[ 1 ] = (UCHAR) gss_mech_krb5_spnego->length;
  884. RtlCopyMemory(
  885. &SerializedOid->OidValue[2],
  886. gss_mech_krb5_spnego->elements,
  887. gss_mech_krb5_spnego->length
  888. );
  889. SerializedOid++ ;
  890. SerializedOid->OidLength = gss_mech_krb5_u2u->length + 2;
  891. SerializedOid->OidAttributes = SECPKG_CRED_INBOUND ;
  892. SerializedOid->OidValue[ 0 ] = 0x06 ; // BER OID type
  893. SerializedOid->OidValue[ 1 ] = (UCHAR) gss_mech_krb5_u2u->length;
  894. RtlCopyMemory(
  895. &SerializedOid->OidValue[2],
  896. gss_mech_krb5_u2u->elements,
  897. gss_mech_krb5_u2u->length
  898. );
  899. *ppInformation = Information ;
  900. Information = NULL ;
  901. break;
  902. default:
  903. return(STATUS_INVALID_INFO_CLASS);
  904. }
  905. Cleanup:
  906. if (Information != NULL)
  907. {
  908. KerbFree(Information);
  909. }
  910. return(Status);
  911. }
  912. //+-------------------------------------------------------------------------
  913. //
  914. // Function: LsaApInitializePackage
  915. //
  916. // Synopsis: Obsolete pacakge initialize function, supported for
  917. // compatibility only. This function has no effect.
  918. //
  919. // Effects: none
  920. //
  921. // Arguments:
  922. //
  923. // Requires:
  924. //
  925. // Returns: STATUS_SUCCESS always
  926. //
  927. // Notes:
  928. //
  929. //
  930. //--------------------------------------------------------------------------
  931. NTSTATUS NTAPI
  932. LsaApInitializePackage(
  933. IN ULONG AuthenticationPackageId,
  934. IN PLSA_DISPATCH_TABLE LsaDispatchTable,
  935. IN PLSA_STRING Database OPTIONAL,
  936. IN PLSA_STRING Confidentiality OPTIONAL,
  937. OUT PLSA_STRING *AuthenticationPackageName
  938. )
  939. {
  940. return(STATUS_SUCCESS);
  941. }
  942. BOOLEAN
  943. KerbIsInitialized(
  944. VOID
  945. )
  946. {
  947. return KerbGlobalInitialized;
  948. }
  949. NTSTATUS
  950. KerbKdcCallBack(
  951. VOID
  952. )
  953. {
  954. PKERB_BINDING_CACHE_ENTRY CacheEntry = NULL;
  955. NTSTATUS Status = STATUS_SUCCESS;
  956. KerbGlobalWriteLock();
  957. KerbGlobalRole = KerbRoleDomainController;
  958. Status = KerbLoadKdc();
  959. //
  960. // Purge the binding cache of entries for this domain
  961. //
  962. CacheEntry = KerbLocateBindingCacheEntry(
  963. &KerbGlobalDnsDomainName,
  964. 0,
  965. TRUE
  966. );
  967. if (CacheEntry != NULL)
  968. {
  969. KerbDereferenceBindingCacheEntry(CacheEntry);
  970. }
  971. CacheEntry = KerbLocateBindingCacheEntry(
  972. &KerbGlobalDomainName,
  973. 0,
  974. TRUE
  975. );
  976. if (CacheEntry != NULL)
  977. {
  978. KerbDereferenceBindingCacheEntry(CacheEntry);
  979. }
  980. //
  981. // PurgeSpnCache, because we may now have "better" state,
  982. // e.g. right after DCPromo our SPNs may not have replicated.
  983. //
  984. KerbCleanupSpnCache();
  985. KerbGlobalReleaseLock();
  986. return Status;
  987. }
  988. #endif // WIN32_CHICAGO