|
|
/*++
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;
USHORT usSidSize; ASSERT(NULL != phkey);
//
// Get sid of the user from the htoken
//
usSidSize= sizeof(szSid); // Size in bytes
lr = (LONG) DwGetSidFromHtoken(hToken, szSid, usSidSize);
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; }
|