passwordapi.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 18k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. /*****************************************************************************
  2.     FILE: passwordapi.cpp
  3.     
  4.     DESCRIPTION:
  5.         We want to store FTP passwords in a secure API.  We will use the
  6.     PStore APIs on WinNT and the PWL APIs on Win9x.  This code was taken
  7.     from wininet.
  8.     Copyright (c) 1998-1999  Microsoft Corporation
  9. *****************************************************************************/
  10. #include "priv.h"
  11. #include <pstore.h>
  12. #include <passwordapi.h>
  13. typedef HRESULT (*PFNPSTORECREATEINSTANCE)(IPStore**, PST_PROVIDERID*, VOID*, DWORD);
  14. // Globals
  15. #define SIZE_MAX_KEY_SIZE               2048    // For lookup key (In our case, URL w/user name & server, without password & path)
  16. #define SIZE_MAX_VALUE_SIZE             2048    // For stored value (In our case the password)
  17. // MPR.DLL exports used by top level API.
  18. typedef DWORD (APIENTRY *PFWNETGETCACHEDPASSWORD)    (LPCSTR, WORD, LPCSTR, LPWORD, BYTE);
  19. typedef DWORD (APIENTRY *PFWNETCACHEPASSWORD)        (LPCSTR, WORD, LPCSTR, WORD, BYTE, UINT);
  20. typedef DWORD (APIENTRY *PFWNETREMOVECACHEDPASSWORD) (LPCSTR, WORD, BYTE);
  21. // PWL related variables.
  22. static HMODULE MhmodWNET                                        = NULL;
  23. static PFWNETGETCACHEDPASSWORD g_pfWNetGetCachedPassword        = NULL;
  24. static PFWNETCACHEPASSWORD g_pfWNetCachePassword                = NULL;
  25. static PFWNETREMOVECACHEDPASSWORD g_pfWNetRemoveCachedPassword  = NULL;
  26. // Pstore related variables.
  27. static PFNPSTORECREATEINSTANCE s_pPStoreCreateInstance = NULL;
  28. #define STR_FTP_CACHE_CREDENTIALS                   L"MS IE FTP Passwords";
  29. #define PSTORE_MODULE                               TEXT("pstorec.dll")
  30. #define WNETDLL_MODULE                              TEXT("mpr.dll")
  31. #define WNETGETCACHEDPASS                           "WNetGetCachedPassword"
  32. #define WNETCACHEPASS                               "WNetCachePassword"
  33. #define WNETREMOVECACHEDPASS                        "WNetRemoveCachedPassword"
  34. #define DISABLE_PASSWORD_CACHE        1
  35. // PWL related defines.
  36. // Password-cache-entry, this should be in PCACHE.
  37. #define PCE_WWW_BASIC 0x13  
  38. // TODO/BUGBUG: We should call FreeLibrary(PSTORE_MODULE) before our DLL unloads.
  39. // Wininet uses this GUID for pstore:
  40. // {5E7E8100-9138-11d1-945A-00C04FC308FF}
  41. static const GUID GUID_PStoreType = 
  42. { 0x5e7e8100, 0x9138, 0x11d1, { 0x94, 0x5a, 0x0, 0xc0, 0x4f, 0xc3, 0x8, 0xff } };
  43. // Private function prototypes.
  44. // PWL private function prototypes.
  45. DWORD PWLSetCachedCredentials(LPCSTR pszKey, DWORD cbKey, LPCSTR pszCred, DWORD cbCred);
  46. DWORD PWLGetCachedCredentials(LPCSTR pszKey, DWORD cbKey, LPSTR cbCred, LPDWORD pcbCred);
  47. DWORD PWLRemoveCachedCredentials(LPCSTR pszKey, DWORD cbKey);
  48. BOOL LoadWNet(VOID);
  49. // PStore private function prototypes.
  50. DWORD PStoreSetCachedCredentials(LPCWSTR pszKey, LPCWSTR pszCred, DWORD cbCred, BOOL fRemove=FALSE);
  51. DWORD PStoreGetCachedCredentials(LPCWSTR pszKey, LPWSTR pszCred, LPDWORD pcbCred);
  52. DWORD PStoreRemoveCachedCredentials(LPCWSTR pszKey);
  53. HRESULT CreatePStore(IPStore **ppIPStore);
  54. STDAPI ReleasePStore(IPStore *pIPStore);
  55. // *--------------------------- Top Level APIs ---------------------------------*
  56. /****************************************************
  57.     FUNCTION: InitCredentialPersist
  58.     DESCRIPTION:
  59.         Try to init the cache.   
  60.     PARAMETERS:
  61.     Return Value:
  62.         S_OK if it will work correctly.
  63.         S_FASE if turned off by admin.
  64.         HRESULT_FROM_WIN32(ERROR_PRODUCT_UNINSTALLED) if the password caching APIs aren't installed on NT.
  65. ****************************************************/
  66. HRESULT InitCredentialPersist(void)
  67. {
  68.     HRESULT hr = S_OK;
  69.     DWORD dwDisable;
  70.     DWORD cbSize = sizeof(dwDisable);
  71.     // First check to see if persistence is disabled via registry.
  72.     if ((ERROR_SUCCESS == SHGetValue(HKEY_CURRENT_USER, SZ_REGKEY_INTERNET_SETTINGS, SZ_REGVALUE_DISABLE_PASSWORD_CACHE, NULL, (void *)&dwDisable, &cbSize))
  73.         && (dwDisable == DISABLE_PASSWORD_CACHE))
  74.     {
  75.         // Persistence disabled via registry.
  76.         hr = S_FALSE;
  77.     }
  78.     if (S_OK == hr)
  79.     {
  80.         // We use PWL for Win95; this should be available.
  81.         if (!IsOS(OS_NT))
  82.         {
  83.             // hr already equals S_OK and no more work is needed.
  84.         }
  85.         else
  86.         {
  87.             HINSTANCE hInstPStoreC = 0;
  88.             // If is WinNT, check if PStore is installed. 
  89.             hInstPStoreC = LoadLibrary(PSTORE_MODULE);
  90.             if (!hInstPStoreC)
  91.                 hr = HRESULT_FROM_WIN32(ERROR_PRODUCT_UNINSTALLED);
  92.             else
  93.             {
  94.                 // Get CreatePStoreInstance function pointer.
  95.                 s_pPStoreCreateInstance = (PFNPSTORECREATEINSTANCE) GetProcAddress(hInstPStoreC, "PStoreCreateInstance");
  96.                 if (!s_pPStoreCreateInstance)
  97.                     hr = HRESULT_FROM_WIN32(ERROR_PRODUCT_UNINSTALLED);
  98.                 else
  99.                 {
  100.                     IPStore * pIPStore = NULL;
  101.                     // Create an IPStore.
  102.                     hr = CreatePStore(&pIPStore);
  103.         
  104.                     // We just did this to see if it worked, so
  105.                     // the hr was set correctly.
  106.                     if (pIPStore)
  107.                         ReleasePStore(pIPStore);
  108.                 }
  109.             }
  110.         }
  111.     }
  112.     return hr;
  113. }
  114. /****************************************************
  115.     FUNCTION: SetCachedCredentials
  116.     DESCRIPTION:
  117.     PARAMETERS:
  118. ****************************************************/
  119. HRESULT SetCachedCredentials(LPCWSTR pwzKey, LPCWSTR pwzValue)
  120. {
  121.     // Check if credential persistence is available.
  122.     HRESULT hr = InitCredentialPersist();
  123.     if (S_OK == hr)
  124.     {
  125.         // Store credentials.
  126.         if (!IsOS(OS_NT))
  127.         {
  128.             CHAR szKey[SIZE_MAX_KEY_SIZE];
  129.             CHAR szValue[SIZE_MAX_VALUE_SIZE];
  130.             ASSERT(lstrlenW(pwzKey) < ARRAYSIZE(szKey));
  131.             ASSERT(lstrlenW(pwzValue) < ARRAYSIZE(szValue));
  132.             SHUnicodeToAnsi(pwzKey, szKey, ARRAYSIZE(szKey));
  133.             SHUnicodeToAnsi(pwzValue, szValue, ARRAYSIZE(szValue));
  134.             DWORD cbKey = ((lstrlenA(szKey) + 1) * sizeof(szKey[0]));
  135.             DWORD cbCred = ((lstrlenA(szValue) + 1) * sizeof(szValue[0]));
  136.             // Store credentials using PWL.
  137.             DWORD dwError = PWLSetCachedCredentials(szKey, cbKey, szValue, cbCred);
  138.             hr = HRESULT_FROM_WIN32(dwError);
  139.         }
  140.         else
  141.         {
  142.             DWORD cbCred = ((lstrlenW(pwzValue) + 1) * sizeof(pwzValue[0]));
  143.             // Store credentials using PStore.
  144.             DWORD dwError = PStoreSetCachedCredentials(pwzKey, pwzValue, cbCred);
  145.             hr = HRESULT_FROM_WIN32(dwError);
  146.         }
  147.     }
  148.     return hr;
  149. }
  150. /****************************************************
  151.     FUNCTION: GetCachedCredentials
  152.     DESCRIPTION:
  153.     PARAMETERS:
  154. ****************************************************/
  155. HRESULT GetCachedCredentials(LPCWSTR pwzKey, LPWSTR pwzValue, DWORD cchSize)
  156. {
  157.     // Check if credential persistence is available.
  158.     HRESULT hr = InitCredentialPersist();
  159.     if (S_OK == hr)
  160.     {
  161.         // Store credentials.
  162.         if (!IsOS(OS_NT))
  163.         {
  164.             CHAR szKey[SIZE_MAX_KEY_SIZE];
  165.             CHAR szValue[SIZE_MAX_VALUE_SIZE];
  166.             DWORD cchTempSize = ARRAYSIZE(szValue);
  167.             ASSERT(lstrlenW(pwzKey) < ARRAYSIZE(szKey));
  168.             ASSERT(cchSize < ARRAYSIZE(szValue));
  169.             SHUnicodeToAnsi(pwzKey, szKey, ARRAYSIZE(szKey));
  170.             DWORD cbKey = ((lstrlenA(szKey) + 1) * sizeof(szKey[0]));
  171.             szValue[0];
  172.             // Store credentials using PWL.
  173.             DWORD dwError = PWLGetCachedCredentials(szKey, cbKey, szValue, &cchTempSize);
  174.             hr = HRESULT_FROM_WIN32(dwError);
  175.             SHAnsiToUnicode(szValue, pwzValue, cchSize);
  176.         }
  177.         else
  178.         {
  179.             cchSize++;  // Include terminator.
  180.             cchSize *= sizeof(pwzValue[0]);
  181.             pwzValue[0] = 0;
  182.             // Store credentials using PStore.
  183.             DWORD dwError = PStoreGetCachedCredentials(pwzKey, pwzValue, &cchSize);
  184.             hr = HRESULT_FROM_WIN32(dwError);
  185.         }
  186.     }
  187.     return hr;
  188. }
  189. /****************************************************
  190.     FUNCTION: RemoveCachedCredentials
  191.     DESCRIPTION:
  192.     PARAMETERS:
  193. ****************************************************/
  194. HRESULT RemoveCachedCredentials(LPCWSTR pwzKey)
  195. {
  196.     // Check if credential persistence is available.
  197.     HRESULT hr = InitCredentialPersist();
  198.     if (S_OK == hr)
  199.     {
  200.         // Store credentials.
  201.         if (!IsOS(OS_NT))
  202.         {
  203.             CHAR szKey[SIZE_MAX_KEY_SIZE];
  204.             ASSERT(lstrlenW(pwzKey) < ARRAYSIZE(szKey));
  205.             SHUnicodeToAnsi(pwzKey, szKey, ARRAYSIZE(szKey));
  206.             DWORD cbKey = (lstrlenA(szKey) * sizeof(szKey[0]));
  207.             // Remove credentials from PWL.
  208.             DWORD dwError = PWLRemoveCachedCredentials(szKey, cbKey);
  209.             hr = HRESULT_FROM_WIN32(dwError);
  210.         }
  211.         else
  212.         {
  213.             // Remove credentials from PStore.
  214.             DWORD dwError = PStoreRemoveCachedCredentials(pwzKey);
  215.             hr = HRESULT_FROM_WIN32(dwError);
  216.         }
  217.     }
  218.     return hr;
  219. }
  220. /*--------------------------- PWL Functions ---------------------------------*/
  221. /*-----------------------------------------------------------------------------
  222.   PWLSetCachedCredentials
  223.   ---------------------------------------------------------------------------*/
  224. DWORD PWLSetCachedCredentials(LPCSTR pszKey, DWORD cbKey, 
  225.                               LPCSTR pszCred, DWORD cbCred)
  226. {
  227.     DWORD dwError;
  228.     // Load WNet.
  229.     if (!LoadWNet())
  230.         return ERROR_INTERNET_INTERNAL_ERROR;
  231.     
  232.     // Store credentials.  
  233.     dwError =  (*g_pfWNetCachePassword) (pszKey, (WORD) cbKey, pszCred, (WORD) cbCred, PCE_WWW_BASIC, 0); 
  234.     return dwError;
  235. }
  236. /*-----------------------------------------------------------------------------
  237.   PWLGetCachedCredentials
  238.   ---------------------------------------------------------------------------*/
  239. DWORD PWLGetCachedCredentials  (LPCSTR pszKey, DWORD cbKey, 
  240.                                 LPSTR pszCred, LPDWORD pcbCred)
  241. {    
  242.     DWORD dwError;
  243.     // Load WNet.
  244.     if (!LoadWNet())
  245.         return ERROR_INTERNET_INTERNAL_ERROR;
  246.     // Retrieve credentials.
  247.     dwError = (*g_pfWNetGetCachedPassword) (pszKey, (WORD) cbKey, pszCred, 
  248.                                           (LPWORD) pcbCred, PCE_WWW_BASIC);
  249.     
  250.     return dwError;
  251. }
  252. /*-----------------------------------------------------------------------------
  253.   PWLRemoveCachedCredentials
  254.   ---------------------------------------------------------------------------*/
  255. DWORD PWLRemoveCachedCredentials  (LPCSTR pszKey, DWORD cbKey)
  256. {
  257.     DWORD dwError;
  258.     // Load WNet.
  259.     if (!LoadWNet())
  260.         return ERROR_INTERNET_INTERNAL_ERROR;
  261.     dwError = (*g_pfWNetRemoveCachedPassword) (pszKey, (WORD) cbKey, PCE_WWW_BASIC);
  262.     return dwError;
  263. }
  264. // PWL utility functions.
  265. /*-----------------------------------------------------------------------------
  266.   LoadWNet
  267.   ---------------------------------------------------------------------------*/
  268. BOOL LoadWNet(VOID)
  269. {
  270.     BOOL fReturn;
  271.     
  272.     // MPR.DLL already loaded.
  273.     if (MhmodWNET) 
  274.     {
  275.         fReturn = TRUE;
  276.         goto quit;
  277.     }
  278.     // Load MPR.DLL
  279.     MhmodWNET = LoadLibrary(WNETDLL_MODULE);
  280.     
  281.     // Fail if not loaded.
  282.     if (MhmodWNET) 
  283.     {
  284.         fReturn = TRUE;
  285.     }
  286.     else
  287.     {
  288.         fReturn = FALSE;
  289.         goto quit;
  290.     }
  291.     g_pfWNetGetCachedPassword    = (PFWNETGETCACHEDPASSWORD)    GetProcAddress(MhmodWNET, WNETGETCACHEDPASS);
  292.     g_pfWNetCachePassword        = (PFWNETCACHEPASSWORD)        GetProcAddress(MhmodWNET, WNETCACHEPASS);
  293.     g_pfWNetRemoveCachedPassword = (PFWNETREMOVECACHEDPASSWORD) GetProcAddress(MhmodWNET, WNETREMOVECACHEDPASS);
  294.     // Ensure we have all function pointers.
  295.     if (!(g_pfWNetGetCachedPassword 
  296.           && g_pfWNetCachePassword
  297.           && g_pfWNetRemoveCachedPassword))
  298.     {
  299.         fReturn = FALSE;
  300.     }
  301. quit:
  302.     
  303.     return fReturn;
  304. }
  305. /*------------------------- PStore Functions -------------------------------*/
  306. /*-----------------------------------------------------------------------------
  307.   PStoreSetCachedCredentials
  308.   ---------------------------------------------------------------------------*/
  309. DWORD PStoreSetCachedCredentials(LPCWSTR pszKey, LPCWSTR pszCred, DWORD cbCred, BOOL fRemove)
  310. {
  311.     ASSERT(s_pPStoreCreateInstance);
  312.     HRESULT         hr;
  313.     DWORD           dwError;
  314.     
  315.     PST_TYPEINFO    typeInfo;
  316.     PST_PROMPTINFO  promptInfo = {0};
  317.     GUID itemType    = GUID_PStoreType;
  318.     GUID itemSubtype = GUID_NULL;
  319.     IPStore *       pStore = NULL;
  320.     
  321.     // PST_TYPEINFO data.
  322.     typeInfo.cbSize = sizeof(typeInfo);
  323.     typeInfo.szDisplayName = STR_FTP_CACHE_CREDENTIALS;
  324.     // PST_PROMPTINFO data (no prompting desired).
  325.     promptInfo.cbSize        = sizeof(promptInfo);
  326.     promptInfo.dwPromptFlags = 0;
  327.     promptInfo.hwndApp       = NULL;
  328.     promptInfo.szPrompt      = NULL;
  329.     // Create a PStore interface.
  330.     hr = CreatePStore(&pStore);
  331.     if (!SUCCEEDED(hr))
  332.         goto quit;
  333.     ASSERT(pStore != NULL);
  334.                
  335.     // Create a type in HKCU.
  336.     hr = pStore->CreateType(PST_KEY_CURRENT_USER, &itemType, &typeInfo, 0);
  337.     if (!((SUCCEEDED(hr)) || (hr == PST_E_TYPE_EXISTS)))
  338.         goto quit;
  339.     // Create subtype.
  340.     hr = pStore->CreateSubtype(PST_KEY_CURRENT_USER, &itemType, 
  341.                                &itemSubtype, &typeInfo, NULL, 0);
  342.     if (!((SUCCEEDED(hr)) || (hr == PST_E_TYPE_EXISTS)))
  343.         goto quit;
  344.             
  345.     // Valid credentials are written; No credentials imples
  346.     // that the key and credentials are to be deleted.
  347.     if (pszCred && cbCred && !fRemove)
  348.     {
  349.         // Write key and credentials to PStore.
  350.         hr = pStore->WriteItem(PST_KEY_CURRENT_USER,
  351.                                &itemType,
  352.                                &itemSubtype,
  353.                                pszKey,
  354.                                cbCred,
  355.                                (LPBYTE) pszCred,
  356.                                &promptInfo,
  357.                                PST_CF_NONE,
  358.                                0);
  359.     }
  360.     else
  361.     {
  362.         // Delete key and credentials from PStore.
  363.         hr = pStore->DeleteItem(PST_KEY_CURRENT_USER,
  364.                                 &itemType,
  365.                                 &itemSubtype,
  366.                                 pszKey,
  367.                                 &promptInfo,
  368.                                 0);
  369.     }
  370. quit:
  371.     // Release the interface, convert error and return.
  372.     ReleasePStore(pStore);
  373.     
  374.     if (SUCCEEDED(hr))
  375.         dwError = ERROR_SUCCESS;
  376.     else
  377.         dwError = ERROR_INTERNET_INTERNAL_ERROR;
  378.     return dwError;
  379. }                                                                       
  380. /*-----------------------------------------------------------------------------
  381.   PStoreGetCachedCredentials
  382.   ---------------------------------------------------------------------------*/
  383. DWORD PStoreGetCachedCredentials(LPCWSTR pszKey, LPWSTR pszCred, LPDWORD pcbCred)
  384. {
  385.     ASSERT(s_pPStoreCreateInstance);
  386.     HRESULT          hr ;
  387.     DWORD            dwError;
  388.     LPBYTE           pbData;
  389.     PST_PROMPTINFO   promptInfo  = {0};
  390.     GUID             itemType    = GUID_PStoreType;
  391.     GUID             itemSubtype = GUID_NULL;
  392.     IPStore*         pStore      = NULL;
  393.     
  394.     // PST_PROMPTINFO data (no prompting desired).
  395.     promptInfo.cbSize        = sizeof(promptInfo);
  396.     promptInfo.dwPromptFlags = 0;
  397.     promptInfo.hwndApp       = NULL;
  398.     promptInfo.szPrompt      = NULL;
  399.     // Create a PStore interface.
  400.     hr = CreatePStore(&pStore);
  401.     if (!SUCCEEDED(hr))
  402.         goto quit;
  403.     ASSERT(pStore != NULL);
  404.     // Read the credentials from PStore.
  405.     hr = pStore->ReadItem(PST_KEY_CURRENT_USER,
  406.                           &itemType,
  407.                           &itemSubtype,
  408.                           pszKey,
  409.                           pcbCred,
  410.                           (LPBYTE*) &pbData,
  411.                           &promptInfo,
  412.                           0);
  413.     // Copy credentials and free buffer allocated by ReadItem.
  414.     if (SUCCEEDED(hr))
  415.     {
  416.         memcpy(pszCred, pbData, *pcbCred);
  417.         CoTaskMemFree(pbData);
  418.         //hr = S_OK;
  419.     }
  420. quit:
  421.     // Release the interface, convert error and return.
  422.     ReleasePStore(pStore);
  423.     if (SUCCEEDED(hr))
  424.         dwError = ERROR_SUCCESS;
  425.     else
  426.         dwError = ERROR_INTERNET_INTERNAL_ERROR;
  427.     
  428.     return dwError;
  429. }
  430. /*-----------------------------------------------------------------------------
  431.   PStoreRemoveCachedCredentials
  432.   ---------------------------------------------------------------------------*/
  433. DWORD PStoreRemoveCachedCredentials(LPCWSTR pszKey)
  434. {
  435.     // Pass in TRUE to remove credentials.
  436.     return PStoreSetCachedCredentials(pszKey, NULL, 0, TRUE);
  437. }
  438. // PStore utility functions
  439. /*-----------------------------------------------------------------------------
  440.   CreatePStore
  441.   ---------------------------------------------------------------------------*/
  442. HRESULT CreatePStore(IPStore **ppIPStore)
  443. {
  444.     return s_pPStoreCreateInstance (ppIPStore, NULL, NULL, 0);
  445. }
  446. /*-----------------------------------------------------------------------------
  447.   ReleasePStore
  448.   ---------------------------------------------------------------------------*/
  449. STDAPI ReleasePStore(IPStore *pIPStore)
  450. {
  451.     HRESULT hr;
  452.     if (pIPStore)
  453.     {
  454.         pIPStore->Release();
  455.         hr = S_OK;
  456.     }
  457.     else
  458.     {
  459.         hr = E_POINTER;
  460.     }
  461.     return hr;
  462. }