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.

695 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. 01-Aug-1998 adriaanc
  12. revised for digest.
  13. --*/
  14. #include "include.hxx"
  15. typedef HRESULT (*PFNPSTORECREATEINSTANCE)(IPStore**, PST_PROVIDERID*, VOID*, DWORD);
  16. // Globals
  17. // PWL related variables.
  18. static HMODULE MhmodWNET = NULL;
  19. static PFWNETGETCACHEDPASSWORD pfWNetGetCachedPassword = NULL;
  20. static PFWNETCACHEPASSWORD pfWNetCachePassword = NULL;
  21. static PFWNETREMOVECACHEDPASSWORD pfWNetRemoveCachedPassword = NULL;
  22. // Pstore related variables.
  23. static WCHAR c_szDigestCacheCredentials[] = L"DigestCacheCredentials";
  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 and digest use 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. // Find platform type.
  45. DWORD PlatformType()
  46. {
  47. OSVERSIONINFO versionInfo;
  48. versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
  49. if (GetVersionEx(&versionInfo))
  50. return versionInfo.dwPlatformId;
  51. return VER_PLATFORM_WIN32_WINDOWS;
  52. }
  53. //--------------------------------------------------------------------
  54. // IsPersistenceDisabled
  55. //--------------------------------------------------------------------
  56. BOOL IsPersistenceDisabled()
  57. {
  58. CHAR szBuf[MAX_PATH];
  59. DWORD dwType, dwError, dwOut = MAX_PATH, cbBuf = MAX_PATH;
  60. BOOL fRet = FALSE;
  61. HKEY hSettings = (HKEY) INVALID_HANDLE_VALUE;
  62. if ((dwError = RegCreateKey(HKEY_CURRENT_USER, INTERNET_SETTINGS_KEY, &hSettings)) == ERROR_SUCCESS)
  63. {
  64. if ((dwError = RegQueryValueEx(hSettings, DISABLE_PASSWORD_CACHE_VALUE, NULL, &dwType, (LPBYTE) szBuf, &cbBuf)) == ERROR_SUCCESS)
  65. {
  66. fRet = TRUE;
  67. }
  68. }
  69. if (hSettings != INVALID_HANDLE_VALUE)
  70. RegCloseKey(hSettings);
  71. return fRet;
  72. }
  73. /*--------------------------- Top Level APIs ---------------------------------*/
  74. //--------------------------------------------------------------------
  75. // InetInitCredentialPersist
  76. //--------------------------------------------------------------------
  77. DWORD InetInitCredentialPersist()
  78. {
  79. HRESULT hr;
  80. IPStore *pIPStore = NULL;
  81. DWORD dwDisable, dwAvail;
  82. HINSTANCE hInstPStoreC = 0;
  83. BOOL fPersistDisabled = FALSE;
  84. // we should have the digest lock at this point.
  85. // AuthLock();
  86. // First check to see if persistence is disabled via registry.
  87. if (IsPersistenceDisabled())
  88. {
  89. // Persistence disabled via registry.
  90. dwAvail= CRED_PERSIST_NOT_AVAIL;
  91. goto quit;
  92. }
  93. // We use PWL for Win95; this should be available.
  94. if (PlatformType() == VER_PLATFORM_WIN32_WINDOWS)
  95. {
  96. dwAvail = CRED_PERSIST_AVAIL;
  97. goto quit;
  98. }
  99. // If is WinNt, check if PStore is installed.
  100. hInstPStoreC = LoadLibrary(PSTORE_MODULE);
  101. if (!hInstPStoreC)
  102. {
  103. dwAvail = CRED_PERSIST_NOT_AVAIL;
  104. goto quit;
  105. }
  106. else
  107. {
  108. // Get CreatePStoreInstance function pointer.
  109. pPStoreCreateInstance = (PFNPSTORECREATEINSTANCE)
  110. GetProcAddress(hInstPStoreC, "PStoreCreateInstance");
  111. if (!pPStoreCreateInstance)
  112. {
  113. dwAvail = CRED_PERSIST_NOT_AVAIL;
  114. goto quit;
  115. }
  116. }
  117. // Create an IPStore.
  118. hr = CreatePStore(&pIPStore);
  119. // Succeeded in creating an IPStore.
  120. if (SUCCEEDED(hr) && pIPStore)
  121. {
  122. ReleasePStore(pIPStore);
  123. dwAvail = CRED_PERSIST_AVAIL;
  124. }
  125. else
  126. {
  127. // Failed to create an IPStore.
  128. dwAvail = CRED_PERSIST_NOT_AVAIL;
  129. }
  130. quit:
  131. g_dwCredPersistAvail = dwAvail;
  132. //AuthUnlock();
  133. return g_dwCredPersistAvail;
  134. }
  135. //--------------------------------------------------------------------
  136. // InetSetCachedCredentials
  137. //--------------------------------------------------------------------
  138. DWORD InetSetCachedCredentials (LPSTR szCtx,
  139. LPSTR szRealm,
  140. LPSTR szUser,
  141. LPSTR szPass)
  142. {
  143. DWORD cbKey, cbCred, dwError;
  144. CHAR szKey [MAX_AUTH_FIELD_LENGTH],
  145. szCred[MAX_AUTH_FIELD_LENGTH];
  146. DIGEST_ASSERT(szCtx && *szCtx && szRealm
  147. && szUser && *szUser && szPass);
  148. // Check if credential persistence is available.
  149. if ((g_dwCredPersistAvail == CRED_PERSIST_UNKNOWN)
  150. && (InetInitCredentialPersist() == CRED_PERSIST_NOT_AVAIL))
  151. {
  152. dwError = ERROR_OPEN_FAILED;
  153. goto quit;
  154. }
  155. // Form key and credential strings.
  156. strcpy(szKey, szCtx);
  157. strcat(szKey, "/");
  158. DWORD dwAvailBuf = MAX_AUTH_FIELD_LENGTH - strlen(szKey);
  159. strncpy(szKey + strlen(szKey), szRealm, dwAvailBuf - 1);
  160. szKey[MAX_AUTH_FIELD_LENGTH-1]= 0;
  161. cbKey = strlen(szKey) + 1;
  162. // cbKey = wsprintf(szKey, "%s/%s", szCtx, szRealm) + 1;
  163. cbCred = wsprintf(szCred,"%s:%s", szUser, szPass) + 1;
  164. // Store credentials.
  165. if (PlatformType() == VER_PLATFORM_WIN32_WINDOWS)
  166. {
  167. // Store credentials using PWL.
  168. dwError = PWLSetCachedCredentials(szKey, cbKey, szCred, cbCred);
  169. }
  170. else
  171. {
  172. // Store credentials using PStore.
  173. dwError = PStoreSetCachedCredentials(szKey, cbKey, szCred, cbCred);
  174. }
  175. quit:
  176. return dwError;
  177. }
  178. //--------------------------------------------------------------------
  179. // InetGetCachedCredentials
  180. //--------------------------------------------------------------------
  181. DWORD InetGetCachedCredentials (LPSTR szCtx,
  182. LPSTR szRealm,
  183. LPSTR szUser,
  184. LPSTR szPass)
  185. {
  186. DWORD cbKey, cbCred, nUser, dwError;
  187. CHAR szKey [MAX_AUTH_FIELD_LENGTH],
  188. szCred[MAX_AUTH_FIELD_LENGTH],
  189. *ptr;
  190. DIGEST_ASSERT(szCtx && *szCtx && szRealm && szUser && szPass);
  191. // Check if credential persistence is available.
  192. if ((g_dwCredPersistAvail == CRED_PERSIST_UNKNOWN)
  193. && (InetInitCredentialPersist() == CRED_PERSIST_NOT_AVAIL))
  194. {
  195. dwError = ERROR_OPEN_FAILED;
  196. goto quit;
  197. }
  198. // Key string is host/realm
  199. strcpy(szKey, szCtx);
  200. strcat(szKey, "/");
  201. DWORD dwAvailBuf = MAX_AUTH_FIELD_LENGTH - strlen(szKey);
  202. strncpy(szKey + strlen(szKey), szRealm, dwAvailBuf - 1);
  203. szKey[MAX_AUTH_FIELD_LENGTH-1]= 0;
  204. cbKey = strlen(szKey) + 1;
  205. // cbKey = wsprintf(szKey, "%s/%s", szCtx, szRealm) + 1;
  206. cbCred = MAX_AUTH_FIELD_LENGTH;
  207. if (PlatformType() == VER_PLATFORM_WIN32_WINDOWS)
  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_OPEN_FAILED;
  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 szCtx, LPSTR szRealm)
  242. {
  243. DWORD cbKey, dwError;
  244. CHAR szKey[MAX_AUTH_FIELD_LENGTH];
  245. DIGEST_ASSERT(szCtx && *szCtx && 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_OPEN_FAILED;
  251. goto quit;
  252. }
  253. // Form key string.
  254. strcpy(szKey, szCtx);
  255. strcat(szKey, "/");
  256. DWORD dwAvailBuf = MAX_AUTH_FIELD_LENGTH - strlen(szKey);
  257. strncpy(szKey + strlen(szKey), szRealm, dwAvailBuf - 1);
  258. szKey[MAX_AUTH_FIELD_LENGTH-1]= 0;
  259. cbKey = strlen(szKey) + 1;
  260. // cbKey = wsprintf(szKey, "%s/%s", szCtx, szRealm) + 1;
  261. if (PlatformType() == VER_PLATFORM_WIN32_WINDOWS)
  262. {
  263. // Remove credentials from PWL.
  264. dwError = PWLRemoveCachedCredentials(szKey, cbKey);
  265. }
  266. else
  267. {
  268. // Remove credentials from PStore.
  269. dwError = PStoreRemoveCachedCredentials(szKey, cbKey);
  270. }
  271. quit:
  272. return dwError;
  273. }
  274. /*--------------------------- PWL Functions ---------------------------------*/
  275. //--------------------------------------------------------------------
  276. // PWLSetCachedCredentials
  277. //--------------------------------------------------------------------
  278. DWORD PWLSetCachedCredentials(LPSTR szKey, DWORD cbKey,
  279. LPSTR szCred, DWORD cbCred)
  280. {
  281. DWORD dwError;
  282. // Load WNet.
  283. if (!LoadWNet())
  284. return ERROR_OPEN_FAILED;
  285. // Store credentials.
  286. dwError = (*pfWNetCachePassword)(szKey, (WORD) cbKey, szCred, (WORD) cbCred, PCE_WWW_BASIC, 0);
  287. return dwError;
  288. }
  289. //--------------------------------------------------------------------
  290. // PWLGetCachedCredentials
  291. //--------------------------------------------------------------------
  292. DWORD PWLGetCachedCredentials (LPSTR szKey, DWORD cbKey,
  293. LPSTR szCred, LPDWORD pcbCred)
  294. {
  295. DWORD dwError;
  296. // Load WNet.
  297. if (!LoadWNet())
  298. return ERROR_OPEN_FAILED;
  299. // Retrieve credentials.
  300. dwError = (*pfWNetGetCachedPassword) (szKey, (WORD) cbKey, szCred,
  301. (LPWORD) pcbCred, PCE_WWW_BASIC);
  302. return dwError;
  303. }
  304. //--------------------------------------------------------------------
  305. // PWLRemoveCachedCredentials
  306. //--------------------------------------------------------------------
  307. DWORD PWLRemoveCachedCredentials (LPSTR szKey, DWORD cbKey)
  308. {
  309. DWORD dwError;
  310. // Load WNet.
  311. if (!LoadWNet())
  312. return ERROR_OPEN_FAILED;
  313. dwError = (*pfWNetRemoveCachedPassword) (szKey, (WORD) cbKey, PCE_WWW_BASIC);
  314. return dwError;
  315. }
  316. // PWL utility functions.
  317. //--------------------------------------------------------------------
  318. // LoadWNet
  319. //--------------------------------------------------------------------
  320. BOOL LoadWNet(VOID)
  321. {
  322. BOOL fReturn;
  323. // we should have the digest lock at this point.
  324. //AuthLock();
  325. // MPR.DLL already loaded.
  326. if (MhmodWNET)
  327. {
  328. fReturn = TRUE;
  329. goto quit;
  330. }
  331. // Load MPR.DLL
  332. MhmodWNET = LoadLibrary(WNETDLL_MODULE);
  333. // Fail if not loaded.
  334. if (MhmodWNET)
  335. {
  336. fReturn = TRUE;
  337. }
  338. else
  339. {
  340. fReturn = FALSE;
  341. goto quit;
  342. }
  343. pfWNetGetCachedPassword = (PFWNETGETCACHEDPASSWORD) GetProcAddress(MhmodWNET, WNETGETCACHEDPASS);
  344. pfWNetCachePassword = (PFWNETCACHEPASSWORD) GetProcAddress(MhmodWNET, WNETCACHEPASS);
  345. pfWNetRemoveCachedPassword = (PFWNETREMOVECACHEDPASSWORD) GetProcAddress(MhmodWNET, WNETREMOVECACHEDPASS);
  346. // Ensure we have all function pointers.
  347. if (!(pfWNetGetCachedPassword
  348. && pfWNetCachePassword
  349. && pfWNetRemoveCachedPassword))
  350. {
  351. fReturn = FALSE;
  352. }
  353. quit:
  354. //AuthUnlock();
  355. return fReturn;
  356. }
  357. /*------------------------- PStore Functions -------------------------------*/
  358. //--------------------------------------------------------------------
  359. // PStoreSetCachedCredentials
  360. //--------------------------------------------------------------------
  361. DWORD PStoreSetCachedCredentials(LPSTR szKey, DWORD cbKey,
  362. LPSTR szCred, DWORD cbCred,
  363. BOOL fRemove)
  364. {
  365. DIGEST_ASSERT(pPStoreCreateInstance);
  366. HRESULT hr;
  367. DWORD dwError;
  368. PST_TYPEINFO typeInfo;
  369. PST_PROMPTINFO promptInfo = {0};
  370. GUID itemType = GUID_PStoreType;
  371. GUID itemSubtype = GUID_NULL;
  372. WCHAR wszKey[MAX_AUTH_FIELD_LENGTH];
  373. IPStore * pStore = NULL;
  374. // PST_TYPEINFO data.
  375. typeInfo.cbSize = sizeof(typeInfo);
  376. typeInfo.szDisplayName = c_szDigestCacheCredentials;
  377. // PST_PROMPTINFO data (no prompting desired).
  378. promptInfo.cbSize = sizeof(promptInfo);
  379. promptInfo.dwPromptFlags = 0;
  380. promptInfo.hwndApp = NULL;
  381. promptInfo.szPrompt = NULL;
  382. // Create a PStore interface.
  383. hr = CreatePStore(&pStore);
  384. if (!SUCCEEDED(hr))
  385. goto quit;
  386. DIGEST_ASSERT(pStore != NULL);
  387. // Create a type in HKCU.
  388. hr = pStore->CreateType(PST_KEY_CURRENT_USER, &itemType, &typeInfo, 0);
  389. if (!((SUCCEEDED(hr)) || (hr == PST_E_TYPE_EXISTS)))
  390. goto quit;
  391. // Create subtype.
  392. hr = pStore->CreateSubtype(PST_KEY_CURRENT_USER, &itemType,
  393. &itemSubtype, &typeInfo, NULL, 0);
  394. if (!((SUCCEEDED(hr)) || (hr == PST_E_TYPE_EXISTS)))
  395. goto quit;
  396. // Convert key to wide char.
  397. MultiByteToWideChar(CP_ACP, 0, szKey, -1, wszKey, MAX_AUTH_FIELD_LENGTH);
  398. // Valid credentials are written; No credentials imples
  399. // that the key and credentials are to be deleted.
  400. if (szCred && cbCred && !fRemove)
  401. {
  402. // Write key and credentials to PStore.
  403. hr = pStore->WriteItem(PST_KEY_CURRENT_USER,
  404. &itemType,
  405. &itemSubtype,
  406. wszKey,
  407. cbCred,
  408. (LPBYTE) szCred,
  409. &promptInfo,
  410. PST_CF_NONE,
  411. 0);
  412. }
  413. else
  414. {
  415. // Delete key and credentials from PStore.
  416. hr = pStore->DeleteItem(PST_KEY_CURRENT_USER,
  417. &itemType,
  418. &itemSubtype,
  419. wszKey,
  420. &promptInfo,
  421. 0);
  422. }
  423. quit:
  424. // Release the interface, convert error and return.
  425. ReleasePStore(pStore);
  426. if (SUCCEEDED(hr))
  427. dwError = ERROR_SUCCESS;
  428. else
  429. dwError = ERROR_OPEN_FAILED;
  430. return dwError;
  431. }
  432. //--------------------------------------------------------------------
  433. // PStoreGetCachedCredentials
  434. //--------------------------------------------------------------------
  435. DWORD PStoreGetCachedCredentials(LPSTR szKey, DWORD cbKey,
  436. LPSTR szCred, LPDWORD pcbCred)
  437. {
  438. DIGEST_ASSERT(pPStoreCreateInstance);
  439. HRESULT hr ;
  440. DWORD dwError;
  441. LPBYTE pbData;
  442. PST_PROMPTINFO promptInfo = {0};
  443. GUID itemType = GUID_PStoreType;
  444. GUID itemSubtype = GUID_NULL;
  445. IPStore* pStore = NULL;
  446. WCHAR wszKey[MAX_AUTH_FIELD_LENGTH];
  447. // PST_PROMPTINFO data (no prompting desired).
  448. promptInfo.cbSize = sizeof(promptInfo);
  449. promptInfo.dwPromptFlags = 0;
  450. promptInfo.hwndApp = NULL;
  451. promptInfo.szPrompt = NULL;
  452. // Create a PStore interface.
  453. hr = CreatePStore(&pStore);
  454. if (!SUCCEEDED(hr))
  455. goto quit;
  456. DIGEST_ASSERT(pStore != NULL);
  457. // Convert key to wide char.
  458. MultiByteToWideChar(CP_ACP, 0, szKey, -1, wszKey, MAX_AUTH_FIELD_LENGTH);
  459. // Read the credentials from PStore.
  460. hr = pStore->ReadItem(PST_KEY_CURRENT_USER,
  461. &itemType,
  462. &itemSubtype,
  463. wszKey,
  464. pcbCred,
  465. (LPBYTE*) &pbData,
  466. &promptInfo,
  467. 0);
  468. // Copy credentials and free buffer allocated by ReadItem.
  469. if (SUCCEEDED(hr))
  470. {
  471. memcpy(szCred, pbData, *pcbCred);
  472. CoTaskMemFree(pbData);
  473. //hr = S_OK;
  474. }
  475. quit:
  476. // Release the interface, convert error and return.
  477. ReleasePStore(pStore);
  478. if (SUCCEEDED(hr))
  479. dwError = ERROR_SUCCESS;
  480. else
  481. dwError = ERROR_OPEN_FAILED;
  482. return dwError;
  483. }
  484. //--------------------------------------------------------------------
  485. // PStoreRemoveCachedCredentials
  486. //--------------------------------------------------------------------
  487. DWORD PStoreRemoveCachedCredentials(LPSTR szKey, DWORD cbKey)
  488. {
  489. // Pass in TRUE to remove credentials.
  490. return PStoreSetCachedCredentials(szKey, cbKey, NULL, 0, TRUE);
  491. }
  492. // PStore utility functions
  493. //--------------------------------------------------------------------
  494. // CreatePStore
  495. //--------------------------------------------------------------------
  496. STDAPI CreatePStore(IPStore **ppIPStore)
  497. {
  498. HRESULT hr;
  499. DWORD dwError;
  500. hr = pPStoreCreateInstance (ppIPStore,
  501. NULL,
  502. NULL,
  503. 0);
  504. if (SUCCEEDED(hr))
  505. dwError = ERROR_SUCCESS;
  506. else
  507. dwError = ERROR_OPEN_FAILED;
  508. return dwError;
  509. }
  510. //--------------------------------------------------------------------
  511. // ReleasePStore
  512. //--------------------------------------------------------------------
  513. STDAPI ReleasePStore(IPStore *pIPStore)
  514. {
  515. HRESULT hr;
  516. if (pIPStore)
  517. {
  518. pIPStore->Release();
  519. hr = S_OK;
  520. }
  521. else
  522. {
  523. hr = E_POINTER;
  524. }
  525. return hr;
  526. }