windows-nt/Source/XPSP1/NT/net/rras/ras/rasman/dll/dlparams.c
2020-09-26 16:20:57 +08:00

957 lines
20 KiB
C

/*++
Copyright (C) 1992-98 Microsft Corporation. All rights reserved.
Module Name:
dlparams.c
Abstract:
Routines for storing and retrieving user Lsa secret
dial parameters.
Author:
Gurdeep Singh Pall (gurdeep) 06-Jun-1997
Revision History:
Miscellaneous Modifications - raos 31-Dec-1997
--*/
#define RASMXS_DYNAMIC_LINK
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <ntlsa.h>
#include <ntmsv1_0.h>
#include <llinfo.h>
#include <rasman.h>
#include <lm.h>
#include <lmwksta.h>
#include <wanpub.h>
#include <raserror.h>
// #include <rasarp.h>
#include <media.h>
#include <device.h>
#include <stdlib.h>
#include <string.h>
#include <ntlsa.h>
#define MAX_REGISTRY_VALUE_LENGTH ((64*1024) - 1)
#define cszEapKeyRas TEXT("Software\\Microsoft\\RAS EAP\\UserEapInfo")
#define cszEapKeyRouter TEXT("Software\\Microsoft\\Router EAP\\IfEapInfo")
#define cszEapValue TEXT("EapInfo")
#define EAP_SIG 0x31504145
#define EAP_SIG_2 0x32504145
typedef struct _EAP_USER_INFO
{
DWORD dwSignature;
DWORD dwEapTypeId;
GUID Guid;
DWORD dwSize;
BYTE abdata[1];
} EAP_USER_INFO, *PEAP_USER_INFO;
typedef struct _EAP_USER_INFO_0
{
DWORD dwUID;
DWORD dwSize;
BYTE abdata[1];
} EAP_USER_INFO_0, *PEAP_USER_INFO_0;
DWORD
DwGetSidFromHtoken(
HANDLE hToken,
PWCHAR pszSid,
USHORT cbSid
)
{
DWORD cbNeeded, dwErr;
BOOL fThreadTokenOpened = FALSE;
UNICODE_STRING unicodeString;
TOKEN_USER *pUserToken = NULL;
if( (NULL == hToken)
|| (INVALID_HANDLE_VALUE == hToken))
{
fThreadTokenOpened = TRUE;
if (!OpenThreadToken(
GetCurrentThread(),
TOKEN_QUERY,
TRUE,
&hToken))
{
dwErr = GetLastError();
if (dwErr == ERROR_NO_TOKEN)
{
//
// This means we are not impersonating
// anyone. Instead, get the token out
// of the process.
//
if (!OpenProcessToken(
GetCurrentProcess(),
TOKEN_QUERY,
&hToken))
{
return GetLastError();
}
}
else
{
return dwErr;
}
}
}
//
// Call GetTokenInformation once to determine
// the number of bytes needed.
//
cbNeeded = 0;
GetTokenInformation(hToken,
TokenUser,
NULL, 0,
&cbNeeded);
if (!cbNeeded)
{
dwErr = GetLastError();
goto done;
}
//
// Allocate the memory and call it again.
//
pUserToken = LocalAlloc(LPTR, cbNeeded);
if (pUserToken == NULL)
{
return GetLastError();
}
if (!GetTokenInformation(
hToken,
TokenUser,
pUserToken,
cbNeeded,
&cbNeeded))
{
dwErr = GetLastError();
goto done;
}
//
// Format the SID as a Unicode string.
//
unicodeString.Length = 0;
unicodeString.MaximumLength = cbSid;
unicodeString.Buffer = pszSid;
dwErr = RtlConvertSidToUnicodeString(
&unicodeString,
pUserToken->User.Sid,
FALSE);
done:
if (pUserToken != NULL)
{
LocalFree(pUserToken);
}
if ( (NULL != hToken)
&& (INVALID_HANDLE_VALUE != hToken)
&& fThreadTokenOpened)
{
CloseHandle(hToken);
}
return dwErr;
}
DWORD
GetUserSid(
IN PWCHAR pszSid,
IN USHORT cbSid
)
{
return DwGetSidFromHtoken(NULL,
pszSid,
cbSid);
}
LONG
lrGetEapKeyFromToken(HANDLE hToken,
HKEY *phkey)
{
LONG lr = ERROR_SUCCESS;
WCHAR szSid[260];
HKEY hkeyUser = NULL;
HKEY hkeyEap = NULL;
DWORD dwDisposition;
ASSERT(NULL != phkey);
//
// Get sid of the user from the htoken
//
lr = (LONG) DwGetSidFromHtoken(hToken,
szSid,
sizeof(szSid));
if(ERROR_SUCCESS != lr)
{
goto done;
}
//
// Open the users registry key
//
lr = RegOpenKeyExW(HKEY_USERS,
szSid,
0,
KEY_ALL_ACCESS,
&hkeyUser);
if(ERROR_SUCCESS != lr)
{
goto done;
}
//
// Create the eap key if required.
//
lr = RegCreateKeyEx(hkeyUser,
cszEapKeyRas,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hkeyEap,
&dwDisposition);
if(ERROR_SUCCESS != lr)
{
goto done;
}
done:
if(NULL != hkeyUser)
{
RegCloseKey(hkeyUser);
}
*phkey = hkeyEap;
return lr;
}
DWORD
DwUpgradeEapInfo(PBYTE *ppbInfo,
DWORD *pdwSize)
{
BYTE *pbInfo;
DWORD dwErr = ERROR_SUCCESS;
EAP_USER_INFO UNALIGNED *pEapInfo;
DWORD dwSize;
DWORD dwRequiredSize = 0;
BYTE *pbNewInfo = NULL;
EAP_USER_INFO *pNewEapInfo;
if( (NULL == ppbInfo)
|| (NULL == pdwSize))
{
dwErr = E_INVALIDARG;
goto done;
}
dwSize = *pdwSize;
pbInfo = *ppbInfo;
pEapInfo = (EAP_USER_INFO *) pbInfo;
while((BYTE *) pEapInfo < pbInfo + dwSize)
{
dwRequiredSize += RASMAN_ALIGN8(
sizeof(EAP_USER_INFO)
+ pEapInfo->dwSize);
((PBYTE) pEapInfo) += (sizeof(EAP_USER_INFO)
+ pEapInfo->dwSize);
}
pbNewInfo = LocalAlloc(LPTR, dwRequiredSize);
if(NULL == pbNewInfo)
{
dwErr = GetLastError();
goto done;
}
pEapInfo = (EAP_USER_INFO *) pbInfo;
pNewEapInfo = (EAP_USER_INFO *) pbNewInfo;
while((BYTE *) pEapInfo < pbInfo + dwSize)
{
CopyMemory(
(BYTE *) pNewEapInfo,
(BYTE *) pEapInfo,
sizeof(EAP_USER_INFO) + pEapInfo->dwSize);
pNewEapInfo->dwSignature = EAP_SIG_2;
(BYTE *) pNewEapInfo += RASMAN_ALIGN8(sizeof(EAP_USER_INFO)
+ pEapInfo->dwSize);
(BYTE *) pEapInfo += (sizeof(EAP_USER_INFO) + pEapInfo->dwSize);
}
*ppbInfo = pbNewInfo;
*pdwSize = dwRequiredSize;
if(NULL != pbInfo)
{
LocalFree(pbInfo);
}
done:
return dwErr;
}
DWORD
DwGetEapInfo(HANDLE hToken,
BOOL fRouter,
PBYTE *ppbInfo,
DWORD *pdwSize,
HKEY *phkey
)
{
LONG lr = ERROR_SUCCESS;
HKEY hkey = NULL;
DWORD dwDisposition;
DWORD dwInfoSize = 0;
DWORD dwType;
PBYTE pbInfo = NULL;
if( (NULL == ppbInfo)
|| (NULL == pdwSize))
{
lr = (LONG) E_INVALIDARG;
goto done;
}
if( (NULL != hToken)
&& (INVALID_HANDLE_VALUE != hToken)
&& !fRouter)
{
//
// If a valid token is passed then its most likely
// a service trying to open users registry. Get the
// sid of the user and open HKU in this case.
//
if(ERROR_SUCCESS != (lr = lrGetEapKeyFromToken(hToken,
&hkey)))
{
goto done;
}
}
else
{
//
// Open the key. Create the key if its not present
//
if(ERROR_SUCCESS != (lr = RegCreateKeyEx(
(fRouter)
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER,
(fRouter)
? cszEapKeyRouter
: cszEapKeyRas,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hkey,
&dwDisposition)))
{
goto done;
}
}
//
// Get size of the binary value. If the value is not
// found, return no information. This value will be
// set the first time we store any eap information.
//
if( (ERROR_SUCCESS != (lr = RegQueryValueEx(
hkey,
cszEapValue,
NULL,
&dwType,
NULL,
&dwInfoSize)))
&& (ERROR_SUCCESS != lr))
{
goto done;
}
#if DBG
ASSERT(REG_BINARY == dwType);
#endif
//
// Allocate a buffer to hold the binary value
//
pbInfo = LocalAlloc(LPTR, dwInfoSize);
if(NULL == pbInfo)
{
lr = (LONG) GetLastError();
goto done;
}
//
// Get the binary value
//
if(ERROR_SUCCESS != (lr = RegQueryValueEx(
hkey,
cszEapValue,
NULL,
&dwType,
pbInfo,
&dwInfoSize)))
{
goto done;
}
done:
if(NULL != phkey)
{
*phkey = hkey;
}
else if (NULL != hkey)
{
RegCloseKey(hkey);
}
if(NULL != ppbInfo)
{
*ppbInfo = pbInfo;
}
else if(NULL != pbInfo)
{
LocalFree(pbInfo);
}
if(NULL != pdwSize)
{
*pdwSize = dwInfoSize;
}
if(ERROR_FILE_NOT_FOUND == lr)
{
lr = ERROR_SUCCESS;
}
return (DWORD) lr;
}
DWORD
DwSetEapInfo(HKEY hkey,
PBYTE pbInfo,
DWORD dwSize)
{
LONG lr = ERROR_SUCCESS;
if(ERROR_SUCCESS != (lr = RegSetValueEx(
hkey,
cszEapValue,
0,
REG_BINARY,
pbInfo,
dwSize)))
{
goto done;
}
done:
return (DWORD) lr;
}
DWORD
DwRemoveEapUserInfo(GUID *pGuid,
PBYTE pbInfo,
PDWORD pdwSize,
HKEY hkey,
BOOL fWrite,
DWORD dwEapTypeId)
{
DWORD dwErr = ERROR_SUCCESS;
DWORD dwcb = 0;
EAP_USER_INFO *pEapInfo = (EAP_USER_INFO *) pbInfo;
DWORD dwNewSize;
DWORD dwSize = *pdwSize;
//
// Find the binary blob with the
// UID
//
while(dwcb < dwSize)
{
if( (0 == memcmp(
(PBYTE) pGuid,
(PBYTE) &pEapInfo->Guid,
sizeof(GUID)))
&& (dwEapTypeId == pEapInfo->dwEapTypeId))
{
break;
}
dwcb += RASMAN_ALIGN8((sizeof(EAP_USER_INFO) + pEapInfo->dwSize));
pEapInfo = (EAP_USER_INFO *) (pbInfo + dwcb);
}
if(dwcb >= dwSize)
{
goto done;
}
#if DBG
ASSERT(dwSize >= dwcb
+ RASMAN_ALIGN8(pEapInfo->dwSize
+ sizeof(EAP_USER_INFO)));
#endif
dwNewSize = dwSize -
RASMAN_ALIGN8(pEapInfo->dwSize + sizeof(EAP_USER_INFO));
//
// Remove the info
//
MoveMemory(
pbInfo + dwcb,
pbInfo + dwcb
+ RASMAN_ALIGN8(sizeof(EAP_USER_INFO) + pEapInfo->dwSize),
dwSize - dwcb
- RASMAN_ALIGN8(sizeof(EAP_USER_INFO) + pEapInfo->dwSize));
if(fWrite)
{
dwErr = DwSetEapInfo(
hkey,
pbInfo,
dwNewSize);
}
else
{
*pdwSize = dwNewSize;
}
done:
return dwErr;
}
DWORD
DwReplaceEapUserInfo(GUID *pGuid,
PBYTE pbUserInfo,
DWORD dwUserInfo,
PBYTE pbInfo,
DWORD dwSize,
HKEY hkey,
DWORD dwEapTypeId)
{
DWORD dwErr = ERROR_SUCCESS;
DWORD dwNewSize = dwSize;
PBYTE pbNewInfo = NULL;
EAP_USER_INFO UNALIGNED *pEapInfo;
if(NULL == pGuid)
{
ASSERT(FALSE);
goto done;
}
//
// Remove the existing eap information corresponding
// to dwUID if any.
//
if(ERROR_SUCCESS != (dwErr = DwRemoveEapUserInfo(
pGuid,
pbInfo,
&dwNewSize,
hkey,
FALSE,
dwEapTypeId)))
{
goto done;
}
//
// Local Alloc a new blob with enough space for the
// eap information of the new entry
//
pbNewInfo = LocalAlloc(LPTR,
dwNewSize
+ RASMAN_ALIGN8(sizeof(EAP_USER_INFO)
+ dwUserInfo));
if(NULL == pbNewInfo)
{
dwErr = GetLastError();
goto done;
}
RtlCopyMemory(
pbNewInfo,
pbInfo,
dwNewSize);
pEapInfo = (EAP_USER_INFO *) (pbNewInfo + dwNewSize);
pEapInfo->Guid = *pGuid;
pEapInfo->dwEapTypeId = dwEapTypeId;
pEapInfo->dwSize = dwUserInfo;
pEapInfo->dwSignature = EAP_SIG_2;
dwNewSize += RASMAN_ALIGN8((sizeof(EAP_USER_INFO) + dwUserInfo));
RtlCopyMemory(
pEapInfo->abdata,
pbUserInfo,
dwUserInfo);
dwErr = DwSetEapInfo(
hkey,
pbNewInfo,
dwNewSize);
done:
if(NULL != pbNewInfo)
{
LocalFree(pbNewInfo);
}
return dwErr;
}
DWORD
DwSetEapUserInfo(HANDLE hToken,
GUID *pGuid,
PBYTE pbUserInfo,
DWORD dwInfoSize,
BOOL fClear,
BOOL fRouter,
DWORD dwEapTypeId)
{
DWORD dwErr = ERROR_SUCCESS;
PBYTE pbInfo = NULL;
DWORD dwSize = 0;
HKEY hkey = NULL;
if(NULL == pGuid)
{
ASSERT(FALSE);
goto done;
}
if(ERROR_SUCCESS != (dwErr = DwGetEapInfo(
hToken,
fRouter,
&pbInfo,
&dwSize,
&hkey)))
{
goto done;
}
#if DBG
ASSERT(NULL != hkey);
#endif
//
// Check to see if the blob is one we recognize
//
if( !fClear
&& ( (sizeof(DWORD) > dwSize)
|| (((*((DWORD *) pbInfo)) != EAP_SIG))
&& ( (*((DWORD *) pbInfo)) != EAP_SIG_2)))
{
EAP_USER_INFO *pEapInfo;
//
// Upgrade?? How? We will just blow away all the old data.
//
pEapInfo = (EAP_USER_INFO *) LocalAlloc(LPTR,
RASMAN_ALIGN8(
sizeof(EAP_USER_INFO)
+ dwInfoSize));
if(NULL == pEapInfo)
{
dwErr = GetLastError();
goto done;
}
pEapInfo->Guid = *pGuid;
pEapInfo->dwEapTypeId = dwEapTypeId;
pEapInfo->dwSize = dwInfoSize;
pEapInfo->dwSignature = EAP_SIG_2;
RtlCopyMemory(
pEapInfo->abdata,
pbUserInfo,
dwInfoSize);
dwErr = DwSetEapInfo(hkey,
(PBYTE) pEapInfo,
RASMAN_ALIGN8(sizeof(EAP_USER_INFO)
+ dwInfoSize));
goto done;
}
else if ( (fClear)
&& ( (sizeof(DWORD) > dwSize)
|| (((*((DWORD *) pbInfo)) != EAP_SIG))
&& ( (*((DWORD *) pbInfo)) != EAP_SIG_2)))
{
//
// Blow away the old information
//
dwErr = RegDeleteValue(
hkey,
cszEapValue);
goto done;
}
if(*((DWORD *) pbInfo) == EAP_SIG)
{
//
// upgrade the blob so that its aligned
// at 8-byte boundaries
//
dwErr = DwUpgradeEapInfo(&pbInfo, &dwSize);
if(ERROR_SUCCESS != dwErr)
{
goto done;
}
}
if(fClear)
{
dwErr = DwRemoveEapUserInfo(pGuid,
pbInfo,
&dwSize,
hkey,
TRUE,
dwEapTypeId);
}
else
{
dwErr = DwReplaceEapUserInfo(
pGuid,
pbUserInfo,
dwInfoSize,
pbInfo,
dwSize,
hkey,
dwEapTypeId);
}
done:
if(NULL != hkey)
{
RegCloseKey(hkey);
}
if(NULL != pbInfo)
{
LocalFree(pbInfo);
}
return dwErr;
}
DWORD
DwGetEapUserInfo(HANDLE hToken,
PBYTE pbEapInfo,
DWORD *pdwInfoSize,
GUID *pGuid,
BOOL fRouter,
DWORD dwEapTypeId)
{
DWORD dwErr = ERROR_SUCCESS;
PBYTE pbInfo = NULL;
DWORD dwSize;
DWORD dwcb = 0;
EAP_USER_INFO UNALIGNED *pEapUserInfo = NULL;
HKEY hkey = NULL;
if(NULL == pdwInfoSize)
{
dwErr = E_INVALIDARG;
goto done;
}
// *pdwInfoSize = 0;
if(NULL == pGuid)
{
ASSERT(FALSE);
*pdwInfoSize = 0;
goto done;
}
//
// Get the binary blob from the registry
//
dwErr = DwGetEapInfo(hToken,
fRouter,
&pbInfo,
&dwSize,
&hkey);
if( (ERROR_SUCCESS != dwErr)
|| (0 == dwSize))
{
goto done;
}
//
// Check to see if the blob is one we recognize
//
if( (sizeof(DWORD) > dwSize)
|| (((*((DWORD *) pbInfo)) != EAP_SIG)
&& ( (*((DWORD *) pbInfo)) != EAP_SIG_2)))
{
//
// Upgrade?? How? We will just blow away all the old data.
//
RegDeleteValue(hkey, cszEapValue);
*pdwInfoSize = 0;
goto done;
}
if(*((DWORD *) pbInfo) == EAP_SIG)
{
//
// Upgrade the blob so that its
// aligned correctly.
//
dwErr = DwUpgradeEapInfo(&pbInfo, &dwSize);
if(ERROR_SUCCESS != dwErr)
{
goto done;
}
}
//
// Loop through the binary blob and look for the
// eap info corresponding to the UID passed in.
//
pEapUserInfo = (EAP_USER_INFO *) pbInfo;
while(dwcb < dwSize)
{
if( (0 == memcmp(
(PBYTE) pGuid,
(PBYTE) &pEapUserInfo->Guid,
sizeof(GUID)))
&& (dwEapTypeId == pEapUserInfo->dwEapTypeId))
{
break;
}
dwcb += RASMAN_ALIGN8((sizeof(EAP_USER_INFO)
+ pEapUserInfo->dwSize));
pEapUserInfo = (EAP_USER_INFO *) (pbInfo + dwcb);
}
if(dwcb >= dwSize)
{
*pdwInfoSize = 0;
goto done;
}
if( (NULL != pbEapInfo)
&& (*pdwInfoSize >= pEapUserInfo->dwSize))
{
RtlCopyMemory(pbEapInfo,
pEapUserInfo->abdata,
pEapUserInfo->dwSize);
}
else
{
dwErr = ERROR_BUFFER_TOO_SMALL;
}
*pdwInfoSize = pEapUserInfo->dwSize;
done:
if(NULL != pbInfo)
{
LocalFree(pbInfo);
}
if(NULL != hkey)
{
RegCloseKey(hkey);
}
return dwErr;
}