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.
3042 lines
74 KiB
3042 lines
74 KiB
#include <pch.cpp>
|
|
#pragma hdrstop
|
|
|
|
|
|
#include "guidcnvt.h"
|
|
|
|
#include "passwd.h"
|
|
#include "storage.h"
|
|
|
|
|
|
|
|
|
|
extern DISPIF_CALLBACKS g_sCallbacks;
|
|
|
|
|
|
// note: REG_PSTTREE_LOC moved to pstprv.h
|
|
|
|
#define REG_DATA_LOC L"Data"
|
|
#define REG_MK_LOC L"Data 2"
|
|
|
|
#define REG_ACCESSRULE_LOC L"Access Rules"
|
|
#define REG_DISPLAYSTRING_VALNAME L"Display String"
|
|
|
|
#define REG_USER_INTERNAL_MAC_KEY L"Blocking"
|
|
|
|
#define REG_ITEM_SECURE_DATA_VALNAME L"Item Data"
|
|
#define REG_ITEM_INSECURE_DATA_VALNAME L"Insecure Data"
|
|
#define REG_ITEM_MK_VALNAME L"Behavior"
|
|
|
|
#define REG_SECURITY_SALT_VALNAME L"Value"
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
// PRIMITIVIES for snagging registry keys
|
|
|
|
DWORD GetPSTUserHKEY(LPCWSTR szUser, HKEY* phUserKey, BOOL* pfExisted)
|
|
{
|
|
HKEY hKeyBase = NULL;
|
|
DWORD dwRet = (DWORD)PST_E_STORAGE_ERROR;
|
|
|
|
DWORD dwCreate;
|
|
DWORD cbKeyName;
|
|
LPWSTR szKeyName = NULL;
|
|
WCHAR FastBuffer[(sizeof(REG_PSTTREE_LOC) / sizeof(WCHAR)) + 64];
|
|
LPWSTR SlowBuffer = NULL;
|
|
LPCWSTR szContainer = szUser;
|
|
DWORD dwDesiredAccess = KEY_READ | KEY_WRITE;
|
|
|
|
cbKeyName = sizeof(REG_PSTTREE_LOC) ;
|
|
|
|
//
|
|
// For Win95, we may have an empty or NULL container
|
|
// name (szUser), so use a default storage area for
|
|
// that scenario
|
|
//
|
|
|
|
if(szContainer == NULL || szContainer[0] == L'\0') {
|
|
// "*" is an invalid LM username character
|
|
szContainer = L"*Default*";
|
|
hKeyBase = HKEY_LOCAL_MACHINE;
|
|
} else {
|
|
|
|
//
|
|
// see if we should go to HKEY_LOCAL_MACHINE or
|
|
// HKEY_CURRENT_USER
|
|
//
|
|
|
|
if( _wcsicmp(WSZ_LOCAL_MACHINE, szContainer) == 0 ) {
|
|
// HKEY_LOCAL_MACHINE
|
|
hKeyBase = HKEY_LOCAL_MACHINE;
|
|
} else {
|
|
// HKEY_CURRENT_USER
|
|
if(!GetUserHKEY(szContainer, dwDesiredAccess, &hKeyBase)) {
|
|
if(FIsWinNT()) {
|
|
goto Ret;
|
|
}
|
|
|
|
//
|
|
// Win95, profiles may be disabled, so go to
|
|
// HKEY_LOCAL_MACHINE\xxx\szContainer
|
|
//
|
|
|
|
hKeyBase = HKEY_LOCAL_MACHINE;
|
|
|
|
} else {
|
|
|
|
//
|
|
// no container name when going to HKEY_CURRENT_USER
|
|
//
|
|
|
|
//
|
|
// sfield: continue to use a container name for HKEY_CURRENT_USER
|
|
// because the configuration may be shared, roamable hives
|
|
// (mandatators profiles, etc, which we are telling people not
|
|
// to use anymore, but never-the-less, this could come up
|
|
//
|
|
|
|
// szContainer = L"\0";
|
|
}
|
|
}
|
|
}
|
|
|
|
cbKeyName += (lstrlenW(szContainer) * sizeof(WCHAR)) +
|
|
sizeof(WCHAR) + // L'\\'
|
|
sizeof(WCHAR) ; // terminal NULL
|
|
|
|
//
|
|
// use faster stack based buffer if the material fits
|
|
//
|
|
|
|
if(cbKeyName > sizeof(FastBuffer)) {
|
|
SlowBuffer = (LPWSTR)SSAlloc( cbKeyName );
|
|
|
|
if (SlowBuffer == NULL)
|
|
{
|
|
dwRet = (DWORD)PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
szKeyName = SlowBuffer;
|
|
} else {
|
|
szKeyName = FastBuffer;
|
|
}
|
|
|
|
wcscpy(szKeyName, REG_PSTTREE_LOC);
|
|
|
|
//
|
|
// work-around bug in RegCreateKeyEx that returns the wrong
|
|
// creation disposition if a trailing "\" is in the key name
|
|
//
|
|
|
|
if(szContainer && szContainer[0] != L'\0') {
|
|
wcscat(szKeyName, L"\\");
|
|
wcscat(szKeyName, szContainer);
|
|
}
|
|
|
|
// Open Base Key //
|
|
// get current user, open (REG_PSTTREE_LOC\\CurrentUser)
|
|
if (ERROR_SUCCESS !=
|
|
RegCreateKeyExU(
|
|
hKeyBase,
|
|
szKeyName,
|
|
0,
|
|
NULL, // address of class string
|
|
0,
|
|
dwDesiredAccess,
|
|
NULL,
|
|
phUserKey,
|
|
&dwCreate))
|
|
{
|
|
goto Ret;
|
|
}
|
|
|
|
if (pfExisted) {
|
|
*pfExisted = (dwCreate == REG_OPENED_EXISTING_KEY);
|
|
}
|
|
|
|
if(dwCreate == REG_CREATED_NEW_KEY && FIsWinNT()) {
|
|
|
|
//
|
|
// WinNT: restrict access to Local System on newly created key.
|
|
//
|
|
|
|
HKEY hKeyWriteDac;
|
|
|
|
//
|
|
// duplicate to WRITE_DAC access key and use that
|
|
//
|
|
|
|
if(ERROR_SUCCESS == RegOpenKeyExW(*phUserKey, NULL, 0, WRITE_DAC, &hKeyWriteDac)) {
|
|
SetRegistrySecurity(hKeyWriteDac);
|
|
RegCloseKey(hKeyWriteDac);
|
|
}
|
|
}
|
|
|
|
dwRet = PST_E_OK;
|
|
Ret:
|
|
|
|
if (SlowBuffer)
|
|
SSFree(SlowBuffer);
|
|
|
|
//
|
|
// close the per-user "root" key
|
|
//
|
|
|
|
if(hKeyBase != NULL && hKeyBase != HKEY_LOCAL_MACHINE)
|
|
RegCloseKey(hKeyBase);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
|
|
DWORD GetPSTTypeHKEY(LPCWSTR szUser, const GUID* pguidType, HKEY* phTypeKey)
|
|
{
|
|
DWORD dwRet;
|
|
HKEY hBaseKey = NULL;
|
|
HKEY hDataKey = NULL;
|
|
|
|
CHAR rgszTypeGuid[MAX_GUID_SZ_CHARS];
|
|
|
|
// Open User Key //
|
|
if (PST_E_OK != (dwRet =
|
|
GetPSTUserHKEY(
|
|
szUser,
|
|
&hBaseKey,
|
|
NULL)) )
|
|
goto Ret;
|
|
|
|
// Open Data Key //
|
|
if (ERROR_SUCCESS !=
|
|
RegOpenKeyExU(
|
|
hBaseKey,
|
|
REG_DATA_LOC,
|
|
0,
|
|
KEY_READ | KEY_WRITE,
|
|
&hDataKey))
|
|
{
|
|
dwRet = (DWORD)PST_E_TYPE_NO_EXISTS;
|
|
goto Ret;
|
|
}
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
MyGuidToStringA(
|
|
pguidType,
|
|
rgszTypeGuid)) )
|
|
goto Ret;
|
|
|
|
// Open Category Key //
|
|
if (ERROR_SUCCESS !=
|
|
RegOpenKeyExA(
|
|
hDataKey,
|
|
rgszTypeGuid,
|
|
0,
|
|
KEY_READ | KEY_WRITE,
|
|
phTypeKey))
|
|
{
|
|
dwRet = (DWORD)PST_E_TYPE_NO_EXISTS;
|
|
goto Ret;
|
|
}
|
|
|
|
dwRet = PST_E_OK;
|
|
Ret:
|
|
if (hBaseKey)
|
|
RegCloseKey(hBaseKey);
|
|
|
|
if (hDataKey)
|
|
RegCloseKey(hDataKey);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
|
|
DWORD CreatePSTTypeHKEY(LPCWSTR szUser, const GUID* pguidType, HKEY* phTypeKey, BOOL* pfExisted)
|
|
{
|
|
DWORD dwRet;
|
|
DWORD dwCreate;
|
|
HKEY hBaseKey = NULL;
|
|
HKEY hDataKey = NULL;
|
|
|
|
CHAR rgszTypeGuid[MAX_GUID_SZ_CHARS];
|
|
|
|
// Open User Key //
|
|
if (PST_E_OK != (dwRet =
|
|
GetPSTUserHKEY(
|
|
szUser,
|
|
&hBaseKey,
|
|
NULL)) )
|
|
goto Ret;
|
|
|
|
// Open Data Key //
|
|
if (ERROR_SUCCESS !=
|
|
RegCreateKeyExU(
|
|
hBaseKey,
|
|
REG_DATA_LOC,
|
|
0,
|
|
NULL, // address of class string
|
|
0,
|
|
KEY_READ | KEY_WRITE,
|
|
NULL,
|
|
&hDataKey,
|
|
&dwCreate))
|
|
{
|
|
dwRet = (DWORD)PST_E_STORAGE_ERROR;
|
|
goto Ret;
|
|
}
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
MyGuidToStringA(
|
|
pguidType,
|
|
rgszTypeGuid)) )
|
|
goto Ret;
|
|
|
|
// Open Category Key //
|
|
if (ERROR_SUCCESS !=
|
|
RegCreateKeyExA(
|
|
hDataKey,
|
|
rgszTypeGuid,
|
|
0,
|
|
NULL, // address of class string
|
|
0,
|
|
KEY_READ | KEY_WRITE,
|
|
NULL,
|
|
phTypeKey,
|
|
&dwCreate))
|
|
{
|
|
dwRet = (DWORD)PST_E_STORAGE_ERROR;
|
|
goto Ret;
|
|
}
|
|
|
|
if (pfExisted)
|
|
*pfExisted = (dwCreate == REG_OPENED_EXISTING_KEY);
|
|
|
|
dwRet = PST_E_OK;
|
|
Ret:
|
|
if (hBaseKey)
|
|
RegCloseKey(hBaseKey);
|
|
|
|
if (hDataKey)
|
|
RegCloseKey(hDataKey);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
DWORD GetPSTMasterKeyHKEY(LPCWSTR szUser, LPCWSTR szMasterKey, HKEY* phMyKey)
|
|
{
|
|
DWORD dwRet;
|
|
DWORD dwCreate;
|
|
HKEY hBaseKey = NULL;
|
|
HKEY hMKKey = NULL;
|
|
|
|
// Open User Key //
|
|
if (PST_E_OK != (dwRet =
|
|
GetPSTUserHKEY(
|
|
szUser,
|
|
&hBaseKey,
|
|
NULL)) )
|
|
goto Ret;
|
|
|
|
// Open Master Key section //
|
|
if (ERROR_SUCCESS !=
|
|
RegCreateKeyExU(
|
|
hBaseKey,
|
|
REG_MK_LOC,
|
|
0,
|
|
NULL, // address of class string
|
|
0,
|
|
KEY_READ | KEY_WRITE,
|
|
NULL,
|
|
&hMKKey,
|
|
&dwCreate))
|
|
{
|
|
dwRet = (DWORD)PST_E_STORAGE_ERROR;
|
|
goto Ret;
|
|
}
|
|
|
|
if (szMasterKey)
|
|
{
|
|
// Open specific Master Key //
|
|
if (ERROR_SUCCESS !=
|
|
RegCreateKeyExU(
|
|
hMKKey,
|
|
szMasterKey,
|
|
0,
|
|
NULL, // address of class string
|
|
0,
|
|
KEY_READ | KEY_WRITE,
|
|
NULL,
|
|
phMyKey,
|
|
&dwCreate))
|
|
{
|
|
dwRet = (DWORD)PST_E_STORAGE_ERROR;
|
|
goto Ret;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// wanted master parent, not specific MK
|
|
*phMyKey = hMKKey;
|
|
}
|
|
|
|
dwRet = PST_E_OK;
|
|
Ret:
|
|
if (hBaseKey)
|
|
RegCloseKey(hBaseKey);
|
|
|
|
// wanted parent, not specific MK
|
|
if ((*phMyKey != hMKKey) && (hMKKey))
|
|
RegCloseKey(hMKKey);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
DWORD GetPSTSubtypeHKEY(LPCWSTR szUser, const GUID* pguidType, const GUID* pguidSubtype, HKEY* phSubTypeKey)
|
|
{
|
|
DWORD dwRet;
|
|
DWORD dwCreate;
|
|
HKEY hTypeKey = NULL;
|
|
CHAR rgszSubtypeGuid[MAX_GUID_SZ_CHARS];
|
|
|
|
// Open User Key //
|
|
if (PST_E_OK != (dwRet =
|
|
GetPSTTypeHKEY(
|
|
szUser,
|
|
pguidType,
|
|
&hTypeKey)) )
|
|
goto Ret;
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
MyGuidToStringA(
|
|
pguidSubtype,
|
|
rgszSubtypeGuid)) )
|
|
goto Ret;
|
|
|
|
// Open SubType Key //
|
|
if (ERROR_SUCCESS !=
|
|
RegOpenKeyExA(
|
|
hTypeKey,
|
|
rgszSubtypeGuid,
|
|
0,
|
|
KEY_READ | KEY_WRITE,
|
|
phSubTypeKey))
|
|
{
|
|
dwRet = (DWORD)PST_E_TYPE_NO_EXISTS;
|
|
goto Ret;
|
|
}
|
|
|
|
dwRet = PST_E_OK;
|
|
Ret:
|
|
if (hTypeKey)
|
|
RegCloseKey(hTypeKey);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
|
|
DWORD CreatePSTSubtypeHKEY(LPCWSTR szUser, const GUID* pguidType, const GUID* pguidSubtype, HKEY* phSubTypeKey, BOOL* pfExisted)
|
|
{
|
|
DWORD dwRet;
|
|
DWORD dwCreate;
|
|
HKEY hTypeKey = NULL;
|
|
CHAR rgszSubtypeGuid[MAX_GUID_SZ_CHARS];
|
|
|
|
// Open Type Key //
|
|
if (PST_E_OK != (dwRet =
|
|
GetPSTTypeHKEY(
|
|
szUser,
|
|
pguidType,
|
|
&hTypeKey)) )
|
|
goto Ret;
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
MyGuidToStringA(
|
|
pguidSubtype,
|
|
rgszSubtypeGuid)) )
|
|
goto Ret;
|
|
|
|
// Open SubType Key //
|
|
if (ERROR_SUCCESS !=
|
|
RegCreateKeyExA(
|
|
hTypeKey,
|
|
rgszSubtypeGuid,
|
|
0,
|
|
NULL, // address of class string
|
|
0,
|
|
KEY_READ | KEY_WRITE,
|
|
NULL,
|
|
phSubTypeKey,
|
|
&dwCreate))
|
|
{
|
|
dwRet = (DWORD)PST_E_STORAGE_ERROR;
|
|
goto Ret;
|
|
}
|
|
|
|
if (pfExisted)
|
|
*pfExisted = (dwCreate == REG_OPENED_EXISTING_KEY);
|
|
|
|
dwRet = PST_E_OK;
|
|
Ret:
|
|
if (hTypeKey)
|
|
RegCloseKey(hTypeKey);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
DWORD CreatePSTItemHKEY(LPCWSTR szUser, const GUID* pguidType, const GUID* pguidSubtype, LPCWSTR szItemName, HKEY* phItemKey, BOOL* pfExisted)
|
|
{
|
|
BOOL dwRet;
|
|
DWORD dwCreate;
|
|
HKEY hSubTypeKey = NULL;
|
|
|
|
// Open SubType key //
|
|
if (PST_E_OK != (dwRet =
|
|
GetPSTSubtypeHKEY(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
&hSubTypeKey)) )
|
|
goto Ret;
|
|
|
|
// Open name key //
|
|
if (ERROR_SUCCESS !=
|
|
RegCreateKeyExU(
|
|
hSubTypeKey,
|
|
szItemName,
|
|
0,
|
|
NULL, // address of class string
|
|
0,
|
|
KEY_READ | KEY_WRITE,
|
|
NULL,
|
|
phItemKey,
|
|
&dwCreate))
|
|
{
|
|
dwRet = (DWORD)PST_E_STORAGE_ERROR;
|
|
goto Ret;
|
|
}
|
|
|
|
if (pfExisted)
|
|
*pfExisted = (dwCreate == REG_OPENED_EXISTING_KEY);
|
|
|
|
dwRet = PST_E_OK;
|
|
Ret:
|
|
if (hSubTypeKey)
|
|
RegCloseKey(hSubTypeKey);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
DWORD GetPSTItemHKEY(LPCWSTR szUser, const GUID* pguidType, const GUID* pguidSubtype, LPCWSTR szItemName, HKEY* phItemKey)
|
|
{
|
|
DWORD dwRet;
|
|
DWORD dwCreate;
|
|
HKEY hSubtypeKey = NULL;
|
|
|
|
// Open SubType key //
|
|
if (PST_E_OK != (dwRet =
|
|
GetPSTSubtypeHKEY(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
&hSubtypeKey)) )
|
|
goto Ret;
|
|
|
|
// Open name key //
|
|
if (ERROR_SUCCESS !=
|
|
RegOpenKeyExU(
|
|
hSubtypeKey,
|
|
szItemName,
|
|
0,
|
|
KEY_READ | KEY_WRITE,
|
|
phItemKey))
|
|
{
|
|
dwRet = (DWORD)PST_E_ITEM_NO_EXISTS;
|
|
goto Ret;
|
|
}
|
|
|
|
dwRet = PST_E_OK;
|
|
Ret:
|
|
if (hSubtypeKey)
|
|
RegCloseKey(hSubtypeKey);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
// end PRIMITIVES
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
// PICKLE routines
|
|
|
|
#if 0
|
|
|
|
BOOL FAccessRulesPickle(
|
|
PST_ACCESSRULESET *psRules,
|
|
PBYTE* ppbPickled,
|
|
DWORD* pcbPickled)
|
|
{
|
|
BOOL fRet = FALSE;
|
|
DWORD cbTotal = 0;
|
|
DWORD dwRule;
|
|
|
|
// ease-of-use write pointer
|
|
PBYTE pbCurrentWrite;
|
|
|
|
// init out params
|
|
*ppbPickled = NULL;
|
|
*pcbPickled = 0;
|
|
|
|
// ASSERT new size member was initialized
|
|
SS_ASSERT(psRules->cbSize == sizeof(PST_ACCESSRULESET));
|
|
if (psRules->cbSize != sizeof(PST_ACCESSRULESET))
|
|
goto Ret;
|
|
|
|
cbTotal += sizeof(DWORD); // Ruleset struct versioning
|
|
|
|
cbTotal += sizeof(DWORD); // # Rules in Ruleset
|
|
|
|
// walk through each Rule in Ruleset
|
|
for (dwRule=0; dwRule<psRules->cRules; dwRule++)
|
|
{
|
|
DWORD cClause;
|
|
|
|
// ASSERT new size member was initialized
|
|
SS_ASSERT(psRules->rgRules[dwRule].cbSize == sizeof(PST_ACCESSRULE));
|
|
if (psRules->rgRules[dwRule].cbSize != sizeof(PST_ACCESSRULE))
|
|
goto Ret;
|
|
|
|
cbTotal += sizeof(DWORD); // Rule struct versioning
|
|
|
|
cbTotal += sizeof(PST_ACCESSMODE); // mode in each Rule
|
|
cbTotal += sizeof(DWORD); // # Clauses in Rule
|
|
|
|
// for each Rule, we'll have array of clauses
|
|
for (cClause=0; cClause<psRules->rgRules[dwRule].cClauses; cClause++)
|
|
{
|
|
// ASSERT new size member was initialized
|
|
SS_ASSERT(psRules->rgRules[dwRule].rgClauses[cClause].cbSize == sizeof(PST_ACCESSCLAUSE));
|
|
if (psRules->rgRules[dwRule].rgClauses[cClause].cbSize != sizeof(PST_ACCESSCLAUSE))
|
|
goto Ret;
|
|
|
|
cbTotal += sizeof(DWORD); // Clause struct versioning
|
|
|
|
// we'll see every clause here
|
|
cbTotal += sizeof(PST_ACCESSCLAUSETYPE); // type in each clause
|
|
cbTotal += sizeof(DWORD); // # bytes in clause buffer
|
|
cbTotal += psRules->rgRules[dwRule].rgClauses[cClause].cbClauseData; // buffer itself
|
|
}
|
|
}
|
|
|
|
*ppbPickled = (BYTE*)SSAlloc(cbTotal);
|
|
if(*ppbPickled == NULL)
|
|
goto Ret;
|
|
|
|
pbCurrentWrite = *ppbPickled;
|
|
|
|
*pcbPickled = cbTotal;
|
|
|
|
|
|
// copy Ruleset struct version
|
|
*(DWORD*)pbCurrentWrite = psRules->cbSize;
|
|
pbCurrentWrite += sizeof(DWORD);
|
|
|
|
// copy # rules in ruleset
|
|
*(DWORD*)pbCurrentWrite = psRules->cRules;
|
|
pbCurrentWrite += sizeof(DWORD);
|
|
|
|
// walk through each Rule in Ruleset
|
|
for (dwRule=0; dwRule<psRules->cRules; dwRule++)
|
|
{
|
|
// copy Rule struct version
|
|
*(DWORD*)pbCurrentWrite = psRules->rgRules[dwRule].cbSize;
|
|
pbCurrentWrite += sizeof(DWORD);
|
|
|
|
// copy # clauses in rule
|
|
*(DWORD*)pbCurrentWrite = psRules->rgRules[dwRule].cClauses;
|
|
pbCurrentWrite += sizeof(DWORD);
|
|
|
|
// copy rule accessmode
|
|
CopyMemory(pbCurrentWrite, &psRules->rgRules[dwRule].AccessModeFlags, sizeof(PST_ACCESSMODE));
|
|
pbCurrentWrite += sizeof(PST_ACCESSMODE);
|
|
|
|
// now for each Rule, we'll have array of clauses
|
|
for (DWORD cClause=0; cClause<psRules->rgRules[dwRule].cClauses; cClause++)
|
|
{
|
|
PST_ACCESSCLAUSE* pTmp = &psRules->rgRules[dwRule].rgClauses[cClause];
|
|
|
|
// copy clause struct version
|
|
*(DWORD*)pbCurrentWrite = pTmp->cbSize;
|
|
pbCurrentWrite += sizeof(DWORD);
|
|
|
|
// clause type
|
|
CopyMemory(pbCurrentWrite, &pTmp->ClauseType, sizeof(PST_ACCESSCLAUSETYPE));
|
|
pbCurrentWrite += sizeof(PST_ACCESSCLAUSETYPE);
|
|
|
|
// clause data buffer len
|
|
*(DWORD*)pbCurrentWrite = pTmp->cbClauseData;
|
|
pbCurrentWrite += sizeof(DWORD);
|
|
|
|
// buffer itself
|
|
CopyMemory(pbCurrentWrite, pTmp->pbClauseData, pTmp->cbClauseData);
|
|
pbCurrentWrite += pTmp->cbClauseData;
|
|
}
|
|
}
|
|
|
|
#if DBG
|
|
{
|
|
// ASSERT!
|
|
DWORD dwWroteBytes = (DWORD) (((DWORD_PTR)pbCurrentWrite) - ((DWORD_PTR)*ppbPickled));
|
|
SS_ASSERT(dwWroteBytes == cbTotal);
|
|
SS_ASSERT(cbTotal == *pcbPickled);
|
|
}
|
|
#endif
|
|
|
|
|
|
fRet = TRUE;
|
|
Ret:
|
|
|
|
// on error and alloc, free
|
|
if ((!fRet) && (*ppbPickled != NULL))
|
|
{
|
|
SSFree(*ppbPickled);
|
|
*ppbPickled = NULL;
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
|
|
BOOL FAccessRulesUnPickle(
|
|
PPST_ACCESSRULESET psRules, // out
|
|
PBYTE pbPickled,
|
|
DWORD cbPickled)
|
|
{
|
|
BOOL fRet = FALSE;
|
|
|
|
PBYTE pbCurrentRead = pbPickled;
|
|
DWORD cRule;
|
|
|
|
// Ruleset struct version
|
|
psRules->cbSize = *(DWORD*)pbCurrentRead;
|
|
pbCurrentRead += sizeof(DWORD);
|
|
|
|
// currently only one version known
|
|
if (psRules->cbSize != sizeof(PST_ACCESSRULESET))
|
|
goto Ret;
|
|
|
|
// get # rules in ruleset
|
|
cRule = *(DWORD*)pbCurrentRead;
|
|
pbCurrentRead += sizeof(DWORD);
|
|
|
|
// now we know how many Rule in Ruleset
|
|
psRules->rgRules = (PST_ACCESSRULE*)SSAlloc(sizeof(PST_ACCESSRULE)*cRule);
|
|
if(psRules->rgRules == NULL)
|
|
goto Ret;
|
|
|
|
psRules->cRules = cRule;
|
|
|
|
// now unpack each Rule
|
|
for (cRule=0; cRule<psRules->cRules; cRule++)
|
|
{
|
|
DWORD cClauses;
|
|
|
|
// Ruleset struct version
|
|
psRules->rgRules[cRule].cbSize = *(DWORD*)pbCurrentRead;
|
|
// currently only one version known
|
|
if (psRules->rgRules[cRule].cbSize != sizeof(PST_ACCESSRULE))
|
|
goto Ret;
|
|
|
|
pbCurrentRead += sizeof(DWORD);
|
|
|
|
// get # clauses in rule
|
|
cClauses = *(DWORD*)pbCurrentRead;
|
|
pbCurrentRead += sizeof(DWORD);
|
|
|
|
// now we know how many Clauses in Rule
|
|
psRules->rgRules[cRule].rgClauses = (PST_ACCESSCLAUSE*)SSAlloc(sizeof(PST_ACCESSCLAUSE)*cClauses);
|
|
if (psRules->rgRules[cRule].rgClauses == NULL) // check allocation
|
|
goto Ret;
|
|
psRules->rgRules[cRule].cClauses = cClauses;
|
|
|
|
// copy rule accessmode flags
|
|
CopyMemory(&psRules->rgRules[cRule].AccessModeFlags, pbCurrentRead, sizeof(PST_ACCESSMODE));
|
|
pbCurrentRead += sizeof(PST_ACCESSMODE);
|
|
|
|
// now load each Clause
|
|
for (DWORD cClause=0; cClause<psRules->rgRules[cRule].cClauses; cClause++)
|
|
{
|
|
PST_ACCESSCLAUSE* pTmp = &psRules->rgRules[cRule].rgClauses[cClause];
|
|
|
|
// Clause struct version
|
|
pTmp->cbSize = *(DWORD*)pbCurrentRead;
|
|
// currently only one version known
|
|
if (pTmp->cbSize != sizeof(PST_ACCESSCLAUSE))
|
|
goto Ret;
|
|
pbCurrentRead += sizeof(DWORD);
|
|
|
|
|
|
CopyMemory(&pTmp->ClauseType, pbCurrentRead, sizeof(PST_ACCESSCLAUSETYPE));
|
|
pbCurrentRead += sizeof(PST_ACCESSCLAUSETYPE);
|
|
|
|
// clause data buffer len
|
|
pTmp->cbClauseData = *(DWORD*)pbCurrentRead;
|
|
pbCurrentRead += sizeof(DWORD);
|
|
|
|
// buffer itself
|
|
pTmp->pbClauseData = (PBYTE) SSAlloc(pTmp->cbClauseData);
|
|
if (pTmp->pbClauseData == NULL) // check allocation
|
|
goto Ret;
|
|
CopyMemory(pTmp->pbClauseData, pbCurrentRead, pTmp->cbClauseData);
|
|
pbCurrentRead += pTmp->cbClauseData;
|
|
}
|
|
}
|
|
|
|
#if DBG
|
|
{
|
|
// ASSERT!
|
|
DWORD dwReadBytes = (DWORD) (((DWORD_PTR)pbCurrentRead) - ((DWORD_PTR)pbPickled));
|
|
SS_ASSERT(dwReadBytes == cbPickled);
|
|
}
|
|
#endif
|
|
|
|
fRet = TRUE;
|
|
Ret:
|
|
if (!fRet)
|
|
FreeRuleset(psRules);
|
|
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
// end PICKLE routines
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
// TYPE management
|
|
|
|
DWORD BPCreateType(
|
|
LPCWSTR szUser, // in
|
|
const GUID* pguidType, // in
|
|
PST_TYPEINFO* pinfoType) // in
|
|
{
|
|
DWORD dwRet;
|
|
BOOL fExisted;
|
|
HKEY hKey = NULL;
|
|
|
|
// now we need to create entries in hierarchy
|
|
if (PST_E_OK != (dwRet =
|
|
CreatePSTTypeHKEY(
|
|
szUser,
|
|
pguidType,
|
|
&hKey,
|
|
&fExisted)) )
|
|
goto Ret;
|
|
|
|
// if we didn't create it, setting is an error
|
|
if (fExisted)
|
|
{
|
|
dwRet = (DWORD)PST_E_TYPE_EXISTS;
|
|
goto Ret;
|
|
}
|
|
|
|
if (ERROR_SUCCESS != (dwRet =
|
|
RegSetValueExU(
|
|
hKey,
|
|
REG_DISPLAYSTRING_VALNAME,
|
|
0,
|
|
REG_SZ,
|
|
(PBYTE)pinfoType->szDisplayName,
|
|
WSZ_BYTECOUNT(pinfoType->szDisplayName))) )
|
|
goto Ret;
|
|
|
|
|
|
dwRet = (DWORD)PST_E_OK;
|
|
Ret:
|
|
if (hKey)
|
|
RegCloseKey(hKey);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
DWORD BPDeleteType(
|
|
LPCWSTR szUser, // in
|
|
const GUID* pguidType) // in
|
|
{
|
|
DWORD dwRet;
|
|
CHAR rgszTypeGuid[MAX_GUID_SZ_CHARS];
|
|
|
|
// now remove the entry in hierarchy
|
|
HKEY hBaseKey = NULL;
|
|
HKEY hDataKey = NULL;
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
GetPSTUserHKEY(
|
|
szUser,
|
|
&hBaseKey,
|
|
NULL)) )
|
|
goto Ret;
|
|
|
|
// Open Data Key //
|
|
if (ERROR_SUCCESS != (dwRet =
|
|
RegOpenKeyExU(
|
|
hBaseKey,
|
|
REG_DATA_LOC,
|
|
0,
|
|
KEY_READ | KEY_WRITE,
|
|
&hDataKey)) )
|
|
goto Ret;
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
MyGuidToStringA(
|
|
pguidType,
|
|
rgszTypeGuid)) )
|
|
goto Ret;
|
|
|
|
if (!FIsWinNT())
|
|
{
|
|
CHAR rgszTmp[MAX_GUID_SZ_CHARS];
|
|
DWORD cbTmp = MAX_GUID_SZ_CHARS;
|
|
FILETIME ft;
|
|
HKEY hTestEmptyKey = NULL;
|
|
|
|
// open the type
|
|
if (ERROR_SUCCESS != (dwRet =
|
|
RegOpenKeyExA(
|
|
hDataKey,
|
|
rgszTypeGuid,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&hTestEmptyKey)) )
|
|
goto Ret;
|
|
|
|
// check for emptiness
|
|
if (ERROR_NO_MORE_ITEMS !=
|
|
RegEnumKeyExA(
|
|
hTestEmptyKey,
|
|
0,
|
|
rgszTmp, // address of buffer for subkey name
|
|
&cbTmp, // address for size of subkey buffer
|
|
NULL, // reserved
|
|
NULL, // pbclass
|
|
NULL, // cbclass
|
|
&ft))
|
|
{
|
|
RegCloseKey(hTestEmptyKey);
|
|
dwRet = (DWORD)PST_E_NOTEMPTY;
|
|
goto Ret;
|
|
}
|
|
|
|
// close key before deletion
|
|
RegCloseKey(hTestEmptyKey);
|
|
}
|
|
|
|
// now, remove the friendly name
|
|
if (ERROR_SUCCESS != (dwRet =
|
|
RegDeleteKeyA(
|
|
hDataKey,
|
|
rgszTypeGuid)) )
|
|
{
|
|
if (dwRet == ERROR_ACCESS_DENIED)
|
|
dwRet = (DWORD)PST_E_NOTEMPTY;
|
|
|
|
goto Ret;
|
|
}
|
|
|
|
dwRet = (DWORD)PST_E_OK;
|
|
Ret:
|
|
if (hBaseKey)
|
|
RegCloseKey(hBaseKey);
|
|
|
|
if (hDataKey)
|
|
RegCloseKey(hDataKey);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
DWORD BPEnumTypes(
|
|
LPCWSTR szUser, // in
|
|
DWORD dwIndex, // in
|
|
GUID* pguidType) // out
|
|
{
|
|
DWORD dwRet;
|
|
|
|
CHAR rgszGuidType[MAX_GUID_SZ_CHARS];
|
|
DWORD cbName = MAX_GUID_SZ_CHARS;
|
|
|
|
FILETIME ft;
|
|
|
|
// now walk through types, returning them one by one
|
|
HKEY hKey=NULL, hDataKey=NULL;
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
GetPSTUserHKEY(
|
|
szUser,
|
|
&hKey,
|
|
NULL)) )
|
|
goto Ret;
|
|
|
|
// Open Data Key //
|
|
if (ERROR_SUCCESS != (dwRet =
|
|
RegOpenKeyExU(
|
|
hKey,
|
|
REG_DATA_LOC,
|
|
0,
|
|
KEY_READ | KEY_WRITE,
|
|
&hDataKey)) )
|
|
goto Ret;
|
|
|
|
// enum the dwIndex'th item, alloc & return
|
|
if (ERROR_SUCCESS != (dwRet =
|
|
RegEnumKeyExA(
|
|
hDataKey,
|
|
dwIndex,
|
|
rgszGuidType, // address of buffer for subkey name
|
|
&cbName, // address for size of subkey buffer
|
|
NULL, // reserved
|
|
NULL, // pbclass
|
|
NULL, // cbclass
|
|
&ft)) )
|
|
goto Ret;
|
|
|
|
if (ERROR_SUCCESS != (dwRet =
|
|
MyGuidFromStringA(
|
|
rgszGuidType,
|
|
pguidType)) )
|
|
goto Ret;
|
|
|
|
dwRet = (DWORD)PST_E_OK;
|
|
Ret:
|
|
if (hKey)
|
|
RegCloseKey(hKey);
|
|
|
|
if (hDataKey)
|
|
RegCloseKey(hDataKey);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
DWORD BPGetTypeName(
|
|
LPCWSTR szUser, // in
|
|
const GUID* pguidType, // in
|
|
LPWSTR* ppszType) // out
|
|
{
|
|
HKEY hKey = NULL;
|
|
DWORD cbName = 0;
|
|
DWORD dwRet;
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
GetPSTTypeHKEY(
|
|
szUser,
|
|
pguidType,
|
|
&hKey)) )
|
|
{
|
|
dwRet = (DWORD)PST_E_TYPE_NO_EXISTS;
|
|
goto Ret;
|
|
}
|
|
|
|
if (ERROR_SUCCESS != (dwRet =
|
|
RegGetStringValue(
|
|
hKey,
|
|
REG_DISPLAYSTRING_VALNAME,
|
|
(PBYTE*)ppszType,
|
|
&cbName)) )
|
|
goto Ret;
|
|
|
|
dwRet = (DWORD)PST_E_OK;
|
|
Ret:
|
|
if (hKey)
|
|
RegCloseKey(hKey);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
// end TYPE management
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
// SUBTYPE management
|
|
|
|
DWORD BPCreateSubtype(
|
|
LPCWSTR szUser, // in
|
|
const GUID* pguidType, // in
|
|
const GUID* pguidSubtype, // in
|
|
PST_TYPEINFO* pinfoSubtype) // in
|
|
{
|
|
DWORD dwRet;
|
|
BOOL fExisted;
|
|
|
|
// now we need to create entries in hierarchy
|
|
HKEY hKey = NULL;
|
|
if (PST_E_OK != (dwRet =
|
|
CreatePSTSubtypeHKEY(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
&hKey,
|
|
&fExisted)) )
|
|
goto Ret;
|
|
|
|
// if we didn't create it, setting is an error
|
|
if (fExisted)
|
|
{
|
|
dwRet = (DWORD)PST_E_TYPE_EXISTS;
|
|
goto Ret;
|
|
}
|
|
|
|
if (ERROR_SUCCESS != (dwRet =
|
|
RegSetValueExU(
|
|
hKey,
|
|
REG_DISPLAYSTRING_VALNAME,
|
|
0,
|
|
REG_SZ,
|
|
(PBYTE)pinfoSubtype->szDisplayName,
|
|
WSZ_BYTECOUNT(pinfoSubtype->szDisplayName) )) )
|
|
goto Ret;
|
|
|
|
dwRet = (DWORD)PST_E_OK;
|
|
Ret:
|
|
if (hKey)
|
|
RegCloseKey(hKey);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
DWORD BPDeleteSubtype(
|
|
LPCWSTR szUser, // in
|
|
const GUID* pguidType, // in
|
|
const GUID* pguidSubtype) // in
|
|
{
|
|
DWORD dwRet;
|
|
CHAR rgszSubtypeGuid[MAX_GUID_SZ_CHARS];
|
|
|
|
// now remove the entry in hierarchy
|
|
HKEY hKey = NULL;
|
|
if (PST_E_OK != (dwRet =
|
|
GetPSTTypeHKEY(
|
|
szUser,
|
|
pguidType,
|
|
&hKey)) )
|
|
{
|
|
dwRet = (DWORD)PST_E_TYPE_NO_EXISTS;
|
|
goto Ret;
|
|
}
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
MyGuidToStringA(
|
|
pguidSubtype,
|
|
rgszSubtypeGuid)) )
|
|
goto Ret;
|
|
|
|
if (!FIsWinNT())
|
|
{
|
|
CHAR rgszTmp[MAX_GUID_SZ_CHARS];
|
|
DWORD cbTmp = MAX_GUID_SZ_CHARS;
|
|
FILETIME ft;
|
|
HKEY hTestEmptyKey = NULL;
|
|
|
|
// open the subtype
|
|
if (ERROR_SUCCESS != (dwRet =
|
|
RegOpenKeyExA(
|
|
hKey,
|
|
rgszSubtypeGuid,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&hTestEmptyKey)) )
|
|
goto Ret;
|
|
|
|
// check for emptiness
|
|
if (ERROR_NO_MORE_ITEMS !=
|
|
RegEnumKeyExA(
|
|
hTestEmptyKey,
|
|
0,
|
|
rgszTmp, // address of buffer for subkey name
|
|
&cbTmp, // address for size of subkey buffer
|
|
NULL, // reserved
|
|
NULL, // pbclass
|
|
NULL, // cbclass
|
|
&ft))
|
|
{
|
|
RegCloseKey(hTestEmptyKey);
|
|
dwRet = (DWORD)PST_E_NOTEMPTY;
|
|
goto Ret;
|
|
}
|
|
|
|
// close key before deletion
|
|
RegCloseKey(hTestEmptyKey);
|
|
}
|
|
|
|
// now, remove the friendly name
|
|
if (ERROR_SUCCESS != (dwRet =
|
|
RegDeleteKeyA(
|
|
hKey,
|
|
rgszSubtypeGuid)) )
|
|
{
|
|
if (dwRet == ERROR_ACCESS_DENIED)
|
|
dwRet = (DWORD)PST_E_NOTEMPTY;
|
|
|
|
goto Ret;
|
|
}
|
|
|
|
dwRet = (DWORD)PST_E_OK;
|
|
Ret:
|
|
if (hKey)
|
|
RegCloseKey(hKey);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
DWORD BPEnumSubtypes(
|
|
LPCWSTR szUser, // in
|
|
DWORD dwIndex, // in
|
|
const GUID* pguidType, // in
|
|
GUID* pguidSubtype) // out
|
|
{
|
|
DWORD dwRet;
|
|
|
|
CHAR rgszGuidSubtype[MAX_GUID_SZ_CHARS];
|
|
DWORD cbName = MAX_GUID_SZ_CHARS;
|
|
|
|
FILETIME ft;
|
|
|
|
// now walk through types, returning them one by one
|
|
HKEY hTypeKey=NULL, hSubtypeKey=NULL;
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
GetPSTTypeHKEY(
|
|
szUser,
|
|
pguidType,
|
|
&hTypeKey)) )
|
|
goto Ret;
|
|
|
|
// enum the dwIndex'th item, alloc & return
|
|
if (ERROR_SUCCESS != (dwRet =
|
|
RegEnumKeyExA(
|
|
hTypeKey,
|
|
dwIndex,
|
|
rgszGuidSubtype, // address of buffer for subkey name
|
|
&cbName, // address for size of subkey buffer
|
|
NULL, // reserved
|
|
NULL, // pbclass
|
|
NULL, // cbclass
|
|
&ft)) )
|
|
goto Ret;
|
|
|
|
if (ERROR_SUCCESS != (dwRet =
|
|
MyGuidFromStringA(
|
|
rgszGuidSubtype,
|
|
pguidSubtype)) )
|
|
goto Ret;
|
|
|
|
if (ERROR_SUCCESS != (dwRet =
|
|
RegOpenKeyExA(
|
|
hTypeKey,
|
|
rgszGuidSubtype,
|
|
0,
|
|
KEY_READ | KEY_WRITE,
|
|
&hSubtypeKey)) )
|
|
goto Ret;
|
|
|
|
dwRet = (DWORD)PST_E_OK;
|
|
Ret:
|
|
if (hTypeKey)
|
|
RegCloseKey(hTypeKey);
|
|
|
|
if (hSubtypeKey)
|
|
RegCloseKey(hSubtypeKey);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
DWORD BPGetSubtypeName(
|
|
LPCWSTR szUser, // in
|
|
const GUID* pguidType, // in
|
|
const GUID* pguidSubtype, // in
|
|
LPWSTR* ppszSubtype) // out
|
|
{
|
|
HKEY hKey = NULL;
|
|
DWORD cbName = 0;
|
|
DWORD dwRet;
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
GetPSTSubtypeHKEY(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
&hKey)) )
|
|
goto Ret;
|
|
|
|
if (ERROR_SUCCESS != (dwRet =
|
|
RegGetStringValue(
|
|
hKey,
|
|
REG_DISPLAYSTRING_VALNAME,
|
|
(PBYTE*)ppszSubtype,
|
|
&cbName)) )
|
|
goto Ret;
|
|
|
|
dwRet = (DWORD)PST_E_OK;
|
|
Ret:
|
|
if (hKey)
|
|
RegCloseKey(hKey);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
// end SUBTYPE management
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
// ITEM management
|
|
|
|
// given uuid, push entries into storage
|
|
DWORD BPCreateItem(
|
|
LPCWSTR szUser, // in
|
|
const GUID* pguidType, // in
|
|
const GUID* pguidSubtype, // in
|
|
LPCWSTR szItemName) // in
|
|
{
|
|
DWORD dwRet;
|
|
BOOL fExisted;
|
|
HKEY hKey = NULL;
|
|
|
|
|
|
//
|
|
// mattt 2/5/97: allow items with \ in them to be created. Urgh!
|
|
//
|
|
// mattt 4/28/97: begin restricting strings.
|
|
// Cert request code has been changed to not create this type of key name
|
|
//
|
|
/*
|
|
if (!FStringIsValidItemName(szItemName))
|
|
{
|
|
dwRet = (DWORD)PST_E_INVALID_STRING;
|
|
goto Ret;
|
|
}
|
|
*/
|
|
// now we need to create entries in hierarchy
|
|
if (PST_E_OK != (dwRet =
|
|
CreatePSTItemHKEY(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
szItemName,
|
|
&hKey,
|
|
&fExisted)) )
|
|
goto Ret;
|
|
|
|
if (fExisted)
|
|
{
|
|
dwRet = (DWORD)PST_E_ITEM_EXISTS;
|
|
goto Ret;
|
|
}
|
|
|
|
dwRet = (DWORD)PST_E_OK;
|
|
Ret:
|
|
if (hKey)
|
|
RegCloseKey(hKey);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
|
|
DWORD BPDeleteItem(
|
|
LPCWSTR szUser, // in
|
|
const GUID* pguidType, // in
|
|
const GUID* pguidSubtype, // in
|
|
LPCWSTR szItemName) // in
|
|
{
|
|
DWORD dwRet;
|
|
HKEY hSubTypeKey = NULL;
|
|
|
|
// now we need to remove entries in hierarchy
|
|
if (PST_E_OK != (dwRet =
|
|
GetPSTSubtypeHKEY(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
&hSubTypeKey)) )
|
|
goto Ret;
|
|
|
|
// now, remove the friendly name
|
|
if (ERROR_SUCCESS != (dwRet =
|
|
RegDeleteKeyU(
|
|
hSubTypeKey,
|
|
szItemName)) )
|
|
goto Ret;
|
|
|
|
dwRet = (DWORD)PST_E_OK;
|
|
Ret:
|
|
if (hSubTypeKey)
|
|
RegCloseKey(hSubTypeKey);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
// Warning: Item path must be fully specified.. szName returned
|
|
DWORD BPEnumItems(
|
|
LPCWSTR szUser, // in
|
|
const GUID* pguidType, // in
|
|
const GUID* pguidSubtype, // in
|
|
DWORD dwIndex, // in
|
|
LPWSTR* ppszName) // out
|
|
{
|
|
DWORD dwRet;
|
|
|
|
WCHAR szName[MAX_PATH];
|
|
DWORD cchName = MAX_PATH;
|
|
FILETIME ft;
|
|
|
|
// now walk through types, returning them one by one
|
|
HKEY hKey = NULL;
|
|
|
|
// Open SubType key //
|
|
if (PST_E_OK != (dwRet =
|
|
GetPSTSubtypeHKEY(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
&hKey)) )
|
|
goto Ret;
|
|
|
|
// enum the dwIndex'th item, alloc & return
|
|
if (ERROR_SUCCESS != (dwRet =
|
|
RegEnumKeyExU(
|
|
hKey,
|
|
dwIndex,
|
|
szName, // address of buffer for subkey name
|
|
&cchName, // address for size of subkey buffer
|
|
NULL, // reserved
|
|
NULL, // pbclass
|
|
NULL, // cbclass
|
|
&ft)) )
|
|
goto Ret;
|
|
|
|
*ppszName = (LPWSTR)SSAlloc((cchName+1)*sizeof(WCHAR));
|
|
if(*ppszName == NULL)
|
|
{
|
|
dwRet = (DWORD)PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
|
|
wcscpy(*ppszName, szName);
|
|
|
|
dwRet = (DWORD)PST_E_OK;
|
|
Ret:
|
|
if (hKey)
|
|
RegCloseKey(hKey);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
// end ITEM management
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
// SECURED DATA
|
|
|
|
BOOL FBPGetSecuredItemData(
|
|
LPCWSTR szUser, // in
|
|
LPCWSTR szMasterKey, // in
|
|
BYTE rgbPwd[A_SHA_DIGEST_LEN], // in
|
|
const GUID* pguidType, // in
|
|
const GUID* pguidSubtype, // in
|
|
LPCWSTR szItemName, // in
|
|
PBYTE* ppbData, // out
|
|
DWORD* pcbData) // out
|
|
{
|
|
DWORD dwRet;
|
|
|
|
*ppbData = NULL; // on err return NULL
|
|
*pcbData = 0;
|
|
|
|
HKEY hItemKey = NULL;
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
GetPSTItemHKEY(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
szItemName,
|
|
&hItemKey)) )
|
|
goto Ret;
|
|
|
|
// Version | Key Block | Secure Data [...]
|
|
if (ERROR_SUCCESS != (dwRet =
|
|
RegGetValue(
|
|
hItemKey,
|
|
REG_ITEM_SECURE_DATA_VALNAME,
|
|
ppbData,
|
|
pcbData)) )
|
|
goto Ret;
|
|
|
|
if (!FProvDecryptData(
|
|
szUser,
|
|
szMasterKey,
|
|
rgbPwd, // in
|
|
ppbData, // in out
|
|
pcbData)) // in out
|
|
{
|
|
dwRet = (DWORD)PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
|
|
dwRet = PST_E_OK;
|
|
Ret:
|
|
if ((dwRet != PST_E_OK) && (*ppbData != NULL))
|
|
{
|
|
SSFree(*ppbData);
|
|
*ppbData = NULL;
|
|
*pcbData = 0;
|
|
}
|
|
|
|
if (hItemKey)
|
|
RegCloseKey(hItemKey);
|
|
|
|
return (dwRet == PST_E_OK);
|
|
}
|
|
|
|
BOOL FBPSetSecuredItemData(
|
|
LPCWSTR szUser, // in
|
|
LPCWSTR szMasterKey, // in
|
|
BYTE rgbPwd[A_SHA_DIGEST_LEN], // in
|
|
const GUID* pguidType, // in
|
|
const GUID* pguidSubtype, // in
|
|
LPCWSTR szItemName, // in
|
|
PBYTE pbData, // in
|
|
DWORD cbData) // in
|
|
{
|
|
#define REALLOC_FUDGESIZE 96 // 5dw + SHA_LEN + KeyBlock + DES_BLOCKLEN (block encr expansion)
|
|
|
|
DWORD dwRet;
|
|
|
|
HKEY hItemKey = NULL;
|
|
|
|
PBYTE pbMyData = NULL;
|
|
DWORD cbMyData;
|
|
|
|
// make whackable copy
|
|
cbMyData = cbData;
|
|
pbMyData = (PBYTE)SSAlloc(cbMyData + REALLOC_FUDGESIZE);
|
|
if (pbMyData == NULL)
|
|
{
|
|
dwRet = (DWORD)PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
|
|
CopyMemory(pbMyData, pbData, cbData);
|
|
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
GetPSTItemHKEY(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
szItemName,
|
|
&hItemKey)) )
|
|
goto Ret;
|
|
|
|
if (!FProvEncryptData(
|
|
szUser,
|
|
szMasterKey,
|
|
rgbPwd, // in
|
|
&pbMyData, // in out
|
|
&cbMyData)) // in out
|
|
{
|
|
dwRet = (DWORD)PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
|
|
if (ERROR_SUCCESS != (dwRet =
|
|
RegSetValueExU(
|
|
hItemKey,
|
|
REG_ITEM_SECURE_DATA_VALNAME,
|
|
0,
|
|
REG_BINARY,
|
|
pbMyData,
|
|
cbMyData)) )
|
|
goto Ret;
|
|
|
|
dwRet = PST_E_OK;
|
|
Ret:
|
|
if (hItemKey)
|
|
RegCloseKey(hItemKey);
|
|
|
|
if (pbMyData)
|
|
SSFree(pbMyData);
|
|
|
|
return (dwRet == PST_E_OK);
|
|
}
|
|
|
|
// end SECURED DATA
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
// INSECURE DATA
|
|
|
|
DWORD BPGetInsecureItemData(
|
|
LPCWSTR szUser, // in
|
|
const GUID* pguidType, // in
|
|
const GUID* pguidSubtype, // in
|
|
LPCWSTR szItemName, // in
|
|
PBYTE* ppbData, // out
|
|
DWORD* pcbData) // out
|
|
{
|
|
DWORD dwRet;
|
|
*ppbData = NULL;
|
|
|
|
HKEY hItemKey = NULL;
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
GetPSTItemHKEY(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
szItemName,
|
|
&hItemKey)) )
|
|
goto Ret;
|
|
|
|
if (ERROR_SUCCESS != (dwRet =
|
|
RegGetValue(
|
|
hItemKey,
|
|
REG_ITEM_INSECURE_DATA_VALNAME,
|
|
ppbData,
|
|
pcbData)) )
|
|
goto Ret;
|
|
|
|
dwRet = PST_E_OK;
|
|
Ret:
|
|
|
|
if (hItemKey)
|
|
RegCloseKey(hItemKey);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
DWORD BPSetInsecureItemData(
|
|
LPCWSTR szUser, // in
|
|
const GUID* pguidType, // in
|
|
const GUID* pguidSubtype, // in
|
|
LPCWSTR szItemName, // in
|
|
PBYTE pbData, // in
|
|
DWORD cbData) // in
|
|
{
|
|
DWORD dwRet;
|
|
|
|
HKEY hItemKey = NULL;
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
GetPSTItemHKEY(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
szItemName,
|
|
&hItemKey)) )
|
|
goto Ret;
|
|
|
|
if (ERROR_SUCCESS != (dwRet =
|
|
RegSetValueExU(
|
|
hItemKey,
|
|
REG_ITEM_INSECURE_DATA_VALNAME,
|
|
0,
|
|
REG_BINARY,
|
|
pbData,
|
|
cbData)) )
|
|
goto Ret;
|
|
|
|
dwRet = PST_E_OK;
|
|
Ret:
|
|
if (hItemKey)
|
|
RegCloseKey(hItemKey);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
// end INSECURE DATA
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
// RULESETS
|
|
|
|
// #define RULESET_VERSION 0x1
|
|
// 6-12-97 incremented version; version 0x1 contains old HMAC
|
|
#define RULESET_VERSION 0x2
|
|
|
|
|
|
#if 0
|
|
|
|
DWORD BPGetSubtypeRuleset(
|
|
PST_PROVIDER_HANDLE* phPSTProv, // in
|
|
LPCWSTR szUser, // in
|
|
const GUID* pguidType, // in
|
|
const GUID* pguidSubtype, // in
|
|
PST_ACCESSRULESET* psRules) // out
|
|
{
|
|
DWORD dwRet;
|
|
HKEY hSubtypeKey = NULL;
|
|
|
|
BYTE rgbHMAC[A_SHA_DIGEST_LEN];
|
|
BYTE rgbPwd[A_SHA_DIGEST_LEN];
|
|
|
|
PBYTE pbBuf = NULL;
|
|
DWORD cbBuf;
|
|
|
|
PBYTE pbCurrent;
|
|
DWORD cbRuleSize;
|
|
PBYTE pbRuleSet;
|
|
|
|
DWORD dwVersion;
|
|
|
|
// Open Subtype //
|
|
if (PST_E_OK != (dwRet =
|
|
GetPSTSubtypeHKEY(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
&hSubtypeKey)) )
|
|
goto Ret;
|
|
|
|
if (ERROR_SUCCESS != (dwRet =
|
|
RegGetValue(
|
|
hSubtypeKey,
|
|
REG_ACCESSRULE_LOC,
|
|
&pbBuf,
|
|
&cbBuf)) )
|
|
goto Ret;
|
|
|
|
|
|
// RULESET DATA FORMAT:
|
|
// version | size(ruleset) | ruleset | size(MAC) | MAC {of type, subtype, ruleset}
|
|
pbCurrent = pbBuf;
|
|
|
|
if( cbBuf < (sizeof(DWORD)*2) ) {
|
|
dwRet = (DWORD)PST_E_INVALID_RULESET;
|
|
goto Ret;
|
|
}
|
|
|
|
// version check
|
|
dwVersion = *(DWORD*)pbCurrent;
|
|
if (dwVersion > RULESET_VERSION)
|
|
{
|
|
dwRet = (DWORD)PST_E_INVALID_RULESET;
|
|
goto Ret;
|
|
}
|
|
|
|
pbCurrent += sizeof(DWORD);
|
|
|
|
|
|
cbRuleSize = *(DWORD*)pbCurrent;
|
|
|
|
// get WinPW
|
|
if (PST_E_OK !=
|
|
BPVerifyPwd(
|
|
phPSTProv,
|
|
szUser,
|
|
WSZ_PASSWORD_WINDOWS,
|
|
rgbPwd,
|
|
BP_CONFIRM_NONE))
|
|
{
|
|
dwRet = (DWORD)PST_E_WRONG_PASSWORD;
|
|
goto Ret;
|
|
}
|
|
|
|
// check MAC
|
|
|
|
// Compute Geographically sensitive (can't move) HMAC on { size(ruleset), ruleset }
|
|
if (!FHMACGeographicallySensitiveData(
|
|
szUser,
|
|
WSZ_PASSWORD_WINDOWS,
|
|
(dwVersion == 0x01) ? OLD_HMAC_VERSION : NEW_HMAC_VERSION,
|
|
rgbPwd,
|
|
pguidType,
|
|
pguidSubtype,
|
|
NULL,
|
|
pbCurrent,
|
|
cbRuleSize + sizeof(DWORD), // include the rulesize
|
|
rgbHMAC))
|
|
{
|
|
dwRet = (DWORD)PST_E_INVALID_RULESET;
|
|
goto Ret;
|
|
}
|
|
|
|
pbCurrent += sizeof(DWORD); // skip past cbRuleSize (already snarfed)
|
|
pbRuleSet = pbCurrent; // point to rules
|
|
pbCurrent += cbRuleSize; // skip past rules
|
|
|
|
// check MAC len
|
|
if (*(DWORD*)pbCurrent != A_SHA_DIGEST_LEN)
|
|
{
|
|
dwRet = (DWORD)PST_E_INVALID_RULESET;
|
|
goto Ret;
|
|
}
|
|
pbCurrent += sizeof(DWORD); // skip past sizeof(MAC)
|
|
|
|
// check MAC
|
|
if (0 != memcmp(rgbHMAC, pbCurrent, A_SHA_DIGEST_LEN))
|
|
{
|
|
dwRet = (DWORD)PST_E_INVALID_RULESET;
|
|
goto Ret;
|
|
}
|
|
|
|
// MAC okay! shrink to rulesize
|
|
MoveMemory(pbBuf, pbRuleSet, cbRuleSize);
|
|
cbBuf = cbRuleSize;
|
|
pbBuf = (PBYTE)SSReAlloc(pbBuf, cbBuf);
|
|
if (pbBuf == NULL) // check allocation
|
|
{
|
|
dwRet = PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
|
|
|
|
// serialize rules out of the buffer
|
|
if (!FAccessRulesUnPickle(
|
|
psRules,
|
|
pbBuf,
|
|
cbBuf))
|
|
{
|
|
dwRet = (DWORD)PST_E_INVALID_RULESET;
|
|
goto Ret;
|
|
}
|
|
|
|
dwRet = (DWORD)PST_E_OK;
|
|
Ret:
|
|
if (pbBuf)
|
|
SSFree(pbBuf);
|
|
|
|
if (hSubtypeKey)
|
|
RegCloseKey(hSubtypeKey);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
|
|
|
|
DWORD BPSetSubtypeRuleset(
|
|
PST_PROVIDER_HANDLE* phPSTProv, // in
|
|
LPCWSTR szUser, // in
|
|
const GUID* pguidType, // in
|
|
const GUID* pguidSubtype, // in
|
|
PST_ACCESSRULESET *psRules) // in
|
|
{
|
|
DWORD dwRet;
|
|
HKEY hSubtypeKey = NULL;
|
|
|
|
BYTE rgbHMAC[A_SHA_DIGEST_LEN];
|
|
BYTE rgbPwd[A_SHA_DIGEST_LEN];
|
|
|
|
PBYTE pbBuf = NULL;
|
|
DWORD cbBuf;
|
|
|
|
PBYTE pbCurPtr;
|
|
DWORD cbNewSize;
|
|
|
|
// serialize rules into a buffer
|
|
if (!FAccessRulesPickle(
|
|
psRules,
|
|
&pbBuf,
|
|
&cbBuf))
|
|
{
|
|
dwRet = (DWORD)PST_E_INVALID_RULESET;
|
|
goto Ret;
|
|
}
|
|
|
|
// RULESET DATA FORMAT:
|
|
// version | size(ruleset) | ruleset | size(MAC) | Geographical MAC {size(ruleset), ruleset}
|
|
cbNewSize = cbBuf + 3*sizeof(DWORD) + A_SHA_DIGEST_LEN;
|
|
pbBuf = (PBYTE)SSReAlloc(pbBuf, cbNewSize);
|
|
if (pbBuf == NULL) // check allocation
|
|
{
|
|
dwRet = PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
MoveMemory(pbBuf + 2*sizeof(DWORD), pbBuf, cbBuf);
|
|
|
|
// helpful pointer
|
|
pbCurPtr = pbBuf;
|
|
|
|
// version
|
|
*(DWORD*)pbCurPtr = (DWORD)RULESET_VERSION;
|
|
pbCurPtr += sizeof(DWORD);
|
|
|
|
// size(ruleset)
|
|
*(DWORD*)pbCurPtr = (DWORD)cbBuf;
|
|
pbCurPtr += sizeof(DWORD);
|
|
|
|
// ruleset previously moved by MoveMemory call
|
|
pbCurPtr += cbBuf; // fwd past ruleset
|
|
|
|
// get WinPW
|
|
if (PST_E_OK !=
|
|
BPVerifyPwd(
|
|
phPSTProv,
|
|
szUser,
|
|
WSZ_PASSWORD_WINDOWS,
|
|
rgbPwd,
|
|
BP_CONFIRM_NONE))
|
|
{
|
|
dwRet = (DWORD)PST_E_WRONG_PASSWORD;
|
|
goto Ret;
|
|
}
|
|
|
|
// check MAC
|
|
// Compute Geographically sensitive (can't move) HMAC on { size(ruleset), ruleset }
|
|
if (!FHMACGeographicallySensitiveData(
|
|
szUser,
|
|
WSZ_PASSWORD_WINDOWS,
|
|
NEW_HMAC_VERSION,
|
|
rgbPwd,
|
|
pguidType,
|
|
pguidSubtype,
|
|
NULL,
|
|
pbBuf + sizeof(DWORD),
|
|
cbBuf + sizeof(DWORD),
|
|
rgbHMAC))
|
|
{
|
|
dwRet = (DWORD)PST_E_INVALID_RULESET;
|
|
goto Ret;
|
|
}
|
|
|
|
// HMAC size
|
|
*(DWORD*)pbCurPtr = (DWORD) sizeof(rgbHMAC);
|
|
pbCurPtr += sizeof(DWORD);
|
|
|
|
// HMAC
|
|
CopyMemory(pbCurPtr, rgbHMAC, sizeof(rgbHMAC));
|
|
|
|
// done; set cbBuf = new size
|
|
cbBuf = cbNewSize;
|
|
|
|
|
|
// Open Subtype //
|
|
if (PST_E_OK != (dwRet =
|
|
GetPSTSubtypeHKEY(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
&hSubtypeKey)) )
|
|
{
|
|
dwRet = (DWORD)PST_E_INVALID_RULESET;
|
|
goto Ret;
|
|
}
|
|
|
|
// now write item
|
|
if (ERROR_SUCCESS != (dwRet =
|
|
RegSetValueExU(
|
|
hSubtypeKey,
|
|
REG_ACCESSRULE_LOC,
|
|
0,
|
|
REG_BINARY,
|
|
pbBuf,
|
|
cbBuf)) )
|
|
{
|
|
dwRet = (DWORD)PST_E_INVALID_RULESET;
|
|
goto Ret;
|
|
}
|
|
|
|
dwRet = (DWORD)PST_E_OK;
|
|
Ret:
|
|
if (pbBuf)
|
|
SSFree(pbBuf);
|
|
|
|
if (hSubtypeKey)
|
|
RegCloseKey(hSubtypeKey);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
|
|
DWORD BPGetItemRuleset(
|
|
PST_PROVIDER_HANDLE* phPSTProv, // in
|
|
LPCWSTR szUser, // in
|
|
const GUID* pguidType, // in
|
|
const GUID* pguidSubtype, // in
|
|
LPCWSTR szItemName, // in
|
|
PST_ACCESSRULESET* psRules) // out
|
|
{
|
|
DWORD dwRet;
|
|
HKEY hItemKey = NULL;
|
|
|
|
PBYTE pbBuf = NULL;
|
|
DWORD cbBuf;
|
|
|
|
if (PST_E_OK != (dwRet =
|
|
GetPSTItemHKEY(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
szItemName,
|
|
&hItemKey)) )
|
|
goto Ret; // item doesn't exist -- ouch!!
|
|
|
|
if (ERROR_SUCCESS != (dwRet =
|
|
RegGetValue(
|
|
hItemKey,
|
|
REG_ACCESSRULE_LOC,
|
|
&pbBuf,
|
|
&cbBuf)) )
|
|
{
|
|
// item exists, rules don't
|
|
// fall back on subtype ruleset
|
|
if (PST_E_OK != (dwRet =
|
|
BPGetSubtypeRuleset(
|
|
phPSTProv,
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
psRules)) )
|
|
goto Ret;
|
|
}
|
|
else
|
|
{
|
|
// serialize rules into a buffer
|
|
if (!FAccessRulesUnPickle(
|
|
psRules,
|
|
pbBuf,
|
|
cbBuf))
|
|
{
|
|
dwRet = (DWORD)PST_E_INVALID_RULESET;
|
|
goto Ret;
|
|
}
|
|
}
|
|
|
|
dwRet = (DWORD)PST_E_OK;
|
|
Ret:
|
|
if (pbBuf)
|
|
SSFree(pbBuf);
|
|
|
|
if (hItemKey)
|
|
RegCloseKey(hItemKey);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
|
|
DWORD BPSetItemRuleset(
|
|
PST_PROVIDER_HANDLE* phPSTProv, // in
|
|
LPCWSTR szUser, // in
|
|
const GUID* pguidType, // in
|
|
const GUID* pguidSubtype, // in
|
|
LPCWSTR szItemName, // in
|
|
PST_ACCESSRULESET *psRules) // in
|
|
{
|
|
DWORD dwRet;
|
|
|
|
HKEY hItemKey = NULL;
|
|
|
|
PBYTE pbBuf = NULL;
|
|
DWORD cbBuf;
|
|
|
|
// serialize rules into a buffer
|
|
if (!FAccessRulesPickle(
|
|
psRules,
|
|
&pbBuf,
|
|
&cbBuf))
|
|
{
|
|
dwRet = (DWORD)PST_E_INVALID_RULESET;
|
|
goto Ret;
|
|
}
|
|
|
|
// Open Subtype //
|
|
if (PST_E_OK != (dwRet =
|
|
GetPSTItemHKEY(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
szItemName,
|
|
&hItemKey)) )
|
|
goto Ret;
|
|
|
|
// now write item
|
|
if (ERROR_SUCCESS != (dwRet =
|
|
RegSetValueExU(
|
|
hItemKey,
|
|
REG_ACCESSRULE_LOC,
|
|
0,
|
|
REG_BINARY,
|
|
pbBuf,
|
|
cbBuf)) )
|
|
goto Ret;
|
|
|
|
dwRet = (DWORD)PST_E_OK;
|
|
Ret:
|
|
if (pbBuf)
|
|
SSFree(pbBuf);
|
|
|
|
if (hItemKey)
|
|
RegCloseKey(hItemKey);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
#endif
|
|
|
|
// end RULESETS
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
// ITEM CONFIRM INFO
|
|
// #define CONFIRMATION_VERSION 0x01
|
|
// 6-12-97 incremented version: version 0x1 contains old HMAC
|
|
#define CONFIRMATION_VERSION 0x02
|
|
|
|
DWORD BPGetItemConfirm(
|
|
PST_PROVIDER_HANDLE* phPSTProv, // in
|
|
LPCWSTR szUser, // in
|
|
const GUID* pguidType, // in
|
|
const GUID* pguidSubtype, // in
|
|
LPCWSTR szItemName, // in
|
|
DWORD* pdwConfirm, // in
|
|
LPWSTR* pszMK) // in
|
|
{
|
|
DWORD dwRet;
|
|
HKEY hItemKey = NULL;
|
|
|
|
|
|
PBYTE pbBuf = NULL;
|
|
DWORD cbBuf = 0;
|
|
|
|
BYTE rgbHMAC[A_SHA_DIGEST_LEN];
|
|
BYTE rgbPwd[A_SHA_DIGEST_LEN];
|
|
|
|
// helpful pointers
|
|
PBYTE pbCurPtr = NULL;
|
|
|
|
PBYTE pbString;
|
|
DWORD cbString;
|
|
|
|
DWORD dwVersion;
|
|
|
|
// Open nonexistent item master key
|
|
if (PST_E_OK != (dwRet =
|
|
GetPSTItemHKEY(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
szItemName,
|
|
&hItemKey)) )
|
|
goto Ret;
|
|
|
|
if (ERROR_SUCCESS != (dwRet =
|
|
RegGetValue(
|
|
hItemKey,
|
|
REG_ITEM_MK_VALNAME,
|
|
&pbBuf,
|
|
&cbBuf)) )
|
|
goto Ret;
|
|
|
|
// Confirmation data format
|
|
// Version | dwConfirm | size(szMasterKey) | szMasterKey | size(MAC) | Geographical MAC { dwConfirm | size(szMasterKey) | szMasterKey }
|
|
|
|
// version check
|
|
dwVersion = *(DWORD*)pbBuf;
|
|
if (CONFIRMATION_VERSION < dwVersion)
|
|
{
|
|
dwRet = (DWORD)PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
pbCurPtr = pbBuf + sizeof(DWORD); // fwd past vers
|
|
|
|
|
|
// get WinPW
|
|
if (PST_E_OK !=
|
|
BPVerifyPwd(
|
|
phPSTProv,
|
|
szUser,
|
|
WSZ_PASSWORD_WINDOWS,
|
|
rgbPwd,
|
|
BP_CONFIRM_NONE))
|
|
{
|
|
dwRet = (DWORD)PST_E_WRONG_PASSWORD;
|
|
goto Ret;
|
|
}
|
|
|
|
// check MAC
|
|
// Compute Geographically sensitive (can't move) HMAC on { dwConfirm | size(szMasterKey) | szMasterKey }
|
|
if (!FHMACGeographicallySensitiveData(
|
|
szUser,
|
|
WSZ_PASSWORD_WINDOWS,
|
|
(dwVersion == 0x01) ? OLD_HMAC_VERSION : NEW_HMAC_VERSION,
|
|
rgbPwd,
|
|
pguidType,
|
|
pguidSubtype,
|
|
szItemName,
|
|
pbBuf + sizeof(DWORD), // fwd past Version
|
|
cbBuf - 2*sizeof(DWORD) - A_SHA_DIGEST_LEN, // Version, size(MAC), MAC
|
|
rgbHMAC))
|
|
{
|
|
dwRet = (DWORD)PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
|
|
// dwConfirm
|
|
*pdwConfirm = *(DWORD*)pbCurPtr; // dwConfirm
|
|
pbCurPtr += sizeof(DWORD); // fwd past dwConfirm
|
|
|
|
// szMasterKey
|
|
cbString = *(DWORD*)pbCurPtr; // strlen
|
|
pbCurPtr += sizeof(DWORD); // fwd past len
|
|
pbString = pbCurPtr; // save ptr to string
|
|
pbCurPtr += cbString; // skip string
|
|
|
|
if (*(DWORD*)pbCurPtr != A_SHA_DIGEST_LEN)
|
|
{
|
|
dwRet = (DWORD)PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
pbCurPtr += sizeof(DWORD);
|
|
|
|
if (0 != memcmp(pbCurPtr, rgbHMAC, A_SHA_DIGEST_LEN))
|
|
{
|
|
dwRet = (DWORD)PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
|
|
|
|
MoveMemory(pbBuf, pbString, cbString); // shift left string
|
|
pbCurPtr = (PBYTE)SSReAlloc(pbBuf, cbString); // shorten to strlen
|
|
if (pbCurPtr == NULL) // check allocation
|
|
{
|
|
dwRet = PST_E_FAIL;
|
|
if (pbBuf) {
|
|
SSFree(pbBuf);
|
|
pbBuf = NULL;
|
|
}
|
|
goto Ret;
|
|
}
|
|
|
|
pbBuf = pbCurPtr;
|
|
|
|
dwRet = (DWORD)PST_E_OK;
|
|
Ret:
|
|
*pszMK = (LPWSTR)pbBuf; // assign to out param
|
|
|
|
if (hItemKey)
|
|
RegCloseKey(hItemKey);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
DWORD BPSetItemConfirm(
|
|
PST_PROVIDER_HANDLE* phPSTProv, // in
|
|
LPCWSTR szUser, // in
|
|
const GUID* pguidType, // in
|
|
const GUID* pguidSubtype, // in
|
|
LPCWSTR szItemName, // in
|
|
DWORD dwConfirm, // in
|
|
LPCWSTR szMK) // in
|
|
{
|
|
DWORD dwRet;
|
|
HKEY hItemKey = NULL;
|
|
|
|
BYTE rgbHMAC[A_SHA_DIGEST_LEN];
|
|
BYTE rgbPwd[A_SHA_DIGEST_LEN];
|
|
|
|
// helpful pointer
|
|
PBYTE pbCurPtr;
|
|
|
|
// Confirmation data format
|
|
// Version | dwConfirm | size(szMasterKey) | szMasterKey | size(MAC) | Geographical MAC { dwConfirm | size(szMasterKey) | szMasterKey }
|
|
DWORD cbBuf = WSZ_BYTECOUNT(szMK)+ 4*sizeof(DWORD) + A_SHA_DIGEST_LEN;
|
|
PBYTE pbBuf = (PBYTE)SSAlloc(cbBuf);
|
|
if (pbBuf == NULL) // check allocation
|
|
{
|
|
dwRet = PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
|
|
pbCurPtr = pbBuf;
|
|
|
|
// version
|
|
*(DWORD*)pbCurPtr = (DWORD)CONFIRMATION_VERSION;
|
|
pbCurPtr += sizeof(DWORD);
|
|
|
|
// dwConfirm
|
|
*(DWORD*)pbCurPtr = dwConfirm;
|
|
pbCurPtr += sizeof(DWORD);
|
|
|
|
// szMasterKey size
|
|
*(DWORD*)pbCurPtr = (DWORD)WSZ_BYTECOUNT(szMK);
|
|
pbCurPtr += sizeof(DWORD);
|
|
|
|
// szMasterKey
|
|
wcscpy((LPWSTR)pbCurPtr, szMK);
|
|
pbCurPtr += WSZ_BYTECOUNT(szMK); // fwd past szMK
|
|
|
|
|
|
// get WinPW
|
|
if (PST_E_OK !=
|
|
BPVerifyPwd(
|
|
phPSTProv,
|
|
szUser,
|
|
WSZ_PASSWORD_WINDOWS,
|
|
rgbPwd,
|
|
BP_CONFIRM_NONE))
|
|
{
|
|
dwRet = (DWORD)PST_E_WRONG_PASSWORD;
|
|
goto Ret;
|
|
}
|
|
|
|
// check MAC
|
|
// Compute Geographically sensitive (can't move) HMAC on { dwConfirm | size(szMasterKey) | szMasterKey }
|
|
if (!FHMACGeographicallySensitiveData(
|
|
szUser,
|
|
WSZ_PASSWORD_WINDOWS,
|
|
NEW_HMAC_VERSION,
|
|
rgbPwd,
|
|
pguidType,
|
|
pguidSubtype,
|
|
szItemName,
|
|
pbBuf + sizeof(DWORD), // fwd past Version
|
|
cbBuf - 2*sizeof(DWORD) - A_SHA_DIGEST_LEN, // Version, size(MAC), MAC
|
|
rgbHMAC))
|
|
{
|
|
dwRet = (DWORD)PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
|
|
// HMAC size
|
|
*(DWORD*)pbCurPtr = (DWORD) sizeof(rgbHMAC);
|
|
pbCurPtr += sizeof(DWORD);
|
|
|
|
// HMAC
|
|
CopyMemory(pbCurPtr, rgbHMAC, sizeof(rgbHMAC));
|
|
|
|
|
|
// Open Item //
|
|
if (PST_E_OK != (dwRet =
|
|
GetPSTItemHKEY(
|
|
szUser,
|
|
pguidType,
|
|
pguidSubtype,
|
|
szItemName,
|
|
&hItemKey)) )
|
|
goto Ret;
|
|
|
|
// now write item
|
|
if (ERROR_SUCCESS != (dwRet =
|
|
RegSetValueExU(
|
|
hItemKey,
|
|
REG_ITEM_MK_VALNAME,
|
|
0,
|
|
REG_BINARY,
|
|
pbBuf,
|
|
cbBuf)) )
|
|
goto Ret;
|
|
|
|
dwRet = (DWORD)PST_E_OK;
|
|
Ret:
|
|
if (hItemKey)
|
|
RegCloseKey(hItemKey);
|
|
|
|
if (pbBuf)
|
|
SSFree(pbBuf);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
// ITEM CONFIRM INFO
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
// MASTER KEYS
|
|
BOOL BPMasterKeyExists(
|
|
LPCWSTR szUser, // in
|
|
LPWSTR szMasterKey) // in
|
|
{
|
|
BOOL fRet = FALSE;
|
|
HKEY hMyKey = NULL;
|
|
HKEY hMasterKey = NULL;
|
|
|
|
// Open Master parent key //
|
|
if (PST_E_OK !=
|
|
GetPSTMasterKeyHKEY(
|
|
szUser,
|
|
NULL,
|
|
&hMyKey))
|
|
goto Ret;
|
|
|
|
// attempt to open the master key location
|
|
if (ERROR_SUCCESS !=
|
|
RegOpenKeyExU(
|
|
hMyKey,
|
|
szMasterKey,
|
|
0,
|
|
KEY_QUERY_VALUE,
|
|
&hMasterKey))
|
|
goto Ret;
|
|
|
|
// key does exist
|
|
fRet = TRUE;
|
|
Ret:
|
|
if (hMyKey)
|
|
RegCloseKey(hMyKey);
|
|
|
|
if (hMasterKey)
|
|
RegCloseKey(hMasterKey);
|
|
|
|
return fRet;
|
|
}
|
|
|
|
DWORD BPEnumMasterKeys(
|
|
LPCWSTR szUser, // in
|
|
DWORD dwIndex, // in
|
|
LPWSTR* ppszMasterKey) // out
|
|
{
|
|
DWORD dwRet;
|
|
HKEY hMyKey = NULL;
|
|
|
|
WCHAR szName[MAX_PATH];
|
|
DWORD cchName = MAX_PATH;
|
|
FILETIME ft;
|
|
|
|
// Open Master parent key //
|
|
if (PST_E_OK != (dwRet =
|
|
GetPSTMasterKeyHKEY(
|
|
szUser,
|
|
NULL,
|
|
&hMyKey)) )
|
|
goto Ret;
|
|
|
|
// enum the dwIndex'th item, alloc & return
|
|
if (ERROR_SUCCESS != (dwRet =
|
|
RegEnumKeyExU(
|
|
hMyKey,
|
|
dwIndex,
|
|
szName, // address of buffer for subkey name
|
|
&cchName, // address for size of subkey buffer
|
|
NULL, // reserved
|
|
NULL, // pbclass
|
|
NULL, // cbclass
|
|
&ft)) )
|
|
goto Ret;
|
|
|
|
*ppszMasterKey = (LPWSTR)SSAlloc(WSZ_BYTECOUNT(szName));
|
|
if(*ppszMasterKey == NULL)
|
|
{
|
|
dwRet = (DWORD)PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
|
|
wcscpy(*ppszMasterKey, szName);
|
|
|
|
dwRet = (DWORD)PST_E_OK;
|
|
Ret:
|
|
if (hMyKey)
|
|
RegCloseKey(hMyKey);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
DWORD BPGetMasterKeys(
|
|
LPCWSTR szUser,
|
|
LPWSTR rgszMasterKeys[],
|
|
DWORD* pcbMasterKeys,
|
|
BOOL fUserFilter)
|
|
{
|
|
DWORD dwRet;
|
|
DWORD cKeys=0;
|
|
|
|
for (DWORD cntEnum=0; cntEnum<*pcbMasterKeys; cntEnum++)
|
|
{
|
|
if (PST_E_OK != (dwRet =
|
|
BPEnumMasterKeys(
|
|
szUser,
|
|
cntEnum,
|
|
&rgszMasterKeys[cKeys])) )
|
|
break;
|
|
|
|
cKeys++;
|
|
|
|
// filter out non-user keys
|
|
if (fUserFilter)
|
|
{
|
|
if (!FIsUserMasterKey(rgszMasterKeys[cKeys-1]))
|
|
SSFree(rgszMasterKeys[--cKeys]);
|
|
}
|
|
}
|
|
|
|
*pcbMasterKeys = cKeys;
|
|
|
|
return PST_E_OK;
|
|
}
|
|
|
|
// end MASTER KEYS
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
// SECURITY STATE
|
|
#define SECURITY_STATE_VERSION 0x01
|
|
|
|
BOOL FBPGetSecurityState(
|
|
LPCWSTR szUser,
|
|
LPCWSTR szMK,
|
|
BYTE rgbSalt[],
|
|
DWORD cbSalt,
|
|
BYTE rgbConfirm[],
|
|
DWORD cbConfirm,
|
|
PBYTE* ppbMK,
|
|
DWORD* pcbMK)
|
|
{
|
|
DWORD dwRet;
|
|
HKEY hMKKey = NULL;
|
|
|
|
// Open MK Key //
|
|
if (PST_E_OK != (dwRet =
|
|
GetPSTMasterKeyHKEY(
|
|
szUser,
|
|
szMK,
|
|
&hMKKey)) )
|
|
goto Ret;
|
|
|
|
dwRet = PST_E_FAIL;
|
|
|
|
if(!FBPGetSecurityStateFromHKEY(
|
|
hMKKey,
|
|
rgbSalt,
|
|
cbSalt,
|
|
rgbConfirm,
|
|
cbConfirm,
|
|
ppbMK,
|
|
pcbMK))
|
|
goto Ret;
|
|
|
|
|
|
dwRet = PST_E_OK;
|
|
Ret:
|
|
if (hMKKey)
|
|
RegCloseKey(hMKKey);
|
|
|
|
return (dwRet == PST_E_OK);
|
|
}
|
|
|
|
BOOL FBPGetSecurityStateFromHKEY(
|
|
HKEY hMKKey,
|
|
BYTE rgbSalt[],
|
|
DWORD cbSalt,
|
|
BYTE rgbConfirm[],
|
|
DWORD cbConfirm,
|
|
PBYTE* ppbMK,
|
|
DWORD* pcbMK)
|
|
{
|
|
DWORD dwRet;
|
|
|
|
PBYTE pbBuf = NULL;
|
|
DWORD cbBuf;
|
|
|
|
// helpful pointer
|
|
PBYTE pbCurPtr;
|
|
|
|
DWORD dwMemberSize;
|
|
DWORD dwCreated;
|
|
|
|
|
|
PBYTE pbLocalSalt;
|
|
PBYTE pbLocalMK;
|
|
PBYTE pbLocalConfirm;
|
|
|
|
DWORD cbLocalSalt;
|
|
DWORD cbLocalMK;
|
|
DWORD cbLocalConfirm;
|
|
|
|
PBYTE pbMaximumPtr;
|
|
PBYTE pbMinimumPtr;
|
|
|
|
|
|
|
|
if (ERROR_SUCCESS != (dwRet =
|
|
RegGetValue(
|
|
hMKKey,
|
|
REG_SECURITY_SALT_VALNAME,
|
|
&pbBuf,
|
|
&cbBuf)) )
|
|
goto Ret;
|
|
|
|
dwRet = PST_E_FAIL;
|
|
|
|
// Security data format
|
|
// Version | size(MK) | MK | size(Salt) | Salt | size(Confirm) | Confirm
|
|
|
|
if ( cbBuf < (sizeof(DWORD)*4) )
|
|
goto Ret;
|
|
|
|
// version check
|
|
if (SECURITY_STATE_VERSION != *(DWORD*)pbBuf)
|
|
goto Ret;
|
|
|
|
pbCurPtr = pbBuf + sizeof(DWORD); // fwd past vers
|
|
|
|
pbMinimumPtr = pbCurPtr;
|
|
pbMaximumPtr = (pbBuf+cbBuf);
|
|
|
|
|
|
//
|
|
// MK
|
|
//
|
|
|
|
if( pbCurPtr >= pbMaximumPtr || pbCurPtr < pbMinimumPtr )
|
|
goto Ret;
|
|
|
|
cbLocalMK = *(DWORD*)pbCurPtr; // size
|
|
|
|
if( cbLocalMK > cbBuf )
|
|
goto Ret;
|
|
|
|
pbCurPtr += sizeof(DWORD); // fwd past size
|
|
|
|
pbLocalMK = pbCurPtr;
|
|
|
|
pbCurPtr += cbLocalMK; // fwd past data
|
|
|
|
//
|
|
// Salt
|
|
//
|
|
|
|
if( pbCurPtr >= pbMaximumPtr || pbCurPtr < pbMinimumPtr )
|
|
goto Ret;
|
|
|
|
cbLocalSalt = *(DWORD*)pbCurPtr; // size
|
|
if( cbLocalSalt > cbBuf )
|
|
goto Ret;
|
|
|
|
pbCurPtr += sizeof(DWORD); // fwd past size
|
|
|
|
pbLocalSalt = pbCurPtr;
|
|
|
|
if (cbLocalSalt != cbSalt) // sizechk
|
|
goto Ret;
|
|
|
|
pbCurPtr += cbSalt; // fwd past data
|
|
|
|
//
|
|
// Confirm
|
|
//
|
|
|
|
if( pbCurPtr >= pbMaximumPtr || pbCurPtr < pbMinimumPtr )
|
|
goto Ret;
|
|
|
|
cbLocalConfirm = *(DWORD*)pbCurPtr; // size
|
|
if( cbLocalConfirm > cbBuf )
|
|
goto Ret;
|
|
|
|
pbCurPtr += sizeof(DWORD); // fwd past size
|
|
|
|
pbLocalConfirm = pbCurPtr;
|
|
|
|
if (cbLocalConfirm != cbConfirm) // sizechk
|
|
goto Ret;
|
|
|
|
pbCurPtr += cbConfirm; // fwd past data
|
|
|
|
|
|
//
|
|
// do a single size sanity check before copying data out.
|
|
//
|
|
|
|
if( pbCurPtr != (pbBuf + cbBuf) )
|
|
goto Ret;
|
|
|
|
MoveMemory(pbBuf, pbLocalMK, cbLocalMK); // move left to front for later realloc
|
|
CopyMemory(rgbSalt, pbLocalSalt, cbLocalSalt); // data
|
|
CopyMemory(rgbConfirm, pbLocalConfirm, cbLocalConfirm); // data
|
|
|
|
//
|
|
// MK fixup
|
|
//
|
|
|
|
*pcbMK = cbLocalMK;
|
|
|
|
pbCurPtr = (PBYTE)SSReAlloc(pbBuf, *pcbMK); // shorten to MK data
|
|
if (pbCurPtr == NULL)
|
|
{
|
|
dwRet = PST_E_FAIL;
|
|
if (pbBuf) {
|
|
SSFree(pbBuf);
|
|
*ppbMK = NULL;
|
|
}
|
|
goto Ret;
|
|
}
|
|
*ppbMK = pbCurPtr;
|
|
|
|
|
|
dwRet = PST_E_OK;
|
|
Ret:
|
|
|
|
return (dwRet == PST_E_OK);
|
|
}
|
|
|
|
BOOL FBPSetSecurityState(
|
|
LPCWSTR szUser,
|
|
LPCWSTR szMK,
|
|
BYTE rgbSalt[],
|
|
DWORD cbSalt,
|
|
BYTE rgbConfirm[],
|
|
DWORD cbConfirm,
|
|
PBYTE pbMK,
|
|
DWORD cbMK)
|
|
{
|
|
DWORD dwRet;
|
|
HKEY hMKKey = NULL;
|
|
|
|
// helpful pointer
|
|
PBYTE pbCurPtr;
|
|
|
|
DWORD cbBuf = cbSalt + cbConfirm + cbMK + 4*sizeof(DWORD); // ver + size + data
|
|
PBYTE pbBuf = (PBYTE)SSAlloc(cbBuf);
|
|
if (pbBuf == NULL)
|
|
{
|
|
dwRet = PST_E_FAIL;
|
|
goto Ret;
|
|
}
|
|
|
|
pbCurPtr = pbBuf;
|
|
|
|
|
|
// Security data format
|
|
// Version | size(MK) | MK | size(Salt) | Salt | size(Confirm) | Confirm
|
|
|
|
*(DWORD*)pbCurPtr = SECURITY_STATE_VERSION; // ver
|
|
pbCurPtr += sizeof(DWORD); // fwd past ver
|
|
|
|
// MK
|
|
*(DWORD*)pbCurPtr = cbMK; // size
|
|
pbCurPtr += sizeof(DWORD); // fwd past size
|
|
CopyMemory(pbCurPtr, pbMK, cbMK); // data
|
|
pbCurPtr += cbMK; // fwd past data
|
|
|
|
// Salt
|
|
*(DWORD*)pbCurPtr = cbSalt; // size
|
|
pbCurPtr += sizeof(DWORD); // fwd past size
|
|
CopyMemory(pbCurPtr, rgbSalt, cbSalt); // data
|
|
pbCurPtr += cbSalt; // fwd past data
|
|
|
|
// Confirm
|
|
*(DWORD*)pbCurPtr = cbConfirm; // size
|
|
pbCurPtr += sizeof(DWORD); // fwd past size
|
|
CopyMemory(pbCurPtr, rgbConfirm, cbConfirm);// data
|
|
pbCurPtr += cbConfirm; // fwd past data
|
|
|
|
|
|
|
|
// Open User Key //
|
|
if (PST_E_OK != (dwRet =
|
|
GetPSTMasterKeyHKEY(
|
|
szUser,
|
|
szMK,
|
|
&hMKKey)) )
|
|
goto Ret;
|
|
|
|
if (ERROR_SUCCESS != (dwRet =
|
|
RegSetValueExU(
|
|
hMKKey,
|
|
REG_SECURITY_SALT_VALNAME,
|
|
0,
|
|
REG_BINARY,
|
|
pbBuf,
|
|
cbBuf)) )
|
|
goto Ret;
|
|
|
|
dwRet = PST_E_OK;
|
|
Ret:
|
|
if (hMKKey)
|
|
RegCloseKey(hMKKey);
|
|
|
|
if (pbBuf)
|
|
SSFree(pbBuf);
|
|
|
|
return (dwRet == PST_E_OK);
|
|
}
|
|
|
|
// end SECURITY STATE
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
// begin global MAC Key storage
|
|
#define INTERNAL_MAC_KEY_VERSION 0x1
|
|
|
|
BOOL FGetInternalMACKey(LPCWSTR szUser, PBYTE* ppbKey, DWORD* pcbKey)
|
|
{
|
|
BOOL fRet = FALSE;
|
|
HKEY hBaseKey = NULL;
|
|
HKEY hDataKey = NULL;
|
|
|
|
// Open User Key //
|
|
if (PST_E_OK !=
|
|
GetPSTUserHKEY(
|
|
szUser,
|
|
&hBaseKey,
|
|
NULL))
|
|
goto Ret;
|
|
|
|
// Open Data Key //
|
|
if (ERROR_SUCCESS !=
|
|
RegOpenKeyExU(
|
|
hBaseKey,
|
|
REG_DATA_LOC,
|
|
0,
|
|
KEY_READ | KEY_WRITE,
|
|
&hDataKey))
|
|
goto Ret;
|
|
|
|
if (ERROR_SUCCESS !=
|
|
RegGetValue(
|
|
hDataKey,
|
|
REG_USER_INTERNAL_MAC_KEY,
|
|
ppbKey,
|
|
pcbKey))
|
|
goto Ret;
|
|
|
|
if(*pcbKey < sizeof(DWORD))
|
|
goto Ret;
|
|
|
|
// only know about ver 1 keys
|
|
if (*(DWORD*)*ppbKey != INTERNAL_MAC_KEY_VERSION)
|
|
goto Ret;
|
|
|
|
// strip version tag, shift left
|
|
*pcbKey -= sizeof(DWORD);
|
|
MoveMemory(*ppbKey, *ppbKey + sizeof(DWORD), *pcbKey);
|
|
|
|
fRet = TRUE;
|
|
Ret:
|
|
if (hBaseKey)
|
|
RegCloseKey(hBaseKey);
|
|
|
|
if (hDataKey)
|
|
RegCloseKey(hDataKey);
|
|
|
|
return fRet;
|
|
}
|
|
|
|
BOOL FSetInternalMACKey(LPCWSTR szUser, PBYTE pbKey, DWORD cbKey)
|
|
{
|
|
BOOL fRet = FALSE;
|
|
HKEY hBaseKey = NULL;
|
|
HKEY hDataKey = NULL;
|
|
|
|
DWORD dwCreate;
|
|
|
|
// no need to alloc, we assume we know cbKey size (2 deskeys + blocklen pad + dwVersion)
|
|
BYTE rgbTmp[(8*3)+sizeof(DWORD)];
|
|
|
|
// ASSUME: two deskeys, each 8 bytes + blocklen pad
|
|
if (cbKey != (8*3))
|
|
goto Ret;
|
|
|
|
// tack version on front
|
|
*(DWORD*)rgbTmp = (DWORD)INTERNAL_MAC_KEY_VERSION;
|
|
CopyMemory(rgbTmp + sizeof(DWORD), pbKey, cbKey);
|
|
|
|
// Open User Key //
|
|
if (PST_E_OK !=
|
|
GetPSTUserHKEY(
|
|
szUser,
|
|
&hBaseKey,
|
|
NULL))
|
|
goto Ret;
|
|
|
|
// Open/Create Data Key //
|
|
if (ERROR_SUCCESS !=
|
|
RegCreateKeyExU(
|
|
hBaseKey,
|
|
REG_DATA_LOC,
|
|
0,
|
|
NULL, // address of class string
|
|
0,
|
|
KEY_READ | KEY_WRITE,
|
|
NULL,
|
|
&hDataKey,
|
|
&dwCreate))
|
|
goto Ret;
|
|
|
|
if (ERROR_SUCCESS !=
|
|
RegSetValueExU(
|
|
hDataKey,
|
|
REG_USER_INTERNAL_MAC_KEY,
|
|
0,
|
|
REG_BINARY,
|
|
rgbTmp,
|
|
sizeof(rgbTmp) ))
|
|
goto Ret;
|
|
|
|
fRet = TRUE;
|
|
Ret:
|
|
if (hBaseKey)
|
|
RegCloseKey(hBaseKey);
|
|
|
|
if (hDataKey)
|
|
RegCloseKey(hDataKey);
|
|
|
|
return fRet;
|
|
}
|
|
|
|
// end global MAC Key storage
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL
|
|
DeleteAllUserData(
|
|
HKEY hKey
|
|
)
|
|
{
|
|
BOOL fRestorePrivs = FALSE;
|
|
BOOL fRet = FALSE;
|
|
|
|
//
|
|
// enable backup and restore privs on NT to circumvent any security
|
|
// settings.
|
|
//
|
|
|
|
if(FIsWinNT()) {
|
|
SetCurrentPrivilege(L"SeRestorePrivilege", TRUE);
|
|
SetCurrentPrivilege(L"SeBackupPrivilege", TRUE);
|
|
|
|
fRestorePrivs = TRUE;
|
|
}
|
|
|
|
fRet = DeleteUserData( hKey );
|
|
|
|
if(fRestorePrivs) {
|
|
SetCurrentPrivilege(L"SeRestorePrivilege", FALSE);
|
|
SetCurrentPrivilege(L"SeBackupPrivilege", FALSE);
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
BOOL
|
|
DeleteUserData(
|
|
HKEY hKey
|
|
)
|
|
{
|
|
LONG rc;
|
|
|
|
WCHAR szSubKey[MAX_PATH];
|
|
DWORD cchSubKeyLength;
|
|
DWORD dwSubKeyMaxIndex;
|
|
DWORD dwDisposition;
|
|
|
|
cchSubKeyLength = sizeof(szSubKey) / sizeof(WCHAR);
|
|
|
|
// First, get the number of subkeys, so we can decrement the index,
|
|
// and avoid and re-indexing of the subkeys
|
|
|
|
if (ERROR_SUCCESS != RegQueryInfoKeyA(hKey,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&dwSubKeyMaxIndex,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (dwSubKeyMaxIndex) dwSubKeyMaxIndex--; // 0 based index, so index = #keys -1
|
|
|
|
|
|
while((rc=RegEnumKeyExU(
|
|
hKey,
|
|
dwSubKeyMaxIndex,
|
|
szSubKey,
|
|
&cchSubKeyLength,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL)
|
|
) != ERROR_NO_MORE_ITEMS) { // are we done?
|
|
|
|
if(rc == ERROR_SUCCESS)
|
|
{
|
|
HKEY hSubKey;
|
|
LONG lRet;
|
|
|
|
lRet = RegCreateKeyExU(
|
|
hKey,
|
|
szSubKey,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_BACKUP_RESTORE, // in winnt.h
|
|
DELETE | KEY_ENUMERATE_SUB_KEYS,
|
|
NULL,
|
|
&hSubKey,
|
|
&dwDisposition
|
|
);
|
|
|
|
if(lRet != ERROR_SUCCESS)
|
|
return FALSE;
|
|
|
|
|
|
//
|
|
// recurse
|
|
//
|
|
|
|
DeleteUserData(hSubKey);
|
|
RegDeleteKeyU(hKey, szSubKey);
|
|
|
|
RegCloseKey(hSubKey);
|
|
|
|
|
|
// increment index into the key
|
|
dwSubKeyMaxIndex--;
|
|
|
|
// reset buffer size
|
|
cchSubKeyLength = sizeof(szSubKey) / sizeof(WCHAR);
|
|
|
|
// Continue the festivities
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// note: we need to watch for ERROR_MORE_DATA
|
|
// this indicates we need a bigger szSubKey buffer
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|