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.
1949 lines
45 KiB
1949 lines
45 KiB
/*
|
|
File: Prov.cpp
|
|
|
|
Title: Protected Storage Base Provider
|
|
Author: Matt Thomlinson
|
|
Date: 10/22/96
|
|
|
|
Protected storage is an area to safely store user belongings.
|
|
This storage is available on both NT and Win95, and offers finer
|
|
granularity over access than do NT ACLs.
|
|
|
|
The PStore architecture resembles the CryptoAPI provider architecture.
|
|
The PStore server, PStoreS, takes requests and forwards them to any one
|
|
of a number of providers, of which PSBase is a single instance. (The
|
|
server exports some basic functionality to ease the pain of provider
|
|
writers, like impersonating the caller and checking access rules.) The
|
|
server gets requests through LPC from a client (PStoreC.dll),
|
|
which wraps a number of operations into a COM object.
|
|
|
|
The base provider supports user storage, where items are stored under
|
|
the namespace of which user called protected storage, and local machine
|
|
storage, a global area that can be accessed by everyone.
|
|
|
|
Rules can be set on subtypes describing under what conditions accesses
|
|
are allowed. Rules can specify callers be Authenticode signed, callers
|
|
simply be unmodified from access to access, and normal (arbitrary) NT Acls
|
|
be satisfied.
|
|
|
|
In addition, items stored in the user namespace have user authentication
|
|
by default, where the user gets to specify what type of user
|
|
confirmation they want to see appear. This confirmation could be
|
|
no confirmation, an ok/cancel dialog, a password, a retinal scan, a
|
|
fingerprint, etc.
|
|
|
|
The base provider stores items in the registry, DES-encrypted with a
|
|
key derived from the user password. Items are also integrity-protected
|
|
by a keyed MAC.
|
|
|
|
Interoperability and transport issues are solved by adding a provider
|
|
supporting the PFX interchange format.
|
|
|
|
The base provider is slightly more special than all other providers, since
|
|
the server stores bootstrap configuration data here. (The base provider
|
|
is guaranteed to always be present). The configuration data includes
|
|
what other providers are ok to be loaded.
|
|
|
|
*/
|
|
|
|
#include <pch.cpp>
|
|
#pragma hdrstop
|
|
|
|
|
|
#include "provif.h"
|
|
#include "provui.h"
|
|
#include "storage.h"
|
|
|
|
#include "passwd.h"
|
|
|
|
|
|
// sfield: legacy migration hack
|
|
#include "migrate.h"
|
|
|
|
|
|
BOOL g_fAllowCachePW = TRUE;
|
|
|
|
// fwd (secure.cpp)
|
|
BOOL FIsEncryptionPermitted();
|
|
|
|
|
|
HINSTANCE g_hInst = NULL;
|
|
BOOL g_fImagesIntegrid = FALSE;
|
|
|
|
DISPIF_CALLBACKS g_sCallbacks;
|
|
BOOL g_fCallbacksInitialized = FALSE;
|
|
|
|
PRIVATE_CALLBACKS g_sPrivateCallbacks;
|
|
|
|
CUAList* g_pCUAList = NULL;
|
|
COpenItemList* g_pCOpenItemList = NULL;
|
|
CCryptProvList* g_pCProvList = NULL;
|
|
|
|
extern CRITICAL_SECTION g_csUIInitialized;
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
// Very important to hook DllMain, do caller authentication
|
|
|
|
|
|
|
|
BOOL WINAPI DllMain (HMODULE hInst,
|
|
ULONG ul_reason_for_call,
|
|
LPVOID lpReserved)
|
|
{
|
|
switch( ul_reason_for_call )
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
{
|
|
|
|
g_hInst = hInst;
|
|
InitializeCriticalSection( &g_csUIInitialized );
|
|
|
|
//
|
|
// just hard-code image verification succeeded.
|
|
//
|
|
|
|
g_fImagesIntegrid = TRUE;
|
|
|
|
|
|
// set up global lists
|
|
g_pCUAList = new CUAList;
|
|
if(g_pCUAList)
|
|
{
|
|
if(!g_pCUAList->Initialize())
|
|
{
|
|
delete g_pCUAList;
|
|
g_pCUAList = NULL;
|
|
}
|
|
}
|
|
|
|
g_pCOpenItemList = new COpenItemList;
|
|
if(g_pCOpenItemList)
|
|
{
|
|
if(!g_pCOpenItemList->Initialize())
|
|
{
|
|
delete g_pCOpenItemList;
|
|
g_pCOpenItemList = NULL;
|
|
}
|
|
}
|
|
|
|
g_pCProvList = new CCryptProvList;
|
|
if(g_pCProvList)
|
|
{
|
|
if(!g_pCProvList->Initialize())
|
|
{
|
|
delete g_pCProvList;
|
|
g_pCProvList = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
DisableThreadLibraryCalls(hInst);
|
|
|
|
// call EncryptionPermitted routine once to initialize globals
|
|
FIsEncryptionPermitted();
|
|
FInitProtectAPIGlobals();
|
|
|
|
|
|
break;
|
|
}
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
|
|
// tear down global lists
|
|
if(g_pCUAList)
|
|
{
|
|
delete g_pCUAList;
|
|
g_pCUAList = NULL;
|
|
}
|
|
|
|
if(g_pCOpenItemList)
|
|
{
|
|
delete g_pCOpenItemList;
|
|
g_pCOpenItemList = NULL;
|
|
}
|
|
|
|
if(g_pCProvList)
|
|
{
|
|
delete g_pCProvList;
|
|
g_pCProvList = NULL;
|
|
}
|
|
|
|
ReleaseUI();
|
|
|
|
|
|
|
|
DeleteCriticalSection( &g_csUIInitialized );
|
|
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
HRESULT SPProviderInitialize(
|
|
DISPIF_CALLBACKS *psCallbacks)
|
|
{
|
|
// only allow one initialization (security check)
|
|
if (g_fCallbacksInitialized)
|
|
return PST_E_FAIL;
|
|
|
|
if( psCallbacks->cbSize < sizeof(DISPIF_CALLBACKS) )
|
|
return PST_E_FAIL;
|
|
|
|
// tuck these callback fxns for later use
|
|
CopyMemory(&g_sCallbacks, psCallbacks, sizeof(DISPIF_CALLBACKS));
|
|
|
|
// now, get the private callbacks from the server
|
|
DWORD cbPrivateCallbacks = sizeof(g_sPrivateCallbacks);
|
|
|
|
if(!g_sCallbacks.pfnFGetServerParam(
|
|
NULL,
|
|
SS_SERVERPARAM_CALLBACKS,
|
|
&g_sPrivateCallbacks,
|
|
&cbPrivateCallbacks
|
|
))
|
|
return PST_E_FAIL;
|
|
|
|
if(g_sPrivateCallbacks.cbSize != sizeof(g_sPrivateCallbacks))
|
|
return PST_E_FAIL;
|
|
|
|
g_fCallbacksInitialized = TRUE;
|
|
|
|
return PST_E_OK;
|
|
}
|
|
|
|
|
|
HRESULT SPAcquireContext(
|
|
/* [in] */ PST_PROVIDER_HANDLE* phPSTProv,
|
|
/* [in] */ DWORD dwFlags)
|
|
{
|
|
HRESULT dwRet = PST_E_FAIL;
|
|
BOOL fExisted = FALSE;
|
|
LPWSTR szUser = NULL;
|
|
|
|
HKEY hUserKey = NULL;
|
|
BOOL fUserExisted;
|
|
|
|
if(!InitUI())
|
|
return FALSE;
|
|
|
|
|
|
if (0 != dwFlags)
|
|
{
|
|
dwRet = PST_E_BAD_FLAGS;
|
|
goto Ret;
|
|
}
|
|
|
|
// get current user
|
|
if (!g_sCallbacks.pfnFGetUser(
|
|
phPSTProv,
|
|
&szUser))
|
|
goto Ret;
|
|
|
|
//
|
|
// migrate password data. This doesn't do anything internally if migration
|
|
// already took place.
|
|
//
|
|
|
|
MigrateData(phPSTProv, TRUE);
|
|
|
|
// One-Time WinPW Init Code
|
|
if (!BPMasterKeyExists(
|
|
szUser,
|
|
WSZ_PASSWORD_WINDOWS))
|
|
{
|
|
BYTE rgbPwd[A_SHA_DIGEST_LEN];
|
|
|
|
// Init the Users' Windows password entry
|
|
if (!FMyGetWinPassword(
|
|
phPSTProv,
|
|
szUser,
|
|
rgbPwd
|
|
))
|
|
goto Ret;
|
|
|
|
if (!FCheckPWConfirm(
|
|
szUser,
|
|
WSZ_PASSWORD_WINDOWS,
|
|
rgbPwd))
|
|
goto Ret;
|
|
|
|
//
|
|
// newly created key: data migration is not necessary.
|
|
// specify that only the migration flag need be updated
|
|
//
|
|
|
|
MigrateData(phPSTProv, FALSE);
|
|
}
|
|
|
|
|
|
dwRet = PST_E_OK;
|
|
Ret:
|
|
if (hUserKey)
|
|
RegCloseKey(hUserKey);
|
|
|
|
if (szUser)
|
|
SSFree(szUser);
|
|
|
|
return dwRet;
|
|
|
|
}
|
|
|
|
HRESULT SPReleaseContext(
|
|
/* [in] */ PST_PROVIDER_HANDLE* phPSTProv,
|
|
/* [in] */ DWORD dwFlags)
|
|
{
|
|
return PST_E_OK;
|
|
}
|
|
|
|
HRESULT SPGetProvInfo(
|
|
PPST_PROVIDERINFO* ppPSTInfo,
|
|
DWORD dwFlags)
|
|
{
|
|
HRESULT hr = PST_E_FAIL;
|
|
|
|
if (0 != dwFlags)
|
|
return PST_E_BAD_FLAGS;
|
|
|
|
// Note: not linked to a specific context (hPSTProv)
|
|
// Note: caller not verified -- give this info to anyone
|
|
|
|
PPST_PROVIDERINFO pPSTInfo;
|
|
if (NULL == (pPSTInfo = (PST_PROVIDERINFO*)SSAlloc(sizeof(PST_PROVIDERINFO))) )
|
|
return PST_E_FAIL;
|
|
ZeroMemory(pPSTInfo, sizeof(PST_PROVIDERINFO));
|
|
|
|
|
|
pPSTInfo->cbSize = sizeof(PST_PROVIDERINFO);
|
|
GUID guidBaseProvider = MS_BASE_PSTPROVIDER_ID;
|
|
CopyMemory(&pPSTInfo->ID, &guidBaseProvider, sizeof(pPSTInfo->ID));
|
|
|
|
pPSTInfo->Capabilities = PST_PC_ROAMABLE;
|
|
|
|
if (NULL == (pPSTInfo->szProviderName = (LPWSTR)SSAlloc(sizeof(MS_BASE_PSTPROVIDER_NAME))) )
|
|
goto Ret;
|
|
wcscpy(pPSTInfo->szProviderName, MS_BASE_PSTPROVIDER_NAME);
|
|
|
|
hr = PST_E_OK;
|
|
Ret:
|
|
if (hr != PST_E_OK)
|
|
{
|
|
if (pPSTInfo->szProviderName)
|
|
SSFree(pPSTInfo->szProviderName);
|
|
|
|
SSFree(pPSTInfo);
|
|
pPSTInfo = NULL;
|
|
}
|
|
|
|
// in either case, return pPSTInfo
|
|
*ppPSTInfo = pPSTInfo;
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT SPGetProvParam(
|
|
/* [in] */ PST_PROVIDER_HANDLE* phPSTProv,
|
|
/* [in] */ DWORD dwParam,
|
|
/* [out] */ DWORD __RPC_FAR *pcbData,
|
|
/* [size_is][size_is][out] */
|
|
BYTE __RPC_FAR *__RPC_FAR *ppbData,
|
|
/* [in] */ DWORD dwFlags)
|
|
{
|
|
|
|
if( pcbData )
|
|
*pcbData = 0;
|
|
|
|
switch(dwParam)
|
|
{
|
|
|
|
case PST_PP_FLUSH_PW_CACHE:
|
|
{
|
|
return PST_E_OK;
|
|
}
|
|
|
|
default:
|
|
{
|
|
return PST_E_NYI;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
HRESULT SPSetProvParam(
|
|
/* [in] */ PST_PROVIDER_HANDLE* phPSTProv,
|
|
/* [in] */ DWORD dwParam,
|
|
/* [in] */ DWORD cbData,
|
|
/* [in] */ BYTE* pbData,
|
|
/* [in] */ DWORD dwFlags)
|
|
{
|
|
HRESULT hr = PST_E_OK;
|
|
|
|
switch(dwParam)
|
|
{
|
|
case PST_PP_FLUSH_PW_CACHE:
|
|
{
|
|
if(g_pCUAList)
|
|
{
|
|
g_pCUAList->Reset();
|
|
hr = PST_E_OK;
|
|
}
|
|
else
|
|
hr = PST_E_FAIL;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
hr = PST_E_NYI;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
HRESULT SPEnumTypes(
|
|
/* [in] */ PST_PROVIDER_HANDLE *phPSTProv,
|
|
/* [in] */ PST_KEY Key,
|
|
/* [out] */ GUID *pguidType,
|
|
/* [in] */ DWORD dwIndex,
|
|
/* [in] */ DWORD dwFlags)
|
|
{
|
|
HRESULT dwRet = PST_E_FAIL;
|
|
LPWSTR szUser = NULL;
|
|
|
|
if (Key & ~(PST_KEY_CURRENT_USER | PST_KEY_LOCAL_MACHINE))
|
|
{
|
|
dwRet = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
if (dwFlags)
|
|
{
|
|
dwRet = PST_E_BAD_FLAGS;
|
|
goto Ret;
|
|
}
|
|
|
|
// get current user
|
|
if (!FGetCurrentUser(
|
|
phPSTProv,
|
|
&szUser,
|
|
Key))
|
|
{
|
|
dwRet = (DWORD)PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
BPEnumTypes(
|
|
szUser,
|
|
dwIndex,
|
|
pguidType)) )
|
|
goto Ret;
|
|
|
|
dwRet = PST_E_OK;
|
|
Ret:
|
|
if (szUser)
|
|
SSFree(szUser);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
HRESULT SPGetTypeInfo(
|
|
/* [in] */ PST_PROVIDER_HANDLE *phPSTProv,
|
|
/* [in] */ PST_KEY Key,
|
|
/* [in] */ const GUID *pguidType,
|
|
/* [in] */ PPST_TYPEINFO *ppinfoType,
|
|
/* [in] */ DWORD dwFlags)
|
|
{
|
|
PST_TYPEINFO infoType = {sizeof(PST_TYPEINFO)};
|
|
*ppinfoType = NULL;
|
|
|
|
LPWSTR szUser = NULL;
|
|
HRESULT dwRet = PST_E_FAIL;
|
|
|
|
if (Key & ~(PST_KEY_CURRENT_USER | PST_KEY_LOCAL_MACHINE))
|
|
{
|
|
dwRet = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
if (dwFlags)
|
|
{
|
|
dwRet = PST_E_BAD_FLAGS;
|
|
goto Ret;
|
|
}
|
|
|
|
// get current user
|
|
if (!FGetCurrentUser(
|
|
phPSTProv,
|
|
&szUser,
|
|
Key))
|
|
{
|
|
dwRet = (DWORD)PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
BPGetTypeName(
|
|
szUser,
|
|
pguidType,
|
|
&infoType.szDisplayName)) )
|
|
goto Ret;
|
|
|
|
dwRet = PST_E_OK;
|
|
Ret:
|
|
if (dwRet == PST_E_OK)
|
|
{
|
|
*ppinfoType = (PPST_TYPEINFO)SSAlloc(sizeof(PST_TYPEINFO));
|
|
if(NULL != *ppinfoType)
|
|
{
|
|
CopyMemory(*ppinfoType, &infoType, sizeof(PST_TYPEINFO));
|
|
}
|
|
}
|
|
|
|
if (szUser)
|
|
SSFree(szUser);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
HRESULT SPEnumSubtypes(
|
|
/* [in] */ PST_PROVIDER_HANDLE *phPSTProv,
|
|
/* [in] */ PST_KEY Key,
|
|
/* [in] */ const GUID *pguidType,
|
|
/* [out] */ GUID *pguidSubtype,
|
|
/* [in] */ DWORD dwIndex,
|
|
/* [in] */ DWORD dwFlags)
|
|
{
|
|
HRESULT dwRet = PST_E_FAIL;
|
|
LPWSTR szUser = NULL;
|
|
|
|
if (Key & ~(PST_KEY_CURRENT_USER | PST_KEY_LOCAL_MACHINE))
|
|
{
|
|
dwRet = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
if (dwFlags)
|
|
{
|
|
dwRet = PST_E_BAD_FLAGS;
|
|
goto Ret;
|
|
}
|
|
|
|
// get current user
|
|
if (!FGetCurrentUser(
|
|
phPSTProv,
|
|
&szUser,
|
|
Key))
|
|
{
|
|
dwRet = (DWORD)PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
BPEnumSubtypes(
|
|
szUser,
|
|
dwIndex,
|
|
pguidType,
|
|
pguidSubtype)) )
|
|
goto Ret;
|
|
|
|
dwRet = PST_E_OK;
|
|
Ret:
|
|
if (szUser)
|
|
SSFree(szUser);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
HRESULT SPGetSubtypeInfo(
|
|
/* [in] */ PST_PROVIDER_HANDLE *phPSTProv,
|
|
/* [in] */ PST_KEY Key,
|
|
/* [in] */ const GUID *pguidType,
|
|
/* [in] */ const GUID *pguidSubtype,
|
|
/* [in] */ PPST_TYPEINFO *ppinfoSubtype,
|
|
/* [in] */ DWORD dwFlags)
|
|
{
|
|
*ppinfoSubtype = NULL;
|
|
PST_TYPEINFO infoSubtype = {sizeof(PST_TYPEINFO)};
|
|
|
|
LPWSTR szUser = NULL;
|
|
HRESULT dwRet = PST_E_FAIL;
|
|
|
|
if (Key & ~(PST_KEY_CURRENT_USER | PST_KEY_LOCAL_MACHINE))
|
|
{
|
|
dwRet = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
if (dwFlags)
|
|
{
|
|
dwRet = PST_E_BAD_FLAGS;
|
|
goto Ret;
|
|
}
|
|
|
|
// get current user
|
|
if (!FGetCurrentUser(
|
|
phPSTProv,
|
|
&szUser,
|
|
Key))
|
|
{
|
|
dwRet = (DWORD)PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
BPGetSubtypeName(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
&infoSubtype.szDisplayName)) )
|
|
goto Ret;
|
|
|
|
dwRet = PST_E_OK;
|
|
Ret:
|
|
if (dwRet == PST_E_OK)
|
|
{
|
|
*ppinfoSubtype = (PPST_TYPEINFO)SSAlloc(sizeof(PST_TYPEINFO));
|
|
if(NULL != *ppinfoSubtype)
|
|
{
|
|
CopyMemory(*ppinfoSubtype, &infoSubtype, sizeof(PST_TYPEINFO));
|
|
}
|
|
}
|
|
|
|
if (szUser)
|
|
SSFree(szUser);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
HRESULT SPEnumItems(
|
|
/* [in] */ PST_PROVIDER_HANDLE *phPSTProv,
|
|
/* [in] */ PST_KEY Key,
|
|
/* [in] */ const GUID *pguidType,
|
|
/* [in] */ const GUID *pguidSubtype,
|
|
/* [out] */ LPWSTR *ppszItemName,
|
|
/* [in] */ DWORD dwIndex,
|
|
/* [in] */ DWORD dwFlags)
|
|
{
|
|
HRESULT dwRet = PST_E_FAIL;
|
|
LPWSTR szUser = NULL;
|
|
|
|
if (Key & ~(PST_KEY_CURRENT_USER | PST_KEY_LOCAL_MACHINE))
|
|
{
|
|
dwRet = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
if (dwFlags)
|
|
{
|
|
dwRet = PST_E_BAD_FLAGS;
|
|
goto Ret;
|
|
}
|
|
|
|
// get current user
|
|
if (!FGetCurrentUser(
|
|
phPSTProv,
|
|
&szUser,
|
|
Key))
|
|
{
|
|
dwRet = (DWORD)PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
BPEnumItems(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
dwIndex,
|
|
ppszItemName)) )
|
|
goto Ret;
|
|
|
|
dwRet = PST_E_OK;
|
|
Ret:
|
|
if (szUser)
|
|
SSFree(szUser);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
HRESULT SPCreateType(
|
|
/* [in] */ PST_PROVIDER_HANDLE *phPSTProv,
|
|
/* [in] */ PST_KEY Key,
|
|
/* [in] */ const GUID *pguidType,
|
|
/* [in] */ PPST_TYPEINFO pinfoType,
|
|
/* [in] */ DWORD dwFlags)
|
|
{
|
|
HRESULT dwRet = PST_E_FAIL;
|
|
LPWSTR szUser = NULL;
|
|
|
|
if (Key & ~(PST_KEY_CURRENT_USER | PST_KEY_LOCAL_MACHINE))
|
|
{
|
|
dwRet = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
if (dwFlags)
|
|
{
|
|
dwRet = PST_E_BAD_FLAGS;
|
|
goto Ret;
|
|
}
|
|
|
|
// Check for invalid "" input
|
|
if (pinfoType == NULL ||
|
|
pinfoType->szDisplayName == NULL ||
|
|
(wcslen(pinfoType->szDisplayName) == 0)
|
|
)
|
|
{
|
|
dwRet = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
if (!FGetCurrentUser(
|
|
phPSTProv,
|
|
&szUser,
|
|
Key))
|
|
{
|
|
dwRet = (DWORD)PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
|
|
// if fail or already exist, fail!
|
|
if (PST_E_OK != (dwRet =
|
|
BPCreateType(
|
|
szUser,
|
|
pguidType,
|
|
pinfoType)) )
|
|
goto Ret;
|
|
|
|
dwRet = PST_E_OK;
|
|
Ret:
|
|
|
|
// if creation didn't happen, item shouldn't exist
|
|
if ((dwRet != PST_E_OK) && (dwRet != PST_E_TYPE_EXISTS))
|
|
BPDeleteType(szUser, pguidType);
|
|
|
|
if (szUser)
|
|
SSFree(szUser);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
HRESULT SPDeleteType(
|
|
/* [in] */ PST_PROVIDER_HANDLE *phPSTProv,
|
|
/* [in] */ PST_KEY Key,
|
|
/* [in] */ const GUID __RPC_FAR *pguidType,
|
|
/* [in] */ DWORD dwFlags)
|
|
{
|
|
HRESULT dwRet = PST_E_FAIL;
|
|
LPWSTR szUser = NULL;
|
|
|
|
if (Key & ~(PST_KEY_CURRENT_USER | PST_KEY_LOCAL_MACHINE))
|
|
{
|
|
dwRet = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
if (dwFlags)
|
|
{
|
|
dwRet = PST_E_BAD_FLAGS;
|
|
goto Ret;
|
|
}
|
|
|
|
if (!FGetCurrentUser(
|
|
phPSTProv,
|
|
&szUser,
|
|
Key))
|
|
{
|
|
dwRet = (DWORD)PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
|
|
// if fail or not empty, fail!
|
|
if (PST_E_OK != (dwRet =
|
|
BPDeleteType(
|
|
szUser,
|
|
pguidType)) )
|
|
goto Ret;
|
|
|
|
dwRet = PST_E_OK;
|
|
Ret:
|
|
|
|
if (szUser)
|
|
SSFree(szUser);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
HRESULT SPCreateSubtype(
|
|
/* [in] */ PST_PROVIDER_HANDLE *phPSTProv,
|
|
/* [in] */ PST_KEY Key,
|
|
/* [in] */ const GUID *pguidType,
|
|
/* [in] */ const GUID *pguidSubtype,
|
|
/* [in] */ PPST_TYPEINFO pinfoSubtype,
|
|
/* [in] */ PPST_ACCESSRULESET psRules,
|
|
/* [in] */ DWORD dwFlags)
|
|
{
|
|
HRESULT dwRet = PST_E_FAIL;
|
|
LPWSTR szUser = NULL;
|
|
|
|
|
|
if (Key & ~(PST_KEY_CURRENT_USER | PST_KEY_LOCAL_MACHINE))
|
|
{
|
|
dwRet = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
if (dwFlags != 0)
|
|
{
|
|
dwRet = PST_E_BAD_FLAGS;
|
|
goto Ret;
|
|
}
|
|
|
|
// NULL Rules
|
|
if (psRules == NULL)
|
|
{
|
|
dwRet = PST_E_INVALID_RULESET;
|
|
goto Ret;
|
|
}
|
|
|
|
if (pinfoSubtype == NULL)
|
|
{
|
|
dwRet = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
// Check for invalid "" input
|
|
if (pinfoSubtype->szDisplayName == NULL || wcslen(pinfoSubtype->szDisplayName) == 0)
|
|
{
|
|
dwRet = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
if (!FGetCurrentUser(
|
|
phPSTProv,
|
|
&szUser,
|
|
Key))
|
|
{
|
|
dwRet = (DWORD)PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
|
|
// if fail or already exist, fail!
|
|
if (PST_E_OK != (dwRet =
|
|
BPCreateSubtype(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
pinfoSubtype)) )
|
|
goto Ret;
|
|
|
|
|
|
dwRet = PST_E_OK;
|
|
Ret:
|
|
// if creation didn't happen, item shouldn't exist
|
|
if ((dwRet != PST_E_OK) && (dwRet != PST_E_TYPE_EXISTS))
|
|
BPDeleteSubtype(szUser, pguidType, pguidSubtype);
|
|
|
|
if (szUser)
|
|
SSFree(szUser);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
HRESULT SPDeleteSubtype(
|
|
/* [in] */ PST_PROVIDER_HANDLE *phPSTProv,
|
|
/* [in] */ PST_KEY Key,
|
|
/* [in] */ const GUID __RPC_FAR *pguidType,
|
|
/* [in] */ const GUID __RPC_FAR *pguidSubtype,
|
|
/* [in] */ DWORD dwFlags)
|
|
{
|
|
HRESULT dwRet = PST_E_FAIL;
|
|
LPWSTR szUser = NULL;
|
|
|
|
PST_ACCESSRULESET sRules = {sizeof(sRules), 0, NULL};
|
|
|
|
if (Key & ~(PST_KEY_CURRENT_USER | PST_KEY_LOCAL_MACHINE))
|
|
{
|
|
dwRet = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
if (dwFlags)
|
|
{
|
|
dwRet = PST_E_BAD_FLAGS;
|
|
goto Ret;
|
|
}
|
|
|
|
// get current user
|
|
if (!FGetCurrentUser(
|
|
phPSTProv,
|
|
&szUser,
|
|
Key))
|
|
{
|
|
dwRet = (DWORD)PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
|
|
|
|
// if fail or not empty, fail!
|
|
if (PST_E_OK != (dwRet =
|
|
BPDeleteSubtype(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype)) )
|
|
goto Ret;
|
|
|
|
dwRet = PST_E_OK;
|
|
Ret:
|
|
|
|
if (szUser)
|
|
SSFree(szUser);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
HRESULT SPWriteItem(
|
|
/* [in] */ PST_PROVIDER_HANDLE *phPSTProv,
|
|
/* [in] */ PST_KEY Key,
|
|
/* [in] */ const GUID *pguidType,
|
|
/* [in] */ const GUID *pguidSubtype,
|
|
/* [in] */ LPCWSTR szItemName,
|
|
/* [in] */ DWORD cbData,
|
|
/* [size_is][in] */ BYTE *pbData,
|
|
/* [in] */ PPST_PROMPTINFO psPrompt,
|
|
/* [in] */ DWORD dwDefaultConfirmationStyle,
|
|
/* [in] */ DWORD dwFlags)
|
|
{
|
|
HRESULT dwRet = PST_E_FAIL;
|
|
|
|
// assume we've made no change
|
|
BOOL fExisted = TRUE;
|
|
LPWSTR szUser = NULL;
|
|
|
|
PST_ACCESSRULESET sRules = {sizeof(sRules), 0, NULL};
|
|
|
|
BYTE rgbPwd[A_SHA_DIGEST_LEN];
|
|
LPWSTR szMasterKey = NULL;
|
|
|
|
LPWSTR szType=NULL, szSubtype=NULL;
|
|
|
|
if (Key & ~(PST_KEY_CURRENT_USER | PST_KEY_LOCAL_MACHINE))
|
|
{
|
|
dwRet = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
if ((dwFlags & ~(PST_UNRESTRICTED_ITEMDATA | PST_NO_OVERWRITE
|
|
)) != 0)
|
|
{
|
|
dwRet = PST_E_BAD_FLAGS;
|
|
goto Ret;
|
|
}
|
|
|
|
if ((dwDefaultConfirmationStyle & ~( PST_CF_DEFAULT |
|
|
PST_CF_NONE
|
|
)) != 0)
|
|
{
|
|
dwRet = PST_E_BAD_FLAGS;
|
|
goto Ret;
|
|
}
|
|
|
|
if (psPrompt == NULL)
|
|
{
|
|
dwRet = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
// Disable UI on write item.
|
|
dwDefaultConfirmationStyle = PST_CF_NONE;
|
|
if(psPrompt != NULL)
|
|
{
|
|
psPrompt->dwPromptFlags = 0;
|
|
}
|
|
|
|
// Check for invalid "" input
|
|
if (wcslen(szItemName) == 0)
|
|
{
|
|
dwRet = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
// get current user
|
|
if (!FGetCurrentUser(
|
|
phPSTProv,
|
|
&szUser,
|
|
Key))
|
|
{
|
|
dwRet = (DWORD)PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
|
|
if (dwFlags & PST_UNRESTRICTED_ITEMDATA)
|
|
{
|
|
// store insecure data stream
|
|
if (PST_E_OK != (dwRet =
|
|
BPSetInsecureItemData(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
szItemName,
|
|
pbData,
|
|
cbData)) )
|
|
goto Ret;
|
|
|
|
dwRet = PST_E_OK;
|
|
goto Ret;
|
|
}
|
|
|
|
// ELSE: secure stream
|
|
|
|
{
|
|
POPENITEM_LIST_ITEM pli;
|
|
|
|
OPENITEM_LIST_ITEM li;
|
|
if(NULL == g_pCOpenItemList)
|
|
{
|
|
dwRet = PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
CreateOpenListItem(&li, phPSTProv, Key, pguidType, pguidSubtype, szItemName);
|
|
|
|
g_pCOpenItemList->LockList();
|
|
|
|
// get opened (cached) item
|
|
pli = g_pCOpenItemList->SearchList(&li);
|
|
|
|
if ((pli != NULL) && (pli->ModeFlags & PST_WRITE) )
|
|
{
|
|
// Error if cached (it must exist) and "No Overwrite" specified
|
|
if (dwFlags & PST_NO_OVERWRITE)
|
|
{
|
|
g_pCOpenItemList->UnlockList();
|
|
dwRet = PST_E_ITEM_EXISTS;
|
|
goto Ret;
|
|
}
|
|
|
|
// found cached item; pull real pwd
|
|
CopyMemory(rgbPwd, pli->rgbPwd, A_SHA_DIGEST_LEN);
|
|
szMasterKey = (LPWSTR) SSAlloc(WSZ_BYTECOUNT(pli->szMasterKey));
|
|
|
|
if( szMasterKey )
|
|
wcscpy(szMasterKey, pli->szMasterKey);
|
|
|
|
//
|
|
// unlock list.
|
|
//
|
|
|
|
g_pCOpenItemList->UnlockList();
|
|
|
|
if( szMasterKey == NULL ) {
|
|
dwRet = E_OUTOFMEMORY;
|
|
goto Ret;
|
|
}
|
|
|
|
// PST_PF_ALWAYS_SHOW always forces UI
|
|
if (PST_PF_ALWAYS_SHOW == psPrompt->dwPromptFlags)
|
|
{
|
|
// retrieve names of type, subtype
|
|
if (PST_E_OK != (dwRet =
|
|
BPGetTypeName(
|
|
szUser,
|
|
pguidType,
|
|
&szType)) )
|
|
goto Ret;
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
BPGetSubtypeName(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
&szSubtype)) )
|
|
goto Ret;
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
ShowOKCancelUI(
|
|
phPSTProv,
|
|
szUser,
|
|
Key,
|
|
szType,
|
|
szSubtype,
|
|
szItemName,
|
|
psPrompt,
|
|
g_PromptWriteItem)) )
|
|
goto Ret;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// unlock list.
|
|
//
|
|
|
|
g_pCOpenItemList->UnlockList();
|
|
|
|
// not cached; do actual work
|
|
|
|
// if fail or already exist
|
|
if (PST_E_OK != (dwRet =
|
|
BPCreateItem(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
szItemName)) )
|
|
{
|
|
|
|
// on "No Overwrite", hr has right error code
|
|
if (dwFlags & PST_NO_OVERWRITE)
|
|
goto Ret;
|
|
|
|
// else swallow overwrite error
|
|
if (dwRet != PST_E_ITEM_EXISTS)
|
|
goto Ret;
|
|
}
|
|
|
|
fExisted = (dwRet == PST_E_ITEM_EXISTS);
|
|
|
|
// retrieve names of type, subtype
|
|
if (PST_E_OK != (dwRet =
|
|
BPGetTypeName(
|
|
szUser,
|
|
pguidType,
|
|
&szType)) )
|
|
goto Ret;
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
BPGetSubtypeName(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
&szSubtype)) )
|
|
goto Ret;
|
|
|
|
// does ALL user confirm work
|
|
if (PST_E_OK != (dwRet =
|
|
GetUserConfirmBuf(
|
|
phPSTProv,
|
|
szUser,
|
|
Key,
|
|
szType,
|
|
pguidType,
|
|
szSubtype,
|
|
pguidSubtype,
|
|
szItemName,
|
|
psPrompt,
|
|
g_PromptWriteItem,
|
|
dwDefaultConfirmationStyle,
|
|
&szMasterKey,
|
|
rgbPwd,
|
|
0)) )
|
|
goto Ret;
|
|
}
|
|
}
|
|
|
|
// store the data itself
|
|
if (!FBPSetSecuredItemData(
|
|
szUser,
|
|
szMasterKey,
|
|
rgbPwd,
|
|
pguidType,
|
|
pguidSubtype,
|
|
szItemName,
|
|
pbData,
|
|
cbData))
|
|
{
|
|
dwRet = PST_E_STORAGE_ERROR;
|
|
goto Ret;
|
|
}
|
|
|
|
dwRet = PST_E_OK;
|
|
Ret:
|
|
|
|
// if creation didn't happen, item shouldn't exist
|
|
if ((dwRet != PST_E_OK) && (!fExisted))
|
|
BPDeleteItem(szUser, pguidType, pguidSubtype, szItemName);
|
|
|
|
|
|
if (szMasterKey)
|
|
SSFree(szMasterKey);
|
|
|
|
if (szUser)
|
|
SSFree(szUser);
|
|
|
|
if (szType)
|
|
SSFree(szType);
|
|
|
|
if (szSubtype)
|
|
SSFree(szSubtype);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
HRESULT SPReadItem(
|
|
/* [in] */ PST_PROVIDER_HANDLE *phPSTProv,
|
|
/* [in] */ PST_KEY Key,
|
|
/* [in] */ const GUID *pguidType,
|
|
/* [in] */ const GUID *pguidSubtype,
|
|
/* [in] */ LPCWSTR szItemName,
|
|
/* [out] */ DWORD *pcbData,
|
|
/* [size_is][size_is][out] */ BYTE **ppbData,
|
|
/* [in] */ PPST_PROMPTINFO psPrompt,
|
|
/* [in] */ DWORD dwFlags)
|
|
{
|
|
HRESULT dwRet = PST_E_FAIL;
|
|
PST_ACCESSRULESET sRules = {sizeof(sRules), 0, NULL};
|
|
|
|
LPWSTR szUser = NULL;
|
|
LPWSTR szMasterKey = NULL;
|
|
LPWSTR szCallerName = NULL;
|
|
|
|
BYTE rgbPwd[A_SHA_DIGEST_LEN];
|
|
LPWSTR szType=NULL, szSubtype=NULL;
|
|
|
|
if (Key & ~(PST_KEY_CURRENT_USER | PST_KEY_LOCAL_MACHINE))
|
|
{
|
|
dwRet = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
if ((dwFlags & ~(PST_UNRESTRICTED_ITEMDATA | PST_PROMPT_QUERY |
|
|
PST_NO_UI_MIGRATION
|
|
)) != 0)
|
|
{
|
|
dwRet = PST_E_BAD_FLAGS;
|
|
goto Ret;
|
|
}
|
|
|
|
// Disable unnecessary UI.
|
|
dwFlags |= PST_NO_UI_MIGRATION;
|
|
|
|
if (psPrompt == NULL)
|
|
{
|
|
dwRet = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
// Check for invalid "" input
|
|
if (wcslen(szItemName) == 0)
|
|
{
|
|
dwRet = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
// get current user
|
|
if (!FGetCurrentUser(
|
|
phPSTProv,
|
|
&szUser,
|
|
Key))
|
|
{
|
|
dwRet = (DWORD)PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
|
|
if (dwFlags & PST_UNRESTRICTED_ITEMDATA)
|
|
{
|
|
// read insecure data stream
|
|
if (PST_E_OK != (dwRet =
|
|
BPGetInsecureItemData(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
szItemName,
|
|
ppbData,
|
|
pcbData)) )
|
|
goto Ret;
|
|
|
|
dwRet = PST_E_OK;
|
|
goto Ret;
|
|
}
|
|
// ELSE: secure stream
|
|
|
|
{
|
|
POPENITEM_LIST_ITEM pli;
|
|
|
|
OPENITEM_LIST_ITEM li;
|
|
if(NULL == g_pCOpenItemList)
|
|
{
|
|
dwRet = PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
CreateOpenListItem(&li, phPSTProv, Key, pguidType, pguidSubtype, szItemName);
|
|
|
|
g_pCOpenItemList->LockList();
|
|
|
|
// get opened (cached) item
|
|
pli = g_pCOpenItemList->SearchList(&li);
|
|
|
|
if ((pli != NULL) && (pli->ModeFlags & PST_READ))
|
|
{
|
|
// found cached item; pull pwd
|
|
CopyMemory(rgbPwd, pli->rgbPwd, A_SHA_DIGEST_LEN);
|
|
szMasterKey = (LPWSTR) SSAlloc(WSZ_BYTECOUNT(pli->szMasterKey));
|
|
if( szMasterKey )
|
|
wcscpy(szMasterKey, pli->szMasterKey);
|
|
|
|
//
|
|
// unlock list.
|
|
//
|
|
|
|
g_pCOpenItemList->UnlockList();
|
|
|
|
if( szMasterKey == NULL ) {
|
|
dwRet = E_OUTOFMEMORY;
|
|
goto Ret;
|
|
}
|
|
|
|
// PST_PF_ALWAYS_SHOW always forces UI
|
|
if (PST_PF_ALWAYS_SHOW == psPrompt->dwPromptFlags)
|
|
{
|
|
// retrieve names of type, subtype
|
|
if (PST_E_OK != (dwRet =
|
|
BPGetTypeName(
|
|
szUser,
|
|
pguidType,
|
|
&szType)) )
|
|
goto Ret;
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
BPGetSubtypeName(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
&szSubtype)) )
|
|
goto Ret;
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
ShowOKCancelUI(
|
|
phPSTProv,
|
|
szUser,
|
|
Key,
|
|
szType,
|
|
szSubtype,
|
|
szItemName,
|
|
psPrompt,
|
|
g_PromptReadItem)) )
|
|
goto Ret;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
//
|
|
// unlock list.
|
|
//
|
|
|
|
g_pCOpenItemList->UnlockList();
|
|
|
|
// not cached; do actual work
|
|
|
|
// retrieve names of type, subtype
|
|
if (PST_E_OK != (dwRet =
|
|
BPGetTypeName(
|
|
szUser,
|
|
pguidType,
|
|
&szType)) )
|
|
goto Ret;
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
BPGetSubtypeName(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
&szSubtype)) )
|
|
goto Ret;
|
|
|
|
// does ALL user confirm work
|
|
if (PST_E_OK != (dwRet =
|
|
GetUserConfirmBuf(
|
|
phPSTProv,
|
|
szUser,
|
|
Key,
|
|
szType,
|
|
pguidType,
|
|
szSubtype,
|
|
pguidSubtype,
|
|
szItemName,
|
|
psPrompt,
|
|
g_PromptReadItem,
|
|
&szMasterKey,
|
|
rgbPwd,
|
|
dwFlags)) )
|
|
goto Ret;
|
|
|
|
}
|
|
}
|
|
|
|
// if checked out, then actually retrieve item
|
|
if (!FBPGetSecuredItemData(
|
|
szUser,
|
|
szMasterKey,
|
|
rgbPwd,
|
|
pguidType,
|
|
pguidSubtype,
|
|
szItemName,
|
|
ppbData,
|
|
pcbData))
|
|
{
|
|
dwRet = PST_E_STORAGE_ERROR;
|
|
goto Ret;
|
|
}
|
|
|
|
dwRet = PST_E_OK;
|
|
|
|
Ret:
|
|
|
|
//
|
|
// see if caller requested UI disposition on item.
|
|
//
|
|
|
|
if( dwRet == PST_E_OK && dwFlags & PST_PROMPT_QUERY ) {
|
|
DWORD dwStoredConfirm;
|
|
LPWSTR pszMasterKey;
|
|
DWORD dwRetVal;
|
|
|
|
dwRetVal = BPGetItemConfirm(
|
|
phPSTProv,
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
szItemName,
|
|
&dwStoredConfirm,
|
|
&pszMasterKey
|
|
);
|
|
|
|
if( dwRetVal == PST_E_OK ) {
|
|
|
|
SSFree( pszMasterKey );
|
|
|
|
if( !(dwStoredConfirm & BP_CONFIRM_NONE) ) {
|
|
if(FIsProviderUIAllowed( szUser ))
|
|
dwRet = PST_E_ITEM_EXISTS;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (szUser)
|
|
SSFree(szUser);
|
|
|
|
if (szMasterKey)
|
|
SSFree(szMasterKey);
|
|
|
|
if (szType)
|
|
SSFree(szType);
|
|
|
|
if (szSubtype)
|
|
SSFree(szSubtype);
|
|
|
|
if (szCallerName)
|
|
SSFree(szCallerName);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
HRESULT SPDeleteItem(
|
|
/* [in] */ PST_PROVIDER_HANDLE *phPSTProv,
|
|
/* [in] */ PST_KEY Key,
|
|
/* [in] */ const GUID *pguidType,
|
|
/* [in] */ const GUID *pguidSubtype,
|
|
/* [in] */ LPCWSTR szItemName,
|
|
/* [in] */ PPST_PROMPTINFO psPrompt,
|
|
/* [in] */ DWORD dwFlags)
|
|
{
|
|
HRESULT dwRet = PST_E_FAIL;
|
|
PST_ACCESSRULESET sRules = {sizeof(sRules), 0, NULL};
|
|
|
|
LPWSTR szUser = NULL;
|
|
LPWSTR szMasterKey = NULL;
|
|
LPWSTR szCallerName = NULL;
|
|
|
|
BYTE rgbPwd[A_SHA_DIGEST_LEN];
|
|
LPWSTR szType=NULL, szSubtype=NULL;
|
|
|
|
if (Key & ~(PST_KEY_CURRENT_USER | PST_KEY_LOCAL_MACHINE))
|
|
{
|
|
dwRet = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
if (dwFlags & ~(PST_NO_UI_MIGRATION))
|
|
{
|
|
dwRet = PST_E_BAD_FLAGS;
|
|
goto Ret;
|
|
}
|
|
|
|
// Disable unnecessary UI.
|
|
dwFlags |= PST_NO_UI_MIGRATION;
|
|
|
|
if (psPrompt == NULL)
|
|
{
|
|
dwRet = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
|
|
// Check for invalid "" input
|
|
if (wcslen(szItemName) == 0)
|
|
{
|
|
dwRet = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
// get current user
|
|
if (!FGetCurrentUser(
|
|
phPSTProv,
|
|
&szUser,
|
|
Key))
|
|
{
|
|
dwRet = (DWORD)PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
|
|
|
|
|
|
{
|
|
POPENITEM_LIST_ITEM pli;
|
|
|
|
OPENITEM_LIST_ITEM li;
|
|
|
|
if(NULL == g_pCOpenItemList)
|
|
{
|
|
dwRet = PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
CreateOpenListItem(&li, phPSTProv, Key, pguidType, pguidSubtype, szItemName);
|
|
|
|
g_pCOpenItemList->LockList();
|
|
|
|
// get opened (cached) item
|
|
pli = g_pCOpenItemList->SearchList(&li);
|
|
|
|
if ((pli != NULL) && (pli->ModeFlags & PST_WRITE))
|
|
{
|
|
// found cached item; pull pwd
|
|
CopyMemory(rgbPwd, pli->rgbPwd, A_SHA_DIGEST_LEN);
|
|
szMasterKey = (LPWSTR) SSAlloc(WSZ_BYTECOUNT(pli->szMasterKey));
|
|
if( szMasterKey )
|
|
wcscpy(szMasterKey, pli->szMasterKey);
|
|
|
|
g_pCOpenItemList->UnlockList();
|
|
|
|
if( szMasterKey == NULL ) {
|
|
dwRet = E_OUTOFMEMORY;
|
|
goto Ret;
|
|
}
|
|
|
|
// PST_PF_ALWAYS_SHOW always forces UI
|
|
if (PST_PF_ALWAYS_SHOW == psPrompt->dwPromptFlags)
|
|
{
|
|
// retrieve names of type, subtype
|
|
if (PST_E_OK != (dwRet =
|
|
BPGetTypeName(
|
|
szUser,
|
|
pguidType,
|
|
&szType)) )
|
|
goto Ret;
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
BPGetSubtypeName(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
&szSubtype)) )
|
|
goto Ret;
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
ShowOKCancelUI(
|
|
phPSTProv,
|
|
szUser,
|
|
Key,
|
|
szType,
|
|
szSubtype,
|
|
szItemName,
|
|
psPrompt,
|
|
g_PromptDeleteItem)) )
|
|
goto Ret;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// unlock list.
|
|
//
|
|
|
|
g_pCOpenItemList->UnlockList();
|
|
|
|
|
|
// retrieve names of type, subtype
|
|
if (PST_E_OK != (dwRet =
|
|
BPGetTypeName(
|
|
szUser,
|
|
pguidType,
|
|
&szType)) )
|
|
goto Ret;
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
BPGetSubtypeName(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
&szSubtype)) )
|
|
goto Ret;
|
|
|
|
// does ALL user confirm work
|
|
if (PST_E_OK != (dwRet =
|
|
GetUserConfirmBuf(
|
|
phPSTProv,
|
|
szUser,
|
|
Key,
|
|
szType,
|
|
pguidType,
|
|
szSubtype,
|
|
pguidSubtype,
|
|
szItemName,
|
|
psPrompt,
|
|
g_PromptDeleteItem,
|
|
&szMasterKey,
|
|
rgbPwd,
|
|
dwFlags)) )
|
|
goto Ret;
|
|
}
|
|
}
|
|
|
|
// if checked out, then actually remove item
|
|
if (PST_E_OK != (dwRet =
|
|
BPDeleteItem(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
szItemName)) )
|
|
goto Ret;
|
|
|
|
dwRet = PST_E_OK;
|
|
|
|
Ret:
|
|
|
|
|
|
if (szUser)
|
|
SSFree(szUser);
|
|
|
|
if (szMasterKey)
|
|
SSFree(szMasterKey);
|
|
|
|
if (szType)
|
|
SSFree(szType);
|
|
|
|
if (szSubtype)
|
|
SSFree(szSubtype);
|
|
|
|
if (szCallerName)
|
|
SSFree(szCallerName);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
|
|
|
|
HRESULT SPOpenItem(
|
|
/* [in] */ PST_PROVIDER_HANDLE *phPSTProv,
|
|
/* [in] */ PST_KEY Key,
|
|
/* [in] */ const GUID *pguidType,
|
|
/* [in] */ const GUID *pguidSubtype,
|
|
/* [in] */ LPCWSTR szItemName,
|
|
/* [in] */ PST_ACCESSMODE ModeFlags,
|
|
/* [in] */ PPST_PROMPTINFO psPrompt,
|
|
/* [in] */ DWORD dwFlags)
|
|
{
|
|
HRESULT dwRet = PST_E_FAIL;
|
|
PST_ACCESSRULESET sRules = {sizeof(sRules), 0, NULL};
|
|
|
|
LPWSTR szUser = NULL;
|
|
LPWSTR szMasterKey = NULL;
|
|
LPWSTR szCallerName = NULL;
|
|
|
|
BYTE rgbPwd[A_SHA_DIGEST_LEN];
|
|
LPWSTR szType=NULL, szSubtype=NULL;
|
|
|
|
POPENITEM_LIST_ITEM pli = NULL;
|
|
|
|
|
|
if (Key & ~(PST_KEY_CURRENT_USER | PST_KEY_LOCAL_MACHINE))
|
|
{
|
|
dwRet = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
if (dwFlags)
|
|
{
|
|
dwRet = PST_E_BAD_FLAGS;
|
|
goto Ret;
|
|
}
|
|
|
|
if(psPrompt == NULL)
|
|
{
|
|
dwRet = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
|
|
// Check for invalid "" input
|
|
if (wcslen(szItemName) == 0)
|
|
{
|
|
dwRet = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
// check for item already open
|
|
{
|
|
OPENITEM_LIST_ITEM li;
|
|
if(NULL == g_pCOpenItemList)
|
|
{
|
|
dwRet = PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
CreateOpenListItem(&li, phPSTProv, Key, pguidType, pguidSubtype, szItemName);
|
|
|
|
// get opened (cached) item
|
|
pli = g_pCOpenItemList->SearchList(&li);
|
|
|
|
if (pli != NULL)
|
|
{
|
|
// item already cached; error!
|
|
dwRet = (DWORD)PST_E_ALREADY_OPEN;
|
|
goto Ret;
|
|
}
|
|
}
|
|
|
|
|
|
// get current user
|
|
if (!FGetCurrentUser(
|
|
phPSTProv,
|
|
&szUser,
|
|
Key))
|
|
{
|
|
dwRet = (DWORD)PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
|
|
// retrieve names of type, subtype
|
|
if (PST_E_OK != (dwRet =
|
|
BPGetTypeName(
|
|
szUser,
|
|
pguidType,
|
|
&szType)) )
|
|
goto Ret;
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
BPGetSubtypeName(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
&szSubtype)) )
|
|
goto Ret;
|
|
|
|
|
|
// does ALL user confirm work
|
|
if (PST_E_OK != (dwRet =
|
|
GetUserConfirmBuf(
|
|
phPSTProv,
|
|
szUser,
|
|
Key,
|
|
szType,
|
|
pguidType,
|
|
szSubtype,
|
|
pguidSubtype,
|
|
szItemName,
|
|
psPrompt,
|
|
g_PromptOpenItem,
|
|
&szMasterKey,
|
|
rgbPwd,
|
|
0)) )
|
|
goto Ret;
|
|
|
|
// if checked out, then add to open item list
|
|
pli = (POPENITEM_LIST_ITEM) SSAlloc(sizeof(OPENITEM_LIST_ITEM));
|
|
if(NULL == pli)
|
|
{
|
|
dwRet = PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
|
|
|
|
// fill in contents
|
|
CreateOpenListItem(pli, phPSTProv, Key, pguidType, pguidSubtype, NULL);
|
|
|
|
pli->szItemName = (LPWSTR)SSAlloc(WSZ_BYTECOUNT(szItemName));
|
|
wcscpy(pli->szItemName, szItemName);
|
|
|
|
pli->szMasterKey = (LPWSTR)SSAlloc(WSZ_BYTECOUNT(szMasterKey));
|
|
wcscpy(pli->szMasterKey, szMasterKey);
|
|
|
|
CopyMemory(pli->rgbPwd, rgbPwd, A_SHA_DIGEST_LEN);
|
|
pli->ModeFlags = ModeFlags;
|
|
|
|
// add to the open list
|
|
g_pCOpenItemList->AddToList(pli);
|
|
|
|
dwRet = PST_E_OK;
|
|
Ret:
|
|
|
|
|
|
if (szUser)
|
|
SSFree(szUser);
|
|
|
|
if (szMasterKey)
|
|
SSFree(szMasterKey);
|
|
|
|
if (szType)
|
|
SSFree(szType);
|
|
|
|
if (szSubtype)
|
|
SSFree(szSubtype);
|
|
|
|
if (szCallerName)
|
|
SSFree(szCallerName);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
|
|
HRESULT SPCloseItem(
|
|
/* [in] */ PST_PROVIDER_HANDLE *phPSTProv,
|
|
/* [in] */ PST_KEY Key,
|
|
/* [in] */ const GUID *pguidType,
|
|
/* [in] */ const GUID *pguidSubtype,
|
|
/* [in] */ LPCWSTR szItemName,
|
|
/* [in] */ DWORD dwFlags)
|
|
{
|
|
HRESULT dwRet = PST_E_FAIL;
|
|
|
|
if (Key & ~(PST_KEY_CURRENT_USER | PST_KEY_LOCAL_MACHINE))
|
|
{
|
|
dwRet = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
if (dwFlags)
|
|
{
|
|
dwRet = PST_E_BAD_FLAGS;
|
|
goto Ret;
|
|
}
|
|
|
|
// Check for invalid "" input
|
|
if (wcslen(szItemName) == 0)
|
|
{
|
|
dwRet = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
// if item found in list, remove it
|
|
OPENITEM_LIST_ITEM li;
|
|
if(NULL == g_pCOpenItemList)
|
|
{
|
|
dwRet = PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
CreateOpenListItem(&li, phPSTProv, Key, pguidType, pguidSubtype, szItemName);
|
|
|
|
if (!g_pCOpenItemList->DelFromList(&li))
|
|
{
|
|
dwRet = PST_E_NOT_OPEN;
|
|
goto Ret;
|
|
}
|
|
|
|
dwRet = PST_E_OK;
|
|
Ret:
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////
|
|
// FInitProtectAPIGlobals
|
|
//
|
|
// Checks for registry overrides for some default values
|
|
// registry entries can change what algs are being used,
|
|
// as well as what provider is used.
|
|
BOOL FInitProtectAPIGlobals()
|
|
{
|
|
HKEY hProtectKey = NULL;
|
|
HKEY hProviderKey = NULL;
|
|
DWORD dwTemp, dwType, cbSize;
|
|
DWORD dwCreate;
|
|
static const WCHAR szProtectKeyName[] = REG_CRYPTPROTECT_LOC;
|
|
static const WCHAR szProviderKeyName[] = L"\\" REG_CRYPTPROTECT_PROVIDERS_SUBKEYLOC L"\\" CRYPTPROTECT_DEFAULT_PROVIDER_GUIDSZ ;
|
|
|
|
LONG lRet;
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// get password cache policy setting.
|
|
//
|
|
|
|
|
|
lRet = RegOpenKeyExU(
|
|
HKEY_LOCAL_MACHINE,
|
|
L"Software\\Policies\\Microsoft\\Cryptography\\Protect",
|
|
0,
|
|
KEY_QUERY_VALUE,
|
|
&hProtectKey
|
|
);
|
|
|
|
if( lRet == ERROR_SUCCESS ) {
|
|
|
|
DWORD cbSize;
|
|
DWORD dwTemp;
|
|
DWORD dwType;
|
|
|
|
//
|
|
// query EnableCachePW value.
|
|
//
|
|
|
|
|
|
cbSize = sizeof(DWORD);
|
|
lRet = RegQueryValueExU(
|
|
hProtectKey,
|
|
REG_CRYPTPROTECT_ALLOW_CACHEPW,
|
|
NULL,
|
|
&dwType,
|
|
(PBYTE)&dwTemp,
|
|
&cbSize
|
|
);
|
|
|
|
if( lRet == ERROR_SUCCESS &&
|
|
dwType == REG_DWORD &&
|
|
dwTemp == 0 // 0 == disablePW cache
|
|
) {
|
|
g_fAllowCachePW = FALSE;
|
|
} else {
|
|
g_fAllowCachePW = TRUE;
|
|
}
|
|
|
|
|
|
RegCloseKey( hProtectKey );
|
|
hProtectKey = NULL;
|
|
} else {
|
|
|
|
g_fAllowCachePW = TRUE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|