|
|
/*++
Copyright (c) 2000, Microsoft Corporation
Module Name: eapolutil.c
Abstract:
Tools and ends
Revision History:
sachins, Apr 23 2000, Created
--*/
#include "pcheapol.h"
#pragma hdrstop
//
// Definitions used to read/write to registry
//
#define MAX_REGISTRY_VALUE_LENGTH ((64*1024) - 1)
// Location of User blob
#define cwszEapKeyEapolUser L"Software\\Microsoft\\EAPOL\\UserEapInfo"
// Location of Connection blob
#define cwszEapKeyEapolConn L"Software\\Microsoft\\EAPOL\\Parameters\\Interfaces"
// Location of EAPOL Parameters Service
#define cwszEapKeyEapolServiceParams L"Software\\Microsoft\\EAPOL\\Parameters\\General"
// Location of EAPOL Global state machine params
#define cwszEAPOLGlobalParams L"Software\\Microsoft\\EAPOL\\Parameters\\General\\Global"
// Location of policy parameters
#define cwszEAPOLPolicyParams L"Software\\Policies\\Microsoft\\Windows\\Network Connections\\8021X"
// Location of netman dll
#define NETMAN_DLL_PATH L"%SystemRoot%\\system32\\netman.dll"
#define cwszEapolEnabled L"EapolEnabled"
#define cwszDefaultEAPType L"DefaultEAPType"
#define cwszLastUsedSSID L"LastUsedSSID"
#define cwszInterfaceList L"InterfaceList"
#define cwszAuthPeriod L"authPeriod"
#define cwszHeldPeriod L"heldPeriod"
#define cwszStartPeriod L"startPeriod"
#define cwszMaxStart L"maxStart"
#define cwszSupplicantMode L"SupplicantMode"
#define cwszAuthMode L"AuthMode"
#define cszCARootHash "8021XCARootHash"
#define SIZE_OF_CA_CONV_STR 3
#define PASSWORDMAGIC 0xA5
#define WZCSVC_SERVICE_NAME L"WZCSVC"
//
// EAPOLRESPUI function mapping
//
EAPOLUIRESPFUNCMAP EapolUIRespFuncMap[NUM_EAPOL_DLG_MSGS]= { {EAPOLUI_GET_USERIDENTITY, ElProcessUserIdentityResponse, 3}, {EAPOLUI_GET_USERNAMEPASSWORD, ElProcessUserNamePasswordResponse, 2}, {EAPOLUI_INVOKEINTERACTIVEUI, ElProcessInvokeInteractiveUIResponse, 1}, {EAPOLUI_EAP_NOTIFICATION, NULL, 0}, {EAPOLUI_REAUTHENTICATE, ElProcessReauthResponse, 0}, {EAPOLUI_CREATEBALLOON, NULL, 0}, {EAPOLUI_CLEANUP, NULL, 0} };
BYTE g_bDefaultSSID[MAX_SSID_LEN]={0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22};
#define MAX_VALUENAME_LEN 33
//
// HostToWireFormat16
//
// Description:
//
// Will convert a 16 bit integer from host format to wire format
//
VOID HostToWireFormat16 ( IN WORD wHostFormat, IN OUT PBYTE pWireFormat ) { *((PBYTE)(pWireFormat)+0) = (BYTE) ((DWORD)(wHostFormat) >> 8); *((PBYTE)(pWireFormat)+1) = (BYTE) (wHostFormat); }
//
// WireToHostFormat16
//
// Description:
//
// Will convert a 16 bit integer from wire format to host format
//
WORD WireToHostFormat16 ( IN PBYTE pWireFormat ) { WORD wHostFormat = ((*((PBYTE)(pWireFormat)+0) << 8) + (*((PBYTE)(pWireFormat)+1)));
return( wHostFormat ); }
//
// HostToWireFormat32
//
// Description:
//
// Will convert a 32 bit integer from host format to wire format
//
VOID HostToWireFormat32 ( IN DWORD dwHostFormat, IN OUT PBYTE pWireFormat ) { *((PBYTE)(pWireFormat)+0) = (BYTE) ((DWORD)(dwHostFormat) >> 24); *((PBYTE)(pWireFormat)+1) = (BYTE) ((DWORD)(dwHostFormat) >> 16); *((PBYTE)(pWireFormat)+2) = (BYTE) ((DWORD)(dwHostFormat) >> 8); *((PBYTE)(pWireFormat)+3) = (BYTE) (dwHostFormat); }
//
// WireToHostFormat32
//
// Description:
//
// Will convert a 32 bit integer from wire format to host format
//
DWORD WireToHostFormat32 ( IN PBYTE pWireFormat ) { DWORD dwHostFormat = ((*((PBYTE)(pWireFormat)+0) << 24) + (*((PBYTE)(pWireFormat)+1) << 16) + (*((PBYTE)(pWireFormat)+2) << 8) + (*((PBYTE)(pWireFormat)+3) ));
return( dwHostFormat ); }
//
// ElSetCustomAuthData
//
// Description:
//
// Function called to set the connection data for an interface for a specific
// EAP type and SSID (if any). Data will be stored in the HKLM hive
//
// Arguments:
// pwszGUID - pointer to GUID string for the interface
// dwEapTypeId - EAP type for which connection data is to be stored
// dwSizeOfSSID - Size of special identifier, if any, for the EAP blob
// pwszSSID - Special identifier, if any, for the EAP blob
// pbConnInfo - pointer to EAP connection data blob
// pdwInfoSize - Size of EAP connection blob
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
DWORD ElSetCustomAuthData ( IN WCHAR *pwszGUID, IN DWORD dwEapTypeId, IN DWORD dwSizeOfSSID, IN BYTE *pbSSID, IN PBYTE pbConnInfo, IN DWORD *pdwInfoSize ) { HKEY hkey = NULL; HKEY hkey1 = NULL; DWORD dwDisposition; DWORD dwNumValues = 0, dwMaxValueNameLen = 0, dwMaxValueLen = 0; DWORD dwIndex = 0, dwMaxValueName = 0; BYTE *pbValueBuf = NULL; DWORD dwValueData = 0; WCHAR *pwszValueName = NULL; WCHAR wcszValueName[MAX_VALUENAME_LEN]; BYTE *pbDefaultValue = NULL; DWORD dwDefaultValueLen = 0; BYTE *pbEapBlob = NULL, *pbEapBlobIn = NULL; DWORD dwEapBlob = 0; BOOLEAN fFoundValue = FALSE; EAPOL_INTF_PARAMS *pRegParams = NULL; EAPOL_INTF_PARAMS *pDefIntfParams = NULL; LONG lError = ERROR_SUCCESS; DWORD dwRetCode = ERROR_SUCCESS;
do { // Validate input params
if (pwszGUID == NULL) { TRACE0 (ANY, "ElSetCustomAuthData: GUID = NULL"); dwRetCode = ERROR_INVALID_PARAMETER; break; } if (dwEapTypeId == 0) { TRACE0 (ANY, "ElSetCustomAuthData: GUID = NULL"); dwRetCode = ERROR_INVALID_PARAMETER; break; } if (dwSizeOfSSID > MAX_SSID_LEN) { TRACE1 (ANY, "ElSetCustomAuthData: Invalid SSID length = (%ld)", dwSizeOfSSID); dwRetCode = ERROR_INVALID_PARAMETER; break; }
// Get handle to HKLM\Software\Microsoft\EAPOL\Parameters\Interfaces
if ((lError = RegCreateKeyEx ( HKEY_LOCAL_MACHINE, cwszEapKeyEapolConn, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwDisposition)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElSetCustomAuthData: Error in RegCreateKeyEx for base key, %ld", lError); dwRetCode = (DWORD)lError; break; }
// Get handle to HKLM\Software\...\Interfaces\<GUID>
if ((lError = RegCreateKeyEx ( hkey, pwszGUID, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey1, &dwDisposition)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElSetCustomAuthData: Error in RegCreateKeyEx for GUID, %ld", lError); dwRetCode = (DWORD)lError; break; }
// Work with appropriate SSID
if ((dwSizeOfSSID == 0) || (pbSSID == NULL)) { pbSSID = g_bDefaultSSID; dwSizeOfSSID = MAX_SSID_LEN; }
if ((lError = RegQueryInfoKey ( hkey1, NULL, NULL, NULL, NULL, NULL, NULL, &dwNumValues, &dwMaxValueNameLen, &dwMaxValueLen, NULL, NULL )) != NO_ERROR) { dwRetCode = (DWORD)lError; TRACE1 (ANY, "ElSetCustomAuthData: RegQueryInfoKey failed with error %ld", dwRetCode); break; }
if (dwMaxValueNameLen > MAX_VALUENAME_LEN) { TRACE1 (ANY, "ElSetCustomAuthData: Valuename too long (%ld)", dwMaxValueLen); break; }
if ((pbValueBuf = MALLOC (dwMaxValueLen)) == NULL) { TRACE0 (ANY, "ElSetCustomAuthData: MALLOC failed for pbValueBuf"); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; }
for (dwIndex = 0; dwIndex < dwNumValues; dwIndex++) { dwValueData = dwMaxValueLen; dwMaxValueNameLen = MAX_VALUENAME_LEN; ZeroMemory (&wcszValueName, MAX_VALUENAME_LEN*sizeof(WCHAR)); if ((lError = RegEnumValue ( hkey1, dwIndex, wcszValueName, &dwMaxValueNameLen, NULL, NULL, pbValueBuf, &dwValueData )) != ERROR_SUCCESS) { if (lError != ERROR_MORE_DATA) { break; } lError = ERROR_SUCCESS; }
if (dwValueData < sizeof (EAPOL_INTF_PARAMS)) { TRACE0 (ANY, "ElSetCustomAuthData: dwValueData < sizeof (EAPOL_INTF_PARAMS"); lError = ERROR_INVALID_DATA; break; } pRegParams = (EAPOL_INTF_PARAMS *)pbValueBuf;
if (((DWORD)_wtol(wcszValueName)) > dwMaxValueName) { dwMaxValueName = _wtol (wcszValueName); }
if (!memcmp (pRegParams->bSSID, pbSSID, dwSizeOfSSID)) { fFoundValue = TRUE; break; }
if (!memcmp (pRegParams->bSSID, g_bDefaultSSID, MAX_SSID_LEN)) { if ((pbDefaultValue = MALLOC (dwValueData)) == NULL) { TRACE0 (ANY, "ElSetCustomAuthData: MALLOC failed for pbDefaultValue"); lError = ERROR_NOT_ENOUGH_MEMORY; break; } memcpy (pbDefaultValue, pbValueBuf, dwValueData); dwDefaultValueLen = dwValueData; } } if ((lError != ERROR_SUCCESS) && (lError != ERROR_NO_MORE_ITEMS)) { dwRetCode = (DWORD)lError; TRACE1 (ANY, "ElSetCustomAuthData: RegQueryInfoKey failed with error %ld", dwRetCode); break; } else { lError = ERROR_SUCCESS; }
if (!fFoundValue) { DWORD dwNewValueName = (dwMaxValueName >= dwNumValues)?(++dwMaxValueName):dwNumValues; _ltow (dwNewValueName, wcszValueName, 10); if ((pbDefaultValue = MALLOC (sizeof(EAPOL_INTF_PARAMS))) == NULL) { TRACE0 (ANY, "ElSetCustomAuthData: MALLOC failed for pbDefaultValue"); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; } pDefIntfParams = (EAPOL_INTF_PARAMS *)pbDefaultValue; pDefIntfParams->dwEapFlags = DEFAULT_EAP_STATE; pDefIntfParams->dwEapType = dwEapTypeId; pDefIntfParams->dwVersion = EAPOL_CURRENT_VERSION; pDefIntfParams->dwSizeOfSSID = dwSizeOfSSID; memcpy (pDefIntfParams->bSSID, pbSSID, dwSizeOfSSID);
dwEapBlob = sizeof(EAPOL_INTF_PARAMS); pbEapBlob = pbDefaultValue; } else { // Use pbValueBuf & dwValueData
pbEapBlob = pbValueBuf; dwEapBlob = dwValueData; }
pbEapBlobIn = pbEapBlob; if ((dwRetCode = ElSetEapData ( dwEapTypeId, &dwEapBlob, &pbEapBlob, sizeof (EAPOL_INTF_PARAMS), *pdwInfoSize, pbConnInfo )) != NO_ERROR) { TRACE1 (ANY, "ElSetCustomAuthData: ElSetEapData failed with error %ld", dwRetCode); break; }
// Overwrite/Create new value
if ((lError = RegSetValueEx ( hkey1, wcszValueName, 0, REG_BINARY, pbEapBlob, dwEapBlob)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElSetCustomAuthData: Error in RegSetValueEx for SSID, %ld", lError); dwRetCode = (DWORD)lError; break; }
TRACE0 (ANY, "ElSetCustomAuthData: Set value succeeded");
} while (FALSE);
if (hkey != NULL) { RegCloseKey (hkey); } if (hkey1 != NULL) { RegCloseKey (hkey1); } if ((pbEapBlob != pbEapBlobIn) && (pbEapBlob != NULL)) { FREE (pbEapBlob); } if (pbValueBuf != NULL) { FREE (pbValueBuf); } if (pbDefaultValue != NULL) { FREE (pbDefaultValue); }
return dwRetCode; }
//
// ElGetCustomAuthData
//
// Description:
//
// Function called to retrieve the connection data for an interface for a
// specific EAP type and SSID (if any). Data is retrieved from the HKLM hive
//
// Arguments:
//
// pwszGUID - pointer to GUID string for the interface
// dwEapTypeId - EAP type for which connection data is to be retrieved
// dwSizeOfSSID - Size of Special identifier if any for the EAP blob
// pbSSID - Special identifier if any for the EAP blob
// pbConnInfo - output: pointer to EAP connection data blob
// pdwInfoSize - output: pointer to size of EAP connection blob
//
// Return values:
//
// NO_ERROR - success
// non-zero - error
//
DWORD ElGetCustomAuthData ( IN WCHAR *pwszGUID, IN DWORD dwEapTypeId, IN DWORD dwSizeOfSSID, IN BYTE *pbSSID, IN OUT BYTE *pbConnInfo, IN OUT DWORD *pdwInfoSize ) { HKEY hkey = NULL; HKEY hkey1 = NULL; DWORD dwNumValues = 0, dwMaxValueNameLen = 0, dwTempValueNameLen = 0, dwMaxValueLen = 0; DWORD dwIndex = 0, dwMaxValueName = 0; WCHAR *pwszValueName = NULL; BYTE *pbValueBuf = NULL; DWORD dwValueData = 0; BYTE *pbDefaultValue = NULL; DWORD dwDefaultValueLen = 0; BYTE *pbEapBlob = NULL; DWORD dwEapBlob = 0; BYTE *pbAuthData = NULL; DWORD dwAuthData = 0; BYTE *pbAuthDataIn = NULL; DWORD dwAuthDataIn = 0; BOOLEAN fFreeAuthData = FALSE; BOOLEAN fFoundValue = FALSE; EAPOL_INTF_PARAMS *pRegParams = NULL; LONG lError = ERROR_SUCCESS; DWORD dwRetCode = ERROR_SUCCESS;
do { // Validate input params
if (pwszGUID == NULL) { TRACE0 (ANY, "ElGetCustomAuthData: GUID = NULL"); dwRetCode = ERROR_INVALID_PARAMETER; break; } if (dwEapTypeId == 0) { TRACE0 (ANY, "ElGetCustomAuthData: EapTypeId invalid"); dwRetCode = ERROR_INVALID_PARAMETER; break; } if (dwSizeOfSSID > MAX_SSID_LEN) { TRACE1 (ANY, "ElGetCustomAuthData: Invalid SSID length = (%ld)", dwSizeOfSSID); dwRetCode = ERROR_INVALID_PARAMETER; break; }
// Work with appropriate SSID
if ((dwSizeOfSSID == 0) || (pbSSID == NULL)) { pbSSID = g_bDefaultSSID; dwSizeOfSSID = MAX_SSID_LEN; }
// Get handle to HKLM\Software\Microsoft\EAPOL\Parameters\Interfaces
if ((lError = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, cwszEapKeyEapolConn, 0, KEY_READ, &hkey )) != ERROR_SUCCESS) { // Assume no value is found and proceed ahead
if (lError == ERROR_FILE_NOT_FOUND) { lError = ERROR_SUCCESS; fFoundValue = FALSE; goto LNotFoundValue; } else { TRACE1 (ANY, "ElGetCustomAuthData: Error in RegOpenKeyEx for base key, %ld", lError); dwRetCode = (DWORD)lError; break; } }
// Get handle to HKLM\Software\...\Interfaces\<GUID>
if ((lError = RegOpenKeyEx ( hkey, pwszGUID, 0, KEY_READ, &hkey1 )) != ERROR_SUCCESS) { // Assume no value is found and proceed ahead
if (lError == ERROR_FILE_NOT_FOUND) { lError = ERROR_SUCCESS; fFoundValue = FALSE; goto LNotFoundValue; } else { TRACE1 (ANY, "ElGetCustomAuthData: Error in RegOpenKeyEx for GUID, %ld", lError); dwRetCode = (DWORD)lError; break; } }
if ((lError = RegQueryInfoKey ( hkey1, NULL, NULL, NULL, NULL, NULL, NULL, &dwNumValues, &dwMaxValueNameLen, &dwMaxValueLen, NULL, NULL )) != NO_ERROR) { dwRetCode = (DWORD)lError; TRACE1 (ANY, "ElGetCustomAuthData: RegQueryInfoKey failed with error %ld", dwRetCode); break; }
if ((pwszValueName = MALLOC ((dwMaxValueNameLen + 1) * sizeof (WCHAR))) == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (ANY, "ElGetCustomAuthData: MALLOC failed for pwszValueName"); break; } dwMaxValueNameLen++; if ((pbValueBuf = MALLOC (dwMaxValueLen)) == NULL) { TRACE0 (ANY, "ElGetCustomAuthData: MALLOC failed for pbValueBuf"); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; }
for (dwIndex = 0; dwIndex < dwNumValues; dwIndex++) { dwTempValueNameLen = dwMaxValueNameLen; dwValueData = dwMaxValueLen; ZeroMemory ((VOID *)pwszValueName, dwMaxValueNameLen*sizeof(WCHAR)); ZeroMemory ((VOID *)pbValueBuf, dwMaxValueLen); if ((lError = RegEnumValue ( hkey1, dwIndex, pwszValueName, &dwTempValueNameLen, NULL, NULL, pbValueBuf, &dwValueData )) != ERROR_SUCCESS) { if (lError != ERROR_MORE_DATA) { break; } lError = ERROR_SUCCESS; }
if (dwValueData < sizeof (EAPOL_INTF_PARAMS)) { lError = ERROR_INVALID_DATA; TRACE0 (ANY, "ElGetCustomAuthData: dwValueData < sizeof (EAPOL_INTF_PARAMS)"); break; } pRegParams = (EAPOL_INTF_PARAMS *)pbValueBuf;
if (((DWORD)_wtol(pwszValueName)) > dwMaxValueName) { dwMaxValueName = _wtol (pwszValueName); }
if (!memcmp (pRegParams->bSSID, pbSSID, dwSizeOfSSID)) { fFoundValue = TRUE; break; } } if ((lError != ERROR_SUCCESS) && (lError != ERROR_NO_MORE_ITEMS)) { dwRetCode = (DWORD)lError; TRACE1 (ANY, "ElGetCustomAuthData: RegEnumValue 2 failed with error %ld", dwRetCode); break; } else { lError = ERROR_SUCCESS; }
LNotFoundValue:
// For SSIDs for which there is no blob stored, create default blob
// For default SSID, there should have been a blob created
if (!fFoundValue) { if ((dwRetCode = ElCreateDefaultEapData (&dwDefaultValueLen, NULL)) == ERROR_BUFFER_TOO_SMALL) { EAPOL_INTF_PARAMS IntfParams; IntfParams.dwVersion = EAPOL_CURRENT_VERSION; if ((pbDefaultValue = MALLOC (dwDefaultValueLen)) == NULL) { TRACE0 (ANY, "ElGetCustomAuthData: MALLOC failed for Conn Prop"); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; } if ((dwRetCode = ElCreateDefaultEapData (&dwDefaultValueLen, pbDefaultValue)) != NO_ERROR) { TRACE1 (ANY, "ElGetCustomAuthData: ElCreateDefaultEapData failed with error (%ld)", dwRetCode); break; } pbEapBlob = (BYTE *)&IntfParams; dwEapBlob = sizeof (EAPOL_INTF_PARAMS); if ((dwRetCode = ElSetEapData ( DEFAULT_EAP_TYPE, &dwEapBlob, &pbEapBlob, sizeof (EAPOL_INTF_PARAMS), dwDefaultValueLen, pbDefaultValue )) != NO_ERROR) { TRACE1 (ANY, "ElGetCustomAuthData: ElSetEapData failed with error %ld", dwRetCode); break; } // Assign to pbDefaultValue for freeing later on
FREE (pbDefaultValue); pbDefaultValue = pbEapBlob; dwDefaultValueLen = dwEapBlob; } else { TRACE0 (ANY, "ElGetCustomAuthData: ElCreateDefaultEapData should have failed !!!"); dwRetCode = ERROR_CAN_NOT_COMPLETE; break; }
// Use pbDefaultValue & dwDefaultValueLen
pbEapBlob = pbDefaultValue; dwEapBlob = dwDefaultValueLen; } else { if (fFoundValue) { // Use pbValueBuf & dwValueData
pbEapBlob = pbValueBuf; dwEapBlob = dwValueData; } }
// If default blob is not present, exit
if ((pbEapBlob == NULL) && (dwEapBlob == 0)) { TRACE0 (ANY, "ElGetCustomAuthData: (pbEapBlob == NULL) && (dwEapBlob == 0)"); dwRetCode = ERROR_INVALID_DATA; break; }
if ((dwRetCode = ElGetEapData ( dwEapTypeId, dwEapBlob, pbEapBlob, sizeof (EAPOL_INTF_PARAMS), &dwAuthData, &pbAuthData )) != NO_ERROR) { TRACE1 (ANY, "ElGetCustomAuthData: ElGetEapData failed with error %ld", dwRetCode); break; }
pbAuthDataIn = pbAuthData; dwAuthDataIn = dwAuthData;
// Get the policy data, if any
// If there is policy data use it instead of the registry setting
if ((dwRetCode = ElGetPolicyCustomAuthData ( dwEapTypeId, dwSizeOfSSID, pbSSID, &pbAuthDataIn, &dwAuthDataIn, &pbAuthData, &dwAuthData )) == NO_ERROR) { TRACE0 (ANY, "ElGetCustomAuthData: POLICY: Initialized with Policy data"); fFreeAuthData = TRUE; } else { if (dwRetCode != ERROR_FILE_NOT_FOUND) { TRACE1 (ANY, "ElGetCustomAuthData: ElGetPolicyCustomAuthData returned error %ld", dwRetCode); } dwRetCode = NO_ERROR; }
// Return the data if sufficient space allocated
if ((pbConnInfo != NULL) && (*pdwInfoSize >= dwAuthData)) { memcpy (pbConnInfo, pbAuthData, dwAuthData); } else { dwRetCode = ERROR_BUFFER_TOO_SMALL; } *pdwInfoSize = dwAuthData;
} while (FALSE);
if (hkey != NULL) { RegCloseKey (hkey); } if (hkey1 != NULL) { RegCloseKey (hkey1); } if (pbValueBuf != NULL) { FREE (pbValueBuf); } if (pbDefaultValue != NULL) { FREE (pbDefaultValue); } if (pwszValueName != NULL) { FREE (pwszValueName); } if (fFreeAuthData) { if (pbAuthData != NULL) { FREE (pbAuthData); } }
return dwRetCode; }
//
// ElReAuthenticateInterface
//
// Description:
//
// Function called to reinitiate authentication on an interface
//
// Arguments:
//
// pwszGUID - pointer to GUID string for the interface
//
// Return values:
//
// NO_ERROR - success
// non-zero - error
//
DWORD ElReAuthenticateInterface ( IN WCHAR *pwszGUID ) { BYTE *pbData = NULL; DWORD dwEventStatus = 0; BOOLEAN fDecrWorkerThreadCount = FALSE; DWORD dwRetCode = NO_ERROR;
do { if (g_hEventTerminateEAPOL == NULL) { dwRetCode = NO_ERROR; break; } if (( dwEventStatus = WaitForSingleObject ( g_hEventTerminateEAPOL, 0)) == WAIT_FAILED) { dwRetCode = GetLastError (); break; } if (dwEventStatus == WAIT_OBJECT_0) { dwRetCode = NO_ERROR; break; }
fDecrWorkerThreadCount = TRUE; InterlockedIncrement (&g_lWorkerThreads);
pbData = (BYTE *) MALLOC ((wcslen(pwszGUID)+1)*sizeof(WCHAR)); if (pbData == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; } wcscpy ((WCHAR *)pbData, pwszGUID);
if (!QueueUserWorkItem ( (LPTHREAD_START_ROUTINE)ElReAuthenticateInterfaceWorker, (PVOID)pbData, WT_EXECUTELONGFUNCTION)) { dwRetCode = GetLastError(); TRACE1 (DEVICE, "ElPostEapConfigChanged: QueueUserWorkItem failed with error %ld", dwRetCode); break; } else { fDecrWorkerThreadCount = FALSE; } } while (FALSE);
if (dwRetCode != NO_ERROR) { if (pbData != NULL) { FREE (pbData); } } if (fDecrWorkerThreadCount) { InterlockedDecrement (&g_lWorkerThreads); }
return dwRetCode; }
//
// ElReAuthenticateInterfaceWorker
//
// Description:
//
// Worker function called to reinitiate authentication on an interface
//
// Arguments:
//
// pwszGUID - pointer to GUID string for the interface
//
// Return values:
//
// NO_ERROR - success
// non-zero - error
//
DWORD WINAPI ElReAuthenticateInterfaceWorker ( IN PVOID pvContext ) { PWCHAR pwszGUID = NULL; DWORD dwRetCode = NO_ERROR;
do { pwszGUID = (PWCHAR)pvContext;
// Do not shutdown interface, merely restart authentication
#if 0
if ((dwRetCode = ElShutdownInterface (pwszGUID)) != NO_ERROR) { TRACE1 (ANY, "ElReAuthenticateInterface: ElShutdownInterface failed with error %ld", dwRetCode); break; } #endif
if ((dwRetCode = ElEnumAndOpenInterfaces ( NULL, pwszGUID, 0, NULL)) != NO_ERROR) { TRACE1 (ANY, "ElReAuthenticateInterface: ElEnumAndOpenInterfaces returned error %ld", dwRetCode); } } while (FALSE);
if (pvContext != NULL) { FREE (pvContext); } InterlockedDecrement (&g_lWorkerThreads);
return dwRetCode; }
//
// ElQueryInterfaceState
//
// Description:
//
// Function called to query the EAPOL state for an interface
//
// Arguments:
//
// pwszGUID - pointer to GUID string for the interface
// pIntfState - pointer to interface state structure
//
// Return values:
//
// NO_ERROR - success
// non-zero - error
//
DWORD ElQueryInterfaceState ( IN WCHAR *pwszGUID, IN OUT EAPOL_INTF_STATE *pIntfState ) { EAPOL_PCB *pPCB = NULL; BOOLEAN fPortReferenced = FALSE; BOOLEAN fPCBLocked = FALSE; DWORD dwRetCode = NO_ERROR;
do { ACQUIRE_WRITE_LOCK (&g_PCBLock); if ((pPCB = ElGetPCBPointerFromPortGUID (pwszGUID)) != NULL) { if (EAPOL_REFERENCE_PORT (pPCB)) { fPortReferenced = TRUE; } else { pPCB = NULL; } } RELEASE_WRITE_LOCK (&g_PCBLock); if (pPCB == NULL) { break; }
ACQUIRE_WRITE_LOCK (&(pPCB->rwLock)); fPCBLocked = TRUE;
if (pPCB->pSSID) { pIntfState->dwSizeOfSSID = pPCB->pSSID->SsidLength; memcpy (pIntfState->bSSID, pPCB->pSSID->Ssid, NDIS_802_11_SSID_LEN-sizeof(ULONG)); } else { pIntfState->dwSizeOfSSID = 0; }
if (pPCB->pszIdentity) { if ((pIntfState->pszEapIdentity = RpcCAlloc((strlen(pPCB->pszIdentity)+1)*sizeof(CHAR))) == NULL) { dwRetCode = GetLastError (); break; } strcpy (pIntfState->pszEapIdentity, (LPSTR)pPCB->pszIdentity); }
if ((pIntfState->pwszLocalMACAddr = RpcCAlloc(3*SIZE_MAC_ADDR*sizeof(WCHAR))) == NULL) { dwRetCode = GetLastError (); break; } ZeroMemory ((PVOID)pIntfState->pwszLocalMACAddr, 3*SIZE_MAC_ADDR*sizeof(WCHAR)); MACADDR_BYTE_TO_WSTR(pPCB->bSrcMacAddr, pIntfState->pwszLocalMACAddr);
if ((pIntfState->pwszRemoteMACAddr = RpcCAlloc(3*SIZE_MAC_ADDR*sizeof(WCHAR))) == NULL) { dwRetCode = GetLastError (); break; } ZeroMemory ((PVOID)pIntfState->pwszRemoteMACAddr, 3*SIZE_MAC_ADDR*sizeof(WCHAR)); MACADDR_BYTE_TO_WSTR(pPCB->bDestMacAddr, pIntfState->pwszRemoteMACAddr);
pIntfState->dwState = pPCB->State; pIntfState->dwEapUIState = pPCB->EapUIState; pIntfState->dwEAPOLAuthMode = pPCB->dwEAPOLAuthMode; pIntfState->dwEAPOLAuthenticationType = pPCB->PreviousAuthenticationType; pIntfState->dwEapType = pPCB->dwEapTypeToBeUsed; pIntfState->dwFailCount = pPCB->dwAuthFailCount; pIntfState->dwPhysicalMediumType = pPCB->PhysicalMediumType; } while (FALSE);
if (fPCBLocked) { RELEASE_WRITE_LOCK (&(pPCB->rwLock)); } if (fPortReferenced) { EAPOL_DEREFERENCE_PORT (pPCB); } if (dwRetCode != NO_ERROR) { RpcFree (pIntfState->pwszLocalMACAddr); RpcFree (pIntfState->pwszRemoteMACAddr); RpcFree (pIntfState->pszEapIdentity); pIntfState->pwszLocalMACAddr = NULL; pIntfState->pwszRemoteMACAddr = NULL; pIntfState->pszEapIdentity = NULL; }
return dwRetCode; }
//
// ElSetEapUserInfo
//
// Description:
//
// Function called to store the user data for an interface for a
// specific EAP type and SSID (if any). Data is stored in the HKCU hive.
// In case of EAP-TLS, this data will be the hash blob of the certificate
// chosen for the last successful authentication.
//
// Arguments:
//
// hToken - Handle to token for the logged on user
// pwszGUID - pointer to GUID string for the interface
// dwEapTypeId - EAP type for which user data is to be stored
// dwSizeOfSSID - Size of Special identifier if any for the EAP user blob
// pbSSID - Special identifier if any for the EAP user blob
// pbUserInfo - pointer to EAP user data blob
// dwInfoSize - Size of EAP user blob
//
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
DWORD ElSetEapUserInfo ( IN HANDLE hToken, IN WCHAR *pwszGUID, IN DWORD dwEapTypeId, IN DWORD dwSizeOfSSID, IN BYTE *pbSSID, IN PBYTE pbUserInfo, IN DWORD dwInfoSize ) { HKEY hkey = NULL; HKEY hkey1 = NULL; HKEY hkey2 = NULL; DWORD dwDisposition; DWORD dwNumValues = 0, dwMaxValueNameLen = 0, dwMaxValueLen = 0; DWORD dwIndex = 0, dwMaxValueName = 0; BYTE *pbValueBuf = NULL; DWORD dwValueData = 0; WCHAR wcszValueName[MAX_VALUENAME_LEN]; WCHAR *pwszValueName = NULL; BYTE *pbDefaultValue = NULL; DWORD dwDefaultValueLen = 0; BYTE *pbEapBlob = NULL, *pbEapBlobIn = NULL; DWORD dwEapBlob = 0; BOOLEAN fFoundValue = FALSE; EAPOL_INTF_PARAMS *pRegParams = NULL; EAPOL_INTF_PARAMS *pDefIntfParams = NULL; LONG lError = ERROR_SUCCESS; DWORD dwRetCode = ERROR_SUCCESS;
do { // Validate input params
if (hToken == NULL) { TRACE0 (ANY, "ElSetEapUserInfo: User Token = NULL"); break; } if (pwszGUID == NULL) { TRACE0 (ANY, "ElSetEapUserInfo: GUID = NULL"); break; } if (dwEapTypeId == 0) { TRACE0 (ANY, "ElSetEapUserInfo: GUID = NULL"); break; } if ((pbUserInfo == NULL) || (dwInfoSize <= 0)) { TRACE0 (ANY, "ElSetEapUserInfo: Invalid blob data"); break; }
// Get handle to HKCU
if ((dwRetCode = ElGetEapKeyFromToken ( hToken, &hkey)) != NO_ERROR) { TRACE1 (ANY, "ElSetEapUserInfo: Error in ElGetEapKeyFromToken %ld", dwRetCode); break; }
if ((lError = RegCreateKeyEx ( hkey, cwszEapKeyEapolUser, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_READ, NULL, &hkey1, &dwDisposition)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElSetEapUserInfo: Error in RegCreateKeyEx for base key, %ld", lError); dwRetCode = (DWORD)lError; break; }
// Get handle to HKCU\Software\...\UserEapInfo\<GUID>
if ((lError = RegCreateKeyEx ( hkey1, pwszGUID, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_READ, NULL, &hkey2, &dwDisposition)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElSetEapUserInfo: Error in RegCreateKeyEx for GUID, %ld", lError); dwRetCode = (DWORD)lError; break; }
if ((lError = RegQueryInfoKey ( hkey2, NULL, NULL, NULL, NULL, NULL, NULL, &dwNumValues, &dwMaxValueNameLen, &dwMaxValueLen, NULL, NULL )) != NO_ERROR) { dwRetCode = (DWORD)lError; TRACE1 (ANY, "ElSetEapUserInfo: RegQueryInfoKey failed with error %ld", dwRetCode); break; }
if (dwMaxValueNameLen > MAX_VALUENAME_LEN) { TRACE1 (ANY, "ElSetEapUserInfo: dwMaxValueNameLen too long (%ld)", dwMaxValueNameLen); } dwMaxValueNameLen = MAX_VALUENAME_LEN; if ((pbValueBuf = MALLOC (dwMaxValueLen)) == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (ANY, "ElSetEapUserInfo: MALLOC failed for pbValueBuf"); break; }
// Set correct SSID
if ((dwSizeOfSSID == 0) || (dwSizeOfSSID > MAX_SSID_LEN) || (pbSSID == NULL)) { pbSSID = g_bDefaultSSID; dwSizeOfSSID = MAX_SSID_LEN; }
for (dwIndex = 0; dwIndex < dwNumValues; dwIndex++) { dwValueData = dwMaxValueLen; dwMaxValueNameLen = MAX_VALUENAME_LEN; ZeroMemory (wcszValueName, MAX_VALUENAME_LEN*sizeof(WCHAR)); if ((lError = RegEnumValue ( hkey2, dwIndex, wcszValueName, &dwMaxValueNameLen, NULL, NULL, pbValueBuf, &dwValueData )) != ERROR_SUCCESS) { if (lError != ERROR_MORE_DATA) { break; } lError = ERROR_SUCCESS; }
if (dwValueData < sizeof (EAPOL_INTF_PARAMS)) { lError = ERROR_INVALID_DATA; TRACE2 (ANY, "ElSetEapUserInfo: dwValueData (%ld) < sizeof (EAPOL_INTF_PARAMS) (%ld)", dwValueData, sizeof (EAPOL_INTF_PARAMS)); break; } pRegParams = (EAPOL_INTF_PARAMS *)pbValueBuf;
if (((DWORD)_wtol(wcszValueName)) > dwMaxValueName) { dwMaxValueName = _wtol (wcszValueName); }
if (!memcmp (pRegParams->bSSID, pbSSID, dwSizeOfSSID)) { fFoundValue = TRUE; break; }
} if ((lError != ERROR_SUCCESS) && (lError != ERROR_NO_MORE_ITEMS)) { dwRetCode = (DWORD)lError; TRACE1 (ANY, "ElSetEapUserInfo: RegEnumValue 2 failed with error %ld", dwRetCode); break; } else { lError = ERROR_SUCCESS; }
if (!fFoundValue) { DWORD dwNewValueName = (dwMaxValueName >= dwNumValues)?(++dwMaxValueName):dwNumValues; _ltow (dwNewValueName, wcszValueName, 10); if ((pbDefaultValue = MALLOC (sizeof(EAPOL_INTF_PARAMS))) == NULL) { TRACE0 (ANY, "ElSetEapUserInfo: MALLOC failed for pbDefaultValue"); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; } // Mark that SSID for this entry
// Rest of the parameters are dummy for UserEapInfo
pDefIntfParams = (EAPOL_INTF_PARAMS *)pbDefaultValue; pDefIntfParams->dwSizeOfSSID = dwSizeOfSSID; memcpy (pDefIntfParams->bSSID, pbSSID, dwSizeOfSSID);
dwEapBlob = sizeof(EAPOL_INTF_PARAMS); pbEapBlob = pbDefaultValue; } else { // Use pbValueBuf & dwValueData
pbEapBlob = pbValueBuf; dwEapBlob = dwValueData; }
pbEapBlobIn = pbEapBlob; if ((dwRetCode = ElSetEapData ( dwEapTypeId, &dwEapBlob, &pbEapBlob, sizeof (EAPOL_INTF_PARAMS), dwInfoSize, pbUserInfo )) != NO_ERROR) { TRACE1 (ANY, "ElSetEapUserInfo: ElSetEapData failed with error %ld", dwRetCode); break; }
// Overwrite/Create new value
if ((lError = RegSetValueEx ( hkey2, wcszValueName, 0, REG_BINARY, pbEapBlob, dwEapBlob)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElSetEapUserInfo: Error in RegSetValueEx for SSID, %ld", lError); dwRetCode = (DWORD)lError; break; }
TRACE0 (ANY, "ElSetEapUserInfo: Set value succeeded");
} while (FALSE);
if (hkey != NULL) { RegCloseKey (hkey); } if (hkey1 != NULL) { RegCloseKey (hkey1); } if (hkey2 != NULL) { RegCloseKey (hkey2); } if ((pbEapBlob != pbEapBlobIn) && (pbEapBlob != NULL)) { FREE (pbEapBlob); } if (pbValueBuf != NULL) { FREE (pbValueBuf); } if (pbDefaultValue != NULL) { FREE (pbDefaultValue); }
return dwRetCode; }
//
// ElGetEapUserInfo
//
// Description:
//
// Function called to retrieve the user data for an interface for a
// specific EAP type and SSID (if any). Data is retrieved from the HKCU hive
//
// Arguments:
// hToken - Handle to token for the logged on user
// pwszGUID - pointer to GUID string for the interface
// dwEapTypeId - EAP type for which user data is to be stored
// dwSizeOfSSID - Size of Special identifier if any for the EAP user blob
// pbSSID - Special identifier if any for the EAP user blob
// pbUserInfo - output: pointer to EAP user data blob
// dwInfoSize - output: pointer to size of EAP user blob
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
DWORD ElGetEapUserInfo ( IN HANDLE hToken, IN WCHAR *pwszGUID, IN DWORD dwEapTypeId, IN DWORD dwSizeOfSSID, IN BYTE *pbSSID, IN OUT PBYTE pbUserInfo, IN OUT DWORD *pdwInfoSize ) { HKEY hkey = NULL; HKEY hkey1 = NULL; HKEY hkey2 = NULL; DWORD dwNumValues = 0, dwMaxValueNameLen = 0, dwTempValueNameLen = 0, dwMaxValueLen = 0; DWORD dwIndex = 0, dwMaxValueName = 0; WCHAR *pwszValueName = NULL; BYTE *pbValueBuf = NULL; DWORD dwValueData = 0; BYTE *pbDefaultValue = NULL; DWORD dwDefaultValueLen = 0; BYTE *pbEapBlob = NULL; DWORD dwEapBlob = 0; BYTE *pbAuthData = NULL; DWORD dwAuthData = 0; BOOLEAN fFoundValue = FALSE; EAPOL_INTF_PARAMS *pRegParams = NULL; LONG lError = ERROR_SUCCESS; DWORD dwRetCode = ERROR_SUCCESS;
do { // Validate input params
if (hToken == NULL) { TRACE0 (ANY, "ElGetEapUserInfo: User Token = NULL"); break; } if (pwszGUID == NULL) { TRACE0 (ANY, "ElGetEapUserInfo: GUID = NULL"); dwRetCode = ERROR_CAN_NOT_COMPLETE; break; } if (dwEapTypeId == 0) { TRACE0 (ANY, "ElGetEapUserInfo: GUID = NULL"); dwRetCode = ERROR_CAN_NOT_COMPLETE; break; }
// Get handle to HKCU
if ((dwRetCode = ElGetEapKeyFromToken ( hToken, &hkey)) != NO_ERROR) { TRACE1 (ANY, "ElGetEapUserInfo: Error in ElGetEapKeyFromToken %ld", dwRetCode); break; }
// Get handle to HKCU\Software\...\UserEapInfo\<GUID>
if ((lError = RegOpenKeyEx ( hkey, cwszEapKeyEapolUser, 0, KEY_READ, &hkey1 )) != ERROR_SUCCESS) { TRACE1 (ANY, "ElGetEapUserInfo: Error in RegOpenKeyEx for base key, %ld", lError); dwRetCode = (DWORD)lError; break; }
// Get handle to HKCU\Software\...\UserEapInfo\<GUID>
if ((lError = RegOpenKeyEx ( hkey1, pwszGUID, 0, KEY_READ, &hkey2 )) != ERROR_SUCCESS) { TRACE1 (ANY, "ElGetEapUserInfo: Error in RegOpenKeyEx for GUID, %ld", lError); dwRetCode = (DWORD)lError; break; }
// Set correct SSID
if ((dwSizeOfSSID == 0) || (dwSizeOfSSID > MAX_SSID_LEN) || (pbSSID == NULL)) { pbSSID = g_bDefaultSSID; dwSizeOfSSID = MAX_SSID_LEN; }
if ((lError = RegQueryInfoKey ( hkey2, NULL, NULL, NULL, NULL, NULL, NULL, &dwNumValues, &dwMaxValueNameLen, &dwMaxValueLen, NULL, NULL )) != NO_ERROR) { dwRetCode = (DWORD)lError; TRACE1 (ANY, "ElGetEapUserInfo: RegQueryInfoKey failed with error %ld", dwRetCode); break; }
if ((pwszValueName = MALLOC ((dwMaxValueNameLen + 1) * sizeof (WCHAR))) == NULL) { TRACE0 (ANY, "ElGetEapUserInfo: MALLOC failed for pwszValueName"); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; } dwMaxValueNameLen++; if ((pbValueBuf = MALLOC (dwMaxValueLen)) == NULL) { TRACE0 (ANY, "ElGetEapUserInfo: MALLOC failed for pbValueBuf"); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; }
for (dwIndex = 0; dwIndex < dwNumValues; dwIndex++) { dwValueData = dwMaxValueLen; dwTempValueNameLen = dwMaxValueNameLen; if ((lError = RegEnumValue ( hkey2, dwIndex, pwszValueName, &dwTempValueNameLen, NULL, NULL, pbValueBuf, &dwValueData )) != ERROR_SUCCESS) { if (lError != ERROR_MORE_DATA) { break; } lError = ERROR_SUCCESS; }
if (dwValueData < sizeof (EAPOL_INTF_PARAMS)) { TRACE0 (ANY, "ElGetEapUserInfo: dwValueData < sizeof (EAPOL_INTF_PARAMS)"); lError = ERROR_INVALID_DATA; break; } pRegParams = (EAPOL_INTF_PARAMS *)pbValueBuf;
if (((DWORD)_wtol(pwszValueName)) > dwMaxValueName) { dwMaxValueName = _wtol (pwszValueName); }
if (!memcmp (pRegParams->bSSID, pbSSID, dwSizeOfSSID)) { fFoundValue = TRUE; break; } } if ((lError != ERROR_SUCCESS) && (lError != ERROR_NO_MORE_ITEMS)) { dwRetCode = (DWORD)lError; TRACE1 (ANY, "ElGetEapUserInfo: RegEnumValue 2 failed with error %ld", dwRetCode); break; } else { lError = ERROR_SUCCESS; }
if (!fFoundValue) { pbEapBlob = NULL; dwEapBlob = 0; } else { // Use pbValueBuf & dwValueData
pbEapBlob = pbValueBuf; dwEapBlob = dwValueData; }
// If blob is not present, exit
if ((pbEapBlob == NULL) && (dwEapBlob == 0)) { TRACE0 (ANY, "ElGetEapUserInfo: (pbEapBlob == NULL) && (dwEapBlob == 0)"); *pdwInfoSize = 0; break; }
if ((dwRetCode = ElGetEapData ( dwEapTypeId, dwEapBlob, pbEapBlob, sizeof (EAPOL_INTF_PARAMS), &dwAuthData, &pbAuthData )) != NO_ERROR) { TRACE1 (ANY, "ElGetEapUserInfo: ElGetEapData failed with error %ld", dwRetCode); break; }
// Return the data if sufficient space allocated
if ((pbUserInfo != NULL) && (*pdwInfoSize >= dwAuthData)) { memcpy (pbUserInfo, pbAuthData, dwAuthData); } else { dwRetCode = ERROR_BUFFER_TOO_SMALL; } *pdwInfoSize = dwAuthData;
TRACE0 (ANY, "ElGetEapUserInfo: Get value succeeded");
} while (FALSE);
if (hkey != NULL) { RegCloseKey (hkey); } if (hkey1 != NULL) { RegCloseKey (hkey1); } if (hkey2 != NULL) { RegCloseKey (hkey2); } if (pbValueBuf != NULL) { FREE (pbValueBuf); } if (pbDefaultValue != NULL) { FREE (pbDefaultValue); } if (pwszValueName != NULL) { FREE (pwszValueName); }
return dwRetCode; }
//
// ElDeleteEapUserInfo
//
// Description:
//
// Function called to delete the user data for an interface for a
// specific EAP type and SSID (if any). Data is stored in the HKCU hive.
// In case of EAP-TLS, this data will be the hash blob of the certificate
// chosen for the last successful authentication.
//
// Arguments:
//
// hToken - Handle to token for the logged on user
// pwszGUID - pointer to GUID string for the interface
// dwEapTypeId - EAP type for which user data is to be stored
// dwSizeOfSSID - Size of Special identifier if any for the EAP user blob
// pbSSID - Special identifier if any for the EAP user blob
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
DWORD ElDeleteEapUserInfo ( IN HANDLE hToken, IN WCHAR *pwszGUID, IN DWORD dwEapTypeId, IN DWORD dwSizeOfSSID, IN BYTE *pbSSID ) { HKEY hkey = NULL; HKEY hkey1 = NULL; HKEY hkey2 = NULL; DWORD dwDisposition; DWORD dwNumValues = 0, dwMaxValueNameLen = 0, dwTempValueNameLen = 0, dwMaxValueLen = 0; DWORD dwIndex = 0, dwMaxValueName = 0; BYTE *pbValueBuf = NULL; DWORD dwValueData = 0; WCHAR *pwszValueName = NULL; DWORD dwDefaultValueLen = 0; BYTE *pbEapBlob = NULL, *pbEapBlobIn = NULL; DWORD dwEapBlob = 0; BOOLEAN fFoundValue = FALSE; EAPOL_INTF_PARAMS *pRegParams = NULL; EAPOL_INTF_PARAMS *pDefIntfParams = NULL; LONG lError = ERROR_SUCCESS; DWORD dwRetCode = ERROR_SUCCESS;
do { // Validate input params
if (hToken == NULL) { TRACE0 (ANY, "ElDeleteEapUserInfo: User Token = NULL"); break; } if (pwszGUID == NULL) { TRACE0 (ANY, "ElDeleteEapUserInfo: GUID = NULL"); break; } if (dwEapTypeId == 0) { TRACE0 (ANY, "ElDeleteEapUserInfo: GUID = NULL"); break; }
// Get handle to HKCU
if ((dwRetCode = ElGetEapKeyFromToken ( hToken, &hkey)) != NO_ERROR) { TRACE1 (ANY, "ElDeleteEapUserInfo: Error in ElGetEapKeyFromToken %ld", dwRetCode); break; }
if ((lError = RegOpenKeyEx ( hkey, cwszEapKeyEapolUser, 0, KEY_ALL_ACCESS, &hkey1)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElDeleteEapUserInfo: Error in RegOpenKeyEx for base key, %ld", lError); dwRetCode = (DWORD)lError; break; }
// Get handle to HKCU\Software\...\UserEapInfo\<GUID>
if ((lError = RegOpenKeyEx ( hkey1, pwszGUID, 0, KEY_ALL_ACCESS, &hkey2)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElDeleteEapUserInfo: Error in RegOpenKeyEx for GUID, %ld", lError); dwRetCode = (DWORD)lError; break; }
if ((lError = RegQueryInfoKey ( hkey2, NULL, NULL, NULL, NULL, NULL, NULL, &dwNumValues, &dwMaxValueNameLen, &dwMaxValueLen, NULL, NULL )) != NO_ERROR) { dwRetCode = (DWORD)lError; TRACE1 (ANY, "ElDeleteEapUserInfo: RegQueryInfoKey failed with error %ld", dwRetCode); break; }
if ((pwszValueName = MALLOC ((dwMaxValueNameLen + 1) * sizeof (WCHAR))) == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (ANY, "ElDeleteEapUserInfo: MALLOC failed for pwszValueName"); break; } dwMaxValueNameLen++; if ((pbValueBuf = MALLOC (dwMaxValueLen)) == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (ANY, "ElDeleteEapUserInfo: MALLOC failed for pbValueBuf"); break; }
// Set correct SSID
if ((dwSizeOfSSID == 0) || (dwSizeOfSSID > MAX_SSID_LEN) || (pbSSID == NULL)) { pbSSID = g_bDefaultSSID; dwSizeOfSSID = MAX_SSID_LEN; }
for (dwIndex = 0; dwIndex < dwNumValues; dwIndex++) { dwValueData = dwMaxValueLen; dwTempValueNameLen = dwMaxValueNameLen; if ((lError = RegEnumValue ( hkey2, dwIndex, pwszValueName, &dwTempValueNameLen, NULL, NULL, pbValueBuf, &dwValueData )) != ERROR_SUCCESS) { if (lError != ERROR_MORE_DATA) { break; } lError = ERROR_SUCCESS; }
if (dwValueData < sizeof (EAPOL_INTF_PARAMS)) { lError = ERROR_INVALID_DATA; TRACE0 (ANY, "ElDeleteEapUserInfo: dwValueData < sizeof (EAPOL_INTF_PARAMS)"); break; } pRegParams = (EAPOL_INTF_PARAMS *)pbValueBuf;
if (((DWORD)_wtol(pwszValueName)) > dwMaxValueName) { dwMaxValueName = _wtol (pwszValueName); }
if (!memcmp (pRegParams->bSSID, pbSSID, dwSizeOfSSID)) { fFoundValue = TRUE; break; } } if ((lError != ERROR_SUCCESS) && (lError != ERROR_NO_MORE_ITEMS)) { dwRetCode = (DWORD)lError; TRACE1 (ANY, "ElDeleteEapUserInfo: RegEnumValue 2 failed with error %ld", dwRetCode); break; } else { lError = ERROR_SUCCESS; }
if (!fFoundValue) { break; } else { // Use pbValueBuf & dwValueData
pbEapBlob = pbValueBuf; dwEapBlob = dwValueData; }
pbEapBlobIn = pbEapBlob; if ((dwRetCode = ElSetEapData ( dwEapTypeId, &dwEapBlob, &pbEapBlob, sizeof(EAPOL_INTF_PARAMS), 0, NULL )) != NO_ERROR) { TRACE1 (ANY, "ElDeleteEapUserInfo: ElSetEapData failed with error %ld", dwRetCode); break; }
// Overwrite value
if ((lError = RegSetValueEx ( hkey2, pwszValueName, 0, REG_BINARY, pbEapBlob, dwEapBlob)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElDeleteEapUserInfo: Error in RegSetValueEx for SSID, %ld", lError); dwRetCode = (DWORD)lError; break; }
TRACE0 (ANY, "ElDeleteEapUserInfo: Delete value succeeded");
} while (FALSE);
if (hkey != NULL) { RegCloseKey (hkey); } if (hkey1 != NULL) { RegCloseKey (hkey1); } if (hkey2 != NULL) { RegCloseKey (hkey2); } if ((pbEapBlob != pbEapBlobIn) && (pbEapBlob != NULL)) { FREE (pbEapBlob); } if (pbValueBuf != NULL) { FREE (pbValueBuf); } if (pwszValueName != NULL) { FREE (pwszValueName); }
return dwRetCode; }
//
// ElGetInterfaceParams
//
// Description:
//
// Function called to retrieve the EAPOL parameters for an interface, stored
// in the HKLM hive.
//
// Arguments:
//
// pwszGUID - pointer to GUID string for the interface
// pIntfParams - pointer to interface parameter structure
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
DWORD ElGetInterfaceParams ( IN WCHAR *pwszGUID, IN OUT EAPOL_INTF_PARAMS *pIntfParams ) { HKEY hkey = NULL; HKEY hkey1 = NULL; BYTE *pbSSID = NULL; BYTE bSSID[MAX_SSID_LEN]; DWORD dwSizeOfSSID = 0; DWORD dwNumValues = 0, dwMaxValueNameLen = 0, dwTempValueNameLen = 0, dwMaxValueLen = 0; DWORD dwIndex = 0, dwMaxValueName = 0; WCHAR *pwszValueName = NULL; BYTE *pbValueBuf = NULL; DWORD dwValueData = 0; BYTE *pbDefaultValue = NULL; DWORD dwDefaultValueLen = 0; BYTE *pbEapBlob = NULL; DWORD dwEapBlob = 0; BOOLEAN fFoundValue = FALSE; EAPOL_INTF_PARAMS *pRegParams = NULL; EAPOL_POLICY_PARAMS EAPOLPolicyParams = {0}; LONG lError = ERROR_SUCCESS; EAPOL_PCB *pPCB = NULL; DWORD dwRetCode = NO_ERROR;
do { // Validate input params
if (pwszGUID == NULL) { dwRetCode = ERROR_CAN_NOT_COMPLETE; TRACE0 (ANY, "ElGetInterfaceParams: GUID = NULL"); break; }
if (pIntfParams == NULL) { dwRetCode = ERROR_CAN_NOT_COMPLETE; break; }
// Work with appropriate SSID
if (pIntfParams->dwSizeOfSSID != 0) { dwSizeOfSSID = pIntfParams->dwSizeOfSSID; if (dwSizeOfSSID > MAX_SSID_LEN) { dwRetCode = ERROR_INVALID_PARAMETER; TRACE2 (ANY, "ElGetInterfaceParams: dwSizeOfSSID (%ld) > MAX_SSID_LEN (%ld)", dwSizeOfSSID, MAX_SSID_LEN); break; } pbSSID = pIntfParams->bSSID; } else { ACQUIRE_WRITE_LOCK (&g_PCBLock);
if ((pPCB = ElGetPCBPointerFromPortGUID (pwszGUID)) != NULL) { ACQUIRE_WRITE_LOCK (&(pPCB->rwLock)); if ((pPCB->pSSID != NULL) && (pPCB->MediaState != MEDIA_STATE_DISCONNECTED)) { dwSizeOfSSID = pPCB->pSSID->SsidLength; ZeroMemory (bSSID, MAX_SSID_LEN); memcpy (bSSID, pPCB->pSSID->Ssid, pPCB->pSSID->SsidLength); pbSSID = bSSID; } RELEASE_WRITE_LOCK (&(pPCB->rwLock)); }
RELEASE_WRITE_LOCK (&g_PCBLock);
if (dwSizeOfSSID == 0) { dwSizeOfSSID = MAX_SSID_LEN; pbSSID = g_bDefaultSSID; } }
// Get handle to HKLM\Software\Microsoft\EAPOL\Parameters\Interfaces
if ((lError = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, cwszEapKeyEapolConn, 0, KEY_READ, &hkey )) != ERROR_SUCCESS) { // Assume no value is found and proceed ahead
if (lError == ERROR_FILE_NOT_FOUND) { lError = ERROR_SUCCESS; fFoundValue = FALSE; goto LNotFoundValue; } else { TRACE1 (ANY, "ElGetInterfaceParams: Error in RegOpenKeyEx for base key, %ld", lError); dwRetCode = (DWORD)lError; break; } }
// Get handle to HKLM\Software\...\Interfaces\<GUID>
if ((lError = RegOpenKeyEx ( hkey, pwszGUID, 0, KEY_READ, &hkey1 )) != ERROR_SUCCESS) { // Assume no value is found and proceed ahead
if (lError == ERROR_FILE_NOT_FOUND) { lError = ERROR_SUCCESS; fFoundValue = FALSE; goto LNotFoundValue; } else { TRACE1 (ANY, "ElGetInterfaceParams: Error in RegOpenKeyEx for GUID, %ld", lError); dwRetCode = (DWORD)lError; break; } }
if ((lError = RegQueryInfoKey ( hkey1, NULL, NULL, NULL, NULL, NULL, NULL, &dwNumValues, &dwMaxValueNameLen, &dwMaxValueLen, NULL, NULL )) != NO_ERROR) { dwRetCode = (DWORD)lError; TRACE1 (ANY, "ElGetInterfaceParams: RegQueryInfoKey failed with error %ld", dwRetCode); break; }
if ((pwszValueName = MALLOC ((dwMaxValueNameLen + 1) * sizeof (WCHAR))) == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (ANY, "ElGetInterfaceParams: MALLOC failed for pwszValueName"); break; } dwMaxValueNameLen++; if ((pbValueBuf = MALLOC (dwMaxValueLen)) == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (ANY, "ElGetInterfaceParams: MALLOC failed for pbValueBuf"); break; }
for (dwIndex = 0; dwIndex < dwNumValues; dwIndex++) { dwValueData = dwMaxValueLen; dwTempValueNameLen = dwMaxValueNameLen; if ((lError = RegEnumValue ( hkey1, dwIndex, pwszValueName, &dwTempValueNameLen, NULL, NULL, pbValueBuf, &dwValueData )) != ERROR_SUCCESS) { if (lError != ERROR_MORE_DATA) { break; } lError = ERROR_SUCCESS; }
if (dwValueData < sizeof (EAPOL_INTF_PARAMS)) { TRACE0 (ANY, "ElGetInterfaceParams: dwValueData < sizeof (EAPOL_INTF_PARAMS)"); lError = ERROR_INVALID_DATA; break; } pRegParams = (EAPOL_INTF_PARAMS *)pbValueBuf;
if (((DWORD)_wtol(pwszValueName)) > dwMaxValueName) { dwMaxValueName = _wtol (pwszValueName); }
if (!memcmp (pRegParams->bSSID, pbSSID, dwSizeOfSSID)) { fFoundValue = TRUE; break; } } if ((lError != ERROR_SUCCESS) && (lError != ERROR_NO_MORE_ITEMS)) { dwRetCode = (DWORD)lError; break; } else { lError = ERROR_SUCCESS; }
LNotFoundValue:
if (!fFoundValue) { if ((pbDefaultValue = MALLOC (sizeof (EAPOL_INTF_PARAMS))) == NULL) { lError = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (ANY, "ElGetInterfaceParams: MALLOC failed for pbDefaultValue"); break; } pRegParams = (EAPOL_INTF_PARAMS *)pbDefaultValue; pRegParams->dwEapType = DEFAULT_EAP_TYPE; pRegParams->dwEapFlags = DEFAULT_EAP_STATE; pRegParams->dwVersion = EAPOL_CURRENT_VERSION; pRegParams->dwSizeOfSSID = dwSizeOfSSID; memcpy (pRegParams->bSSID, pbSSID, dwSizeOfSSID); dwDefaultValueLen = sizeof(EAPOL_INTF_PARAMS);
// Use pbDefaultValue & dwDefaultValueLen
pbEapBlob = pbDefaultValue; dwEapBlob = dwDefaultValueLen; } else { if (dwSizeOfSSID == MAX_SSID_LEN) { if (!memcmp (pbSSID, g_bDefaultSSID, MAX_SSID_LEN)) { pRegParams = (EAPOL_INTF_PARAMS *)pbValueBuf; if ((pRegParams->dwVersion != EAPOL_CURRENT_VERSION) && (pRegParams->dwEapType == EAP_TYPE_TLS)) { pRegParams->dwVersion = EAPOL_CURRENT_VERSION; pRegParams->dwEapFlags |= DEFAULT_MACHINE_AUTH_STATE; pRegParams->dwEapFlags &= ~EAPOL_GUEST_AUTH_ENABLED; } } }
// Use pbValueBuf & dwValueData
pbEapBlob = pbValueBuf; dwEapBlob = dwValueData; }
if ((dwRetCode = ElGetPolicyInterfaceParams ( dwSizeOfSSID, pbSSID, &EAPOLPolicyParams )) == NO_ERROR) { TRACE0 (ANY, "ElGetInterfaceParams: POLICY: ElGetPolicyInterfaceParams found relevant data"); pbEapBlob = (PBYTE)(&(EAPOLPolicyParams.IntfParams)); dwEapBlob = sizeof(EAPOL_INTF_PARAMS); } else { if (dwRetCode != ERROR_FILE_NOT_FOUND) { TRACE1 (ANY, "ElGetInterfaceParams: ElGetPolicyInterfaceParams failed with error (%ld)", dwRetCode); } dwRetCode = NO_ERROR; }
// Existing blob is not valid
if ((dwEapBlob < sizeof(EAPOL_INTF_PARAMS))) { dwRetCode = ERROR_FILE_NOT_FOUND; TRACE0 (ANY, "ElGetInterfaceParams: (dwEapBlob < sizeof(EAPOL_INTF_PARAMS)) || (pbEapBlob == NULL)"); break; }
memcpy ((BYTE *)pIntfParams, (BYTE *)pbEapBlob, sizeof(EAPOL_INTF_PARAMS)); } while (FALSE);
if (hkey != NULL) { RegCloseKey (hkey); } if (hkey1 != NULL) { RegCloseKey (hkey1); } if (pbValueBuf != NULL) { FREE (pbValueBuf); } if (pbDefaultValue != NULL) { FREE (pbDefaultValue); } if (pwszValueName != NULL) { FREE (pwszValueName); }
return dwRetCode; }
//
// ElSetInterfaceParams
//
// Description:
//
// Function called to set the EAPOL parameters for an interface, in the HKLM
// hive
//
// Arguments:
//
// pwszGUID - Pointer to GUID string for the interface
// pIntfParams - pointer to interface parameter structure
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
//
DWORD ElSetInterfaceParams ( IN WCHAR *pwszGUID, IN OUT EAPOL_INTF_PARAMS *pIntfParams ) { HKEY hkey = NULL; HKEY hkey1 = NULL; DWORD dwDisposition; BYTE *pbSSID = NULL; DWORD dwSizeOfSSID = 0; DWORD dwNumValues = 0, dwMaxValueNameLen = 0, dwMaxValueLen = 0; DWORD dwIndex = 0, dwMaxValueName = 0; WCHAR wcszValueName[MAX_VALUENAME_LEN]; BYTE *pbValueBuf = NULL; DWORD dwValueData = 0; BYTE *pbDefaultValue = NULL; DWORD dwDefaultValueLen = 0; BYTE *pbEapBlob = NULL; DWORD dwEapBlob = 0; BOOLEAN fFoundValue = FALSE; EAPOL_INTF_PARAMS *pRegParams = NULL; LONG lError = ERROR_SUCCESS; DWORD dwRetCode = NO_ERROR;
do { // Validate input params
if (pwszGUID == NULL) { TRACE0 (ANY, "ElSetInterfaceParams: GUID = NULL"); break; }
if (pIntfParams == NULL) { dwRetCode = ERROR_CAN_NOT_COMPLETE; break; }
TRACE1 (ANY, "Setting stuff in registry for %ws", pwszGUID);
// Get handle to HKLM\Software\Microsoft\EAPOL\Parameters\Interfaces
if ((lError = RegCreateKeyEx ( HKEY_LOCAL_MACHINE, cwszEapKeyEapolConn, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_READ, NULL, &hkey, &dwDisposition)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElSetInterfaceParams: Error in RegCreateKeyEx for base key, %ld", lError); dwRetCode = (DWORD)lError; break; }
// Get handle to HKLM\Software\...\Interfaces\<GUID>
if ((lError = RegCreateKeyEx ( hkey, pwszGUID, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_READ, NULL, &hkey1, &dwDisposition)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElSetInterfaceParams: Error in RegCreateKeyEx for GUID, %ld", lError); dwRetCode = (DWORD)lError; break; }
// Select correct SSID value
if (pIntfParams->dwSizeOfSSID != 0) { dwSizeOfSSID = pIntfParams->dwSizeOfSSID; if (dwSizeOfSSID > MAX_SSID_LEN) { dwRetCode = ERROR_INVALID_PARAMETER; TRACE2 (ANY, "ElSetInterfaceParams: dwSizeOfSSID (%ld) > MAX_SSID_LEN (%ld)", dwSizeOfSSID, MAX_SSID_LEN); break; } pbSSID = pIntfParams->bSSID; } else { dwSizeOfSSID = MAX_SSID_LEN; pbSSID = g_bDefaultSSID; }
if ((lError = RegQueryInfoKey ( hkey1, NULL, NULL, NULL, NULL, NULL, NULL, &dwNumValues, &dwMaxValueNameLen, &dwMaxValueLen, NULL, NULL )) != NO_ERROR) { dwRetCode = (DWORD)lError; break; }
if (dwMaxValueNameLen > MAX_VALUENAME_LEN) { dwRetCode = ERROR_INVALID_DATA; TRACE1 (ANY, "ElSetInterfaceParams: dwMaxValueNameLen too long (%ld)", dwMaxValueNameLen); break; } if ((pbValueBuf = MALLOC (dwMaxValueLen)) == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; }
for (dwIndex = 0; dwIndex < dwNumValues; dwIndex++) { dwValueData = dwMaxValueLen; dwMaxValueNameLen = MAX_VALUENAME_LEN; ZeroMemory (wcszValueName, MAX_VALUENAME_LEN*sizeof(WCHAR));
if ((lError = RegEnumValue ( hkey1, dwIndex, wcszValueName, &dwMaxValueNameLen, NULL, NULL, pbValueBuf, &dwValueData )) != ERROR_SUCCESS) { if (lError != ERROR_MORE_DATA) { break; } lError = ERROR_SUCCESS; }
if (dwValueData < sizeof (EAPOL_INTF_PARAMS)) { lError = ERROR_INVALID_DATA; TRACE0 (ANY, "ElSetInterfaceParams: dwValueData < sizeof (EAPOL_INTF_PARAMS)"); break; } pRegParams = (EAPOL_INTF_PARAMS *)pbValueBuf;
if (((DWORD)_wtol(wcszValueName)) > dwMaxValueName) { dwMaxValueName = _wtol (wcszValueName); }
if (!memcmp (pRegParams->bSSID, pbSSID, dwSizeOfSSID)) { fFoundValue = TRUE; break; }
} if ((lError != ERROR_SUCCESS) && (lError != ERROR_NO_MORE_ITEMS)) { dwRetCode = (DWORD)lError; TRACE1 (ANY, "ElSetInterfaceParams: RegEnumValue 2 failed with error %ld", dwRetCode); break; } else { lError = ERROR_SUCCESS; }
if (!fFoundValue) { DWORD dwNewValueName = (dwMaxValueName >= dwNumValues)?(++dwMaxValueName):dwNumValues; _ltow (dwNewValueName, wcszValueName, 10); } else { // Use pbValueBuf & dwValueData
pbEapBlob = pbValueBuf; dwEapBlob = dwValueData; }
if ((dwEapBlob < sizeof(EAPOL_INTF_PARAMS)) && (pbEapBlob != NULL)) { TRACE0 (ANY, "ElSetInterfaceParams: (dwEapBlob < sizeof(EAPOL_INTF_PARAMS)) && (pbEapBlob != NULL)"); break; }
if (pbEapBlob != NULL) { memcpy ((BYTE *)pbEapBlob, (BYTE *)pIntfParams, sizeof(EAPOL_INTF_PARAMS)); } else { pbEapBlob = (BYTE *)pIntfParams; dwEapBlob = sizeof(EAPOL_INTF_PARAMS); } pRegParams = (EAPOL_INTF_PARAMS *)pbEapBlob; pRegParams->dwVersion = EAPOL_CURRENT_VERSION; pRegParams->dwSizeOfSSID = dwSizeOfSSID; memcpy (pRegParams->bSSID, pbSSID, dwSizeOfSSID);
// Overwrite/Create new value
if ((lError = RegSetValueEx ( hkey1, wcszValueName, 0, REG_BINARY, pbEapBlob, dwEapBlob)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElSetInterfaceParams: Error in RegSetValueEx for SSID, %ld", lError); dwRetCode = (DWORD)lError; break; }
TRACE0 (ANY, "ElSetInterfaceParams: Succeeded");
} while (FALSE);
if (hkey != NULL) { RegCloseKey (hkey); } if (hkey1 != NULL) { RegCloseKey (hkey1); } if (pbValueBuf != NULL) { FREE (pbValueBuf); } if (pbDefaultValue != NULL) { FREE (pbDefaultValue); }
return dwRetCode; }
//
// ElGetEapData
//
// Description:
//
// Function to extract Eap Data out of a blob containing many EAP data
//
// Arguments:
// dwEapType -
// dwSizeOfIn -
// pbBufferIn -
// dwOffset -
// pdwSizeOfOut -
// ppbBufferOut -
//
// Return values:
//
//
DWORD ElGetEapData ( IN DWORD dwEapType, IN DWORD dwSizeOfIn, IN BYTE *pbBufferIn, IN DWORD dwOffset, IN DWORD *pdwSizeOfOut, IN PBYTE *ppbBufferOut ) { DWORD dwRetCode = NO_ERROR; DWORD cbOffset = 0; EAPOL_AUTH_DATA *pCustomData = NULL;
do { *pdwSizeOfOut = 0; *ppbBufferOut = NULL;
if (pbBufferIn == NULL) { break; }
// Align to start of EAP blob
cbOffset = dwOffset;
while (cbOffset < dwSizeOfIn) { pCustomData = (EAPOL_AUTH_DATA *) ((PBYTE) pbBufferIn + cbOffset);
if (pCustomData->dwEapType == dwEapType) { break; } cbOffset += sizeof (EAPOL_AUTH_DATA) + pCustomData->dwSize; }
if (cbOffset < dwSizeOfIn) { *pdwSizeOfOut = pCustomData->dwSize; *ppbBufferOut = pCustomData->bData; } } while (FALSE);
return dwRetCode; }
//
// ElSetEapData
//
// Description:
//
// Function to set Eap Data in a blob containing many EAP data
//
// Arguments:
// dwEapType -
// dwSizeOfIn -
// pbBufferIn -
// dwOffset -
// pdwSizeOfOut -
// ppbBufferOut -
//
// Return values:
//
//
DWORD ElSetEapData ( IN DWORD dwEapType, IN DWORD *pdwSizeOfIn, IN PBYTE *ppbBufferIn, IN DWORD dwOffset, IN DWORD dwAuthData, IN PBYTE pbAuthData ) { DWORD cbOffset = 0; EAPOL_AUTH_DATA *pCustomData = NULL; BYTE *pbNewAuthData = NULL; DWORD dwSize = 0; DWORD dwRetCode = NO_ERROR;
do { // Align to start of EAP blob
cbOffset = dwOffset;
// Find the old EAP Data
while (cbOffset < *pdwSizeOfIn) { pCustomData = (EAPOL_AUTH_DATA *) ((PBYTE) *ppbBufferIn + cbOffset);
if (pCustomData->dwEapType == dwEapType) { break; } cbOffset += sizeof (EAPOL_AUTH_DATA) + pCustomData->dwSize; }
if (cbOffset < *pdwSizeOfIn) { dwSize = sizeof (EAPOL_AUTH_DATA) + pCustomData->dwSize; MoveMemory (*ppbBufferIn + cbOffset, *ppbBufferIn + cbOffset + dwSize, *pdwSizeOfIn - cbOffset - dwSize); *pdwSizeOfIn -= dwSize; } if ((*pdwSizeOfIn == 0) && (*ppbBufferIn != NULL)) { // FREE (*ppbBufferIn);
*ppbBufferIn = NULL; }
if ((dwAuthData == 0) || (pbAuthData == NULL)) { break; }
#ifdef _WIN64
dwSize = ((dwAuthData+7) & 0xfffffff8) + *pdwSizeOfIn + sizeof (EAPOL_AUTH_DATA); #else
dwSize = dwAuthData + *pdwSizeOfIn + sizeof (EAPOL_AUTH_DATA); #endif
if ((pbNewAuthData = MALLOC (dwSize)) == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; }
CopyMemory (pbNewAuthData, *ppbBufferIn, *pdwSizeOfIn);
pCustomData = (EAPOL_AUTH_DATA *) (pbNewAuthData + *pdwSizeOfIn);
pCustomData->dwEapType = dwEapType; CopyMemory (pCustomData->bData, pbAuthData, dwAuthData); #ifdef _WIN64
pCustomData->dwSize = (dwAuthData+7) & 0xfffffff8; #else
pCustomData->dwSize = dwAuthData; #endif
if (*ppbBufferIn != NULL) { // FREE (*ppbBufferIn);
}
*ppbBufferIn = pbNewAuthData; *pdwSizeOfIn = dwSize; } while (FALSE);
return dwRetCode; }
//
// ElGetEapKeyFromToken
//
// Description:
//
// Function to get handle to User hive from User Token
//
// Arguments:
// hUserToken - handle to user token
// phkey - output: pointer to handle to user hive
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
DWORD ElGetEapKeyFromToken ( IN HANDLE hUserToken, OUT HKEY *phkey ) { DWORD dwSizeNeeded; TOKEN_USER *pTokenData = NULL; UNICODE_STRING UnicodeSidString; WCHAR wsUnicodeBuffer[256]; HKEY hUserKey; HKEY hkeyEap; DWORD dwDisposition; NTSTATUS Status = STATUS_SUCCESS; PBYTE pbInfo = NULL; CHAR *pszInfo = NULL; DWORD dwType; DWORD dwInfoSize = 0; LONG lRetVal; EAPOL_PCB *pPCB; DWORD i; LONG lError = ERROR_SUCCESS; DWORD dwRetCode = NO_ERROR;
do { if (hUserToken != NULL) { if (!GetTokenInformation(hUserToken, TokenUser, 0, 0, &dwSizeNeeded)) { if ((dwRetCode = GetLastError()) == ERROR_INSUFFICIENT_BUFFER) { pTokenData = (TOKEN_USER *) MALLOC (dwSizeNeeded);
if (pTokenData == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (ANY,"ElGetEapKeyFromToken: Allocation for TokenData failed"); break; } // Reset error code since we are continuing processing
// This was a valid scenario
dwRetCode = NO_ERROR; } else { TRACE1 (ANY,"ElGetEapKeyFromToken: Error in GetTokenInformation = %ld", dwRetCode); break; }
if (!GetTokenInformation (hUserToken, TokenUser, pTokenData, dwSizeNeeded, &dwSizeNeeded)) { dwRetCode = GetLastError (); TRACE1 (ANY,"ElGetEapKeyFromToken: GetTokenInformation failed with error %ld", dwRetCode); break; }
UnicodeSidString.Buffer = wsUnicodeBuffer; UnicodeSidString.Length = 0; UnicodeSidString.MaximumLength = sizeof(wsUnicodeBuffer);
Status = RtlConvertSidToUnicodeString ( &UnicodeSidString, pTokenData->User.Sid, FALSE);
if (!NT_SUCCESS(Status)) { dwRetCode = GetLastError (); TRACE1 (ANY, "ElGetEapKeyFromToken: RtlconvertSidToUnicodeString failed with error %ld", dwRetCode); break; }
UnicodeSidString.Buffer[UnicodeSidString.Length] = 0;
// Open the user's key
if ((lError = RegOpenKeyEx(HKEY_USERS, UnicodeSidString.Buffer, 0, KEY_ALL_ACCESS, &hUserKey)) != ERROR_SUCCESS) { dwRetCode = (DWORD)lError; TRACE1 (USER, "ElGetEapKeyFromToken: RegOpenKeyEx failed with error %ld", dwRetCode); break; } else { TRACE0 (ANY, "ElGetEapKeyFromToken: RegOpenKeyEx succeeded"); }
} else { TRACE0 (ANY,"ElGetEapKeyFromToken: GetTokenInformation succeeded when it should have failed"); break; } } else { TRACE0 (ANY, "ElGetEapKeyFromToken: Error, hUserToken == NULL "); dwRetCode = ERROR_NO_TOKEN; break; }
*phkey = hUserKey;
} while (FALSE);
if (pTokenData != NULL) { FREE (pTokenData); }
return dwRetCode; }
//
// ElInitRegPortData
//
// Description:
//
// Function to verify existence of connection data for the port
// If no data exists, initialize with default values
// For EAP-TLS, default settings are no server certificate authentication,
// registry certificates
//
// Arguments:
// pwszDeviceGUID - Pointer to GUID string for the port for which data is being
// initiialized
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
DWORD ElInitRegPortData ( WCHAR *pwszDeviceGUID ) { DWORD dwAuthData = 0; BYTE *pConnProp = NULL; DWORD dwSizeOfConnProp = 0; DWORD dwRetCode = NO_ERROR;
do { // Get the size of the Eap data first
if ((dwRetCode = ElGetCustomAuthData ( pwszDeviceGUID, DEFAULT_EAP_TYPE, 0, NULL, NULL, &dwAuthData )) != NO_ERROR) { TRACE1 (ANY, "ElInitRegPortData: ElGetCustomAuthData returned error %ld", dwRetCode);
// There is data in the registry
if (dwRetCode == ERROR_BUFFER_TOO_SMALL) { dwRetCode = NO_ERROR; break; }
if ((dwRetCode = ElCreateDefaultEapData (&dwSizeOfConnProp, NULL)) == ERROR_BUFFER_TOO_SMALL) { if ((pConnProp = MALLOC (dwSizeOfConnProp)) == NULL) { TRACE0 (ANY, "ElInitRegPortData: MALLOC failed for Conn Prop"); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; } if ((dwRetCode = ElCreateDefaultEapData (&dwSizeOfConnProp, pConnProp)) != NO_ERROR) { TRACE1 (ANY, "ElInitRegPortData: ElCreateDefaultEapData failed with error (%ld)", dwRetCode); break; } }
// Set this blob into the registry for the port
if ((dwRetCode = ElSetCustomAuthData ( pwszDeviceGUID, DEFAULT_EAP_TYPE, 0, NULL, pConnProp, &dwSizeOfConnProp )) != NO_ERROR) { TRACE1 (ANY, "ElInitRegPortData: ElSetCustomAuthData failed with %ld", dwRetCode); break; } }
} while (FALSE);
if (pConnProp != NULL) { FREE (pConnProp); pConnProp = NULL; }
TRACE1 (ANY, "ElInitRegPortData: completed with error %ld", dwRetCode);
return dwRetCode; }
//
// ElCreateDefaultEapData
//
// Description:
//
// Function to create default EAP data for a connection
// Current default EAP type is EAP-TLS.
// For EAP-TLS, default settings are no server certificate authentication,
// registry certificates
//
// Arguments:
// *pdwSizeOfEapData -
// pbEapData -
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
DWORD ElCreateDefaultEapData ( IN OUT DWORD *pdwSizeOfEapData, IN OUT BYTE *pbEapData ) { EAPTLS_CONN_PROPERTIES ConnProp; DWORD dwRetCode = NO_ERROR;
do { if (*pdwSizeOfEapData < sizeof (EAPTLS_CONN_PROPERTIES)) { *pdwSizeOfEapData = sizeof (EAPTLS_CONN_PROPERTIES); dwRetCode = ERROR_BUFFER_TOO_SMALL; break; }
ZeroMemory ((VOID *)&ConnProp, sizeof (EAPTLS_CONN_PROPERTIES));
// Registry certs, Server cert validation, No server name
// comparison
ConnProp.fFlags = (EAPTLS_CONN_FLAG_REGISTRY | EAPTLS_CONN_FLAG_NO_VALIDATE_CERT | EAPTLS_CONN_FLAG_NO_VALIDATE_NAME);
ConnProp.fFlags &= ~EAPTLS_CONN_FLAG_NO_VALIDATE_CERT; ConnProp.dwSize = sizeof (EAPTLS_CONN_PROPERTIES);
memcpy ((VOID *)pbEapData, (VOID *)&ConnProp, sizeof (EAPTLS_CONN_PROPERTIES)); *pdwSizeOfEapData = sizeof (EAPTLS_CONN_PROPERTIES);
} while (FALSE);
return dwRetCode; }
//
// ElAuthAttributeGetVendorSpecific
//
//
// Description:
// Helper function used to extract MPPE Key out of Attrribute.
//
RAS_AUTH_ATTRIBUTE * ElAuthAttributeGetVendorSpecific ( IN DWORD dwVendorId, IN DWORD dwVendorType, IN RAS_AUTH_ATTRIBUTE * pAttributes ) { HANDLE hAttribute; RAS_AUTH_ATTRIBUTE * pAttribute;
//
// First search for the vendor specific attribute
//
pAttribute = ElAuthAttributeGetFirst ( raatVendorSpecific, pAttributes, &hAttribute );
while ( pAttribute != NULL ) { //
// If this attribute is of at least size to hold vendor Id/Type
//
if ( pAttribute->dwLength >= 8 ) { //
// Does this have the correct VendorId
//
if (WireToHostFormat32( (PBYTE)(pAttribute->Value) ) == dwVendorId) { //
// Does this have the correct Vendor Type
//
if ( *(((PBYTE)(pAttribute->Value))+4) == dwVendorType ) { return( pAttribute ); } } }
pAttribute = ElAuthAttributeGetNext ( &hAttribute, raatVendorSpecific ); }
return( NULL ); }
//
// ElAuthAttributeGetFirst
//
// Description:
// Helper function used to extract MPPE Key out of Attrribute.
//
RAS_AUTH_ATTRIBUTE * ElAuthAttributeGetFirst ( IN RAS_AUTH_ATTRIBUTE_TYPE raaType, IN RAS_AUTH_ATTRIBUTE * pAttributes, OUT HANDLE * phAttribute ) { DWORD dwIndex; RAS_AUTH_ATTRIBUTE * pRequiredAttribute;
pRequiredAttribute = ElAuthAttributeGet ( raaType, pAttributes );
if ( pRequiredAttribute == NULL ) { *phAttribute = NULL;
return( NULL ); }
*phAttribute = pRequiredAttribute;
return( pRequiredAttribute ); }
//
// ElAuthAttributeGetNext
//
// Description:
// Helper function used to extract MPPE Key out of Attrribute.
//
RAS_AUTH_ATTRIBUTE * ElAuthAttributeGetNext ( IN OUT HANDLE * phAttribute, IN RAS_AUTH_ATTRIBUTE_TYPE raaType ) { DWORD dwIndex; RAS_AUTH_ATTRIBUTE * pAttributes = (RAS_AUTH_ATTRIBUTE *)*phAttribute;
if ( pAttributes == NULL ) { return( NULL ); }
pAttributes++;
while( pAttributes->raaType != raatMinimum ) { if ( pAttributes->raaType == raaType ) { *phAttribute = pAttributes; return( pAttributes ); }
pAttributes++; }
*phAttribute = NULL; return( NULL ); }
//
// ElAuthAttributeGet
//
// Description:
// Helper function used to extract MPPE Key out of Attrribute.
//
RAS_AUTH_ATTRIBUTE * ElAuthAttributeGet ( IN RAS_AUTH_ATTRIBUTE_TYPE raaType, IN RAS_AUTH_ATTRIBUTE * pAttributes ) { DWORD dwIndex;
if ( pAttributes == NULL ) { return( NULL ); }
for( dwIndex = 0; pAttributes[dwIndex].raaType != raatMinimum; dwIndex++ ) { if ( pAttributes[dwIndex].raaType == raaType ) { return( &(pAttributes[dwIndex]) ); } }
return( NULL ); }
//
// ElReverseString
//
// Description:
// Reverses order of characters in 'psz'
//
VOID ElReverseString ( CHAR* psz ) { CHAR* pszBegin; CHAR* pszEnd;
for (pszBegin = psz, pszEnd = psz + strlen( psz ) - 1; pszBegin < pszEnd; ++pszBegin, --pszEnd) { CHAR ch = *pszBegin; *pszBegin = *pszEnd; *pszEnd = ch; } }
//
// ElEncodePw
//
// Description:
//
// Obfuscate 'pszPassword' in place to foil memory scans for passwords.
// Returns the address of 'pszPassword'.
//
CHAR* ElEncodePw ( IN OUT CHAR* pszPassword ) { if (pszPassword) { CHAR* psz;
ElReverseString (pszPassword);
for (psz = pszPassword; *psz != '\0'; ++psz) { if (*psz != (CHAR)PASSWORDMAGIC) *psz ^= PASSWORDMAGIC; } }
return pszPassword; }
//
// ElDecodePw
//
// Description:
//
// Un-obfuscate 'pszPassword' in place.
// Returns the address of 'pszPassword'.
//
CHAR* ElDecodePw ( IN OUT CHAR* pszPassword ) { return ElEncodePw (pszPassword); }
//
// ElSecureEncodePw
//
// Description:
//
// Encrypt password locally using user-ACL
//
DWORD ElSecureEncodePw ( IN BYTE *pbPassword, IN DWORD dwSizeOfPassword, OUT DATA_BLOB *pDataBlob ) { DWORD dwRetCode = NO_ERROR; DATA_BLOB blobIn = {0}, blobOut = {0};
do { blobIn.cbData = dwSizeOfPassword; blobIn.pbData = pbPassword;
if (!CryptProtectData ( &blobIn, L"", NULL, NULL, NULL, 0, &blobOut)) { dwRetCode = GetLastError (); break; } // copy over blob to password
if (pDataBlob->pbData != NULL) { FREE (pDataBlob->pbData); pDataBlob->pbData = NULL; pDataBlob->cbData = 0; }
pDataBlob->pbData = MALLOC (blobOut.cbData); if (pDataBlob->pbData == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; }
memcpy (pDataBlob->pbData, blobOut.pbData, blobOut.cbData); pDataBlob->cbData = blobOut.cbData; } while (FALSE);
if (blobOut.pbData != NULL) { LocalFree (blobOut.pbData); }
if (dwRetCode != NO_ERROR) { if (pDataBlob->pbData != NULL) { FREE (pDataBlob->pbData); pDataBlob->pbData = NULL; pDataBlob->cbData = 0; } }
return dwRetCode; }
//
// ElDecodePw
//
// Description:
//
// Decrypt password locally using user-ACL
//
DWORD ElSecureDecodePw ( IN DATA_BLOB *pDataBlob, OUT PBYTE *ppbPassword, OUT DWORD *pdwSizeOfPassword ) { DWORD dwRetCode = NO_ERROR; DATA_BLOB blobOut = {0}; LPWSTR pDescrOut = NULL; // NULL;
do { if (!CryptUnprotectData ( pDataBlob, &pDescrOut, NULL, NULL, NULL, 0, &blobOut)) { dwRetCode = GetLastError (); break; } // copy over blob to password
if (*ppbPassword != NULL) { FREE (*ppbPassword); *ppbPassword = NULL; }
*ppbPassword = MALLOC (blobOut.cbData); if (*ppbPassword == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; }
*pdwSizeOfPassword = blobOut.cbData; memcpy ((BYTE *)*ppbPassword, blobOut.pbData, blobOut.cbData); // TRACE1 (ANY, "SecureDecode: Password = %ws", *ppbPassword);
} while (FALSE);
if (blobOut.pbData != NULL) { LocalFree (blobOut.pbData); } if (pDescrOut) { LocalFree (pDescrOut); }
if (dwRetCode != NO_ERROR) { if (*ppbPassword != NULL) { FREE (*ppbPassword); *ppbPassword = NULL; } }
return dwRetCode; }
//
// Call: ElEncryptKeyUsingMD5
//
// Description:
// Given a secret, encrypt a given blob
//
//
//
VOID ElEncryptBlockUsingMD5 ( IN BYTE *pbSecret, IN ULONG ulSecretLen, IN OUT BYTE *pbBuf, IN ULONG ulBufLen ) { MD5_CTX MD5Context; BYTE bcipherText[MD5DIGESTLEN]; BYTE *pbWork = NULL, *pbEnd = NULL; BYTE *pbEndBlock = NULL, *pbSrc = NULL;
//
// Compute the beginning and end of the data to be crypted
//
pbWork = pbBuf; pbEnd = pbBuf + ulBufLen;
//
// Loop through the buffer
//
while (pbWork < pbEnd) { // Compute the digest
MD5Init (&MD5Context); MD5Update (&MD5Context, pbSecret, ulSecretLen); MD5Final (&MD5Context);
// Find the end of the block to be decrypted
pbEndBlock = pbWork + MD5DIGESTLEN; if (pbEndBlock >= pbEnd) { // We've reached the end of the buffer
pbEndBlock = pbEnd; } else { // ISSUE: Save the ciphertext for the next pass?
} // Crypt the block
for (pbSrc = MD5Context.digest; pbWork < pbEndBlock; ++pbWork, ++pbSrc) { *pbWork ^= *pbSrc; } } }
//
// ElDecryptKeyUsingMD5
//
// Description:
// Given a secret, decrypt a given blob
//
//
//
VOID ElDecryptBlockUsingMD5 ( IN BYTE *pbSecret, IN ULONG ulSecretLen, IN OUT BYTE *pbBuf, IN ULONG ulBufLen ) { MD5_CTX MD5Context; BYTE bcipherText[MD5DIGESTLEN]; BYTE *pbWork = NULL, *pbEnd = NULL; BYTE *pbEndBlock = NULL, *pbSrc = NULL; DWORD dwNumBlocks = 0; DWORD dwBlock = 0; DWORD dwIndex = 0;
dwNumBlocks = ( ulBufLen - 2 ) / MD5DIGESTLEN;
//
// Walk through the blocks
//
for (dwBlock = 0; dwBlock < dwNumBlocks; dwBlock++ ) { MD5Init ( &MD5Context); MD5Update ( &MD5Context, (PBYTE)pbSecret, ulSecretLen);
//
// ISSUE:
// Do we use any part of the ciphertext at all to generate
// the digest
//
MD5Final ( &MD5Context);
for ( dwIndex = 0; dwIndex < MD5DIGESTLEN; dwIndex++ ) { *pbBuf ^= MD5Context.digest[dwIndex]; pbBuf++; } }
}
//
// ElGetHMACMD5Digest
//
// Description:
//
// Given a secret, generate a MD5 digest
//
// Arguments:
// pbBuf - pointer to data stream
// dwBufLen - length of data stream
// pbKey - pointer to authentication key
// dwKeyLen - length of authentication key
// pvDigest - caller digest to be filled in
//
// Return values:
// None
//
VOID ElGetHMACMD5Digest ( IN BYTE *pbBuf, IN DWORD dwBufLen, IN BYTE *pbKey, IN DWORD dwKeyLen, IN OUT VOID *pvDigest ) { MD5_CTX MD5context; UCHAR k_ipad[65]; /* inner padding - key XORd with ipad */ UCHAR k_opad[65]; /* outer padding - key XORd with opad */ UCHAR tk[16]; DWORD dwIndex = 0;
// if key is longer than 64 bytes reset it to key=MD5(key)
if (dwKeyLen > 64) { MD5_CTX tctx;
MD5Init (&tctx); MD5Update (&tctx, pbKey, dwKeyLen); MD5Final (&tctx); memcpy (tk, tctx.digest, 16); pbKey = tk; dwKeyLen = 16; } //
// the HMAC_MD5 transform looks like:
//
// MD5(K XOR opad, MD5(K XOR ipad, text))
//
// where K is an n byte key
// ipad is the byte 0x36 repeated 64 times
// opad is the byte 0x5c repeated 64 times
// and text is the data being protected
//
// start out by storing key in pads
ZeroMemory ( k_ipad, sizeof k_ipad); ZeroMemory ( k_opad, sizeof k_opad); memcpy ( k_ipad, pbKey, dwKeyLen); memcpy ( k_opad, pbKey, dwKeyLen);
// XOR key with ipad and opad values
for (dwIndex=0; dwIndex<64; dwIndex++) { k_ipad[dwIndex] ^= 0x36; k_opad[dwIndex] ^= 0x5c; }
//
// perform inner MD5
//
// init context for 1st pass
MD5Init(&MD5context); // start with inner pad
MD5Update(&MD5context, k_ipad, 64); // then text of datagram
MD5Update(&MD5context, pbBuf, dwBufLen); // finish up 1st pass
MD5Final(&MD5context); memcpy (pvDigest, MD5context.digest, MD5DIGESTLEN);
//
// perform outer MD5
//
// init context for 2nd pass
MD5Init(&MD5context); // start with outer pad
MD5Update(&MD5context, k_opad, 64); // then results of 1st hash
MD5Update(&MD5context, pvDigest, 16); // finish up 2nd pass
MD5Final(&MD5context); memcpy (pvDigest, MD5context.digest, MD5DIGESTLEN); }
//
// ElWmiGetValue
//
// Description:
//
// Get a value for a GUID instance through WMI
//
// Arguments:
// pGuid - Pointer to guid for which value is to be fetched
// pszInstanceName - Friendly name for the interface
// pbInputBuffer - Pointer to data
// dwInputBufferSize - Size of data
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
DWORD ElWmiGetValue ( IN GUID *pGuid, IN CHAR *pszInstanceName, IN OUT BYTE *pbOutputBuffer, IN OUT DWORD *pdwOutputBufferSize ) { WMIHANDLE WmiHandle = NULL; PWNODE_SINGLE_INSTANCE pWnode; ULONG ulBufferSize = 0; WCHAR *pwszInstanceName = NULL; BYTE *pbLocalBuffer = NULL; DWORD dwLocalBufferSize = 0; LONG lStatus = ERROR_SUCCESS;
do {
if ((pwszInstanceName = MALLOC ((strlen(pszInstanceName)+1) * sizeof (WCHAR))) == NULL) { TRACE2 (ANY, "ElWmiGetValue: MALLOC failed for pwszInstanceName, Friendlyname =%s, len= %ld", pszInstanceName, strlen(pszInstanceName)); lStatus = ERROR_NOT_ENOUGH_MEMORY; break; }
if (0 == MultiByteToWideChar( CP_ACP, 0, pszInstanceName, -1, pwszInstanceName, strlen(pszInstanceName)+1 ) ) { lStatus = GetLastError(); TRACE2 (ANY, "ElWmiGetValue: MultiByteToWideChar(%s) failed: %ld", pszInstanceName, lStatus); break; } pwszInstanceName[strlen(pszInstanceName)] = L'\0'; TRACE1 (ANY, "ElWmiGetValue: MultiByteToWideChar succeeded: %ws", pwszInstanceName);
if ((lStatus = WmiOpenBlock (pGuid, 0, &WmiHandle)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElWmiGetValue: WmiOpenBlock failed with error %ld", lStatus); break; }
if ((lStatus = WmiQuerySingleInstance (WmiHandle, pwszInstanceName, &dwLocalBufferSize, NULL)) != ERROR_SUCCESS) {
if (lStatus == ERROR_INSUFFICIENT_BUFFER) { TRACE1 (ANY, "ElWmiGetValue: Size Required = %ld", dwLocalBufferSize);
if ((pbLocalBuffer = MALLOC (dwLocalBufferSize)) == NULL) { TRACE0 (ANY, "ElWmiGetValue: MALLOC failed for pbLocalBuffer"); lStatus = ERROR_NOT_ENOUGH_MEMORY; break; }
if ((lStatus = WmiQuerySingleInstance (WmiHandle, pwszInstanceName, &dwLocalBufferSize, pbLocalBuffer)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElWmiGetValue: WmiQuerySingleInstance failed with error %ld", lStatus); break; }
pWnode = (PWNODE_SINGLE_INSTANCE)pbLocalBuffer;
// If enough space in the output buffer, copy the data block
if (*pdwOutputBufferSize >= pWnode->SizeDataBlock) { memcpy (pbOutputBuffer, (PBYTE)((BYTE *)pWnode + pWnode->DataBlockOffset), pWnode->SizeDataBlock ); } else { lStatus = ERROR_INSUFFICIENT_BUFFER; TRACE0 (ANY, "ElWmiGetValue: Not sufficient space to copy DataBlock"); *pdwOutputBufferSize = pWnode->SizeDataBlock; break; } *pdwOutputBufferSize = pWnode->SizeDataBlock; TRACE0 (ANY, "ElWmiGetValue: Got values from Wmi"); TRACE1 (ANY, "SizeofDataBlock = %ld", pWnode->SizeDataBlock); EAPOL_DUMPBA (pbOutputBuffer, *pdwOutputBufferSize); } else { TRACE1 (ANY, "ElWmiGetValue: WmiQuerySingleInstance failed with error %ld", lStatus); break; }
}
} while (FALSE);
if (WmiHandle != NULL) { if ((lStatus = WmiCloseBlock (WmiHandle)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElWmiGetValue: WmiOpenBlock failed with error %ld", lStatus); } }
if (pbLocalBuffer != NULL) { FREE (pbLocalBuffer); }
if (pwszInstanceName != NULL) { FREE (pwszInstanceName); }
return (DWORD)lStatus;
}
//
// ElWmiSetValue
//
// Description:
//
// Set a value for a GUID instance through WMI
//
// Arguments:
// pGuid - Pointer to guid for which value is to be set
// pszInstanceName - Friendly name for the interface
// pbInputBuffer - Pointer to data
// dwInputBufferSize - Size of data
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
DWORD ElWmiSetValue ( IN GUID *pGuid, IN CHAR *pszInstanceName, IN BYTE *pbInputBuffer, IN DWORD dwInputBufferSize ) { WMIHANDLE WmiHandle = NULL; PWNODE_SINGLE_INSTANCE pWnode; ULONG ulBufferSize = 0; WCHAR *pwszInstanceName = NULL; BYTE bBuffer[4096];
LONG lStatus = ERROR_SUCCESS;
do {
if ((pwszInstanceName = MALLOC ((strlen(pszInstanceName)+1) * sizeof (WCHAR))) == NULL) { TRACE0 (ANY, "ElWmiSetValue: MALLOC failed for pwszInstanceName"); lStatus = ERROR_NOT_ENOUGH_MEMORY; break; }
if (0 == MultiByteToWideChar( CP_ACP, 0, pszInstanceName, -1, pwszInstanceName, strlen(pszInstanceName)+1 ) ) { lStatus = GetLastError(); TRACE2 (ANY, "ElWmiSetValue: MultiByteToWideChar(%s) failed: %d", pszInstanceName, lStatus); break; } pwszInstanceName[strlen(pszInstanceName)] = L'\0'; if ((lStatus = WmiOpenBlock (pGuid, 0, &WmiHandle)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElWmiSetValue: WmiOpenBlock failed with error %ld", lStatus); break; }
if ((lStatus = WmiSetSingleInstance (WmiHandle, pwszInstanceName, 1, dwInputBufferSize, pbInputBuffer)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElWmiSetValue: WmiSetSingleInstance failed with error %ld", lStatus); break; }
TRACE0 (ANY, "ElWmiSetValue: Successful !!!");
} while (FALSE);
if (WmiHandle != NULL) { if ((lStatus = WmiCloseBlock (WmiHandle)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElWmiSetValue: WmiOpenBlock failed with error %ld", lStatus); } }
if (pwszInstanceName != NULL) { FREE (pwszInstanceName); }
return (DWORD)lStatus;
}
//
// ElNdisuioSetOIDValue
//
// Description:
//
// Set a value for an OID for an interface using Ndisuio
//
// Arguments:
// hInterface - Ndisuio handle to interface
// Oid - Oid for which value needs to be set
// pbOidData - Pointer to Oid data
// ulOidDataLength - Oid data length
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
DWORD ElNdisuioSetOIDValue ( IN HANDLE hInterface, IN NDIS_OID Oid, IN BYTE *pbOidData, IN ULONG ulOidDataLength ) { PNDISUIO_SET_OID pSetOid = NULL; DWORD BytesReturned = 0; BOOLEAN fSuccess = TRUE; DWORD dwRetCode = NO_ERROR;
do { pSetOid = (PNDISUIO_SET_OID) MALLOC (ulOidDataLength + sizeof(NDISUIO_SET_OID));
if (pSetOid == NULL) { TRACE0 (ANY, "ElNdisuioSetOIDValue: MALLOC failed for pSetOid"); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; } pSetOid->Oid = Oid; memcpy(&pSetOid->Data[0], pbOidData, ulOidDataLength);
fSuccess = (BOOLEAN) DeviceIoControl ( hInterface, IOCTL_NDISUIO_SET_OID_VALUE, (LPVOID)pSetOid, FIELD_OFFSET(NDISUIO_SET_OID, Data) + ulOidDataLength, (LPVOID)pSetOid, 0, &BytesReturned, NULL); if (!fSuccess) { TRACE1 (ANY, "ElNdisuioSetOIDValue: DeviceIoControl failed with error %ld", (dwRetCode = GetLastError())); break; } else { TRACE0 (ANY, "ElNdisuioSetOIDValue: DeviceIoControl succeeded"); }
} while (FALSE);
if (pSetOid != NULL) { FREE (pSetOid); }
return dwRetCode; }
//
// ElNdisuioQueryOIDValue
//
// Description:
//
// Query the value for an OID for an interface using Ndisuio
//
// Arguments:
// hInterface - Ndisuio handle to interface
// Oid - Oid for which value needs to be set
// pbOidValue - Pointer to Oid value
// pulOidDataLength - Pointer to Oid data length
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
DWORD ElNdisuioQueryOIDValue ( IN HANDLE hInterface, IN NDIS_OID Oid, IN BYTE *pbOidData, IN ULONG *pulOidDataLength ) { PNDISUIO_QUERY_OID pQueryOid = NULL; DWORD BytesReturned = 0; BOOLEAN fSuccess = TRUE; DWORD dwRetCode = NO_ERROR;
do { pQueryOid = (PNDISUIO_QUERY_OID) MALLOC (*pulOidDataLength + sizeof(NDISUIO_QUERY_OID));
if (pQueryOid == NULL) { TRACE0 (ANY, "ElNdisuioQueryOIDValue: MALLOC failed for pQueryOid"); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; } pQueryOid->Oid = Oid;
fSuccess = (BOOLEAN) DeviceIoControl ( hInterface, IOCTL_NDISUIO_QUERY_OID_VALUE, (LPVOID)pQueryOid, FIELD_OFFSET(NDISUIO_QUERY_OID, Data) + *pulOidDataLength, (LPVOID)pQueryOid, FIELD_OFFSET(NDISUIO_QUERY_OID, Data) + *pulOidDataLength, &BytesReturned, NULL); if (!fSuccess) { dwRetCode = GetLastError(); TRACE2 (ANY, "ElNdisuioQueryOIDValue: DeviceIoControl failed with error %ld, BytesReturned = %ld", dwRetCode, BytesReturned); *pulOidDataLength = BytesReturned; break; } else { BytesReturned -= FIELD_OFFSET(NDISUIO_QUERY_OID, Data);
if (BytesReturned > *pulOidDataLength) { BytesReturned = *pulOidDataLength; } else { *pulOidDataLength = BytesReturned; }
memcpy(pbOidData, &pQueryOid->Data[0], BytesReturned); } } while (FALSE);
if (pQueryOid != NULL) { FREE (pQueryOid); }
return dwRetCode; }
//
// ElGuidFromString
//
// Description:
//
// Convert a GUID-string to GUID
//
// Arguments:
// pGuid - pointer to GUID
// pwszGuidString - pointer to string version of GUID
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
DWORD ElGuidFromString ( IN OUT GUID *pGuid, IN WCHAR *pwszGuidString ) { DWORD dwGuidLen = 0; WCHAR wszGuidString[64]; LPWSTR lpwszWithBraces = NULL; HRESULT hr = S_OK; DWORD dwRetCode = NO_ERROR;
do {
if (pwszGuidString == NULL) { break; }
ZeroMemory (pGuid, sizeof(GUID));
if ((hr = CLSIDFromString (pwszGuidString, pGuid)) != NOERROR) { TRACE1 (ANY, "ElGuidFromString: CLSIDFromString failed with error %0lx", hr); dwRetCode = ERROR_CAN_NOT_COMPLETE; }
} while (FALSE);
return dwRetCode; }
//
// ElGetLoggedOnUserName
//
// Description:
//
// Get the Username and Domain of the currently logged in user
//
// Arguments:
// hToken - User token
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
//
DWORD ElGetLoggedOnUserName ( IN HANDLE hToken, OUT PWCHAR *ppwszActiveUserName ) { HANDLE hUserToken; WCHAR *pwszUserNameBuffer = NULL; DWORD dwBufferSize = 0; BOOL fNeedToRevertToSelf = FALSE; DWORD dwRetCode = NO_ERROR;
do { hUserToken = hToken;
if (hUserToken != NULL) { if (!ImpersonateLoggedOnUser (hUserToken)) { dwRetCode = GetLastError(); TRACE1 (USER, "ElGetLoggedOnUserName: ImpersonateLoggedOnUser failed with error %ld", dwRetCode); break; }
fNeedToRevertToSelf = TRUE;
dwBufferSize = 0; if (!GetUserNameEx (NameSamCompatible, NULL, &dwBufferSize)) { dwRetCode = GetLastError (); if (dwRetCode == ERROR_MORE_DATA) { dwRetCode = NO_ERROR; if ((pwszUserNameBuffer = MALLOC (dwBufferSize*sizeof(WCHAR))) == NULL) { TRACE0 (ANY, "ElGetLoggedOnUserName: MALLOC failed for pwszUserNameBuffer"); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; } if (!GetUserNameEx (NameSamCompatible, pwszUserNameBuffer, &dwBufferSize)) { dwRetCode = GetLastError (); TRACE1 (ANY, "ElGetLoggedOnUserName: GetUserNameEx failed with error %ld", dwRetCode); break; } TRACE1 (ANY, "ElGetLoggedOnUserName: Got User Name %ws", pwszUserNameBuffer); } else { TRACE1 (ANY, "ElGetLoggedOnUserName: GetUserNameEx failed with error %ld", dwRetCode); break; } } } else { dwRetCode = ERROR_CAN_NOT_COMPLETE; TRACE0 (ANY, "ElGetLoggedOnUserName: UserToken is NULL"); break; }
} while (FALSE);
if (pwszUserNameBuffer != NULL) { *ppwszActiveUserName = pwszUserNameBuffer; }
// Revert impersonation
if (fNeedToRevertToSelf) { if (!RevertToSelf()) { DWORD dwRetCode1 = NO_ERROR; dwRetCode1 = GetLastError(); TRACE1 (USER, "ElGetLoggedOnUserName: Error in RevertToSelf = %ld", dwRetCode1); dwRetCode = ERROR_BAD_IMPERSONATION_LEVEL; } }
return dwRetCode; }
//
// ElGetMachineName
//
// Description:
//
// Get the machine name of the computer the service is currently running on
//
// Arguments:
// pPCB - Pointer to PCB for the port on which machine name is to
// to be obtained
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
//
DWORD ElGetMachineName ( IN EAPOL_PCB *pPCB ) { WCHAR *pwszComputerNameBuffer = NULL; CHAR *pszComputerNameBuffer = NULL; WCHAR *pwszComputerDomainBuffer = NULL; CHAR *pszComputerDomainBuffer = NULL; DWORD dwBufferSize = 0; DWORD dwRetCode = NO_ERROR;
do { dwBufferSize = 0; if (!GetComputerNameEx (ComputerNamePhysicalNetBIOS, NULL, &dwBufferSize)) { dwRetCode = GetLastError (); if (dwRetCode == ERROR_MORE_DATA) { // Reset error
dwRetCode = NO_ERROR; if ((pwszComputerNameBuffer = MALLOC (dwBufferSize*sizeof(WCHAR))) == NULL) { TRACE0 (ANY, "ElGetMachineName: MALLOC failed for pwszComputerNameBuffer"); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; }
if (!GetComputerNameEx (ComputerNamePhysicalNetBIOS, pwszComputerNameBuffer, &dwBufferSize)) { dwRetCode = GetLastError (); TRACE1 (ANY, "ElGetMachineName: GetComputerNameEx failed with error %ld", dwRetCode); break; }
TRACE1 (ANY, "ElGetMachineName: Got Computer Name %ws", pwszComputerNameBuffer);
pszComputerNameBuffer = MALLOC (wcslen(pwszComputerNameBuffer) + 1); if (pszComputerNameBuffer == NULL) { TRACE0 (ANY, "ElGetMachineName: MALLOC failed for pszComputerNameBuffer"); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; }
if (0 == WideCharToMultiByte ( CP_ACP, 0, pwszComputerNameBuffer, -1, pszComputerNameBuffer, wcslen(pwszComputerNameBuffer)+1, NULL, NULL )) { dwRetCode = GetLastError(); TRACE2 (ANY, "ElGetMachineName: WideCharToMultiByte (%ws) failed: %ld", pwszComputerNameBuffer, dwRetCode); break; }
pszComputerNameBuffer[wcslen(pwszComputerNameBuffer)] = L'\0';
} else { TRACE1 (ANY, "ElGetMachineName: GetComputerNameEx failed with error %ld", dwRetCode); break; } }
dwBufferSize = 0; if (!GetComputerNameEx (ComputerNamePhysicalDnsDomain, NULL, &dwBufferSize)) { dwRetCode = GetLastError (); if (dwRetCode == ERROR_MORE_DATA) { // Reset error
dwRetCode = NO_ERROR; if ((pwszComputerDomainBuffer = MALLOC (dwBufferSize*sizeof(WCHAR))) == NULL) { TRACE0 (ANY, "ElGetMachineName: MALLOC failed for pwszComputerDomainBuffer"); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; }
if (!GetComputerNameEx (ComputerNamePhysicalDnsDomain, pwszComputerDomainBuffer, &dwBufferSize)) { dwRetCode = GetLastError (); TRACE1 (ANY, "ElGetMachineName: GetComputerNameEx Domain failed with error %ld", dwRetCode); break; }
TRACE1 (ANY, "ElGetMachineName: Got Computer Domain %ws", pwszComputerDomainBuffer);
pszComputerDomainBuffer = MALLOC (wcslen(pwszComputerDomainBuffer) + 1); if (pszComputerDomainBuffer == NULL) { TRACE0 (ANY, "ElGetMachineName: MALLOC failed for pszComputerDomainBuffer"); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; }
if (0 == WideCharToMultiByte ( CP_ACP, 0, pwszComputerDomainBuffer, -1, pszComputerDomainBuffer, wcslen(pwszComputerDomainBuffer)+1, NULL, NULL )) { dwRetCode = GetLastError(); TRACE2 (ANY, "ElGetMachineName: WideCharToMultiByte (%ws) failed: %ld", pwszComputerDomainBuffer, dwRetCode); break; }
pszComputerDomainBuffer[wcslen(pwszComputerDomainBuffer)] = L'\0'; *(strrchr (pszComputerDomainBuffer, '.')) = '\0';
if (pPCB->pszIdentity != NULL) { FREE (pPCB->pszIdentity); pPCB->pszIdentity = NULL; }
pPCB->pszIdentity = MALLOC (strlen(pszComputerDomainBuffer) + strlen(pszComputerNameBuffer) + 3);
if (pPCB->pszIdentity == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (ANY, "ElGetMachineName: MALLOC failed for pPCB->pszIdentity"); break; } memcpy (pPCB->pszIdentity, pszComputerDomainBuffer, strlen(pszComputerDomainBuffer)); pPCB->pszIdentity[strlen(pszComputerDomainBuffer)] = '\\'; memcpy (&pPCB->pszIdentity[strlen(pszComputerDomainBuffer)+1], pszComputerNameBuffer, strlen(pszComputerNameBuffer));
pPCB->pszIdentity[strlen(pszComputerDomainBuffer)+1+strlen(pszComputerNameBuffer)] = '$'; pPCB->pszIdentity[strlen(pszComputerDomainBuffer)+1+strlen(pszComputerNameBuffer)+1] = '\0';
} else { TRACE1 (ANY, "ElGetMachineName: GetComputerNameEx failed with error %ld", dwRetCode); break; } }
} while (FALSE);
if (pwszComputerNameBuffer != NULL) { FREE (pwszComputerNameBuffer); }
if (pszComputerNameBuffer != NULL) { FREE (pszComputerNameBuffer); }
if (pwszComputerDomainBuffer != NULL) { FREE (pwszComputerDomainBuffer); }
if (pszComputerDomainBuffer != NULL) { FREE (pszComputerDomainBuffer); }
return dwRetCode;
}
//
// ElUpdateRegistryInterfaceList
//
// Description:
//
// Write the interface list to which NDISUIO is bound to, to the registry
//
// Arguments:
// Interfaces - Interface list containing Device Name and Description
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
//
DWORD ElUpdateRegistryInterfaceList ( IN PNDIS_ENUM_INTF Interfaces ) { WCHAR *pwszRegInterfaceList = NULL; HKEY hkey = NULL; DWORD dwDisposition = 0; LONG lError = ERROR_SUCCESS;
DWORD dwRetCode = NO_ERROR;
do { ANSI_STRING InterfaceName; UCHAR ucBuffer[256]; DWORD i; DWORD dwSizeOfList = 0;
// Determine the number of bytes in the list
for (i=0; i < Interfaces->TotalInterfaces; i++) { if (Interfaces->Interface[i].DeviceName.Buffer != NULL) { dwSizeOfList += wcslen(Interfaces->Interface[i].DeviceName.Buffer); } else { TRACE0 (ANY, "ElUpdateRegistryInterfaceList: Device Name was NULL"); continue; } }
// One extra char for terminating NULL char
pwszRegInterfaceList = (WCHAR *) MALLOC ((dwSizeOfList + 1)*sizeof(WCHAR));
if ( pwszRegInterfaceList == NULL ) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (ANY, "ElUpdateRegistryInterfaceList: MALLOC failed for pwszRegInterfaceList"); break; }
// Start again
dwSizeOfList = 0;
// Create the string in REG_SZ format
for (i=0; i < Interfaces->TotalInterfaces; i++) { if (Interfaces->Interface[i].DeviceName.Buffer != NULL) { wcscat (pwszRegInterfaceList, Interfaces->Interface[i].DeviceName.Buffer); dwSizeOfList += (wcslen(Interfaces->Interface[i].DeviceName.Buffer)); } else { TRACE0 (ANY, "ElUpdateRegistryInterfaceList: Device Name was NULL"); continue; } }
// Final NULL character
pwszRegInterfaceList[dwSizeOfList++] = L'\0';
// Write the string as a REG_SZ value
// Get handle to
// HKLM\Software\Microsoft\EAPOL\Parameters\General
if ((lError = RegCreateKeyEx ( HKEY_LOCAL_MACHINE, cwszEapKeyEapolServiceParams, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dwDisposition)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElUpdateRegistryInterfaceList: Error in RegCreateKeyEx for base key, %ld", lError); dwRetCode = (DWORD)lError; break; }
//
// Set the value of
// ...\EAPOL\Parameters\General\InterfaceList key
//
if ((lError = RegSetValueEx ( hkey, cwszInterfaceList, 0, REG_SZ, (BYTE *)pwszRegInterfaceList, dwSizeOfList*sizeof(WCHAR))) != ERROR_SUCCESS) { TRACE1 (ANY, "ElUpdateRegistryInterfaceList: Error in RegSetValueEx for InterfaceList, %ld", lError); dwRetCode = (DWORD)lError; break; }
} while (FALSE);
if (hkey != NULL) { RegCloseKey (hkey); }
if (pwszRegInterfaceList != NULL) { FREE (pwszRegInterfaceList); }
return dwRetCode; }
//
// ElEnumAndUpdateRegistryInterfaceList
//
// Description:
//
// Enumerate the interface list to which NDISUIO is bound to.
// Write the interface list to the registry
//
// Arguments:
// None
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
//
DWORD ElEnumAndUpdateRegistryInterfaceList ( ) { CHAR EnumerateBuffer[256]; PNDIS_ENUM_INTF Interfaces = NULL; BYTE *pbNdisuioEnumBuffer = NULL; DWORD dwNdisuioEnumBufferSize = 0; DWORD dwAvailableInterfaces = 0; WCHAR *pwszRegInterfaceList = NULL; HKEY hkey = NULL; DWORD dwDisposition = 0; ANSI_STRING InterfaceName; UCHAR ucBuffer[256]; DWORD i; DWORD dwSizeOfList = 0; LONG lError = ERROR_SUCCESS; DWORD dwRetCode = NO_ERROR;
do { ZeroMemory (EnumerateBuffer, 256); Interfaces = (PNDIS_ENUM_INTF)EnumerateBuffer;
// Allocate amount of memory as instructed by NdisEnumerateInterfaces
// once the API allows querying of bytes required
if (!NdisEnumerateInterfaces(Interfaces, 256)) { dwRetCode = GetLastError (); TRACE1 (ANY, "ElEnumAndUpdateRegistryInterfaceList: NdisEnumerateInterfaces failed with error %ld", dwRetCode); break; }
dwNdisuioEnumBufferSize = (Interfaces->BytesNeeded + 7) & 0xfffffff8; dwAvailableInterfaces = Interfaces->AvailableInterfaces; if (dwNdisuioEnumBufferSize == 0) { TRACE0 (ANY, "ElEnumAndUpdateRegistryInterfaceList: MALLOC skipped for pbNdisuioEnumBuffer as dwNdisuioEnumBufferSize == 0"); dwRetCode = NO_ERROR; break; }
pbNdisuioEnumBuffer = (BYTE *) MALLOC (4*dwNdisuioEnumBufferSize);
if (pbNdisuioEnumBuffer == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (ANY, "ElEnumAndUpdateRegistryInterfaceList: MALLOC failed for pbNdisuioEnumBuffer"); break; } Interfaces = (PNDIS_ENUM_INTF)pbNdisuioEnumBuffer;
// Enumerate all the interfaces present on the machine
if ((dwRetCode = ElNdisuioEnumerateInterfaces ( Interfaces, dwAvailableInterfaces, 4*dwNdisuioEnumBufferSize)) != NO_ERROR) { TRACE1(ANY, "ElEnumAndUpdateRegistryInterfaceList: ElNdisuioEnumerateInterfaces failed with error %d", dwRetCode); break; }
// Update the interface list in the registry that NDISUIO has bound to.
// The current interface list is just overwritten into the registry.
// Determine the number of bytes in the list
for (i=0; i < Interfaces->TotalInterfaces; i++) { if (Interfaces->Interface[i].DeviceName.Buffer != NULL) { dwSizeOfList += wcslen(Interfaces->Interface[i].DeviceName.Buffer); } else { TRACE0 (ANY, "ElEnumAndUpdateRegistryInterfaceList: Device Name was NULL"); continue; } }
// One extra char for terminating NULL char
pwszRegInterfaceList = (WCHAR *) MALLOC ((dwSizeOfList + 1)*sizeof(WCHAR));
if ( pwszRegInterfaceList == NULL ) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (ANY, "ElEnumAndUpdateRegistryInterfaceList: MALLOC failed for pwszRegInterfaceList"); break; }
// Start again
dwSizeOfList = 0;
// Create the string in REG_SZ format
for (i=0; i < Interfaces->TotalInterfaces; i++) { if (Interfaces->Interface[i].DeviceName.Buffer != NULL) { wcscat (pwszRegInterfaceList, Interfaces->Interface[i].DeviceName.Buffer); dwSizeOfList += (wcslen(Interfaces->Interface[i].DeviceName.Buffer)); } else { TRACE0 (ANY, "ElEnumAndUpdateRegistryInterfaceList: Device Name was NULL"); continue; } }
// Final NULL character
pwszRegInterfaceList[dwSizeOfList++] = L'\0';
// Write the string as a REG_SZ value
// Get handle to
// HKLM\Software\Microsoft\EAPOL\Parameters\General
if ((lError = RegCreateKeyEx ( HKEY_LOCAL_MACHINE, cwszEapKeyEapolServiceParams, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dwDisposition)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElEnumAndUpdateRegistryInterfaceList: Error in RegCreateKeyEx for base key, %ld", lError); dwRetCode = (DWORD)lError; break; }
//
// Set the value of
// ...\EAPOL\Parameters\General\InterfaceList key
//
if ((lError = RegSetValueEx ( hkey, cwszInterfaceList, 0, REG_SZ, (BYTE *)pwszRegInterfaceList, dwSizeOfList*sizeof(WCHAR))) != ERROR_SUCCESS) { TRACE1 (ANY, "ElEnumAndUpdateRegistryInterfaceList: Error in RegSetValueEx for InterfaceList, %ld", lError); dwRetCode = (DWORD)lError; break; }
} while (FALSE);
if (pbNdisuioEnumBuffer != NULL) { FREE(pbNdisuioEnumBuffer); } if (hkey != NULL) { RegCloseKey (hkey); } if (pwszRegInterfaceList != NULL) { FREE (pwszRegInterfaceList); }
return dwRetCode; }
//
// ElReadGlobalRegistryParams
//
// Description:
//
// Read registry parameters global to EAPOL state machine
// i.e. maxStart, startPeriod, authPeriod, heldPeriod
//
// Arguments:
// Unused
//
// Return values:
//
// NO_ERROR - success
// non-zero - error
//
DWORD ElReadGlobalRegistryParams () { HKEY hKey = NULL; DWORD dwDisposition = 0; DWORD dwType = 0; DWORD dwInfoSize = 0; DWORD lError = 0; DWORD dwmaxStart=0, dwstartPeriod=0, dwauthPeriod=0, dwheldPeriod=0; DWORD dwSupplicantMode = EAPOL_DEFAULT_SUPPLICANT_MODE; DWORD dwEAPOLAuthMode = EAPOL_DEFAULT_AUTH_MODE; DWORD dwRetCode = NO_ERROR;
do {
// Get handle to
// HKLM\Software\Microsoft\EAPOL\Parameters\General\Global
if ((lError = RegCreateKeyEx ( HKEY_LOCAL_MACHINE, cwszEAPOLGlobalParams, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ, NULL, &hKey, &dwDisposition)) != ERROR_SUCCESS) { if (lError != ERROR_FILE_NOT_FOUND) { TRACE1 (ANY, "ElReadGlobalRegistryParams: Error in RegCreateKeyEx for base key, %ld", lError); } break; }
ACQUIRE_WRITE_LOCK (&g_EAPOLConfig);
// If setting values for the first time, initialize values
if (!(g_dwmaxStart || g_dwstartPeriod || g_dwauthPeriod || g_dwheldPeriod || g_dwSupplicantMode)) { g_dwmaxStart = EAPOL_MAX_START; g_dwstartPeriod = EAPOL_START_PERIOD; g_dwauthPeriod = EAPOL_AUTH_PERIOD; g_dwheldPeriod = EAPOL_HELD_PERIOD; g_dwSupplicantMode = EAPOL_DEFAULT_SUPPLICANT_MODE; } RELEASE_WRITE_LOCK (&g_EAPOLConfig);
dwmaxStart = g_dwmaxStart; dwstartPeriod = g_dwstartPeriod; dwauthPeriod = g_dwauthPeriod; dwheldPeriod = g_dwheldPeriod;
// Get the value of ..\General\EAPOLGlobal\authPeriod
dwInfoSize = sizeof(DWORD); if ((lError = RegQueryValueEx ( hKey, cwszAuthPeriod, 0, &dwType, (BYTE *)&dwauthPeriod, &dwInfoSize)) != ERROR_SUCCESS) { if (lError != ERROR_FILE_NOT_FOUND) { TRACE2 (ANY, "ElReadGlobalRegistryParams: Error in RegQueryValueEx for cszAuthPeriod, %ld, InfoSize=%ld", lError, dwInfoSize); } dwauthPeriod = g_dwauthPeriod; lError = ERROR_SUCCESS; }
// Get the value of ..\General\EAPOLGlobal\heldPeriod
dwInfoSize = sizeof(DWORD); if ((lError = RegQueryValueEx ( hKey, cwszHeldPeriod, 0, &dwType, (BYTE *)&dwheldPeriod, &dwInfoSize)) != ERROR_SUCCESS) { if (lError != ERROR_FILE_NOT_FOUND) { TRACE2 (ANY, "ElReadGlobalRegistryParams: Error in RegQueryValueEx for cszHeldPeriod, %ld, InfoSize=%ld", lError, dwInfoSize); } dwheldPeriod = g_dwheldPeriod; lError = ERROR_SUCCESS; }
// Get the value of ..\General\EAPOLGlobal\startPeriod
dwInfoSize = sizeof(DWORD); if ((lError = RegQueryValueEx ( hKey, cwszStartPeriod, 0, &dwType, (BYTE *)&dwstartPeriod, &dwInfoSize)) != ERROR_SUCCESS) { if (lError != ERROR_FILE_NOT_FOUND) { TRACE2 (ANY, "ElReadGlobalRegistryParams: Error in RegQueryValueEx for cszStartPeriod, %ld, InfoSize=%ld", lError, dwInfoSize); } dwstartPeriod = g_dwstartPeriod; lError = ERROR_SUCCESS; }
// Get the value of ..\General\EAPOLGlobal\maxStart
dwInfoSize = sizeof(DWORD); if ((lError = RegQueryValueEx ( hKey, cwszMaxStart, 0, &dwType, (BYTE *)&dwmaxStart, &dwInfoSize)) != ERROR_SUCCESS) { if (lError != ERROR_FILE_NOT_FOUND) { TRACE2 (ANY, "ElReadGlobalRegistryParams: Error in RegQueryValueEx for cszMaxStart, %ld, InfoSize=%ld", lError, dwInfoSize); } dwmaxStart = g_dwmaxStart; lError = ERROR_SUCCESS; }
// Get the value of ..\General\EAPOLGlobal\SupplicantMode
dwInfoSize = sizeof(DWORD); if ((lError = RegQueryValueEx ( hKey, cwszSupplicantMode, 0, &dwType, (BYTE *)&dwSupplicantMode, &dwInfoSize)) != ERROR_SUCCESS) { TRACE2 (ANY, "ElReadGlobalRegistryParams: Error in RegQueryValueEx for cwszSupplicantMode, %ld, InfoSize=%ld", lError, dwInfoSize); dwSupplicantMode = g_dwSupplicantMode; lError = ERROR_SUCCESS; } if (dwSupplicantMode > MAX_SUPPLICANT_MODE) { dwSupplicantMode = EAPOL_DEFAULT_SUPPLICANT_MODE; } g_dwSupplicantMode = dwSupplicantMode;
// Get the value of ..\General\EAPOLGlobal\AuthMode
dwInfoSize = sizeof(DWORD); if ((lError = RegQueryValueEx ( hKey, cwszAuthMode, 0, &dwType, (BYTE *)&dwEAPOLAuthMode, &dwInfoSize)) != ERROR_SUCCESS) { TRACE2 (ANY, "ElReadGlobalRegistryParams: Error in RegQueryValueEx for cwszAuthMode, %ld, InfoSize=%ld", lError, dwInfoSize); dwEAPOLAuthMode = g_dwEAPOLAuthMode; lError = ERROR_SUCCESS; } if (dwEAPOLAuthMode > MAX_EAPOL_AUTH_MODE) { dwEAPOLAuthMode = EAPOL_DEFAULT_AUTH_MODE; } g_dwEAPOLAuthMode = dwEAPOLAuthMode;
// Successful in reading all parameters
ACQUIRE_WRITE_LOCK (&g_EAPOLConfig);
g_dwmaxStart = dwmaxStart; g_dwstartPeriod = dwstartPeriod; g_dwauthPeriod = dwauthPeriod; g_dwheldPeriod = dwheldPeriod;
RELEASE_WRITE_LOCK (&g_EAPOLConfig);
} while (FALSE); dwRetCode = (DWORD)lError; if (dwRetCode != NO_ERROR) { TRACE1 (ANY, "ElReadGlobalRegistryParams: failed with error %ld", dwRetCode); }
if (hKey != NULL) { RegCloseKey(hKey); }
return dwRetCode;
}
//
// ElPostEapConfigChanged
//
// Description:
//
// Watch the registry for changes in EAP config
// - HKLM - EAP type
// - HKLM - EAPOLEnabled
//
// Restart the state machine if the params change
//
// Arguments:
// pwszGuid - Interface GUID string
//
// Return values:
// NO_ERROR - success
// !NO_ERROR - error
//
//
DWORD ElPostEapConfigChanged ( IN WCHAR *pwszGuid, IN EAPOL_INTF_PARAMS *pIntfParams ) { DWORD dwEventStatus = 0; BYTE *pbData = NULL; BOOLEAN fDecrWorkerThreadCount = FALSE; DWORD dwRetCode = NO_ERROR;
do { if (g_hEventTerminateEAPOL == NULL) { dwRetCode = NO_ERROR; break; } if (( dwEventStatus = WaitForSingleObject ( g_hEventTerminateEAPOL, 0)) == WAIT_FAILED) { dwRetCode = GetLastError (); break; } if (dwEventStatus == WAIT_OBJECT_0) { dwRetCode = NO_ERROR; break; }
fDecrWorkerThreadCount = TRUE; InterlockedIncrement (&g_lWorkerThreads);
pbData = (BYTE *) MALLOC ((((wcslen(pwszGuid)+1)*sizeof(WCHAR) + 7) & 0xfffffff8) + sizeof (EAPOL_INTF_PARAMS)); if (pbData == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; }
wcscpy ((WCHAR *)pbData, pwszGuid); memcpy (pbData + (((wcslen(pwszGuid)+1)*sizeof(WCHAR) + 7) & 0xfffffff8), (BYTE *)pIntfParams, sizeof(EAPOL_INTF_PARAMS));
if (!QueueUserWorkItem ( (LPTHREAD_START_ROUTINE)ElProcessEapConfigChange, (PVOID)pbData, WT_EXECUTELONGFUNCTION)) { dwRetCode = GetLastError(); TRACE1 (DEVICE, "ElPostEapConfigChanged: QueueUserWorkItem failed with error %ld", dwRetCode); break; } else { fDecrWorkerThreadCount = FALSE; } } while (FALSE);
if (dwRetCode != NO_ERROR) { if (pbData != NULL) { FREE (pbData); } }
if (fDecrWorkerThreadCount) { InterlockedDecrement (&g_lWorkerThreads); }
return dwRetCode; }
//
// ElProcessEapConfigChange
//
// Description:
//
// Read EAP config changes made in registry. Restart EAPOL on the particular
// interface or stop EAPOL
//
// Arguments:
// pvContext - GUID String
//
// Return values:
//
// NO_ERROR - success
// non-zero - error
//
DWORD WINAPI ElProcessEapConfigChange ( IN PVOID pvContext ) { DWORD dwEapFlags = 0; DWORD dwEapTypeToBeUsed = 0; WCHAR *pwszModifiedGUID = NULL; DWORD dwSizeOfAuthData = 0; PBYTE pbAuthData = NULL; EAPOL_PCB *pPCB = NULL; BOOL fReStartPort = FALSE; EAPOL_ZC_INTF ZCData; EAPOL_INTF_PARAMS EapolIntfParams, *pTmpIntfParams = NULL; BYTE *pbModifiedSSID = NULL; DWORD dwSizeOfModifiedSSID = 0; BOOLEAN fPCBReferenced = FALSE; BOOLEAN fPCBLocked = FALSE; LONG lError = 0; DWORD dwRetCode = NO_ERROR;
do { // Get the GUID for the interface for which EAP config was modified
pwszModifiedGUID = (WCHAR *)pvContext; pTmpIntfParams = (EAPOL_INTF_PARAMS *)((BYTE *)pvContext + (((wcslen(pwszModifiedGUID)+1)*sizeof(WCHAR) + 7 ) & 0xfffffff8)); pbModifiedSSID = (BYTE *)(&pTmpIntfParams->bSSID[0]); dwSizeOfModifiedSSID = pTmpIntfParams->dwSizeOfSSID;
// Get interface-wide parameters
ZeroMemory ((BYTE *)&EapolIntfParams, sizeof(EAPOL_INTF_PARAMS)); EapolIntfParams.dwEapFlags = DEFAULT_EAP_STATE; EapolIntfParams.dwEapType = DEFAULT_EAP_TYPE; if ((dwRetCode = ElGetInterfaceParams ( pwszModifiedGUID, &EapolIntfParams )) != NO_ERROR) { if (dwRetCode == ERROR_FILE_NOT_FOUND) { TRACE1 (PORT, "ElProcessEapConfigChange: ElGetInterfaceParams failed with error %ld", dwRetCode); dwRetCode = NO_ERROR; } else { break; } } dwEapTypeToBeUsed = EapolIntfParams.dwEapType; dwEapFlags = EapolIntfParams.dwEapFlags;
// Check if PCB exists
ACQUIRE_WRITE_LOCK (&(g_PCBLock)); if ((pPCB = ElGetPCBPointerFromPortGUID (pwszModifiedGUID)) != NULL) { EAPOL_REFERENCE_PORT (pPCB); fPCBReferenced = TRUE; } RELEASE_WRITE_LOCK (&(g_PCBLock));
if (!fPCBReferenced) { if (IS_EAPOL_ENABLED(dwEapFlags)) { TRACE0 (ANY, "ElProcessEapConfigChange: PCB not started, enabled, starting PCB"); fReStartPort = TRUE; } else { TRACE0 (ANY, "ElProcessEapConfigChange: PCB not started, not enabled"); } break; } else { if (!IS_EAPOL_ENABLED(dwEapFlags)) { // Found PCB for interface, where EAPOLEnabled = 0
// Stop EAPOL on the port and remove the port from the module
TRACE0 (ANY, "ElProcessEapConfigChange: PCB ref'd, need to disable"); #if 0
pPCB->dwFlags &= ~EAPOL_PORT_FLAG_ACTIVE; pPCB->dwFlags |= EAPOL_PORT_FLAG_DISABLED; #endif
fReStartPort = TRUE;
if ((dwRetCode = ElShutdownInterface (pwszModifiedGUID)) != NO_ERROR) { TRACE1 (ANY, "ElProcessEapConfigChange: ElShutdownInterface failed with error %ld", dwRetCode); break; }
break; } else { TRACE0 (ANY, "ElProcessEapConfigChange: PCB ref and enabled, continue check"); } }
ACQUIRE_WRITE_LOCK (&(pPCB->rwLock)); fPCBLocked = TRUE;
// If SSID changed != current SSID of PCB, do not worry
if (pPCB->pSSID != NULL) { if (dwSizeOfModifiedSSID != pPCB->pSSID->SsidLength) { TRACE0 (ANY, "ElProcessEapConfigChange: Set for different SSID, ignore"); break; } else { if (memcmp (pPCB->pSSID->Ssid, pbModifiedSSID, pPCB->pSSID->SsidLength)) { TRACE0 (ANY, "ElProcessEapConfigChange: Same non-NULL length, diff SSID, ignoring"); break; } } } else { // No SSID on current PCB
if (dwSizeOfModifiedSSID != 0) { // Only if default SSID, should we proceed for further checks
if (dwSizeOfModifiedSSID == MAX_SSID_LEN) { if (memcmp (pbModifiedSSID, g_bDefaultSSID, MAX_SSID_LEN)) { TRACE0 (ANY, "ElProcessEapConfigChange: Modified SSID MAX_SSID_LEN, not default SSID"); break; } } else { TRACE0 (ANY, "ElProcessEapConfigChange: Modified SSID non-NULL, PCB SSID NULL"); break; } } }
// Restart port for the following cases:
// EAPOL_INTF_PARAMS for SSID changed
// CustomAuthData for default EAP type changed
if ((dwEapFlags != pPCB->dwEapFlags) || (dwEapTypeToBeUsed != pPCB->dwEapTypeToBeUsed)) { TRACE0 (ANY, "ElProcessEapConfigChange: dwEapFlags != pPCB->dwEapFlags || dwEapTypeToBeUsed != pPCB->dwEapTypeToBeUsed"); fReStartPort = TRUE; break; }
// Get Custom auth data for the current default EAP Type
// Get the size of the EAP blob
if ((dwRetCode = ElGetCustomAuthData ( pwszModifiedGUID, dwEapTypeToBeUsed, dwSizeOfModifiedSSID, pbModifiedSSID, NULL, &dwSizeOfAuthData )) != NO_ERROR) { if (dwRetCode == ERROR_BUFFER_TOO_SMALL) { if (dwSizeOfAuthData <= 0) { // No EAP blob stored in the registry
pbAuthData = NULL;
if (pPCB->pCustomAuthConnData) { if (pPCB->pCustomAuthConnData->dwSizeOfCustomAuthData > 0) { TRACE0 (ANY, "ElProcessEapConfigChange: Current customauthdata = 0; PCB != 0"); fReStartPort = TRUE; } } dwRetCode = NO_ERROR; break; } else { pbAuthData = MALLOC (dwSizeOfAuthData); if (pbAuthData == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (ANY, "ElProcessEapConfigChange: MALLOC failed for pbAuthData"); break; } if ((dwRetCode = ElGetCustomAuthData ( pwszModifiedGUID, dwEapTypeToBeUsed, dwSizeOfModifiedSSID, pbModifiedSSID, pbAuthData, &dwSizeOfAuthData )) != NO_ERROR) { TRACE1 (ANY, "ElProcessEapConfigChange: ElGetCustomAuthData failed with %ld", dwRetCode); break; } } } else { dwRetCode = ERROR_CAN_NOT_COMPLETE; // CustomAuthData for "Default" is always created for an
// interface when EAPOL starts up
TRACE1 (ANY, "ElProcessEapConfigChange: ElGetCustomAuthData size estimation failed with error %ld", dwRetCode); break; } }
if (pPCB->pCustomAuthConnData == NULL) { if (dwSizeOfAuthData > 0) { fReStartPort = TRUE; break; } } else { if (pPCB->pCustomAuthConnData->dwSizeOfCustomAuthData != dwSizeOfAuthData) { // Same EAP Type, but different lengths
fReStartPort = TRUE; break; } else { if (memcmp ( pPCB->pCustomAuthConnData->pbCustomAuthData, pbAuthData, dwSizeOfAuthData) != 0) { // Same EAP Type, same auth data length, but
// different contents
fReStartPort = TRUE; break; } else { // No change in EAP config data for this
// interface
TRACE0 (ANY, "ElProcessEapConfigChange: Same SSID, EAPType, CustomAuth, No content change"); } } } } while (FALSE);
if (fPCBLocked && fPCBReferenced && fReStartPort) { // Reset connection to go through full authentication
if (pPCB->pSSID != NULL) { FREE (pPCB->pSSID); pPCB->pSSID = NULL; } }
if (fPCBLocked) { RELEASE_WRITE_LOCK (&(pPCB->rwLock)); }
if (fPCBReferenced) { EAPOL_DEREFERENCE_PORT (pPCB); } if (fReStartPort) { #ifdef ZEROCONFIG_LINKED
// Indicate hard-reset to WZC
ZeroMemory ((PVOID)&ZCData, sizeof(EAPOL_ZC_INTF)); ZCData.dwAuthFailCount = 0; ZCData.PreviousAuthenticationType = 0; if ((dwRetCode = ElZeroConfigNotify ( 0, WZCCMD_HARD_RESET, pwszModifiedGUID, &ZCData )) != NO_ERROR) { TRACE1 (EAPOL, "ElProcessEapConfigChange: ElZeroConfigNotify failed with error %ld", dwRetCode); dwRetCode = NO_ERROR; } #endif // ZEROCONFIG_LINKED
DbLogPCBEvent (DBLOG_CATEG_INFO, NULL, EAPOL_PARAMS_CHANGE, pwszModifiedGUID);
if ((dwRetCode = ElEnumAndOpenInterfaces ( NULL, pwszModifiedGUID, 0, NULL)) != NO_ERROR) { TRACE1 (ANY, "ElProcessEapConfigChange: ElEnumAndOpenInterfaces returned error %ld", dwRetCode); dwRetCode = NO_ERROR; } }
TRACE1 (ANY, "ElProcessEapConfigChange: Finished with error %ld", dwRetCode);
if (pvContext != NULL) { FREE (pvContext); }
if (pbAuthData != NULL) { FREE (pbAuthData); }
InterlockedDecrement (&g_lWorkerThreads);
return 0; }
//
// ElStringToGuid
//
// Description:
//
// Function to convert a Guid-String to a GUID
//
// Arguments:
// psGuid - String-ized Guid
// pGuid - Pointer to Guid
//
// Return values:
// None
//
VOID ElStringToGuid ( IN WCHAR *pwsGuid, OUT LPGUID pGuid ) { WCHAR wc; DWORD i=0;
//
// If the first character is a '{', skip it.
//
if ( pwsGuid[0] == L'{' ) pwsGuid++;
//
// Convert string to guid
// (since pwsGuid may be used again below, no permanent modification to
// it may be made)
//
wc = pwsGuid[8]; pwsGuid[8] = 0; pGuid->Data1 = wcstoul ( &pwsGuid[0], 0, 16 ); pwsGuid[8] = wc; wc = pwsGuid[13]; pwsGuid[13] = 0; pGuid->Data2 = (USHORT)wcstoul ( &pwsGuid[9], 0, 16 ); pwsGuid[13] = wc; wc = pwsGuid[18]; pwsGuid[18] = 0; pGuid->Data3 = (USHORT)wcstoul ( &pwsGuid[14], 0, 16 ); pwsGuid[18] = wc;
wc = pwsGuid[21]; pwsGuid[21] = 0; pGuid->Data4[0] = (unsigned char)wcstoul ( &pwsGuid[19], 0, 16 ); pwsGuid[21] = wc; wc = pwsGuid[23]; pwsGuid[23] = 0; pGuid->Data4[1] = (unsigned char)wcstoul ( &pwsGuid[21], 0, 16 ); pwsGuid[23] = wc;
for ( i=0; i < 6; i++ ) { wc = pwsGuid[26+i*2]; pwsGuid[26+i*2] = 0; pGuid->Data4[2+i] = (unsigned char)wcstoul ( &pwsGuid[24+i*2], 0, 16 ); pwsGuid[26+i*2] = wc; }
return; }
//
// ElGetIdentity
//
// Description:
//
// Get the identity depending on the authentication type being used
//
// Arguments:
// pPCB - Pointer to PCB for the port
//
// Return values:
//
// NO_ERROR - success
// non-zero - error
//
DWORD ElGetIdentity ( IN EAPOL_PCB *pPCB ) { BOOLEAN fUserLogonAllowed = FALSE; DWORD dwRetCode = NO_ERROR;
do { switch (pPCB->dwEAPOLAuthMode) { case EAPOL_AUTH_MODE_0: fUserLogonAllowed = TRUE; break; case EAPOL_AUTH_MODE_1: fUserLogonAllowed = TRUE; break; case EAPOL_AUTH_MODE_2: fUserLogonAllowed = FALSE; break; }
// Get user's identity if it has not been obtained till now
if ((g_fUserLoggedOn) && (fUserLogonAllowed) && (pPCB->PreviousAuthenticationType != EAPOL_MACHINE_AUTHENTICATION)) { TRACE0 (ANY, "ElGetIdentity: Userlogged, Prev !Machine auth"); if (!(pPCB->fGotUserIdentity)) { if (pPCB->dwAuthFailCount < EAPOL_MAX_AUTH_FAIL_COUNT) { pPCB->PreviousAuthenticationType = EAPOL_USER_AUTHENTICATION; if (pPCB->dwEapTypeToBeUsed == EAP_TYPE_MD5) { TRACE0 (ANY, "ElGetIdentity: Userlogged, <Maxauth, Prev !Machine auth: MD5"); // EAP-MD5CHAP
if ((dwRetCode = ElGetUserNamePassword ( pPCB)) != NO_ERROR) { TRACE1 (ANY, "ElGetIdentity: Error in ElGetUserNamePassword %ld", dwRetCode); } } else { TRACE0 (ANY, "ElGetIdentity: Userlogged, <Maxauth, Prev !Machine auth: !MD5"); // All other EAP Types
if ((dwRetCode = ElGetUserIdentity ( pPCB)) != NO_ERROR) { TRACE1 (ANY, "ElGetIdentity: Error in ElGetUserIdentity %ld", dwRetCode); } }
if ((dwRetCode == NO_ERROR) || (dwRetCode == ERROR_IO_PENDING)) { TRACE0 (ANY, "ElGetIdentity: Userlogged, <Maxauth, Prev !Machine auth: No Error: User Auth fine"); break; } else { pPCB->PreviousAuthenticationType = EAPOL_UNAUTHENTICATED_ACCESS; TRACE0 (ANY, "ElGetIdentity: Userlogged, <Maxauth, Prev !Machine auth: ERROR"); } } else { TRACE0 (ANY, "ElGetIdentity: Userlogged, >Maxauth, Prev !Machine auth"); if (!IS_GUEST_AUTH_ENABLED(pPCB->dwEapFlags)) { TRACE0 (ANY, "ElGetIdentity: Userlogged, Prev !Machine auth:>MaxAuth: Guest disabled"); dwRetCode = ERROR_CAN_NOT_COMPLETE; break; }
if (pPCB->pszIdentity != NULL) { FREE (pPCB->pszIdentity); pPCB->pszIdentity = NULL; } pPCB->PreviousAuthenticationType = EAPOL_UNAUTHENTICATED_ACCESS; dwRetCode = NO_ERROR; TRACE0 (ANY, "ElGetIdentity: Userlogged, Prev !Machine auth:>MaxAuth OR Error: Guest identity sent");
} } else { TRACE0 (ANY, "ElGetIdentity: Already got identity"); } } else { if (pPCB->hUserToken != NULL) { CloseHandle (pPCB->hUserToken); pPCB->hUserToken = NULL; }
TRACE3 (ANY, "ElGetIdentity: Userlogged=%ld, AuthMode=%ld, Prev Machine auth?=%ld", g_fUserLoggedOn?1:0, pPCB->dwEAPOLAuthMode, (pPCB->PreviousAuthenticationType==EAPOL_MACHINE_AUTHENTICATION)?1:0 );
// No UI required
if ((pPCB->dwEapTypeToBeUsed != EAP_TYPE_MD5) && (IS_MACHINE_AUTH_ENABLED(pPCB->dwEapFlags)) && (pPCB->dwAuthFailCount < EAPOL_MAX_AUTH_FAIL_COUNT)) { TRACE0 (ANY, "ElGetIdentity: !MD5, <MaxAuth, Machine auth");
pPCB->PreviousAuthenticationType = EAPOL_MACHINE_AUTHENTICATION; // Get Machine credentials
dwRetCode = ElGetUserIdentity (pPCB);
if (dwRetCode != NO_ERROR) { TRACE1 (ANY, "ElGetIdentity: ElGetUserIdentity, Machine auth, failed with error %ld", dwRetCode); pPCB->PreviousAuthenticationType = EAPOL_UNAUTHENTICATED_ACCESS; } break; }
if ((!IS_MACHINE_AUTH_ENABLED(pPCB->dwEapFlags)) || (pPCB->dwAuthFailCount >= EAPOL_MAX_AUTH_FAIL_COUNT) || (pPCB->dwEapTypeToBeUsed == EAP_TYPE_MD5)) { TRACE5 (ANY, "ElGetIdentity: Error=%ld, Machine auth enabled=%ld, MD5=%ld, auth fail (%ld), max fail (%ld)", dwRetCode?1:0, IS_MACHINE_AUTH_ENABLED(pPCB->dwEapFlags)?1:0, (pPCB->dwEapTypeToBeUsed == EAP_TYPE_MD5)?1:0, pPCB->dwAuthFailCount, EAPOL_MAX_AUTH_FAIL_COUNT); if (!IS_GUEST_AUTH_ENABLED (pPCB->dwEapFlags)) { dwRetCode = ERROR_CAN_NOT_COMPLETE; break; }
if (pPCB->pszIdentity != NULL) { FREE (pPCB->pszIdentity); pPCB->pszIdentity = NULL; }
pPCB->PreviousAuthenticationType = EAPOL_UNAUTHENTICATED_ACCESS; dwRetCode = NO_ERROR;
TRACE0 (ANY, "ElGetIdentity: machine auth, Guest identity sent"); } }
} while (FALSE);
return dwRetCode; }
//
// ElNLAConnectLPC
//
// Description:
//
// Function called to connect to the LPC port for NLA service
//
// Arguments:
// None
//
// Return values:
// Non-NULL - valid handle
// NULL - error
//
HANDLE ElNLAConnectLPC () {
HANDLE h = NULL; LARGE_INTEGER sectionSize; UNICODE_STRING portName; SECURITY_QUALITY_OF_SERVICE dynamicQoS = { sizeof(SECURITY_QUALITY_OF_SERVICE), SecurityAnonymous, SECURITY_DYNAMIC_TRACKING, FALSE }; WSM_LPC_DATA data; ULONG dataLength;
NTSTATUS status = STATUS_SUCCESS;
do { TRACE0 (EAP, "NLAConnectLPC: Entered");
// Create a shared section for passing the large-size LPC messages.
RtlZeroMemory(&g_ClientView, sizeof(g_ClientView)); g_ClientView.Length = sizeof(g_ClientView); g_ClientView.ViewSize = sizeof(LOCATION_802_1X); sectionSize.QuadPart = sizeof(LOCATION_802_1X); status = NtCreateSection (&g_ClientView.SectionHandle, (SECTION_MAP_READ | SECTION_MAP_WRITE), NULL, §ionSize, PAGE_READWRITE, SEC_COMMIT, NULL ); if (!NT_SUCCESS(status)) { h = NULL; TRACE1 (EAP, "NLAConnectLPC: NtCreateSection failed with error", status); break; } // Connect via LPC to the Network Location Awareness (NLA) service.
RtlInitUnicodeString (&portName, WSM_PRIVATE_PORT_NAME); RtlZeroMemory (&data, sizeof (data)); data.signature = WSM_SIGNATURE; data.connect.version.major = WSM_VERSION_MAJOR; data.connect.version.minor = WSM_VERSION_MINOR; dataLength = sizeof (data); status = NtConnectPort (&h, &portName, &dynamicQoS, &g_ClientView, NULL, NULL, &data, &dataLength ); // If NtConnectPort() succeeded, LPC will maintain a reference
// to the section, otherwise we no longer need it.
NtClose (g_ClientView.SectionHandle); g_ClientView.SectionHandle = NULL; if (!NT_SUCCESS(status)) { TRACE1 (EAP, "NLAConnectLPC: NtConnectPort failed with error %ld", status); }
} while (FALSE);
return (h);
}
//
// ElNLACleanupLPC
//
// Description:
//
// Function called to close the LPC port for NLA service
//
// Arguments:
// None
//
// Return values:
// None
//
VOID ElNLACleanupLPC () { if (g_hNLA_LPC_Port != NULL) { NtClose (g_hNLA_LPC_Port); g_hNLA_LPC_Port = NULL; } }
//
// ElNLARegister_802_1X
//
// Description:
//
// Function called to register 802.1X information with NLA
//
// Arguments:
// plocation - Pointer to data needed to be registered with NLA
//
// Return values:
// None
//
VOID ElNLARegister_802_1X ( IN PLOCATION_802_1X plocation ) {
WSM_LPC_MESSAGE message; NTSTATUS status;
ACQUIRE_WRITE_LOCK (&g_NLALock);
do {
TRACE0 (EAP, "NLARegister_802_1X: Entered");
// Connect to the Network Location Awareness (NLA) service if
// necessary.
if (g_hNLA_LPC_Port == NULL) { if ((g_hNLA_LPC_Port = ElNLAConnectLPC ()) == NULL) { RELEASE_WRITE_LOCK (&g_NLALock); return; } }
TRACE0 (EAP, "NLARegister_802_1X: g_hNLA_LPC_Port != NULL");
// Send information to the NLA service.
RtlZeroMemory (&message, sizeof (message)); message.portMsg.u1.s1.TotalLength = sizeof (message); message.portMsg.u1.s1.DataLength = sizeof (message.data); message.data.signature = WSM_SIGNATURE; message.data.request.type = LOCATION_802_1X_REGISTER; __try { RtlCopyMemory (g_ClientView.ViewBase, plocation, sizeof(LOCATION_802_1X)); } __except (EXCEPTION_EXECUTE_HANDLER) { RELEASE_WRITE_LOCK (&g_NLALock); return; }
status = NtRequestWaitReplyPort ( g_hNLA_LPC_Port, (PPORT_MESSAGE)&message, (PPORT_MESSAGE)&message);
if (status != STATUS_SUCCESS) { TRACE1 (EAP, "NLARegister_802_1X: NtWaitReplyPort failed with error", status);
// It's possible the service was stopped and restarted.
// Ditch the old LPC connection.
CloseHandle (g_hNLA_LPC_Port); // Create a new LPC connection.
if ((g_hNLA_LPC_Port = ElNLAConnectLPC ()) == NULL) { RELEASE_WRITE_LOCK (&g_NLALock); TRACE0 (EAP, "NLARegister_802_1X: NLAConnectLPC failed"); return; }
// Try the send one last time.
status = NtRequestWaitReplyPort (g_hNLA_LPC_Port, (PPORT_MESSAGE)&message, (PPORT_MESSAGE)&message); TRACE1 (EAP, "NLARegister_802_1X: NtWaitReplyPort, try 2, failed with error", status);
}
TRACE1 (EAP, "NLARegister_802_1X: Completed with status = %ld", status);
} while (FALSE); RELEASE_WRITE_LOCK (&g_NLALock);
}
//
// ElNLADelete_802_1X
//
// Description:
//
// Function called to de-register 802.1X information registered with NLA
//
// Arguments:
// plocation - Pointer to data to be de-registered from NLA
//
// Return values:
// None
//
VOID ElNLADelete_802_1X ( IN PLOCATION_802_1X plocation ) {
WSM_LPC_MESSAGE message; NTSTATUS status;
ACQUIRE_WRITE_LOCK (&g_NLALock);
do {
// Connect to the NLA service if necessary.
if (g_hNLA_LPC_Port == NULL) { if ((g_hNLA_LPC_Port = ElNLAConnectLPC ()) == NULL) { RELEASE_WRITE_LOCK (&g_NLALock); return; } }
// Send information to the NLA service.
RtlZeroMemory (&message, sizeof(message)); message.portMsg.u1.s1.TotalLength = sizeof (message); message.portMsg.u1.s1.DataLength = sizeof (message.data); message.data.signature = WSM_SIGNATURE; message.data.request.type = LOCATION_802_1X_DELETE; __try { RtlCopyMemory (g_ClientView.ViewBase, plocation, sizeof(plocation->adapterName)); } __except (EXCEPTION_EXECUTE_HANDLER) { RELEASE_WRITE_LOCK (&g_NLALock); return; }
status = NtRequestWaitReplyPort (g_hNLA_LPC_Port, (PPORT_MESSAGE)&message, (PPORT_MESSAGE)&message);
if (status != STATUS_SUCCESS) { // If the service was stopped (and possibly restarted), we don't
// care ... it won't have this information in its list for us
// to bother deleting.
CloseHandle (g_hNLA_LPC_Port); g_hNLA_LPC_Port = NULL; }
} while (FALSE);
RELEASE_WRITE_LOCK (&g_NLALock);
}
//
// ElGetInterfaceNdisStatistics
//
// Function to query NDIS NIC_STATISTICS parameters for an interface
//
// Input arguments:
// pszInterfaceName - Interface Name
//
// Return values:
// pStats - NIC_STATISTICS structure
//
//
DWORD ElGetInterfaceNdisStatistics ( IN WCHAR *pwszInterfaceName, IN OUT NIC_STATISTICS *pStats ) { WCHAR *pwszDeviceInterfaceName = NULL; UNICODE_STRING UInterfaceName; DWORD dwRetCode = NO_ERROR;
do { pwszDeviceInterfaceName = MALLOC ((wcslen (pwszInterfaceName)+12)*sizeof(WCHAR)); if (pwszDeviceInterfaceName == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (ANY, "ElGetInterfaceNdisStatistics: MALLOC failed for pwszDeviceInterfaceName"); break; }
wcscpy (pwszDeviceInterfaceName, L"\\Device\\"); wcscat (pwszDeviceInterfaceName, pwszInterfaceName);
TRACE1 (ANY, "ElGetInterfaceNdisStatistics: pwszDeviceInterfaceName = (%ws)", pwszDeviceInterfaceName);
RtlInitUnicodeString (&UInterfaceName, pwszDeviceInterfaceName); pStats->Size = sizeof(NIC_STATISTICS); if (NdisQueryStatistics (&UInterfaceName, pStats)) { } else { dwRetCode = GetLastError (); TRACE2 (ANY, "ElGetInterfaceNdisStatistics: NdisQueryStatistics failed with error (%ld), Interface=(%ws)", dwRetCode, UInterfaceName.Buffer); } } while (FALSE);
if (pwszDeviceInterfaceName != NULL) { FREE (pwszDeviceInterfaceName); }
return dwRetCode; }
//
// ElCheckUserLoggedOn
//
// Function to query if interactive user has logged on prior to service start
//
// Input arguments:
// None
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
DWORD ElCheckUserLoggedOn ( ) { BOOLEAN fDecrWorkerThreadCount = TRUE; HANDLE hUserToken = NULL; PWTS_SESSION_INFO pSessionInfo = NULL; WTS_SESSION_INFO SessionInfo; BOOL fFoundActiveConsoleId = FALSE; DWORD dwCount = 0; DWORD dwSession; PVOID pvBuffer = NULL; DWORD dwRetCode = NO_ERROR;
InterlockedIncrement (&g_lWorkerThreads);
do { TRACE1 (ANY, "ElCheckUserLoggedOn: ActiveConsoleId = (%ld)", USER_SHARED_DATA->ActiveConsoleId);
if (WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSessionInfo, &dwCount)) { TRACE1 (ANY, "ElCheckUserLoggedOn: WTSEnumerateSessions, count = (%ld)", dwCount); for (dwSession = 0; dwSession < dwCount; dwSession++) { SessionInfo = pSessionInfo[dwSession]; TRACE2 (ANY, "ElCheckUserLoggedOn: WTSEnumerateSessions: enumerating SessionId =(%ld), State =(%ld)", SessionInfo.SessionId, SessionInfo.State); // Check if the user is active or connected
if ((SessionInfo.State != WTSActive) && (SessionInfo.State != WTSConnected)) { continue; }
// Check if user has actually logged in
if (ElGetWinStationUserToken (dwSession, &hUserToken) != NO_ERROR) { continue; }
if (dwSession == USER_SHARED_DATA->ActiveConsoleId) { fFoundActiveConsoleId = TRUE; g_dwCurrentSessionId = dwSession; g_fUserLoggedOn = TRUE; TRACE1 (ANY, "ElCheckUserLoggedOn: Session (%ld) is active console id", dwSession); break; } else { if (hUserToken != NULL) { CloseHandle (hUserToken); hUserToken = NULL; } } } WTSFreeMemory(pSessionInfo); } else { dwRetCode = GetLastError (); if (dwRetCode == RPC_S_INVALID_BINDING) //Due to Terminal Services Disabled
{ // Check if we can get user token for SessionId 0
if (ElGetWinStationUserToken (0, &hUserToken) == NO_ERROR) { fFoundActiveConsoleId = TRUE; g_dwCurrentSessionId = 0; g_fUserLoggedOn = TRUE; TRACE0 (ANY, "ElCheckUserLoggedOn: Session 0 is active console id"); } } else { TRACE1 (ANY, "ElCheckUserLoggedOn: WTSEnumerateSessions failed with error (%ld)", dwRetCode); } } } while (FALSE);
if (hUserToken != NULL) { CloseHandle (hUserToken); }
if (dwRetCode != NO_ERROR) { if (pvBuffer != NULL) { FREE (pvBuffer); } }
if (fDecrWorkerThreadCount) { InterlockedDecrement (&g_lWorkerThreads); }
return dwRetCode; }
typedef HRESULT (APIENTRY *GETCLIENTADVISES)(LPWSTR**, LPDWORD);
//
// ElCheckUserModuleReady
//
// Function to query if interactive user context for current
// interactive session is ready to be notified
//
// Input arguments:
// None
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
DWORD ElCheckUserModuleReady ( ) { HANDLE hToken = NULL; WCHAR *pwszActiveUserName = NULL; LPWSTR *ppwszAdviseUsers = NULL; DWORD dwCount = 0, dwIndex = 0; HMODULE hLib = NULL; PWCHAR pwszNetmanDllExpandedPath = NULL; DWORD cbSize = 0; GETCLIENTADVISES pGetClientAdvises = NULL; HRESULT hr = S_OK; DWORD dwRetCode = NO_ERROR;
do { // Try only if user has logged on
if (g_dwCurrentSessionId != 0xffffffff) { if ((dwRetCode = ElGetWinStationUserToken (g_dwCurrentSessionId, &hToken)) != NO_ERROR) { TRACE1 (NOTIFY, "ElCheckUserModuleReady: ElGetWinStationUserToken failed with error %ld", dwRetCode); break; } if ((dwRetCode = ElGetLoggedOnUserName (hToken, &pwszActiveUserName)) != NO_ERROR) { TRACE1 (NOTIFY, "ElCheckUserModuleReady: ElGetLoggedOnUserName failed with error %ld", dwRetCode); break; }
// Replace the %SystemRoot% with the actual path.
cbSize = ExpandEnvironmentStrings (NETMAN_DLL_PATH, NULL, 0); if (cbSize == 0) { dwRetCode = GetLastError(); break; } pwszNetmanDllExpandedPath = (LPWSTR) MALLOC (cbSize*sizeof(WCHAR)); if (pwszNetmanDllExpandedPath == (LPWSTR)NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; }
cbSize = ExpandEnvironmentStrings (NETMAN_DLL_PATH, pwszNetmanDllExpandedPath, cbSize); if (cbSize == 0) { dwRetCode = GetLastError(); break; }
hLib = LoadLibrary (pwszNetmanDllExpandedPath); if (hLib == NULL) { dwRetCode = GetLastError (); TRACE2 (NOTIFY, "ElCheckUserModuleReady: LoadLibrary for (%ws) failed with error %ld", NETMAN_DLL_PATH, dwRetCode); break; } if ((pGetClientAdvises = (GETCLIENTADVISES)GetProcAddress (hLib, "GetClientAdvises")) == NULL) { dwRetCode = GetLastError (); TRACE1 (NOTIFY, "ElCheckUserModuleReady: GetProcAddress failed with error %ld", dwRetCode); break; }
hr = (* pGetClientAdvises) (&ppwszAdviseUsers, &dwCount); if (FAILED(hr)) { TRACE1 (NOTIFY, "ElCheckUserModuleReady: GetClientAdvises failed with error %0lx", hr); break; }
for (dwIndex = 0; dwIndex < dwCount; dwIndex++) { TRACE2 (NOTIFY, "ElCheckUserModuleReady: Advise[%ld] = %ws", dwIndex, ppwszAdviseUsers[dwIndex]); if (!wcscmp (ppwszAdviseUsers[dwIndex], pwszActiveUserName)) { TRACE1 (NOTIFY, "ElCheckUserModuleReady: Tray icon ready for username %ws", ppwszAdviseUsers[dwIndex]); g_fTrayIconReady = TRUE; break; } }
if (!g_fTrayIconReady) { TRACE0 (NOTIFY, "ElCheckUserModuleReady: No appropriate advise found"); } } else { TRACE0 (NOTIFY, "ElCheckUserModuleReady: No user logged on"); } } while (FALSE);
if (hToken != NULL) { CloseHandle (hToken); }
if (hLib != NULL) { FreeLibrary (hLib); }
if (pwszNetmanDllExpandedPath != NULL) { FREE (pwszNetmanDllExpandedPath); }
if (pwszActiveUserName != NULL) { FREE (pwszActiveUserName); pwszActiveUserName = NULL; }
if (ppwszAdviseUsers != NULL) { CoTaskMemFree (ppwszAdviseUsers); }
return dwRetCode; }
//
// ElGetWinStationUserToken
//
// Function to get the user token for specified session id
//
// Input arguments:
// dwSessionId - Session Id
// pUserToken - Pointer to user token
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
DWORD ElGetWinStationUserToken ( IN DWORD dwSessionId, IN OUT PHANDLE pUserToken ) { HANDLE hUserToken = NULL; HANDLE hImpersonationToken = NULL; DWORD dwRetCode = NO_ERROR;
do { *pUserToken = NULL; if (GetWinStationUserToken (dwSessionId, pUserToken)) { // TRACE0 (ANY, "ElGetWinStationUserToken: GetWinStationUserToken successful");
} else { dwRetCode = GetLastError(); TRACE2 (ANY, "ElGetWinStationUserToken: GetWinStationUserToken failed for SessionId (%ld) with error (%ld)", dwSessionId, dwRetCode); // if ((dwRetCode == RPC_S_INVALID_BINDING) && (dwSessionId == 0))
if (dwSessionId == 0) { dwRetCode = NO_ERROR; *pUserToken = NULL; hUserToken = GetCurrentUserTokenW ( L"WinSta0", TOKEN_ALL_ACCESS); if (hUserToken == NULL) { dwRetCode = GetLastError(); TRACE1 (ANY, "ElGetWinStationUserToken: GetCurrentUserTokenW failed with error (%ld)", dwRetCode); break; } else { if (!DuplicateTokenEx (hUserToken, 0, NULL, SecurityImpersonation, TokenImpersonation, &hImpersonationToken)) { dwRetCode = GetLastError(); TRACE1 (ANY, "ElGetWinStationUserToken: DuplicateTokenEx for sessionid 0 failed with error (%ld)", dwRetCode); break; } *pUserToken = hImpersonationToken;
// TRACE0 (ANY, "ElGetWinStationUserToken: GetCurrentUserTokenW succeeded");
} } else // (dwSessionId == 0)
{ TRACE2 (ANY, "ElGetWinStationUserToken: GetWinStationUserToken failed for session= (%ld) with error= (%ld)", dwSessionId, dwRetCode); } }
if (pUserToken == NULL) { dwRetCode = ERROR_CAN_NOT_COMPLETE; TRACE0 (ANY, "ElGetWinStationUserToken: UserToken = NULL after fetching successfully\n"); break; } } while (FALSE);
return dwRetCode; }
#ifdef ZEROCONFIG_LINKED
//
// ElZeroConfigEvent
//
// Description:
//
// Callback function called by Zero-Config on media events
//
// Arguments:
// dwHandle - unique transaction id
// pwzcDeviceNotif - media specific identifier
// ndSSID - SSID of network currently associated to
// prdUserData - 802.1X data stored with zero-config
//
// Return values:
// NO_ERROR - Success
// non-zero - Error
//
DWORD ElZeroConfigEvent ( IN DWORD dwHandle, IN WCHAR *pwszGuid, IN NDIS_802_11_SSID ndSSID, IN PRAW_DATA prdUserData ) { WCHAR *pDummyPtr = NULL; WCHAR cwsDummyBuffer[256]; DWORD dwEapTypeToBeUsed = DEFAULT_EAP_TYPE; DWORD dwEapolEnabled = DEFAULT_EAPOL_STATE; EAPOL_ZC_INTF ZCData, *pZCData = NULL; DWORD dwEventStatus = 0; EAPOL_INTF_PARAMS EapolIntfParams; DWORD dwRetCode = NO_ERROR;
do { if (g_hEventTerminateEAPOL == NULL) { break; } if (!(g_dwModulesStarted & ALL_MODULES_STARTED)) { TRACE0 (DEVICE, "ElZeroConfigEvent: Received notification before module started"); break; } if (( dwEventStatus = WaitForSingleObject ( g_hEventTerminateEAPOL, 0)) == WAIT_FAILED) { dwRetCode = GetLastError (); TRACE1 (ANY, "ElZeroConfigEvent: WaitForSingleObject failed with error %ld, Terminating !!!", dwRetCode); break; } if (dwEventStatus == WAIT_OBJECT_0) { dwRetCode = NO_ERROR; TRACE0 (ANY, "ElZeroConfigEvent: g_hEventTerminateEAPOL already signaled, returning"); break; }
// Verify if 802.1X can start on this interface
ZeroMemory ((BYTE *)&EapolIntfParams, sizeof(EAPOL_INTF_PARAMS)); if (prdUserData != NULL) { if ((prdUserData->dwDataLen >= sizeof (EAPOL_ZC_INTF)) && (prdUserData->pData != NULL)) { // Extract information stored with Zero-Config
pZCData = (EAPOL_ZC_INTF *)prdUserData->pData; } } memcpy (EapolIntfParams.bSSID, ndSSID.Ssid, ndSSID.SsidLength); EapolIntfParams.dwSizeOfSSID = ndSSID.SsidLength; EapolIntfParams.dwEapFlags = DEFAULT_EAP_STATE; if ((dwRetCode = ElGetInterfaceParams ( pwszGuid, &EapolIntfParams )) != NO_ERROR) { TRACE2 (DEVICE, "ElZeroConfigEvent: ElGetInterfaceParams failed with error %ld for interface %ws", dwRetCode, pwszGuid);
if (dwRetCode == ERROR_FILE_NOT_FOUND) { EapolIntfParams.dwEapFlags = DEFAULT_EAP_STATE; EapolIntfParams.dwEapType = DEFAULT_EAP_TYPE; } else { break; } }
// Start 802.1X state machine
if ((dwRetCode = ElEnumAndOpenInterfaces ( 0, pwszGuid, dwHandle, prdUserData )) != NO_ERROR) { TRACE1 (DEVICE, "ElZeroConfigEvent: ElEnumAndOpenInterfaces failed with error %ld", dwRetCode); break; }
if (!IS_EAPOL_ENABLED(EapolIntfParams.dwEapFlags)) { dwRetCode = ERROR_CAN_NOT_COMPLETE; break; } } while (FALSE);
// If not possible send RpcCmdInterface - WZCCMD_AUTH_DISABLED to
// Zero Config
if (dwRetCode != NO_ERROR) { ZeroMemory ((PVOID)&ZCData, sizeof(EAPOL_ZC_INTF)); ElZeroConfigNotify ( dwHandle, WZCCMD_CFG_NOOP, pwszGuid, &ZCData ); }
return dwRetCode; }
//
// ElZeroConfigNotify
//
// Description:
//
// Function called to notify Zero-Config about 802.1X events
//
// Arguments:
// dwHandle - unique transaction id
// dwCmdCode -
// pwszGuid - Interface GUID
// pZCData - Data to be stored with ZC for next retry
//
// Return values:
// NO_ERROR - Success
// non-zero - Error
//
DWORD ElZeroConfigNotify ( IN DWORD dwHandle, IN DWORD dwCmdCode, IN WCHAR *pwszGuid, IN EAPOL_ZC_INTF *pZCData ) { RAW_DATA rdUserData; DWORD dwRetCode = NO_ERROR;
TRACE3 (ANY, "ElZeroConfigNotify: Handle=(%ld), failcount=(%ld), lastauthtype=(%ld)", dwHandle, pZCData->dwAuthFailCount, pZCData->PreviousAuthenticationType);
do { ZeroMemory ((PVOID)&rdUserData, sizeof (RAW_DATA)); rdUserData.dwDataLen = sizeof (EAPOL_ZC_INTF); rdUserData.pData = MALLOC (rdUserData.dwDataLen); if (rdUserData.pData == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (ANY, "ElZeroConfigNotify: MALLOC failed for rdUserData.pData"); break; }
memcpy (rdUserData.pData, (BYTE *)pZCData, sizeof (EAPOL_ZC_INTF));
if ((dwRetCode = RpcCmdInterface ( dwHandle, dwCmdCode, pwszGuid, &rdUserData )) != NO_ERROR) { TRACE1 (ANY, "ElZeroConfigNotify: RpcCmdInterface failed with error %ld", dwRetCode); break; } } while (FALSE);
if (rdUserData.pData != NULL) { FREE (rdUserData.pData); }
return dwRetCode; }
#endif // ZEROCONFIG_LINKED
//
// ElNetmanNotify
//
// Description:
//
// Function to update status and display balloon with netman
//
// Arguments:
// pPCB - Pointer to PCB
//
// Return values:
// NO_ERROR - Success
// non-zero - Error
//
DWORD ElNetmanNotify ( IN EAPOL_PCB *pPCB, IN EAPOL_NCS_STATUS Status, IN WCHAR *pwszDisplayMessage ) { GUID DeviceGuid; WCHAR wcszDummy[]=L"EAPOL"; WCHAR * pwszBalloonMessage = NULL; BSTR pwszDummy = NULL; NETCON_STATUS ncsStatus = 0; EAPOL_EAP_UI_CONTEXT *pEAPUIContext = NULL; HRESULT hr = S_OK; DWORD dwRetCode = NO_ERROR;
do { ElStringToGuid (pPCB->pwszDeviceGUID, &DeviceGuid);
if ((Status == EAPOL_NCS_NOTIFICATION) || (Status == EAPOL_NCS_AUTHENTICATION_FAILED)) { if (Status == EAPOL_NCS_NOTIFICATION) { pwszBalloonMessage = pPCB->pwszEapReplyMessage; }
pEAPUIContext = MALLOC (sizeof(EAPOL_EAP_UI_CONTEXT)); if (pEAPUIContext == NULL) { TRACE0 (USER, "ElNetmanNotify: MALLOC failed for pEAPUIContext"); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; }
if (Status == EAPOL_NCS_NOTIFICATION) { pEAPUIContext->dwEAPOLUIMsgType = EAPOLUI_EAP_NOTIFICATION; } else { pEAPUIContext->dwEAPOLUIMsgType = EAPOLUI_CREATEBALLOON; } wcsncpy (pEAPUIContext->wszGUID, pPCB->pwszDeviceGUID, sizeof(pEAPUIContext->wszGUID)); // Do not increment invocation id, since these are notification
// balloons
pEAPUIContext->dwSessionId = g_dwCurrentSessionId; pEAPUIContext->dwContextId = pPCB->dwUIInvocationId; pEAPUIContext->dwEapId = pPCB->bCurrentEAPId; pEAPUIContext->dwEapTypeId = pPCB->dwEapTypeToBeUsed; if (pPCB->pwszSSID) { wcscpy (pEAPUIContext->wszSSID, pPCB->pwszSSID); } if (pPCB->pSSID) { pEAPUIContext->dwSizeOfSSID = pPCB->pSSID->SsidLength; memcpy ((BYTE *)pEAPUIContext->bSSID, (BYTE *)pPCB->pSSID->Ssid, NDIS_802_11_SSID_LEN-sizeof(ULONG)); }
// Post the message to netman
if ((dwRetCode = ElPostShowBalloonMessage ( pPCB, sizeof(EAPOL_EAP_UI_CONTEXT), (BYTE *)pEAPUIContext, pwszBalloonMessage?(wcslen(pwszBalloonMessage)*sizeof(WCHAR)):0, pwszBalloonMessage )) != NO_ERROR) { TRACE1 (USER, "ElGetUserIdentity: ElPostShowBalloonMessage failed with error %ld", dwRetCode); break; }
}
hr = S_OK;
if (Status != EAPOL_NCS_NOTIFICATION) { switch (pPCB->State) { case EAPOLSTATE_LOGOFF: hr = S_FALSE; break; case EAPOLSTATE_DISCONNECTED: hr = S_FALSE; break; case EAPOLSTATE_CONNECTING: hr = S_FALSE; break; case EAPOLSTATE_ACQUIRED: ncsStatus = NCS_CREDENTIALS_REQUIRED; break; case EAPOLSTATE_AUTHENTICATING: ncsStatus = NCS_AUTHENTICATING; break; case EAPOLSTATE_HELD: ncsStatus = NCS_AUTHENTICATION_FAILED; break; case EAPOLSTATE_AUTHENTICATED: ncsStatus = NCS_AUTHENTICATION_SUCCEEDED; break; default: hr = S_FALSE; break; }
if (SUCCEEDED (hr)) { hr = WZCNetmanConnectionStatusChanged ( &DeviceGuid, ncsStatus); }
if (FAILED (hr)) { dwRetCode = ERROR_CAN_NOT_COMPLETE; break; } } } while (FALSE);
if (pwszDummy != NULL) { SysFreeString (pwszDummy); }
if (pEAPUIContext != NULL) { FREE (pEAPUIContext); }
return dwRetCode; }
//
// ElPostShowBalloonMessage
//
// Description:
//
// Function to display balloon on tray icon
//
// Arguments:
// pPCB - Pointer to PCB
// cbCookieLen - Cookie Length
// pbCookie - Pointer to cookie
// cbMessageLen - Message Length
// pbMessage - Pointer to message
//
// Return values:
// NO_ERROR - Success
// non-zero - Error
//
DWORD ElPostShowBalloonMessage ( IN EAPOL_PCB *pPCB, IN DWORD cbCookieLen, IN BYTE *pbCookie, IN DWORD cbMessageLen, IN WCHAR *pwszMessage ) { GUID DeviceGuid; BSTR pwszBalloonMessage = NULL; WCHAR wcszDummy[] = L"Dummy"; BSTR pwszCookie = NULL; HRESULT hr = S_OK; DWORD dwRetCode = NO_ERROR;
do { ElStringToGuid (pPCB->pwszDeviceGUID, &DeviceGuid);
pwszCookie = SysAllocStringByteLen (pbCookie, cbCookieLen); if (pwszCookie == NULL) { dwRetCode = ERROR_CAN_NOT_COMPLETE; break; } if (cbMessageLen != 0) { pwszBalloonMessage = SysAllocString (pwszMessage); } else { pwszBalloonMessage = SysAllocString (wcszDummy); } if (pwszBalloonMessage == NULL) { dwRetCode = ERROR_CAN_NOT_COMPLETE; break; }
hr = WZCNetmanShowBalloon ( &DeviceGuid, pwszCookie, pwszBalloonMessage);
if (FAILED (hr)) { dwRetCode = ERROR_CAN_NOT_COMPLETE; break; } } while (FALSE);
if (pwszBalloonMessage != NULL) { SysFreeString (pwszBalloonMessage); }
if (pwszCookie != NULL) { SysFreeString (pwszCookie); }
return dwRetCode; }
//
// ElProcessReauthResponse
//
// Description:
//
// Function to handle UI response for initiating re-auth
//
// Arguments:
//
// Return values:
//
//
DWORD ElProcessReauthResponse ( IN EAPOL_EAP_UI_CONTEXT EapolUIContext, IN EAPOLUI_RESP EapolUIResp ) { DWORD dwRetCode = NO_ERROR;
do { } while (FALSE);
return dwRetCode; }
//
// ElIPPnpWorker
//
// Description:
//
// Function to renew address on a particular interface
//
// Arguments:
// pvContext - GUID string for the intended interface
//
// Return values:
//
//
DWORD WINAPI ElIPPnPWorker ( IN PVOID pvContext ) { DHCP_PNP_CHANGE DhcpPnpChange; WCHAR *pwszGUID = NULL; DWORD dwRetCode = NO_ERROR;
do { if (pvContext == NULL) { break; }
pwszGUID = (WCHAR *)pvContext;
// Call DHCP to do PnP
ZeroMemory(&DhcpPnpChange, sizeof(DHCP_PNP_CHANGE)); DhcpPnpChange.Version = DHCP_PNP_CHANGE_VERSION_0; if ((dwRetCode = DhcpHandlePnPEvent( 0, DHCP_CALLER_TCPUI, pwszGUID, &DhcpPnpChange, NULL)) != NO_ERROR) { TRACE1 (ANY, "ElIPPnPWorker: DHCPHandlePnPEvent returned error %ld", dwRetCode); // Ignore DHCP error, it's outside 802.1X logic
dwRetCode = NO_ERROR; } else { TRACE0 (EAPOL, "ElIPPnPWorker: DHCPHandlePnPEvent successful"); }
// Call IPv6 to renew this interface
dwRetCode = Ip6RenewInterface(pwszGUID); if (dwRetCode != NO_ERROR) { TRACE1(EAPOL, "ElIPPnPWorker: Ip6RenewInterface returned error %ld", dwRetCode); // Failure not fatal! Stack might be uninstalled.
// Ignore IPv6 error, it's outside the 802.1x logic.
dwRetCode = NO_ERROR; } else { TRACE0(EAPOL, "ElIPPnPWorker: Ip6RenewInterface successful"); } } while (FALSE);
if (pvContext != NULL) { FREE (pvContext); }
InterlockedDecrement (&g_lWorkerThreads);
return dwRetCode; }
//
// ElUpdateRegistry
//
// Description:
//
// Function to modify keys left behind in earlier versions
//
// Arguments:
// None
//
// Return values:
// NO_ERROR - success
// !NO_ERROR - error
//
DWORD ElUpdateRegistry ( ) { DWORD dwRetCode = NO_ERROR;
do { if ((dwRetCode = ElRegistryUpdateXPBeta2 ()) != NO_ERROR) { TRACE1 (ANY, "ElUpdateRegistry: ElRegistryUpdateXPBeta2 failed with error %ld", dwRetCode); dwRetCode = NO_ERROR; }
if ((dwRetCode = ElRegistryUpdateXPSP1 ()) != NO_ERROR) { TRACE1 (ANY, "ElUpdateRegistry: ElRegistryUpdateXPSP1 failed with error %ld", dwRetCode); dwRetCode = NO_ERROR; } } while (FALSE);
return dwRetCode; }
//
// ElRegistryUpdateXPBeta2
//
// Description:
//
// Function to cleanup keys left behind prior 2 Beta2
//
// Arguments:
// None
//
// Return values:
// NO_ERROR - success
// !NO_ERROR - error
//
DWORD ElRegistryUpdateXPBeta2 ( ) { HKEY hkey = NULL; HKEY hkey1 = NULL; DWORD dwDisposition; DWORD dwNumValues = 0, dwMaxValueNameLen = 0, dwMaxValueLen = 0; DWORD dwNumSubKeys = 0, dwMaxSubKeyLen = 0; DWORD dwMaxValueName = 0; DWORD dwNumValues1 = 0, dwMaxValueNameLen1 = 0, dwMaxValueLen1 = 0; DWORD dwNumSubKeys1 = 0, dwMaxSubKeyLen1 = 0; DWORD dwMaxValueName1 = 0; LONG lIndex = 0, lIndex1 = 0; BYTE *pbKeyBuf = NULL; DWORD dwKeyBufLen = 0; BYTE *pbKeyBuf1 = NULL; DWORD dwKeyBufLen1 = 0; WCHAR *pwszValueName = NULL; LONG lError = ERROR_SUCCESS; DWORD dwRetCode = ERROR_SUCCESS;
do { // Delete keys in HKLM\Software\Microsoft\EAPOL\Parameters\Interfaces
// with no "{"
// Get handle to HKLM\Software\Microsoft\EAPOL\Parameters\Interfaces
if ((lError = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, cwszEapKeyEapolConn, 0, KEY_ALL_ACCESS, &hkey )) != ERROR_SUCCESS) { TRACE1 (ANY, "ElRegistryUpdateXPBeta2: Error in RegOpenKeyEx for base key, %ld", lError); dwRetCode = (DWORD)lError; break; }
if ((lError = RegQueryInfoKey ( hkey, NULL, NULL, NULL, &dwNumSubKeys, &dwMaxSubKeyLen, NULL, NULL, NULL, NULL, NULL, NULL )) != NO_ERROR) { dwRetCode = (DWORD)lError; TRACE1 (ANY, "ElRegistryUpdateXPBeta2: RegQueryInfoKey failed with error %ld", dwRetCode); break; }
dwMaxSubKeyLen++; if ((pbKeyBuf = MALLOC (dwMaxSubKeyLen*sizeof(WCHAR))) == NULL) { TRACE0 (ANY, "ElRegistryUpdateXPBeta2: MALLOC failed for dwMaxSubKeyLen"); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; }
for (lIndex = (dwNumSubKeys-1); lIndex >= 0, dwNumSubKeys > 0; lIndex--) { dwKeyBufLen = dwMaxSubKeyLen; ZeroMemory (pbKeyBuf, dwMaxSubKeyLen*sizeof(WCHAR)); if ((lError = RegEnumKey ( hkey, lIndex, (WCHAR *)pbKeyBuf, dwKeyBufLen )) != ERROR_SUCCESS) { TRACE1 (ANY, "ElRegistryUpdateXPBeta2: RegEnumValue failed with error %ld", lError); break; }
// If the first character in the key is not a '{' delete it
if (wcsncmp ((WCHAR *)pbKeyBuf, L"{", 1)) { if ((dwRetCode = SHDeleteKey ( hkey, (WCHAR *)pbKeyBuf )) != ERROR_SUCCESS) { TRACE2 (ANY, "ElRegistryUpdateXPBeta2: RegDelete of (%ws) failed with error %ld", (WCHAR *)pbKeyBuf, dwRetCode); dwRetCode = ERROR_SUCCESS; }
continue; }
// This is a "{GUID}" type key
// Delete all sub-keys under this
if ((lError = RegOpenKeyEx ( hkey, (WCHAR *)pbKeyBuf, 0, KEY_ALL_ACCESS, &hkey1 )) != ERROR_SUCCESS) { TRACE1 (ANY, "ElRegistryUpdateXPBeta2: Error in RegOpenKeyEx for hkey1, %ld", lError); dwRetCode = (DWORD)lError; break; }
do {
if ((lError = RegQueryInfoKey ( hkey1, NULL, NULL, NULL, &dwNumSubKeys1, &dwMaxSubKeyLen1, NULL, &dwNumValues1, &dwMaxValueNameLen1, &dwMaxValueLen1, NULL, NULL )) != NO_ERROR) { dwRetCode = (DWORD)lError; TRACE1 (ANY, "ElRegistryUpdateXPBeta2: RegQueryInfoKey failed with error %ld", dwRetCode); break; }
dwMaxSubKeyLen1++; if ((pbKeyBuf1 = MALLOC (dwMaxSubKeyLen1*sizeof(WCHAR))) == NULL) { TRACE0 (ANY, "ElRegistryUpdateXPBeta2: MALLOC failed for dwMaxSubKeyLen"); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; } for (lIndex1 = (dwNumSubKeys1-1); lIndex1 >= 0, dwNumSubKeys1 > 0; lIndex1--) { dwKeyBufLen1 = dwMaxSubKeyLen1; ZeroMemory (pbKeyBuf1, dwMaxSubKeyLen1*sizeof(WCHAR)); if ((lError = RegEnumKey ( hkey1, lIndex1, (WCHAR *)pbKeyBuf1, dwKeyBufLen1 )) != ERROR_SUCCESS) { TRACE1 (ANY, "ElRegistryUpdateXPBeta2: RegEnumValue failed with error %ld", lError); break; } // Delete all sub-keys
if ((dwRetCode = SHDeleteKey ( hkey1, (WCHAR *)pbKeyBuf1 )) != ERROR_SUCCESS) { TRACE2 (ANY, "ElRegistryUpdateXPBeta2: RegDelete of (%ws) failed with error %ld", (WCHAR *)pbKeyBuf1, dwRetCode); dwRetCode = ERROR_SUCCESS; } } if (pbKeyBuf1 != NULL) { FREE (pbKeyBuf1); pbKeyBuf1 = NULL; } if ((lError != ERROR_SUCCESS) && (lError != ERROR_NO_MORE_ITEMS)) { dwRetCode = (DWORD)lError; TRACE1 (ANY, "ElRegistryUpdateXPBeta2: RegEnumKey failed with error %ld", dwRetCode); break; } else { lError = ERROR_SUCCESS; }
// Delete all values with names "DefaultEapType", "EapolEnabled",
// "LastModifiedSSID"
dwMaxValueNameLen1++; if ((pwszValueName = MALLOC (dwMaxValueNameLen1*sizeof(WCHAR))) == NULL) { TRACE0 (ANY, "ElRegistryUpdateXPBeta2: MALLOC failed for pwszValueName"); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; } for (lIndex1 = (dwNumValues1-1); lIndex1 >= 0, dwNumValues1 > 0; lIndex1--) { dwMaxValueNameLen = dwMaxValueNameLen1; ZeroMemory (pwszValueName, dwMaxValueNameLen1*sizeof(WCHAR)); if ((lError = RegEnumValue ( hkey1, lIndex1, pwszValueName, &dwMaxValueNameLen, NULL, NULL, NULL, NULL )) != ERROR_SUCCESS) { if (lError != ERROR_MORE_DATA) { break; } lError = ERROR_SUCCESS; }
if ((!wcscmp (pwszValueName, cwszDefaultEAPType)) || (!wcscmp (pwszValueName, cwszEapolEnabled)) || (!wcscmp (pwszValueName, cwszLastUsedSSID))) { if ((lError = RegDeleteValue ( hkey1, pwszValueName )) != ERROR_SUCCESS) { TRACE1 (ANY, "ElRegistryUpdateXPBeta2: RegDeleteValue failed with error %ld", lError); lError = ERROR_SUCCESS; } } } if (pwszValueName != NULL) { FREE (pwszValueName); pwszValueName = NULL; } if ((lError != ERROR_SUCCESS) && (lError != ERROR_NO_MORE_ITEMS)) { dwRetCode = (DWORD)lError; TRACE1 (ANY, "ElRegistryUpdateXPBeta2: RegEnumValue failed with error %ld", dwRetCode); break; } else { lError = ERROR_SUCCESS; }
} while (FALSE);
if (hkey1 != NULL) { RegCloseKey (hkey1); hkey1 = NULL; } } if ((lError != ERROR_SUCCESS) && (lError != ERROR_NO_MORE_ITEMS)) { dwRetCode = (DWORD)lError; TRACE1 (ANY, "ElRegistryUpdateXPBeta2: RegQueryInfoKey failed with error %ld", dwRetCode); break; } else { lError = ERROR_SUCCESS; }
} while (FALSE);
if (hkey != NULL) { RegCloseKey (hkey); } if (hkey1 != NULL) { RegCloseKey (hkey1); } if (pbKeyBuf != NULL) { FREE (pbKeyBuf); }
return dwRetCode; }
BOOLEAN IsSSIDPresentInWZCList ( PEAPOL_INTF_PARAMS pIntfParams, PWZC_802_11_CONFIG_LIST pwzcCfgList ) { DWORD dwIndex = 0; BOOLEAN fFound = FALSE; do { for (dwIndex=0; dwIndex<pwzcCfgList->NumberOfItems; dwIndex++) { if (pwzcCfgList->Config[dwIndex].Ssid.SsidLength == pIntfParams->dwSizeOfSSID) { if (memcmp(pwzcCfgList->Config[dwIndex].Ssid.Ssid, pIntfParams->bSSID, pIntfParams->dwSizeOfSSID) == 0) { fFound = TRUE; break; } } } } while (FALSE);
return fFound; }
DWORD ElWZCCfgChangeHandler ( IN LPWSTR pwszGUID, PWZC_802_11_CONFIG_LIST pwzcCfgList ) { HKEY hkey = NULL; HKEY hkey1 = NULL; DWORD dwNumValues = 0, dwMaxValueNameLen = 0, dwMaxValueLen = 0; WCHAR *pwszValueName = NULL; BYTE *pbValueBuf = NULL; LONG lError = ERROR_SUCCESS; LONG lIndex = 0; DWORD dwValueData = 0; EAPOL_INTF_PARAMS *pRegParams = NULL; DWORD dwTempValueNameLen = 0; BOOLEAN fFreeWZCCfgList = FALSE; DWORD dwRetCode = NO_ERROR;
do { // Enumerate registry blobs
if (pwzcCfgList == NULL) { // Create structure with zero items in list
pwzcCfgList = (PWZC_802_11_CONFIG_LIST) MALLOC (sizeof(WZC_802_11_CONFIG_LIST)); if (pwzcCfgList == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (ANY, "ElWZCCfgChangeHandler: pwzcCfgList = NULL"); break; } else { fFreeWZCCfgList = TRUE; } }
// Get handle to HKLM\Software\Microsoft\EAPOL\Parameters\Interfaces
if ((lError = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, cwszEapKeyEapolConn, 0, KEY_ALL_ACCESS, &hkey )) != ERROR_SUCCESS) { TRACE1 (ANY, "ElWZCCfgChangeHandler: Error in RegOpenKeyEx for base key, %ld", lError); dwRetCode = (DWORD)lError; break; }
// Get handle to HKLM\Software\...\Interfaces\<GUID>
if ((lError = RegOpenKeyEx ( hkey, pwszGUID, 0, KEY_ALL_ACCESS, &hkey1 )) != ERROR_SUCCESS) { TRACE1 (ANY, "ElWZCCfgChangeHandler: Error in RegOpenKeyEx for GUID, %ld", lError); dwRetCode = (DWORD)lError; break; }
if ((lError = RegQueryInfoKey ( hkey1, NULL, NULL, NULL, NULL, NULL, NULL, &dwNumValues, &dwMaxValueNameLen, &dwMaxValueLen, NULL, NULL )) != NO_ERROR) { dwRetCode = (DWORD)lError; TRACE1 (ANY, "ElWZCCfgChangeHandler: RegQueryInfoKey failed with error %ld", dwRetCode); break; }
if ((pwszValueName = MALLOC ((dwMaxValueNameLen + 1) * sizeof (WCHAR))) == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (ANY, "ElWZCCfgChangeHandler: MALLOC failed for pwszValueName"); break; } dwMaxValueNameLen++; if ((pbValueBuf = MALLOC (dwMaxValueLen)) == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (ANY, "ElWZCCfgChangeHandler: MALLOC failed for pbValueBuf"); break; }
for (lIndex = (dwNumValues-1); lIndex >= 0, dwNumValues > 0; lIndex--) { dwValueData = dwMaxValueLen; dwTempValueNameLen = dwMaxValueNameLen; if ((lError = RegEnumValue ( hkey1, lIndex, pwszValueName, &dwTempValueNameLen, NULL, NULL, pbValueBuf, &dwValueData )) != ERROR_SUCCESS) { break; }
if (dwValueData < sizeof (EAPOL_INTF_PARAMS)) { TRACE0 (ANY, "ElWZCCfgChangeHandler: dwValueData < sizeof (EAPOL_INTF_PARAMS)"); lError = ERROR_INVALID_DATA; break; } pRegParams = (EAPOL_INTF_PARAMS *)pbValueBuf;
// Ignore default setting since this is needed
if ((memcmp (pRegParams->bSSID, g_bDefaultSSID, MAX_SSID_LEN)) == 0) { continue; }
// If SSID corresponding to registry blob is not found in
// WZC list, delete it
if (!IsSSIDPresentInWZCList (pRegParams, pwzcCfgList )) { // Delete Registry Value
if ((lError = RegDeleteValue ( hkey1, pwszValueName )) != ERROR_SUCCESS) { TRACE1 (ANY, "ElWZCCfgChangeHandler: RegDeleteValue failed with error (%ld)", lError); lError = ERROR_SUCCESS; } } } if ((lError != ERROR_SUCCESS) && (lError != ERROR_NO_MORE_ITEMS)) { dwRetCode = (DWORD)lError; break; } else { lError = ERROR_SUCCESS; } } while (FALSE);
if (hkey != NULL) { RegCloseKey (hkey); } if (hkey1 != NULL) { RegCloseKey (hkey1); } if (pbValueBuf != NULL) { FREE (pbValueBuf); } if (pwszValueName != NULL) { FREE (pwszValueName); } if (fFreeWZCCfgList) { FREE (pwzcCfgList); }
return dwRetCode; }
//
// ElRegistryUpdateXPSP1
//
// Description:
//
// Function to modify 802.1X settings created prior to SP1. This will disable
// 802.1x on all existing configurations. 802.1x, if required, will have to
// be enabled by the user on the existing connection.
//
// Arguments:
// None
//
// Return values:
// NO_ERROR - success
// !NO_ERROR - error
//
DWORD ElRegistryUpdateXPSP1 ( ) { HKEY hkey = NULL; HKEY hkey1 = NULL; DWORD dwNumValues=0, dwMaxValueNameLen=0, dwMaxValueLen=0; WCHAR *pwszValueName=NULL; WCHAR wszGUID[GUID_STRING_LEN_WITH_TERM]; WCHAR *pwszGUID = NULL; DWORD dwSubKeys=0, dwSubKeyLen = 0; BYTE *pbValueBuf = NULL; LONG lError = ERROR_SUCCESS; LONG lKey=0, lIndex=0; DWORD dwValueData=0; EAPOL_INTF_PARAMS *pRegParams = NULL; DWORD dwTempValueNameLen=0; DWORD dwRetCode = NO_ERROR;
do { // Enumerate registry blobs
// Get handle to HKLM\Software\Microsoft\EAPOL\Parameters\Interfaces
if ((lError = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, cwszEapKeyEapolConn, 0, KEY_ALL_ACCESS, &hkey )) != ERROR_SUCCESS) { TRACE1 (ANY, "ElRegistryUpdateXPSP1: Error in RegOpenKeyEx for base key, %ld", lError); dwRetCode = (DWORD)lError; break; }
if ((lError = RegQueryInfoKey ( hkey, NULL, NULL, NULL, &dwSubKeys, &dwSubKeyLen, NULL, NULL, NULL, NULL, NULL, NULL )) != NO_ERROR) { dwRetCode = (DWORD)lError; TRACE1 (ANY, "ElRegistryUpdateXPSP1: RegQueryInfoKey hkey failed with error %ld", dwRetCode); break; }
for (lKey = (dwSubKeys-1); lKey >= 0, dwSubKeys > 0; lKey--) { ZeroMemory (&wszGUID[0], GUID_STRING_LEN_WITH_TERM*sizeof(WCHAR)); pwszGUID = &wszGUID[0]; dwSubKeyLen = GUID_STRING_LEN_WITH_TERM; if ((lError = RegEnumKeyEx ( hkey, lKey, pwszGUID, &dwSubKeyLen, NULL, NULL, NULL, NULL )) != ERROR_SUCCESS) { break; }
if (dwSubKeyLen < (GUID_STRING_LEN_WITH_TERM - 1)) { TRACE0 (ANY, "ElRegistryUpdateXPSP1: dwValueData < sizeof (EAPOL_INTF_PARAMS)"); lError = ERROR_INVALID_DATA; break; } if (hkey1) { RegCloseKey (hkey1); hkey1 = NULL; }
// Get handle to HKLM\Software\...\Interfaces\<GUID>
if ((lError = RegOpenKeyEx ( hkey, pwszGUID, 0, KEY_ALL_ACCESS, &hkey1 )) != ERROR_SUCCESS) { TRACE1 (ANY, "ElRegistryUpdateXPSP1: Error in RegOpenKeyEx for GUID, %ld", lError); break; }
dwNumValues = 0; dwMaxValueNameLen = 0; if ((lError = RegQueryInfoKey ( hkey1, NULL, NULL, NULL, NULL, NULL, NULL, &dwNumValues, &dwMaxValueNameLen, &dwMaxValueLen, NULL, NULL )) != NO_ERROR) { TRACE1 (ANY, "ElRegistryUpdateXPSP1: RegQueryInfoKey failed with error %ld", lError); break; }
if (pwszValueName) { FREE (pwszValueName); pwszValueName = NULL; } if (pbValueBuf) { FREE (pbValueBuf); pbValueBuf = NULL; } if ((pwszValueName = MALLOC ((dwMaxValueNameLen + 1) * sizeof (WCHAR))) == NULL) { lError = dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (ANY, "ElRegistryUpdateXPSP1: MALLOC failed for pwszValueName"); break; } dwMaxValueNameLen++; if ((pbValueBuf = MALLOC (dwMaxValueLen)) == NULL) { lError = dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (ANY, "ElRegistryUpdateXPSP1: MALLOC failed for pbValueBuf"); break; } for (lIndex = (dwNumValues-1); lIndex >= 0, dwNumValues > 0; lIndex--) { dwValueData = dwMaxValueLen; dwTempValueNameLen = dwMaxValueNameLen; if ((lError = RegEnumValue ( hkey1, lIndex, pwszValueName, &dwTempValueNameLen, NULL, NULL, pbValueBuf, &dwValueData )) != ERROR_SUCCESS) { break; } if (dwValueData < sizeof (EAPOL_INTF_PARAMS)) { TRACE0 (ANY, "ElRegistryUpdateXPSP1: dwValueData < sizeof (EAPOL_INTF_PARAMS)"); lError = ERROR_INVALID_DATA; break; } pRegParams = (EAPOL_INTF_PARAMS *)pbValueBuf; if (pRegParams->dwVersion != EAPOL_CURRENT_VERSION) { pRegParams->dwVersion = EAPOL_CURRENT_VERSION; if ((dwRetCode = ElSetInterfaceParams ( pwszGUID, pRegParams )) != NO_ERROR) { TRACE1 (PORT, "ElRegistryUpdateXPSP1: ElSetInterfaceParams failed with error %ld, continuing", dwRetCode); dwRetCode = NO_ERROR; } } } if ((lError != ERROR_SUCCESS) && (lError != ERROR_NO_MORE_ITEMS)) { TRACE1 (ANY, "ElRegistryUpdateXPSP1: RegEnumValue hkey1 failed with error (%ld)", lError); dwRetCode = (DWORD)lError; break; } else { lError = ERROR_SUCCESS; } } if ((lError != ERROR_SUCCESS) && (lError != ERROR_NO_MORE_ITEMS)) { dwRetCode = (DWORD)lError; break; } else { lError = ERROR_SUCCESS; } } while (FALSE);
if (hkey != NULL) { RegCloseKey (hkey); } if (hkey1 != NULL) { RegCloseKey (hkey1); } if (pbValueBuf != NULL) { FREE (pbValueBuf); } if (pwszValueName != NULL) { FREE (pwszValueName); }
return dwRetCode; }
|