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.

686 lines
19 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. persist.cxx
  5. Abstract:
  6. Author:
  7. Adriaan Canter (adriaanc) 13-Jan-1998
  8. Revision History:
  9. 13-Jan-1998 adriaanc
  10. Created
  11. --*/
  12. #include <wininetp.h>
  13. #include <persist.h>
  14. typedef HRESULT (*PFNPSTORECREATEINSTANCE)(IPStore**, PST_PROVIDERID*, VOID*, DWORD);
  15. // Globals
  16. // PWL related variables.
  17. static HMODULE MhmodWNET = NULL;
  18. static PFWNETGETCACHEDPASSWORD pfWNetGetCachedPassword = NULL;
  19. static PFWNETCACHEPASSWORD pfWNetCachePassword = NULL;
  20. static PFWNETREMOVECACHEDPASSWORD pfWNetRemoveCachedPassword = NULL;
  21. // Pstore related variables.
  22. static PST_PROVIDERID s_provID = GUID_NULL;
  23. static WCHAR c_szWininetCacheCredentials[] = L"WininetCacheCredentials";
  24. static PFNPSTORECREATEINSTANCE pPStoreCreateInstance = NULL;
  25. // Webcheck is currently using this GUID for pstore:
  26. // {14D96C20-255B-11d1-898F-00C04FB6BFC4}
  27. // static const GUID GUID_PStoreType = { 0x14d96c20, 0x255b, 0x11d1, { 0x89, 0x8f, 0x0, 0xc0, 0x4f, 0xb6, 0xbf, 0xc4 } };
  28. // Wininet uses this GUID for pstore:
  29. // {5E7E8100-9138-11d1-945A-00C04FC308FF}
  30. static const GUID GUID_PStoreType =
  31. { 0x5e7e8100, 0x9138, 0x11d1, { 0x94, 0x5a, 0x0, 0xc0, 0x4f, 0xc3, 0x8, 0xff } };
  32. // Private function prototypes.
  33. // PWL private function prototypes.
  34. DWORD PWLSetCachedCredentials(LPSTR szKey, DWORD cbKey, LPSTR szCred, DWORD cbCred);
  35. DWORD PWLGetCachedCredentials (LPSTR szKey, DWORD cbKey, LPSTR cbCred, LPDWORD pcbCred);
  36. DWORD PWLRemoveCachedCredentials (LPSTR szKey, DWORD cbKey);
  37. BOOL LoadWNet(VOID);
  38. // PStore private function prototypes.
  39. DWORD PStoreSetCachedCredentials(LPSTR szKey, DWORD cbKey, LPSTR szCred, DWORD cbCred, BOOL fRemove=FALSE);
  40. DWORD PStoreGetCachedCredentials(LPSTR szKey, DWORD cbKey, LPSTR szCred, LPDWORD pcbCred);
  41. DWORD PStoreRemoveCachedCredentials(LPSTR szKey, DWORD cbKey);
  42. STDAPI CreatePStore (IPStore **ppIPStore);
  43. STDAPI ReleasePStore(IPStore *pIPStore);
  44. /*--------------------------- Top Level APIs ---------------------------------*/
  45. BOOL ReadLSARegistryDword( CHAR* lpszValueName, DWORD* pdwValue)
  46. {
  47. BOOL bRetVal = FALSE;
  48. HKEY key;
  49. DWORD dwType;
  50. if ( RegOpenKeyEx(
  51. HKEY_LOCAL_MACHINE,
  52. "SYSTEM\\CurrentControlSet\\Control\\Lsa",
  53. 0,
  54. KEY_READ,
  55. &key) == ERROR_SUCCESS)
  56. {
  57. DWORD dwSize = sizeof(DWORD);
  58. if ( RegQueryValueEx(
  59. key,
  60. lpszValueName,
  61. NULL,
  62. &dwType,
  63. (LPBYTE)pdwValue,
  64. &dwSize ) == ERROR_SUCCESS )
  65. {
  66. bRetVal = TRUE;
  67. }
  68. RegCloseKey(key);
  69. }
  70. return bRetVal;
  71. }
  72. /*-----------------------------------------------------------------------------
  73. InetInitCredentialPersist
  74. ---------------------------------------------------------------------------*/
  75. DWORD InetInitCredentialPersist()
  76. {
  77. HRESULT hr;
  78. IPStore *pIPStore = NULL;
  79. DWORD dwDisable, dwAvail, dwLSADisable;
  80. HINSTANCE hInstPStoreC = 0;
  81. BOOL fPersistDisabled = FALSE;
  82. AuthLock();
  83. // First check to see if persistence is disabled via registry.
  84. if ((InternetReadRegistryDword(DISABLE_PASSWORD_CACHE_VALUE, &dwDisable) == ERROR_SUCCESS)
  85. && (dwDisable == CRED_PERSIST_AVAIL))
  86. {
  87. // Persistence disabled via registry.
  88. dwAvail= CRED_PERSIST_NOT_AVAIL;
  89. goto quit;
  90. }
  91. // check to see if credmgr registry has disabled it
  92. if ( ReadLSARegistryDword( "DisableDomainCreds", & dwLSADisable ) && dwLSADisable )
  93. {
  94. // Persistence disabled via registry.
  95. dwAvail= CRED_PERSIST_NOT_AVAIL;
  96. goto quit;
  97. }
  98. // We use PWL for Win95; this should be available.
  99. if (IsPlatformWin95())
  100. {
  101. dwAvail = CRED_PERSIST_AVAIL;
  102. goto quit;
  103. }
  104. // If is WinNt, check if PStore is installed.
  105. hInstPStoreC = LoadLibrary(PSTORE_MODULE);
  106. if (!hInstPStoreC)
  107. {
  108. dwAvail = CRED_PERSIST_NOT_AVAIL;
  109. goto quit;
  110. }
  111. else
  112. {
  113. // Get CreatePStoreInstance function pointer.
  114. pPStoreCreateInstance = (PFNPSTORECREATEINSTANCE)
  115. GetProcAddress(hInstPStoreC, "PStoreCreateInstance");
  116. if (!pPStoreCreateInstance)
  117. {
  118. dwAvail = CRED_PERSIST_NOT_AVAIL;
  119. goto quit;
  120. }
  121. }
  122. // Create an IPStore.
  123. hr = CreatePStore(&pIPStore);
  124. // Succeeded in creating an IPStore.
  125. if (SUCCEEDED(hr) && pIPStore)
  126. {
  127. ReleasePStore(pIPStore);
  128. dwAvail = CRED_PERSIST_AVAIL;
  129. }
  130. else
  131. {
  132. // Failed to create an IPStore.
  133. dwAvail = CRED_PERSIST_NOT_AVAIL;
  134. }
  135. quit:
  136. g_dwCredPersistAvail = dwAvail;
  137. AuthUnlock();
  138. return g_dwCredPersistAvail;
  139. }
  140. /*-----------------------------------------------------------------------------
  141. InetSetCachedCredentials
  142. ---------------------------------------------------------------------------*/
  143. DWORD InetSetCachedCredentials (LPSTR szHost,
  144. LPSTR szRealm,
  145. LPSTR szUser,
  146. LPSTR szPass)
  147. {
  148. DWORD cbKey, cbCred, dwError = ERROR_INTERNET_INTERNAL_ERROR;
  149. CHAR szKey [MAX_AUTH_FIELD_LENGTH],
  150. szCred[MAX_AUTH_FIELD_LENGTH];
  151. INET_ASSERT(szHost && *szHost && szRealm
  152. && szUser && *szUser && szPass);
  153. // Check if credential persistence is available.
  154. if ((g_dwCredPersistAvail == CRED_PERSIST_UNKNOWN)
  155. && (InetInitCredentialPersist() == CRED_PERSIST_NOT_AVAIL))
  156. {
  157. dwError = ERROR_INTERNET_INTERNAL_ERROR;
  158. goto quit;
  159. }
  160. // Form key and credential strings.
  161. cbKey = wsprintf(szKey, "%s/%s", szHost, szRealm) + 1;
  162. #ifndef UNIX
  163. cbCred = wsprintf(szCred,"%s:%s", szUser, szPass) + 1;
  164. #else
  165. /* wsprintf on UNIX puts "(null)" if szPass is null. */
  166. cbCred = szPass ? (wsprintf(szCred,"%s:%s", szUser, szPass) + 1) :
  167. (wsprintf(szCred,"%s:", szUser) + 1);
  168. #endif /* UNIX */
  169. // Store credentials.
  170. if (IsPlatformWin95())
  171. {
  172. // Store credentials using PWL.
  173. dwError = PWLSetCachedCredentials(szKey, cbKey, szCred, cbCred);
  174. }
  175. else
  176. {
  177. // Store credentials using PStore.
  178. dwError = PStoreSetCachedCredentials(szKey, cbKey, szCred, cbCred);
  179. }
  180. quit:
  181. return dwError;
  182. }
  183. /*-----------------------------------------------------------------------------
  184. InetGetCachedCredentials
  185. ---------------------------------------------------------------------------*/
  186. DWORD InetGetCachedCredentials (LPSTR szHost,
  187. LPSTR szRealm,
  188. LPSTR szUser,
  189. LPSTR szPass)
  190. {
  191. DWORD cbKey, cbCred, nUser, dwError;
  192. CHAR szKey [MAX_AUTH_FIELD_LENGTH],
  193. szCred[MAX_AUTH_FIELD_LENGTH],
  194. *ptr;
  195. INET_ASSERT(szHost && *szHost && szRealm && szUser && szPass);
  196. // Check if credential persistence is available.
  197. if (g_dwCredPersistAvail == CRED_PERSIST_UNKNOWN)
  198. InetInitCredentialPersist();
  199. if (g_dwCredPersistAvail == CRED_PERSIST_NOT_AVAIL)
  200. {
  201. dwError = ERROR_INTERNET_INTERNAL_ERROR;
  202. goto quit;
  203. }
  204. // Key string in form of host/[realm or domain].
  205. cbKey = wsprintf(szKey, "%s/%s", szHost, szRealm) + 1;
  206. cbCred = MAX_AUTH_FIELD_LENGTH;
  207. if (IsPlatformWin95())
  208. {
  209. // Store credentials using PWL.
  210. if ((dwError = PWLGetCachedCredentials(szKey, cbKey,
  211. szCred, &cbCred)) != WN_SUCCESS)
  212. goto quit;
  213. }
  214. else
  215. {
  216. // Store credentials using PStore.
  217. if ((dwError = PStoreGetCachedCredentials(szKey, cbKey,
  218. szCred, &cbCred)) != ERROR_SUCCESS)
  219. goto quit;
  220. }
  221. // Should have retrieved credentials in form of username:password.
  222. ptr = strchr(szCred, ':');
  223. // Should never happen since username & password are required.
  224. if (!ptr || (ptr == szCred))
  225. {
  226. dwError = ERROR_INTERNET_INTERNAL_ERROR;
  227. goto quit;
  228. }
  229. // Copy username & null terminate.
  230. nUser = (DWORD)(ptr - szCred);
  231. memcpy(szUser, szCred, nUser);
  232. szUser[nUser] = '\0';
  233. // Copy password with null terminator.
  234. memcpy(szPass, ptr+1, cbCred - nUser);
  235. quit:
  236. return dwError;
  237. }
  238. /*-----------------------------------------------------------------------------
  239. InetRemoveCachedCredentials
  240. ---------------------------------------------------------------------------*/
  241. DWORD InetRemoveCachedCredentials (LPSTR szHost, LPSTR szRealm)
  242. {
  243. DWORD cbKey, dwError;
  244. CHAR szKey[MAX_AUTH_FIELD_LENGTH];
  245. INET_ASSERT(szHost && *szHost && szRealm);
  246. // Check if credential persistence is available.
  247. if ((g_dwCredPersistAvail == CRED_PERSIST_UNKNOWN)
  248. && (InetInitCredentialPersist() == CRED_PERSIST_NOT_AVAIL))
  249. {
  250. dwError = ERROR_INTERNET_INTERNAL_ERROR;
  251. goto quit;
  252. }
  253. // Form key string.
  254. cbKey = wsprintf(szKey, "%s/%s", szHost, szRealm) + 1;
  255. if (IsPlatformWin95())
  256. {
  257. // Remove credentials from PWL.
  258. dwError = PWLRemoveCachedCredentials(szKey, cbKey);
  259. }
  260. else
  261. {
  262. // Remove credentials from PStore.
  263. dwError = PStoreRemoveCachedCredentials(szKey, cbKey);
  264. }
  265. quit:
  266. return dwError;
  267. }
  268. /*--------------------------- PWL Functions ---------------------------------*/
  269. /*-----------------------------------------------------------------------------
  270. PWLSetCachedCredentials
  271. ---------------------------------------------------------------------------*/
  272. DWORD PWLSetCachedCredentials(LPSTR szKey, DWORD cbKey,
  273. LPSTR szCred, DWORD cbCred)
  274. {
  275. DWORD dwError;
  276. // Load WNet.
  277. if (!LoadWNet())
  278. return ERROR_INTERNET_INTERNAL_ERROR;
  279. // Store credentials.
  280. dwError = (*pfWNetCachePassword)(szKey, (WORD) cbKey, szCred, (WORD) cbCred, PCE_WWW_BASIC, 0);
  281. return dwError;
  282. }
  283. /*-----------------------------------------------------------------------------
  284. PWLGetCachedCredentials
  285. ---------------------------------------------------------------------------*/
  286. DWORD PWLGetCachedCredentials (LPSTR szKey, DWORD cbKey,
  287. LPSTR szCred, LPDWORD pcbCred)
  288. {
  289. DWORD dwError;
  290. // Load WNet.
  291. if (!LoadWNet())
  292. return ERROR_INTERNET_INTERNAL_ERROR;
  293. // Retrieve credentials.
  294. dwError = (*pfWNetGetCachedPassword) (szKey, (WORD) cbKey, szCred,
  295. (LPWORD) pcbCred, PCE_WWW_BASIC);
  296. return dwError;
  297. }
  298. /*-----------------------------------------------------------------------------
  299. PWLRemoveCachedCredentials
  300. ---------------------------------------------------------------------------*/
  301. DWORD PWLRemoveCachedCredentials (LPSTR szKey, DWORD cbKey)
  302. {
  303. DWORD dwError;
  304. // Load WNet.
  305. if (!LoadWNet())
  306. return ERROR_INTERNET_INTERNAL_ERROR;
  307. dwError = (*pfWNetRemoveCachedPassword) (szKey, (WORD) cbKey, PCE_WWW_BASIC);
  308. return dwError;
  309. }
  310. // PWL utility functions.
  311. /*-----------------------------------------------------------------------------
  312. LoadWNet
  313. ---------------------------------------------------------------------------*/
  314. BOOL LoadWNet(VOID)
  315. {
  316. BOOL fReturn;
  317. AuthLock();
  318. // MPR.DLL already loaded.
  319. if (MhmodWNET)
  320. {
  321. fReturn = TRUE;
  322. goto quit;
  323. }
  324. // Load MPR.DLL
  325. MhmodWNET = LoadLibrary(WNETDLL_MODULE);
  326. // Fail if not loaded.
  327. if (MhmodWNET)
  328. {
  329. fReturn = TRUE;
  330. }
  331. else
  332. {
  333. fReturn = FALSE;
  334. goto quit;
  335. }
  336. pfWNetGetCachedPassword = (PFWNETGETCACHEDPASSWORD) GetProcAddress(MhmodWNET, WNETGETCACHEDPASS);
  337. pfWNetCachePassword = (PFWNETCACHEPASSWORD) GetProcAddress(MhmodWNET, WNETCACHEPASS);
  338. pfWNetRemoveCachedPassword = (PFWNETREMOVECACHEDPASSWORD) GetProcAddress(MhmodWNET, WNETREMOVECACHEDPASS);
  339. // Ensure we have all function pointers.
  340. if (!(pfWNetGetCachedPassword
  341. && pfWNetCachePassword
  342. && pfWNetRemoveCachedPassword))
  343. {
  344. fReturn = FALSE;
  345. }
  346. quit:
  347. AuthUnlock();
  348. return fReturn;
  349. }
  350. /*------------------------- PStore Functions -------------------------------*/
  351. /*-----------------------------------------------------------------------------
  352. PStoreSetCachedCredentials
  353. ---------------------------------------------------------------------------*/
  354. DWORD PStoreSetCachedCredentials(LPSTR szKey, DWORD cbKey,
  355. LPSTR szCred, DWORD cbCred,
  356. BOOL fRemove)
  357. {
  358. INET_ASSERT(pPStoreCreateInstance);
  359. HRESULT hr;
  360. DWORD dwError;
  361. PST_TYPEINFO typeInfo;
  362. PST_PROMPTINFO promptInfo = {0};
  363. GUID itemType = GUID_PStoreType;
  364. GUID itemSubtype = GUID_NULL;
  365. WCHAR wszKey[MAX_AUTH_FIELD_LENGTH];
  366. IPStore * pStore = NULL;
  367. // PST_TYPEINFO data.
  368. typeInfo.cbSize = sizeof(typeInfo);
  369. typeInfo.szDisplayName = c_szWininetCacheCredentials;
  370. // PST_PROMPTINFO data (no prompting desired).
  371. promptInfo.cbSize = sizeof(promptInfo);
  372. promptInfo.dwPromptFlags = 0;
  373. promptInfo.hwndApp = NULL;
  374. promptInfo.szPrompt = NULL;
  375. // Create a PStore interface.
  376. hr = CreatePStore(&pStore);
  377. if (!SUCCEEDED(hr))
  378. goto quit;
  379. INET_ASSERT(pStore != NULL);
  380. // Create a type in HKCU.
  381. hr = pStore->CreateType(PST_KEY_CURRENT_USER, &itemType, &typeInfo, 0);
  382. if (!((SUCCEEDED(hr)) || (hr == PST_E_TYPE_EXISTS)))
  383. goto quit;
  384. // Create subtype.
  385. hr = pStore->CreateSubtype(PST_KEY_CURRENT_USER, &itemType,
  386. &itemSubtype, &typeInfo, NULL, 0);
  387. if (!((SUCCEEDED(hr)) || (hr == PST_E_TYPE_EXISTS)))
  388. goto quit;
  389. // Convert key to wide char.
  390. MultiByteToWideChar(CP_ACP, 0, szKey, -1, wszKey, MAX_AUTH_FIELD_LENGTH);
  391. // Valid credentials are written; No credentials imples
  392. // that the key and credentials are to be deleted.
  393. if (szCred && cbCred && !fRemove)
  394. {
  395. // Write key and credentials to PStore.
  396. hr = pStore->WriteItem(PST_KEY_CURRENT_USER,
  397. &itemType,
  398. &itemSubtype,
  399. wszKey,
  400. cbCred,
  401. (LPBYTE) szCred,
  402. &promptInfo,
  403. PST_CF_NONE,
  404. 0);
  405. }
  406. else
  407. {
  408. // Delete key and credentials from PStore.
  409. hr = pStore->DeleteItem(PST_KEY_CURRENT_USER,
  410. &itemType,
  411. &itemSubtype,
  412. wszKey,
  413. &promptInfo,
  414. 0);
  415. }
  416. quit:
  417. // Release the interface, convert error and return.
  418. ReleasePStore(pStore);
  419. if (SUCCEEDED(hr))
  420. dwError = ERROR_SUCCESS;
  421. else
  422. dwError = ERROR_INTERNET_INTERNAL_ERROR;
  423. return dwError;
  424. }
  425. /*-----------------------------------------------------------------------------
  426. PStoreGetCachedCredentials
  427. ---------------------------------------------------------------------------*/
  428. DWORD PStoreGetCachedCredentials(LPSTR szKey, DWORD cbKey,
  429. LPSTR szCred, LPDWORD pcbCred)
  430. {
  431. INET_ASSERT(pPStoreCreateInstance);
  432. HRESULT hr ;
  433. DWORD dwError;
  434. LPBYTE pbData;
  435. PST_PROMPTINFO promptInfo = {0};
  436. GUID itemType = GUID_PStoreType;
  437. GUID itemSubtype = GUID_NULL;
  438. IPStore* pStore = NULL;
  439. WCHAR wszKey[MAX_AUTH_FIELD_LENGTH];
  440. // PST_PROMPTINFO data (no prompting desired).
  441. promptInfo.cbSize = sizeof(promptInfo);
  442. promptInfo.dwPromptFlags = 0;
  443. promptInfo.hwndApp = NULL;
  444. promptInfo.szPrompt = NULL;
  445. // Create a PStore interface.
  446. hr = CreatePStore(&pStore);
  447. if (!SUCCEEDED(hr))
  448. goto quit;
  449. INET_ASSERT(pStore != NULL);
  450. // Convert key to wide char.
  451. MultiByteToWideChar(CP_ACP, 0, szKey, -1, wszKey, MAX_AUTH_FIELD_LENGTH);
  452. // Read the credentials from PStore.
  453. hr = pStore->ReadItem(PST_KEY_CURRENT_USER,
  454. &itemType,
  455. &itemSubtype,
  456. wszKey,
  457. pcbCred,
  458. (LPBYTE*) &pbData,
  459. &promptInfo,
  460. 0);
  461. // Copy credentials and free buffer allocated by ReadItem.
  462. if (SUCCEEDED(hr))
  463. {
  464. memcpy(szCred, pbData, *pcbCred);
  465. CoTaskMemFree(pbData);
  466. //hr = S_OK;
  467. }
  468. quit:
  469. // Release the interface, convert error and return.
  470. ReleasePStore(pStore);
  471. if (SUCCEEDED(hr))
  472. dwError = ERROR_SUCCESS;
  473. else
  474. dwError = ERROR_INTERNET_INTERNAL_ERROR;
  475. return dwError;
  476. }
  477. /*-----------------------------------------------------------------------------
  478. PStoreRemoveCachedCredentials
  479. ---------------------------------------------------------------------------*/
  480. DWORD PStoreRemoveCachedCredentials(LPSTR szKey, DWORD cbKey)
  481. {
  482. // Pass in TRUE to remove credentials.
  483. return PStoreSetCachedCredentials(szKey, cbKey, NULL, 0, TRUE);
  484. }
  485. // PStore utility functions
  486. /*-----------------------------------------------------------------------------
  487. CreatePStore
  488. ---------------------------------------------------------------------------*/
  489. STDAPI CreatePStore(IPStore **ppIPStore)
  490. {
  491. HRESULT hr;
  492. DWORD dwError;
  493. hr = pPStoreCreateInstance (ppIPStore,
  494. IsEqualGUID(s_provID, GUID_NULL) ? NULL : &s_provID,
  495. NULL,
  496. 0);
  497. if (SUCCEEDED(hr))
  498. dwError = ERROR_SUCCESS;
  499. else
  500. dwError = ERROR_INTERNET_INTERNAL_ERROR;
  501. return dwError;
  502. }
  503. /*-----------------------------------------------------------------------------
  504. ReleasePStore
  505. ---------------------------------------------------------------------------*/
  506. STDAPI ReleasePStore(IPStore *pIPStore)
  507. {
  508. HRESULT hr;
  509. if (pIPStore)
  510. {
  511. pIPStore->Release();
  512. hr = S_OK;
  513. }
  514. else
  515. {
  516. hr = E_POINTER;
  517. }
  518. return hr;
  519. }