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.

848 lines
24 KiB

  1. //+--------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) Microsoft Corporation 2000
  6. //
  7. // File: ntdigest.c
  8. //
  9. // Contents: main entrypoints for the digest security package
  10. // SpLsaModeInitialize
  11. // SpInitialize
  12. // SpShutdown
  13. // SpGetInfo
  14. //
  15. // Helper functions:
  16. //
  17. // History: KDamour 10Mar00 Stolen from msv_sspi\ntlm.cxx
  18. //
  19. //---------------------------------------------------------------------
  20. #define NTDIGEST_GLOBAL
  21. #include "global.h"
  22. /* Debugging information setup */
  23. DEFINE_DEBUG2(Digest);
  24. DEBUG_KEY MyDebugKeys[] = {{DEB_ERROR, "Error"},
  25. {DEB_WARN, "Warning"},
  26. {DEB_TRACE, "Trace"},
  27. {DEB_TRACE_ASC, "TraceASC"},
  28. {DEB_TRACE_ISC, "TraceISC"},
  29. {DEB_TRACE_LSA, "TraceLSA"},
  30. {DEB_TRACE_USER, "TraceUser"},
  31. {DEB_TRACE_FUNC, "TraceFuncs"},
  32. {DEB_TRACE_MEM, "TraceMem"},
  33. {TRACE_STUFF, "Stuff"},
  34. {0, NULL}
  35. };
  36. // set to TRUE once initialized
  37. BOOL l_bDebugInitialized = FALSE;
  38. BOOL l_bDigestInitialized = FALSE;
  39. // Registry reading
  40. HKEY g_hkBase = NULL;
  41. HANDLE g_hParamEvent = NULL;
  42. HANDLE g_hWait = NULL;
  43. #define COMPUTER_NAME_SIZE (MAX_COMPUTERNAME_LENGTH + 1)
  44. //+--------------------------------------------------------------------
  45. //
  46. // Function: SpLsaModeInitialize
  47. //
  48. // Synopsis: This function is called by the LSA when this DLL is loaded.
  49. // It returns security package function tables for all
  50. // security packages in the DLL.
  51. //
  52. // Arguments: LsaVersion - Version number of the LSA
  53. // PackageVersion - Returns version number of the package
  54. // Tables - Returns array of function tables for the package
  55. // TableCount - Returns number of entries in array of
  56. // function tables.
  57. //
  58. // Returns: PackageVersion (as above)
  59. // Tables (as above)
  60. // TableCount (as above)
  61. //
  62. // Notes:
  63. //
  64. //---------------------------------------------------------------------
  65. NTSTATUS NTAPI
  66. SpLsaModeInitialize(
  67. IN ULONG LsaVersion,
  68. OUT PULONG PackageVersion,
  69. OUT PSECPKG_FUNCTION_TABLE * Tables,
  70. OUT PULONG TableCount
  71. )
  72. {
  73. #if DBG
  74. DebugInitialize();
  75. #endif
  76. DebugLog((DEB_TRACE_FUNC, "SpLsaModeInitialize: Entering\n"));
  77. SECURITY_STATUS Status = SEC_E_OK;
  78. if (LsaVersion != SECPKG_INTERFACE_VERSION)
  79. {
  80. DebugLog((DEB_ERROR, "SpLsaModeInitialize: Invalid LSA version: %d\n", LsaVersion));
  81. Status = STATUS_INVALID_PARAMETER;
  82. goto CleanUp;
  83. }
  84. // Fill in the dispatch table for functions exported by ssp
  85. g_NtDigestFunctionTable.InitializePackage = NULL;
  86. g_NtDigestFunctionTable.LogonUser = NULL;
  87. g_NtDigestFunctionTable.CallPackage = LsaApCallPackage;
  88. g_NtDigestFunctionTable.LogonTerminated = LsaApLogonTerminated;
  89. g_NtDigestFunctionTable.CallPackageUntrusted = LsaApCallPackageUntrusted;
  90. g_NtDigestFunctionTable.LogonUserEx = NULL;
  91. g_NtDigestFunctionTable.LogonUserEx2 = LsaApLogonUserEx2;
  92. g_NtDigestFunctionTable.Initialize = SpInitialize;
  93. g_NtDigestFunctionTable.Shutdown = SpShutdown;
  94. g_NtDigestFunctionTable.GetInfo = SpGetInfo;
  95. g_NtDigestFunctionTable.AcceptCredentials = SpAcceptCredentials;
  96. g_NtDigestFunctionTable.AcquireCredentialsHandle = SpAcquireCredentialsHandle;
  97. g_NtDigestFunctionTable.FreeCredentialsHandle = SpFreeCredentialsHandle;
  98. g_NtDigestFunctionTable.SaveCredentials = SpSaveCredentials;
  99. g_NtDigestFunctionTable.GetCredentials = SpGetCredentials;
  100. g_NtDigestFunctionTable.DeleteCredentials = SpDeleteCredentials;
  101. g_NtDigestFunctionTable.InitLsaModeContext = SpInitLsaModeContext;
  102. g_NtDigestFunctionTable.AcceptLsaModeContext = SpAcceptLsaModeContext;
  103. g_NtDigestFunctionTable.DeleteContext = SpDeleteContext;
  104. g_NtDigestFunctionTable.ApplyControlToken = SpApplyControlToken;
  105. g_NtDigestFunctionTable.GetUserInfo = SpGetUserInfo;
  106. g_NtDigestFunctionTable.QueryCredentialsAttributes = SpQueryCredentialsAttributes ;
  107. g_NtDigestFunctionTable.GetExtendedInformation = SpGetExtendedInformation ;
  108. g_NtDigestFunctionTable.SetExtendedInformation = SpSetExtendedInformation ;
  109. g_NtDigestFunctionTable.CallPackagePassthrough = LsaApCallPackagePassthrough;
  110. *PackageVersion = SECPKG_INTERFACE_VERSION;
  111. *Tables = &g_NtDigestFunctionTable;
  112. *TableCount = 1;
  113. CleanUp:
  114. DebugLog((DEB_TRACE_FUNC, "SpLsaModeInitialize:Leaving\n"));
  115. return(Status);
  116. }
  117. //+--------------------------------------------------------------------
  118. //
  119. // Function: SpInitialize
  120. //
  121. // Synopsis: Initializes the Security package
  122. //
  123. // Arguments: PackageId - Contains ID for this package assigned by LSA
  124. // Parameters - Contains machine-specific information
  125. // FunctionTable - Contains table of LSA helper routines
  126. //
  127. // Returns: None
  128. //
  129. // Notes: Everything that was done in LsaApInitializePackage
  130. // should be done here. Lsa assures us that only
  131. // one thread is executing this at a time. Don't
  132. // have to worry about concurrency problems.(BUGBUG verify)
  133. //
  134. //---------------------------------------------------------------------
  135. NTSTATUS NTAPI
  136. SpInitialize(
  137. IN ULONG_PTR pPackageId,
  138. IN PSECPKG_PARAMETERS pParameters,
  139. IN PLSA_SECPKG_FUNCTION_TABLE pFunctionTable
  140. )
  141. {
  142. SECURITY_STATUS Status = SEC_E_OK;
  143. DWORD dwWinErr = 0;
  144. NT_PRODUCT_TYPE NtProductType = NtProductWinNt;
  145. WCHAR wszComputerName[COMPUTER_NAME_SIZE];
  146. DWORD dwComputerNameLen = COMPUTER_NAME_SIZE;
  147. DebugLog((DEB_TRACE_FUNC, "SpInitialize: Entering\n"));
  148. // Indicate that we completed initialization
  149. ASSERT(l_bDigestInitialized == FALSE); // never called more than once
  150. l_bDigestInitialized = TRUE;
  151. // Initialize global values
  152. ZeroMemory(&g_strNtDigestUTF8ServerRealm, sizeof(g_strNtDigestUTF8ServerRealm));
  153. ZeroMemory(&g_strNTDigestISO8859ServerRealm, sizeof(g_strNTDigestISO8859ServerRealm));
  154. // Define time for AcquirCredentialHandle
  155. // We really need this to be a day less than maxtime so when callers
  156. // of sspi convert to utc, they won't get time in the past.
  157. g_TimeForever.HighPart = 0x7FFFFFFF;
  158. g_TimeForever.LowPart = 0xFFFFFFFF;
  159. //
  160. // All the following are global
  161. //
  162. g_NtDigestState = NtDigestLsaMode; /* enum */
  163. g_NtDigestPackageId = pPackageId;
  164. //
  165. // Save away the Lsa functions
  166. //
  167. g_LsaFunctions = pFunctionTable;
  168. //
  169. // Establish the packagename
  170. //
  171. RtlInitUnicodeString(
  172. &g_ustrNtDigestPackageName,
  173. WDIGEST_SP_NAME
  174. );
  175. // Set the WorkstationName
  176. if (!GetComputerNameExW(ComputerNameNetBIOS, wszComputerName, &dwComputerNameLen))
  177. {
  178. ZeroMemory(&g_ustrWorkstationName, sizeof(g_ustrWorkstationName));
  179. DebugLog((DEB_ERROR, "SpInitialize: Get ComputerName error 0x%x\n", GetLastError()));
  180. }
  181. else
  182. {
  183. Status = UnicodeStringWCharDuplicate(&g_ustrWorkstationName, wszComputerName);
  184. if (!NT_SUCCESS (Status))
  185. {
  186. DebugLog((DEB_ERROR, "SpInitialize: ComputerName copy status 0x%x\n", Status));
  187. goto CleanUp;
  188. }
  189. }
  190. // Need to initialize Crypto stuff and nonce creations
  191. Status = NonceInitialize();
  192. if (!NT_SUCCESS (Status))
  193. {
  194. DebugLog((DEB_ERROR, "SpInitialize: Error from NonceInitialize status 0x%x\n", Status));
  195. goto CleanUp;
  196. }
  197. //
  198. // Determine if this machine is running Windows NT or Lanman NT.
  199. // LanMan NT runs on a domain controller.
  200. //
  201. if ( !RtlGetNtProductType( &NtProductType ) ) {
  202. // Nt Product Type undefined - WinNt assumed
  203. NtProductType = NtProductWinNt;
  204. }
  205. if (NtProductType == NtProductLanManNt)
  206. {
  207. g_fDomainController = TRUE; // Allow password checking only on DomainControllers
  208. }
  209. //
  210. // Save the Parameters info to a global struct
  211. //
  212. g_NtDigestSecPkg.MachineState = pParameters->MachineState;
  213. g_NtDigestSecPkg.SetupMode = pParameters->SetupMode;
  214. g_NtDigestSecPkg.Version = pParameters->Version;
  215. Status = UnicodeStringDuplicate(
  216. &g_NtDigestSecPkg.DnsDomainName,
  217. &(pParameters->DnsDomainName));
  218. if (!NT_SUCCESS (Status))
  219. {
  220. DebugLog((DEB_ERROR, "SpInitialize: Error from UnicodeStringDuplicate status 0x%x\n", Status));
  221. goto CleanUp;
  222. }
  223. Status = UnicodeStringDuplicate(
  224. &g_NtDigestSecPkg.DomainName,
  225. &(pParameters->DomainName));
  226. if (!NT_SUCCESS (Status))
  227. {
  228. DebugLog((DEB_ERROR, "SpInitialize: Error from UnicodeStringDuplicate status 0x%x\n", Status));
  229. goto CleanUp;
  230. }
  231. if (pParameters->DomainSid != NULL) {
  232. Status = SidDuplicate( &g_NtDigestSecPkg.DomainSid,
  233. pParameters->DomainSid );
  234. if (!NT_SUCCESS (Status))
  235. {
  236. DebugLog((DEB_ERROR, "SpInitialize: Error from SidDuplicate status 0x%x\n", Status));
  237. goto CleanUp;
  238. }
  239. }
  240. else
  241. g_NtDigestSecPkg.DomainSid = NULL;
  242. DebugLog((DEB_TRACE, "SpInitialize: DNSDomain = %wZ, Domain = %wZ\n", &(g_NtDigestSecPkg.DnsDomainName),
  243. &(g_NtDigestSecPkg.DomainName)));
  244. // For server challenges, precalculate the UTF-8 and ISO versions of the realm
  245. Status = EncodeUnicodeString(&(g_NtDigestSecPkg.DnsDomainName), CP_8859_1, &g_strNTDigestISO8859ServerRealm, NULL);
  246. if (!NT_SUCCESS(Status))
  247. {
  248. DebugLog((DEB_WARN, "SpInitialize: Error in encoding domain in ISO-8859-1\n"));
  249. ZeroMemory(&g_strNTDigestISO8859ServerRealm, sizeof(STRING));
  250. }
  251. Status = EncodeUnicodeString(&(g_NtDigestSecPkg.DnsDomainName), CP_UTF8, &g_strNtDigestUTF8ServerRealm, NULL);
  252. if (!NT_SUCCESS(Status))
  253. {
  254. DebugLog((DEB_WARN, "SpInitialize: Error in encoding domain in UTF-8\n"));
  255. ZeroMemory(&g_strNtDigestUTF8ServerRealm, sizeof(STRING));
  256. }
  257. //
  258. // Initialize the digest token source
  259. //
  260. RtlCopyMemory(
  261. g_DigestSource.SourceName,
  262. NTDIGEST_TOKEN_NAME_A,
  263. sizeof(NTDIGEST_TOKEN_NAME_A)
  264. );
  265. NtAllocateLocallyUniqueId(&g_DigestSource.SourceIdentifier);
  266. //
  267. // Init the LogonSession stuff
  268. //
  269. Status = LogSessHandlerInit();
  270. if (!NT_SUCCESS (Status))
  271. {
  272. DebugLog((DEB_ERROR, "SpInitialize: Error from LogSessHandlerInit status 0x%x\n", Status));
  273. goto CleanUp;
  274. }
  275. //
  276. // Init the Credential stuff
  277. //
  278. Status = CredHandlerInit();
  279. if (!NT_SUCCESS (Status))
  280. {
  281. DebugLog((DEB_ERROR, "SpInitialize: Error from CredHandlerInit status 0x%x\n", Status));
  282. goto CleanUp;
  283. }
  284. //
  285. // Init the Context stuff
  286. //
  287. Status = CtxtHandlerInit();
  288. if (!NT_SUCCESS (Status))
  289. {
  290. DebugLog((DEB_ERROR, "SpInitialize: Error from ContextInitialize status 0x%x\n", Status));
  291. goto CleanUp;
  292. }
  293. //
  294. // Read in the registry values for SSP configuration - in LSA space
  295. //
  296. SPLoadRegOptions();
  297. CleanUp:
  298. if (!NT_SUCCESS (Status))
  299. {
  300. SPUnloadRegOptions();
  301. SpShutdown();
  302. }
  303. DebugLog((DEB_TRACE_FUNC, "SpInitialize: Leaving\n"));
  304. return(Status);
  305. }
  306. //+--------------------------------------------------------------------
  307. //
  308. // Function: SpShutdown
  309. //
  310. // Synopsis: Exported function to shutdown the Security package.
  311. //
  312. // Effects: Forces the freeing of all credentials, contexts
  313. // and frees all global data
  314. //
  315. // Arguments: none
  316. //
  317. // Returns:
  318. //
  319. // Notes: SEC_E_OK in all cases
  320. // Most of the stuff was taken from SspCommonShutdown()
  321. // from svcdlls\ntlmssp\common\initcomn.c
  322. //
  323. //
  324. //---------------------------------------------------------------------
  325. NTSTATUS NTAPI
  326. SpShutdown(
  327. VOID
  328. )
  329. {
  330. DebugLog((DEB_TRACE_FUNC, "SpShutdown: Entering\n"));
  331. // Need to identify how to shutdown without causing faults with
  332. // incoming messages
  333. DebugLog((DEB_TRACE_FUNC, "SpShutdown: Leaving\n"));
  334. return(SEC_E_OK);
  335. }
  336. //+--------------------------------------------------------------------
  337. //
  338. // Function: SpGetInfo
  339. //
  340. // Synopsis: Returns information about the package
  341. //
  342. // Effects: returns pointers to global data
  343. //
  344. // Arguments: PackageInfo - Receives security package information
  345. //
  346. // Returns: SEC_E_OK in all cases
  347. //
  348. // Notes: Pointers to constants ok. Lsa will copy the data
  349. // before sending it to someone else. This function required
  350. // to return SUCCESS for the package to stay loaded.
  351. //
  352. //---------------------------------------------------------------------
  353. NTSTATUS NTAPI
  354. SpGetInfo(
  355. OUT PSecPkgInfo PackageInfo
  356. )
  357. {
  358. DebugLog((DEB_TRACE_FUNC, "SpGetInfo: Entering\n"));
  359. PackageInfo->fCapabilities = NTDIGEST_SP_CAPS;
  360. PackageInfo->wVersion = SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION;
  361. PackageInfo->wRPCID = RPC_C_AUTHN_DIGEST;
  362. PackageInfo->cbMaxToken = NTDIGEST_SP_MAX_TOKEN_SIZE;
  363. PackageInfo->Name = WDIGEST_SP_NAME;
  364. PackageInfo->Comment = NTDIGEST_SP_COMMENT;
  365. DebugLog((DEB_TRACE_FUNC, "SpGetInfo: Leaving\n"));
  366. return(SEC_E_OK);
  367. }
  368. // Misc SECPKG Functions
  369. NTSTATUS NTAPI
  370. SpGetUserInfo(
  371. IN PLUID LogonId,
  372. IN ULONG Flags,
  373. OUT PSecurityUserData * UserData
  374. )
  375. {
  376. DebugLog((DEB_TRACE_FUNC, "SpGetUserInfo: Entering/Leaving\n"));
  377. // FIXIFX Fields of UserData are username, domain, server
  378. UNREFERENCED_PARAMETER(LogonId);
  379. UNREFERENCED_PARAMETER(Flags);
  380. UNREFERENCED_PARAMETER(UserData);
  381. return(SEC_E_UNSUPPORTED_FUNCTION);
  382. }
  383. //+---------------------------------------------------------------------------
  384. //
  385. // Function: SpGetExtendedInformation
  386. //
  387. // Synopsis: Return extended information to the LSA
  388. //
  389. // Arguments: [Class] -- Information Class
  390. // [pInfo] -- Returned Information Pointer
  391. //
  392. //
  393. // Notes:
  394. //
  395. //----------------------------------------------------------------------------
  396. NTSTATUS
  397. NTAPI
  398. SpGetExtendedInformation(
  399. IN SECPKG_EXTENDED_INFORMATION_CLASS Class,
  400. OUT PSECPKG_EXTENDED_INFORMATION * ppInformation
  401. )
  402. {
  403. NTSTATUS Status = STATUS_SUCCESS;
  404. PSECPKG_EXTENDED_INFORMATION Information = NULL;
  405. ULONG Size = 0;
  406. DebugLog((DEB_TRACE_FUNC, "SpGetExtendedInformation: Entering\n"));
  407. switch ( Class )
  408. {
  409. case SecpkgWowClientDll:
  410. //
  411. // This indicates that we're smart enough to handle wow client processes
  412. //
  413. Information = (PSECPKG_EXTENDED_INFORMATION)
  414. DigestAllocateMemory( sizeof( SECPKG_EXTENDED_INFORMATION ) +
  415. (MAX_PATH * sizeof(WCHAR) ) );
  416. if ( Information == NULL )
  417. {
  418. Status = STATUS_INSUFFICIENT_RESOURCES ;
  419. goto Cleanup ;
  420. }
  421. Information->Class = SecpkgWowClientDll ;
  422. Information->Info.WowClientDll.WowClientDllPath.Buffer = (PWSTR) (Information + 1);
  423. Size = ExpandEnvironmentStrings(
  424. L"%SystemRoot%\\" WOW64_SYSTEM_DIRECTORY_U L"\\" NTDIGEST_DLL_NAME,
  425. Information->Info.WowClientDll.WowClientDllPath.Buffer,
  426. MAX_PATH );
  427. Information->Info.WowClientDll.WowClientDllPath.Length = (USHORT) (Size * sizeof(WCHAR));
  428. Information->Info.WowClientDll.WowClientDllPath.MaximumLength = (USHORT) ((Size + 1) * sizeof(WCHAR) );
  429. *ppInformation = Information ;
  430. Information = NULL ;
  431. break;
  432. default:
  433. Status = SEC_E_UNSUPPORTED_FUNCTION ;
  434. }
  435. Cleanup:
  436. if ( Information != NULL )
  437. {
  438. DigestFreeMemory( Information );
  439. }
  440. DebugLog((DEB_TRACE_FUNC, "SpGetExtendedInformation: Leaving Status %d\n", Status));
  441. return Status ;
  442. }
  443. NTSTATUS NTAPI
  444. SpSetExtendedInformation(
  445. IN SECPKG_EXTENDED_INFORMATION_CLASS Class,
  446. IN PSECPKG_EXTENDED_INFORMATION Info
  447. )
  448. {
  449. DebugLog((DEB_TRACE_FUNC, "SpSetExtendedInformation: Entering/Leaving \n"));
  450. UNREFERENCED_PARAMETER(Class);
  451. UNREFERENCED_PARAMETER(Info);
  452. return(SEC_E_UNSUPPORTED_FUNCTION) ;
  453. }
  454. //
  455. // Registry Reading routines
  456. // This routine is called in single-threaded mode from the LSA for SpInitialize and SPInstanceInit
  457. // In user applications only SPInstanceInit calls this function
  458. //
  459. BOOL SPLoadRegOptions(void)
  460. {
  461. if (NULL != g_hParamEvent)
  462. {
  463. // Already called - no need to re-execute
  464. DebugLog((DEB_TRACE, "SPLoadRegOptions: Already initialized - Leaving \n"));
  465. return TRUE;
  466. }
  467. g_hParamEvent = CreateEvent(NULL,
  468. FALSE,
  469. FALSE,
  470. NULL);
  471. DigestWatchParamKey(g_hParamEvent, FALSE);
  472. return TRUE;
  473. }
  474. void SPUnloadRegOptions(void)
  475. {
  476. if (NULL != g_hWait)
  477. {
  478. RtlDeregisterWaitEx(g_hWait, (HANDLE)-1);
  479. g_hWait = NULL;
  480. }
  481. if(NULL != g_hkBase)
  482. {
  483. RegCloseKey(g_hkBase);
  484. g_hkBase = NULL;
  485. }
  486. if(NULL != g_hParamEvent)
  487. {
  488. CloseHandle(g_hParamEvent);
  489. g_hParamEvent = NULL;
  490. }
  491. }
  492. // Helper function to read in a DWORD - sets value if not present in registry
  493. void
  494. ReadDwordRegistrySetting(
  495. HKEY hReadKey,
  496. HKEY hWriteKey,
  497. LPCTSTR pszValueName,
  498. DWORD * pdwValue,
  499. DWORD dwDefaultValue)
  500. {
  501. DWORD dwSize = 0;
  502. DWORD dwType = 0;
  503. dwSize = sizeof(DWORD);
  504. if(RegQueryValueEx(hReadKey,
  505. pszValueName,
  506. NULL,
  507. &dwType,
  508. (PUCHAR)pdwValue,
  509. &dwSize) != STATUS_SUCCESS)
  510. {
  511. *pdwValue = dwDefaultValue;
  512. if(hWriteKey)
  513. {
  514. RegSetValueEx(hWriteKey,
  515. pszValueName,
  516. 0,
  517. REG_DWORD,
  518. (PUCHAR)pdwValue,
  519. sizeof(DWORD));
  520. }
  521. }
  522. }
  523. // Can be called at any time to change the default values
  524. // As long as a DWORD assignment can be done in a single step
  525. BOOL
  526. NtDigestReadRegistry(BOOL fFirstTime)
  527. {
  528. DWORD dwBool = 0;
  529. DWORD dwDebug = 0;
  530. HKEY hWriteKey = 0;
  531. // Open top-level key that has write access.
  532. if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  533. REG_DIGEST_BASE,
  534. 0,
  535. KEY_READ | KEY_SET_VALUE,
  536. &hWriteKey) != STATUS_SUCCESS)
  537. {
  538. hWriteKey = 0;
  539. }
  540. // "LifeTime"
  541. ReadDwordRegistrySetting(
  542. g_hkBase,
  543. hWriteKey,
  544. REG_DIGEST_OPT_LIFETIME,
  545. &g_dwParameter_Lifetime,
  546. PARAMETER_LIFETIME);
  547. // "Negotiate" Supported - BOOL value
  548. ReadDwordRegistrySetting(
  549. g_hkBase,
  550. hWriteKey,
  551. REG_DIGEST_OPT_NEGOTIATE,
  552. &dwBool,
  553. PARAMETER_NEGOTIATE);
  554. if (dwBool)
  555. g_fParameter_Negotiate = TRUE;
  556. else
  557. g_fParameter_Negotiate = FALSE;
  558. // UTF8 Supported in HTTP mode - BOOL value
  559. ReadDwordRegistrySetting(
  560. g_hkBase,
  561. hWriteKey,
  562. REG_DIGEST_OPT_UTF8HTTP,
  563. &dwBool,
  564. PARAMETER_UTF8_HTTP);
  565. if (dwBool)
  566. g_fParameter_UTF8HTTP = TRUE;
  567. else
  568. g_fParameter_UTF8HTTP = FALSE;
  569. // UTF8 supported in SASL - BOOL value
  570. ReadDwordRegistrySetting(
  571. g_hkBase,
  572. hWriteKey,
  573. REG_DIGEST_OPT_UTF8SASL,
  574. &dwBool,
  575. PARAMETER_UTF8_SASL);
  576. if (dwBool)
  577. g_fParameter_UTF8SASL = TRUE;
  578. else
  579. g_fParameter_UTF8SASL = FALSE;
  580. // MaxContextCount
  581. /*
  582. ReadDwordRegistrySetting(
  583. g_hkBase,
  584. hWriteKey,
  585. REG_DIGEST_OPT_MAXCTXTCOUNT,
  586. &g_dwParameter_MaxCtxtCount,
  587. PARAMETER_MAXCTXTCOUNT);
  588. */
  589. #if DBG
  590. // DebugLevel
  591. ReadDwordRegistrySetting(
  592. g_hkBase,
  593. hWriteKey,
  594. REG_DIGEST_OPT_DEBUGLEVEL,
  595. &dwDebug,
  596. 0);
  597. DigestInfoLevel = dwDebug; // Turn on/off selected messages
  598. #endif
  599. if(hWriteKey)
  600. {
  601. RegCloseKey(hWriteKey);
  602. hWriteKey = 0;
  603. }
  604. DebugLog((DEB_TRACE, "NtDigestReadRegistry: Lifetime %lu, Negotiate %d, UTF-8 HTTP %d, UTF-8 SASL %d, DebugLevel 0x%x\n",
  605. g_dwParameter_Lifetime,
  606. g_fParameter_Negotiate,
  607. g_fParameter_UTF8HTTP,
  608. g_fParameter_UTF8SASL,
  609. dwDebug));
  610. return TRUE;
  611. }
  612. // This routine is called in single-threaded mode from the LSA for SpLsaModeInitialize and SPInstanceInit
  613. // In user applications only SPInstanceInit calls this function
  614. void
  615. DebugInitialize(void)
  616. {
  617. #if DBG
  618. if (l_bDebugInitialized == TRUE)
  619. {
  620. return;
  621. }
  622. l_bDebugInitialized = TRUE;
  623. DigestInitDebug(MyDebugKeys);
  624. DigestInfoLevel = 0x0; // Turn on OFF messages - Registry read will adjust which ones to keep on
  625. #endif
  626. return;
  627. }
  628. ////////////////////////////////////////////////////////////////////
  629. //
  630. // Name: DigestWatchParamKey
  631. //
  632. // Synopsis: Sets RegNotifyChangeKeyValue() on param key, initializes
  633. // debug level, then utilizes thread pool to wait on
  634. // changes to this registry key. Enables dynamic debug
  635. // level changes, as this function will also be callback
  636. // if registry key modified.
  637. //
  638. // Arguments: pCtxt is actually a HANDLE to an event. This event
  639. // will be triggered when key is modified.
  640. //
  641. // Notes: .
  642. //
  643. VOID
  644. DigestWatchParamKey(
  645. PVOID pCtxt,
  646. BOOLEAN fWaitStatus)
  647. {
  648. NTSTATUS Status;
  649. LONG lRes = ERROR_SUCCESS;
  650. BOOL fFirstTime = FALSE;
  651. DWORD disp;
  652. if(g_hkBase == NULL)
  653. {
  654. // First time we've been called.
  655. Status = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  656. REG_DIGEST_BASE,
  657. 0,
  658. TEXT(""),
  659. REG_OPTION_NON_VOLATILE,
  660. KEY_READ,
  661. NULL,
  662. &g_hkBase,
  663. &disp);
  664. if(Status)
  665. {
  666. DebugLog((DEB_WARN,"Failed to open WDigest key: 0x%x\n", Status));
  667. return;
  668. }
  669. fFirstTime = TRUE;
  670. }
  671. if(pCtxt != NULL)
  672. {
  673. if (NULL != g_hWait)
  674. {
  675. Status = RtlDeregisterWait(g_hWait);
  676. if(!NT_SUCCESS(Status))
  677. {
  678. DebugLog((DEB_WARN, "Failed to Deregister wait on registry key: 0x%x\n", Status));
  679. goto Reregister;
  680. }
  681. }
  682. lRes = RegNotifyChangeKeyValue(
  683. g_hkBase,
  684. TRUE,
  685. REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_LAST_SET,
  686. (HANDLE)pCtxt,
  687. TRUE);
  688. if (ERROR_SUCCESS != lRes)
  689. {
  690. DebugLog((DEB_ERROR,"Debug RegNotify setup failed: 0x%x\n", lRes));
  691. // we're tanked now. No further notifications, so get this one
  692. }
  693. }
  694. NtDigestReadRegistry(fFirstTime);
  695. Reregister:
  696. if(pCtxt != NULL)
  697. {
  698. Status = RtlRegisterWait(&g_hWait,
  699. (HANDLE)pCtxt,
  700. DigestWatchParamKey,
  701. (HANDLE)pCtxt,
  702. INFINITE,
  703. WT_EXECUTEINPERSISTENTIOTHREAD|
  704. WT_EXECUTEONLYONCE);
  705. }
  706. }