/*++ 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 #include #include #include #include #include #include #include #include #include #include // #include #include #include #include #include #include #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; }