|
|
/*++
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 cszEapKeyEapolUser "Software\\Microsoft\\EAPOL\\UserEapInfo"
// Location of Connection blob
#define cszEapKeyEapolConn "Software\\Microsoft\\EAPOL\\Parameters\\Interfaces"
// Location of EAPOL Parameters Service
#define cszEapKeyEapolServiceParams "Software\\Microsoft\\EAPOL\\Parameters\\General"
// Location of EAPOL Global state machine params
#define cszEAPOLGlobalParams "Software\\Microsoft\\EAPOL\\Parameters\\General\\Global"
// Location of EAPOL Global Workspace
#define cszEAPOLWorkspace "Software\\Microsoft\\EAPOL\\Parameters\\General\\Workspace"
#define cszDefault "Default"
#define cszDefault "Default"
#define cszEapolEnabled "EapolEnabled"
#define cszDefaultEAPType "DefaultEAPType"
#define cszLastUsedSSID "LastUsedSSID"
#define cszInterfaceList "InterfaceList"
#define cszAuthPeriod "authPeriod"
#define cszHeldPeriod "heldPeriod"
#define cszStartPeriod "startPeriod"
#define cszMaxStart "maxStart"
#define cszLastModifiedGUID "LastModifiedGUID"
//
// Definitions and structures used in creating default EAP-TLS connection
// blob in the registry
//
#define EAPTLS_CONN_FLAG_REGISTRY 0x00000001
#define EAPTLS_CONN_FLAG_NO_VALIDATE_CERT 0x00000002
#define EAPTLS_CONN_FLAG_NO_VALIDATE_NAME 0x00000004
typedef struct _EAPTLS_CONN_PROPERTIES { DWORD dwVersion; DWORD dwSize; DWORD fFlags; //EAPTLS_HASH Hash;
DWORD cbHash; BYTE pbHash[20]; // MAX_HASH_SIZE = 20
WCHAR awszServerName[1]; } EAPTLS_CONN_PROPERTIES, *PEAPTLS_CONN_PROPERTIES;
#define PASSWORDMAGIC 0xA5
//
// 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:
// pszGUID - pointer to GUID string for the interface
// dwEapTypeId - EAP type for which connection data is to be stored
// pszSSID - Special identifier, if any, for the EAP blob
// pbConnInfo - pointer to EAP connection data blob
// dwInfoSize - Size of EAP connection blob
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
// ISSUE:
// Can we optimize the key openings??? Only open 1 key somehow?
DWORD ElSetCustomAuthData ( IN CHAR *pszGUID, IN DWORD dwEapTypeId, IN CHAR *pszSSID, IN PBYTE pbConnInfo, IN DWORD dwInfoSize ) { HKEY hkey = NULL; HKEY hkey1 = NULL; HKEY hkey2 = NULL; DWORD dwDisposition; CHAR szEapTypeId[4]; // EapTypeId can be max 256 + 1 for null char
LONG lError = ERROR_SUCCESS; DWORD dwRetCode = ERROR_SUCCESS;
do { // Validate input params
if (pszGUID == NULL) { TRACE0 (ANY, "ElSetCustomAuthData: GUID = NULL"); break; } if (dwEapTypeId == 0) { TRACE0 (ANY, "ElSetCustomAuthData: GUID = NULL"); break; } if ((pbConnInfo == NULL) || (dwInfoSize <= 0)) { TRACE0 (ANY, "ElSetCustomAuthData: Invalid blob data"); break; }
// Get handle to HKLM\Software\Microsoft\EAPOL\Parameters\Interfaces
if ((lError = RegCreateKeyExA ( HKEY_LOCAL_MACHINE, cszEapKeyEapolConn, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dwDisposition)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElSetCustomAuthData: Error in RegCreateKeyExA for base key, %ld", lError); dwRetCode = (DWORD)lError; break; }
// Get handle to HKLM\Software\...\Interfaces\<GUID>
if ((lError = RegCreateKeyExA ( hkey, pszGUID, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey1, &dwDisposition)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElSetCustomAuthData: Error in RegCreateKeyExA for GUID, %ld", lError); dwRetCode = (DWORD)lError; break; }
_ltoa(dwEapTypeId, szEapTypeId, 10);
// Get handle to HKLM\Software\...\Interfaces\<GUID>\<EapTypeId>
if ((lError = RegCreateKeyExA ( hkey1, szEapTypeId, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey2, &dwDisposition)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElSetCustomAuthData: Error in RegCreateKeyExA for EapTypeId, %ld", lError); dwRetCode = (DWORD)lError; break; }
// If no SSID is supplied, set the blob as value for "Default"
if (pszSSID == NULL) { pszSSID = cszDefault; }
//
// Set the value of ..\Interfaces\GUID\<EAPTypeId>\(<SSID> or default)
// key
if ((lError = RegSetValueExA ( hkey2, pszSSID, 0, REG_BINARY, pbConnInfo, dwInfoSize)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElSetCustomAuthData: Error in RegSetValueExA 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 (hkey2 != NULL) { RegCloseKey (hkey2); } 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:
//
// pszGUID - pointer to GUID string for the interface
// dwEapTypeId - EAP type for which connection data is to be retrieved
// pszSSID - Special identifier if any for the EAP blob
// pbUserInfo - output: pointer to EAP connection data blob
// dwInfoSize - output: pointer to size of EAP connection blob
//
// Return values:
//
// NO_ERROR - success
// non-zero - error
//
DWORD ElGetCustomAuthData ( IN CHAR *pszGUID, IN DWORD dwEapTypeId, IN CHAR *pszSSID, IN OUT BYTE *pbConnInfo, IN OUT DWORD *pdwInfoSize ) { HKEY hkey = NULL; HKEY hkey1 = NULL; HKEY hkey2 = NULL; PBYTE pbInfo = NULL; DWORD dwInfoSize = 0; DWORD dwType = 0; CHAR szEapTypeId[4]; // EapTypeId can be max 256 + 1 for null char
LONG lError = ERROR_SUCCESS; DWORD dwRetCode = ERROR_SUCCESS;
do { // Validate input params
if (pszGUID == NULL) { TRACE0 (ANY, "ElGetCustomAuthData: GUID = NULL"); break; } if (dwEapTypeId == 0) { TRACE0 (ANY, "ElGetCustomAuthData: GUID = NULL"); break; }
// Get handle to HKLM\Software\Microsoft\EAPOL\Parameters\Interfaces
if ((lError = RegOpenKeyExA ( HKEY_LOCAL_MACHINE, cszEapKeyEapolConn, 0, KEY_READ, &hkey )) != ERROR_SUCCESS) { TRACE1 (ANY, "ElGetCustomAuthData: Error in RegOpenKeyExA for base key, %ld", lError); dwRetCode = (DWORD)lError; break; }
// Get handle to HKLM\Software\...\Interfaces\<GUID>
if ((lError = RegOpenKeyExA ( hkey, pszGUID, 0, KEY_READ, &hkey1 )) != ERROR_SUCCESS) { TRACE1 (ANY, "ElGetCustomAuthData: Error in RegOpenKeyExA for GUID, %ld", lError); dwRetCode = (DWORD)lError; break; }
_ltoa(dwEapTypeId, szEapTypeId, 10);
// Get handle to HKLM\Software\...\Interfaces\<GUID>\<EapTypeId>
if ((lError = RegOpenKeyExA ( hkey1, szEapTypeId, 0, KEY_READ, &hkey2 )) != ERROR_SUCCESS) { TRACE1 (ANY, "ElGetCustomAuthData: Error in RegOpenKeyExA for EapTypeId, %ld", lError); dwRetCode = (DWORD)lError; break; }
// If no SSID is supplied, set the blob as value for "Default"
if (pszSSID == NULL) { pszSSID = cszDefault; }
// Get the value of ..\Interfaces\GUID\<EAPType>\(<SSID> or default)
// key
if ((lError = RegQueryValueExA ( hkey2, pszSSID, 0, &dwType, NULL, &dwInfoSize)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElGetCustomAuthData: Error in RegQueryValueExA for size estimation for SSID, %ld", lError);
// If pszSSID is "Default" and we cannot read the value for
// the key, bail out
if (!strcmp(pszSSID, cszDefault)) { dwRetCode = (DWORD)lError; break; } else { // Second try with pszSSID = cszDefault
TRACE0 (ANY, "ElGetCustomAuthData: Second try for size estimation with SSID = Default"); pszSSID = cszDefault; if ((lError = RegQueryValueExA ( hkey2, pszSSID, 0, &dwType, NULL, &dwInfoSize)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElGetCustomAuthData: Error in RegQueryValueExA for SSID=Default, 2nd try , %ld", lError);
dwRetCode = (DWORD)lError; break; } } }
// Data can be read
pbInfo = MALLOC (dwInfoSize); if (pbInfo == NULL) { TRACE0 (ANY, "ElGetCustomAuthData: Error in memory allocation"); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; }
if ((lError = RegQueryValueExA ( hkey2, pszSSID, 0, &dwType, pbInfo, &dwInfoSize)) != ERROR_SUCCESS) { TRACE2 (ANY, "ElGetCustomAuthData: Error in RegQueryValueExA for SSID = %s, %ld", pszSSID, lError); dwRetCode = (DWORD)lError; break; }
TRACE1 (ANY, "ElGetCustomAuthData: Succeeded: Data size = %ld", dwInfoSize);
} while (FALSE);
if (hkey != NULL) { RegCloseKey (hkey); } if (hkey1 != NULL) { RegCloseKey (hkey1); } if (hkey2 != NULL) { RegCloseKey (hkey2); }
// check if caller has allocated enough memory
// to hold the info
if ((pbConnInfo != NULL) && (*pdwInfoSize >= dwInfoSize)) { memcpy ((VOID *)pbConnInfo, (VOID *)pbInfo, dwInfoSize); } else { dwRetCode = ERROR_BUFFER_TOO_SMALL; }
*pdwInfoSize = dwInfoSize; // Free the memory allocated for holding blob
if (pbInfo != NULL) { FREE (pbInfo); pbInfo = 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
// pszGUID - pointer to GUID string for the interface
// dwEapTypeId - EAP type for which user data is to be stored
// pszSSID - 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 CHAR *pszGUID, IN DWORD dwEapTypeId, IN CHAR *pszSSID, IN PBYTE pbUserInfo, IN DWORD dwInfoSize ) { HKEY hkey = NULL; HKEY hkey1 = NULL; HKEY hkey2 = NULL; HKEY hkey3 = NULL; DWORD dwDisposition; CHAR szEapTypeId[4]; // EapTypeId can be max 256 + 1 for null char
LONG lError = ERROR_SUCCESS; DWORD dwRetCode = ERROR_SUCCESS;
do { // Validate input params
if (hToken == NULL) { TRACE0 (ANY, "ElSetEapUserInfo: User Token = NULL"); break; } if (pszGUID == 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 = RegCreateKeyExA ( hkey, cszEapKeyEapolUser, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey1, &dwDisposition)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElSetEapUserInfo: Error in RegCreateKeyExA for base key, %ld", lError); dwRetCode = (DWORD)lError; break; }
// Get handle to HKCU\Software\...\UserEapInfo\<GUID>
if ((lError = RegCreateKeyExA ( hkey1, pszGUID, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey2, &dwDisposition)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElSetEapUserInfo: Error in RegCreateKeyExA for GUID, %ld", lError); dwRetCode = (DWORD)lError; break; }
_ltoa(dwEapTypeId, szEapTypeId, 10);
// Get handle to HKCU\Software\...\UserEapInfo\<GUID>\<EAPTypeId>
if ((lError = RegCreateKeyExA ( hkey2, szEapTypeId, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey3, &dwDisposition)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElSetEapUserInfo: Error in RegCreateKeyExA for EapTypeId, %ld", lError); dwRetCode = (DWORD)lError; break; }
// If no SSID is supplied, set the blob as value for "Default"
if (pszSSID == NULL) { pszSSID = cszDefault; }
// Set value of ...\UserEapInfo\<GUID>\<EAPTypeId>\(<SSID> or default)
// key
if ((lError = RegSetValueExA ( hkey3, pszSSID, 0, REG_BINARY, pbUserInfo, dwInfoSize)) != ERROR_SUCCESS) { TRACE2 (ANY, "ElSetEapUserInfo: Error in RegSetValueExA for SSID = %s, %ld", pszSSID, 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 (hkey3 != NULL) { RegCloseKey (hkey3); } 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
// pszGUID - pointer to GUID string for the interface
// dwEapTypeId - EAP type for which user data is to be stored
// pszSSID - 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 CHAR *pszGUID, IN DWORD dwEapTypeId, IN CHAR *pszSSID, IN OUT PBYTE pbUserInfo, IN OUT DWORD *pdwInfoSize ) { HKEY hkey = NULL; HKEY hkey1 = NULL; HKEY hkey2 = NULL; HKEY hkey3 = NULL; PBYTE pbInfo = NULL; DWORD dwInfoSize = 0; DWORD dwType = 0; CHAR szEapTypeId[4]; // EapTypeId can be max 256 + 1 for null char
LONG lError = ERROR_SUCCESS; DWORD dwRetCode = ERROR_SUCCESS;
do { // Validate input params
if (pszGUID == 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 = RegOpenKeyExA ( hkey, cszEapKeyEapolUser, 0, KEY_READ, &hkey1 )) != ERROR_SUCCESS) { TRACE1 (ANY, "ElGetEapUserInfo: Error in RegOpenKeyExA for base key, %ld", lError); dwRetCode = (DWORD)lError; break; }
// Get handle to HKCU\Software\...\UserEapInfo\<GUID>
if ((lError = RegOpenKeyExA ( hkey1, pszGUID, 0, KEY_READ, &hkey2 )) != ERROR_SUCCESS) { TRACE1 (ANY, "ElGetEapUserInfo: Error in RegOpenKeyExA for GUID, %ld", lError); dwRetCode = (DWORD)lError; break; }
_ltoa(dwEapTypeId, szEapTypeId, 10);
// Get handle to HKCU\Software\...\UserEapInfo\<GUID>\<EAPTypeId>
if ((lError = RegOpenKeyExA ( hkey2, szEapTypeId, 0, KEY_READ, &hkey3 )) != ERROR_SUCCESS) { TRACE1 (ANY, "ElGetEapUserInfo: Error in RegOpenKeyExA for EapTypeId, %ld", lError); dwRetCode = (DWORD)lError; break; }
// If no SSID is supplied, set the blob as value for "Default"
if (pszSSID == NULL) { pszSSID = cszDefault; }
// Get value of ...\UserEapInfo\<GUID>\<EAPTypeId>\(<SSID> or default)
// key
if ((lError = RegQueryValueExA ( hkey3, pszSSID, 0, &dwType, NULL, &dwInfoSize)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElGetEapUserInfo: Error in RegQueryValueExA for size estimation for SSID, %ld", lError);
// If pszSSID is "Default" and we cannot read the value for
// the key, bail out
if (!strcmp(pszSSID, cszDefault)) { dwRetCode = (DWORD)lError; break; } else { // Second try with pszSSID = cszDefault
TRACE0 (ANY, "ElGetEapUserInfo: Second try for size estimation with SSID = Default"); pszSSID = cszDefault; if ((lError = RegQueryValueExA ( hkey3, pszSSID, 0, &dwType, NULL, &dwInfoSize)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElGetEapUserInfo: Error in RegOpenKeyExA for SSID=Default in 2nd try , %ld", lError);
dwRetCode = (DWORD)lError; break; } } }
// Data can be read
pbInfo = MALLOC (dwInfoSize); if (pbInfo == NULL) { TRACE0 (ANY, "ElGetEapUserInfo: Error in memory allocation"); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; }
if ((lError = RegQueryValueExA ( hkey3, pszSSID, 0, &dwType, pbInfo, &dwInfoSize)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElGetEapUserInfo: Error in RegQueryValueExA, %ld", lError); dwRetCode = (DWORD)lError; break; }
TRACE0 (ANY, "ElGetEapUserInfo: Get value succeeded");
} while (FALSE);
// Close all the open registry keys
if (hkey != NULL) { RegCloseKey (hkey); } if (hkey1 != NULL) { RegCloseKey (hkey1); } if (hkey2 != NULL) { RegCloseKey (hkey2); } if (hkey3 != NULL) { RegCloseKey (hkey3); }
if (dwRetCode == ERROR_SUCCESS) {
// check if caller has allocated enough memory
// to hold the info
if ((pbUserInfo != NULL) && (*pdwInfoSize >= dwInfoSize)) { memcpy ((VOID *)pbUserInfo, (VOID *)pbInfo, dwInfoSize); } else { // Else just return the size of the blob but not the blob
dwRetCode = ERROR_BUFFER_TOO_SMALL; }
*pdwInfoSize = dwInfoSize;
} // Free the memory allocated for holding blob
if (pbInfo != NULL) { FREE (pbInfo); } return dwRetCode; }
//
// ElGetInterfaceParams
//
// Description:
//
// Function called to retrieve the EAPOL parameters for an interface, stored
// in the HKLM hive.
//
// Arguments:
//
// pszGUID - pointer to GUID string for the interface
// pdwDefaultEAPType - output: Pointer to default EAP type for interface
// pszLastUsedSSID - output: Pointer to last used SSID for the interface
// pdwEapolEnabled - output: Is EAPOL enabled for the interface?
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
DWORD ElGetInterfaceParams ( IN CHAR *pszGUID, IN OUT DWORD *pdwDefaultEAPType, IN OUT CHAR *pszLastUsedSSID, IN OUT DWORD *pdwEapolEnabled ) { HKEY hkey = NULL; HKEY hkey1 = NULL; DWORD dwInfoSize = 0; DWORD dwType = 0; BYTE bValueBuffer[256]; LONG lError = ERROR_SUCCESS; DWORD dwRetCode = ERROR_SUCCESS;
do { // Validate input params
if (pszGUID == NULL) { TRACE0 (ANY, "ElGetInterfaceParams: GUID = NULL"); break; }
TRACE1 (ANY, "ElGetInterfaceParams: Getting stuff from registry for %s", pszGUID);
// Get handle to HKLM\Software\Microsoft\EAPOL\Parameters\Interfaces
if ((lError = RegOpenKeyExA ( HKEY_LOCAL_MACHINE, cszEapKeyEapolConn, 0, KEY_READ, &hkey )) != ERROR_SUCCESS) { TRACE1 (ANY, "ElGetInterfaceParams: Error in RegOpenKeyExA for base key, %ld", lError); dwRetCode = (DWORD)lError; break; }
// Get handle to HKLM\Software\...\Interfaces\<GUID>
if ((lError = RegOpenKeyExA ( hkey, pszGUID, 0, KEY_READ, &hkey1 )) != ERROR_SUCCESS) { TRACE1 (ANY, "ElGetInterfaceParams: Error in RegOpenKeyExA for GUID, %ld", lError); dwRetCode = (DWORD)lError; break; }
// Get the value of ..\Interfaces\GUID\EapolEnabled
dwInfoSize = sizeof(DWORD); if ((lError = RegQueryValueExA ( hkey1, cszEapolEnabled, 0, &dwType, (BYTE *)pdwEapolEnabled, &dwInfoSize)) != ERROR_SUCCESS) { TRACE2 (ANY, "ElGetInterfaceParams: Error in RegQueryValueExA for EapolEnabled, %ld, InfoSize=%ld", lError, dwInfoSize); *pdwEapolEnabled = DEFAULT_EAPOL_STATE; }
TRACE1 (ANY, "ElGetInterfaceParams: Got EapolEnabled = %ld", *pdwEapolEnabled);
// Get the value of ..\Interfaces\GUID\DefaultEAPType
dwInfoSize = sizeof(DWORD); if ((lError = RegQueryValueExA ( hkey1, cszDefaultEAPType, 0, &dwType, (BYTE *)pdwDefaultEAPType, &dwInfoSize)) != ERROR_SUCCESS) { TRACE2 (ANY, "ElGetInterfaceParams: Error in RegQueryValueExA for DefaultEAPType, %ld, InfoSize=%ld", lError, dwInfoSize); *pdwDefaultEAPType = DEFAULT_EAP_TYPE; }
TRACE1 (ANY, "ElGetInterfaceParams: Got DefaultEAPType = %ld", *pdwDefaultEAPType);
// Get the value of ..\Interfaces\GUID\LastUsedSSID
dwInfoSize = 256; if ((lError = RegQueryValueExA ( hkey1, cszLastUsedSSID, 0, &dwType, (PUCHAR)pszLastUsedSSID, &dwInfoSize)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElGetInterfaceParams: Error in RegQueryValueExA for LastUsedSSID, %ld", lError); pszLastUsedSSID = NULL; }
} while (FALSE);
if (hkey != NULL) { RegCloseKey (hkey); } if (hkey1 != NULL) { RegCloseKey (hkey1); }
return dwRetCode;
}
//
// ElSetInterfaceParams
//
// Description:
//
// Function called to set the EAPOL parameters for an interface, in the HKLM
// hive
//
// Arguments:
//
// pszGUID - Pointer to GUID string for the interface
// pdwDefaultEAPType - default EAP type for interface
// pszLastUsedSSID - SSID that was received in the last EAP-Request/Identity
// packet
// pdwEapolEnabled - Is EAPOL enabled for the interface
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
//
DWORD ElSetInterfaceParams ( IN CHAR *pszGUID, IN DWORD *pdwDefaultEAPType, IN CHAR *pszLastUsedSSID, IN DWORD *pdwEapolEnabled ) { HKEY hkey = NULL; HKEY hkey1 = NULL; DWORD dwInfoSize = 0; DWORD dwType = 0; LONG lError = ERROR_SUCCESS; DWORD dwRetCode = ERROR_SUCCESS;
do { // Validate input params
if (pszGUID == NULL) { TRACE0 (ANY, "ElSetInterfaceParams: GUID = NULL"); break; }
TRACE1 (ANY, "Setting stuff from registry for %s", pszGUID);
// Get handle to HKLM\Software\Microsoft\EAPOL\Parameters\Interfaces
if ((lError = RegOpenKeyExA ( HKEY_LOCAL_MACHINE, cszEapKeyEapolConn, 0, KEY_WRITE, &hkey )) != ERROR_SUCCESS) { TRACE1 (ANY, "ElSetInterfaceParams: Error in RegOpenKeyExA for base key, %ld", lError); dwRetCode = (DWORD)lError; break; }
// Get handle to HKLM\Software\...\Interfaces\<GUID>
if ((lError = RegOpenKeyExA ( hkey, pszGUID, 0, KEY_WRITE, &hkey1 )) != ERROR_SUCCESS) { TRACE1 (ANY, "ElSetInterfaceParams: Error in RegOpenKeyExA for GUID, %ld", lError); dwRetCode = (DWORD)lError; break; }
// Set the value of ..\Interfaces\GUID\EapolEnabled
if ((lError = RegSetValueExA ( hkey1, cszEapolEnabled, 0, REG_DWORD, (BYTE *)pdwEapolEnabled, sizeof(DWORD))) != ERROR_SUCCESS) { TRACE1 (ANY, "ElSetInterfaceParams: Error in RegSetValueExA for EapolEnabled, %ld", lError); }
// Set the value of ..\Interfaces\GUID\DefaultEAPType
if ((lError = RegSetValueExA ( hkey1, cszDefaultEAPType, 0, REG_DWORD, (BYTE *)pdwDefaultEAPType, sizeof(DWORD))) != ERROR_SUCCESS) { TRACE1 (ANY, "ElSetInterfaceParams: Error in RegSetValueExA for DefaultEAPType, %ld", lError); }
// Set the value of ..\Interfaces\GUID\LastUsedSSID
if ((lError = RegSetValueExA ( hkey1, cszLastUsedSSID, 0, REG_SZ, pszLastUsedSSID, strlen(pszLastUsedSSID))) != ERROR_SUCCESS) { TRACE1 (ANY, "ElGetInterfaceParams: Error in RegSetValueExA for LastUsedSSID, %ld", lError); }
} while (FALSE);
if (hkey != NULL) { RegCloseKey (hkey); } if (hkey1 != NULL) { RegCloseKey (hkey1); }
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: RegOpenKeyExA failed with error %ld", dwRetCode); break; } else { TRACE0 (ANY, "ElGetEapKeyFromToken: RegOpenKeyExA succeeded"); }
} else { TRACE0 (ANY,"ElGetEapKeyFromToken: GetTokenInformation succeeded when it should have failed"); break; } } else { TRACE0 (ANY, "ElGetEapKeyFromToken: Error, hUserToken == NULL "); 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:
// pszDeviceGUID - Pointer to GUID string for the port for which data is being
// initialized
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
DWORD ElInitRegPortData ( CHAR *pszDeviceGUID ) { PBYTE pbInfo = NULL; DWORD dwInfoSize = 0; EAPTLS_CONN_PROPERTIES *pConnProp = NULL; DWORD dwRetCode = NO_ERROR;
do { // Get the size of the Eap data first
if ((dwRetCode = ElGetCustomAuthData ( pszDeviceGUID, EAPCFG_DefaultKey, NULL, // SSID
NULL, // pbInfo
&dwInfoSize )) != NO_ERROR) { TRACE1 (ANY, "ElInitRegPortData: ElGetCustomAuthData returned error %ld", dwRetCode);
if ((dwRetCode == ERROR_BUFFER_TOO_SMALL) && (dwInfoSize != 0)) { // There is valid data in the default key in the registry
dwRetCode = NO_ERROR; TRACE1 (ANY, "ElInitRegPortData: ElGetCustomAuthData returned blob size = %ld", dwInfoSize); break; }
// Initialize port place with default data
pConnProp = MALLOC (sizeof (EAPTLS_CONN_PROPERTIES)); if (pConnProp == NULL) { TRACE0 (ANY, "ElInitRegPortData: Failed allocation for Conn Prop"); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; }
// Registry certs, No server cert validation, No server name
// comparison
pConnProp->fFlags = (EAPTLS_CONN_FLAG_REGISTRY | EAPTLS_CONN_FLAG_NO_VALIDATE_CERT | EAPTLS_CONN_FLAG_NO_VALIDATE_NAME); #if REG_CERT_VALIDATE
pConnProp->fFlags = EAPTLS_CONN_FLAG_REGISTRY; pConnProp->fFlags &= ~EAPTLS_CONN_FLAG_NO_VALIDATE_CERT; pConnProp->fFlags &= ~EAPTLS_CONN_FLAG_NO_VALIDATE_NAME; #endif
pConnProp->dwSize = sizeof (EAPTLS_CONN_PROPERTIES);
// Set this blob into the registry for the port
if ((dwRetCode = ElSetCustomAuthData ( pszDeviceGUID, EAPCFG_DefaultKey, NULL, (BYTE *)pConnProp, pConnProp->dwSize )) != 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; }
//
// 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); }
//
// 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; //
// 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: %S", 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 { TRACE0 (ANY, "ElNdisuioQueryOIDValue: DeviceIoControl succeeded");
if (BytesReturned >= *pulOidDataLength) { TRACE2 (ANY, "ElNdisuioQueryOIDValue: BytesRet (%ld) >= SizeofInput (%ld); truncating data", BytesReturned, *pulOidDataLength); BytesReturned = *pulOidDataLength; } else { dwRetCode = ERROR_INVALID_DATA; TRACE2 (ANY, "ElNdisuioQueryOIDValue: BytesRet (%ld) < SizeofInput (%ld)", BytesReturned, *pulOidDataLength); *pulOidDataLength = BytesReturned; }
memcpy(pbOidData, &pQueryOid->Data[0], BytesReturned); }
} while (FALSE);
if (pQueryOid != NULL) { FREE (pQueryOid); }
return dwRetCode; }
#if 0
//
// ElGuidFromString
//
// Description:
//
// Convert a GUID-string to GUID
//
// Arguments:
// pGuid - pointer to GUID
// pszGuidString - pointer to string version of GUID
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
DWORD ElGuidFromString ( IN OUT GUID *pGuid, IN CHAR *pszGuidString ) { DWORD dwGuidLen = 0; WCHAR wszGuidString[64]; LPWSTR lpwszWithBraces = NULL; DWORD dwRetCode = NO_ERROR;
do {
if (pszGuidString == NULL) { break; }
ZeroMemory (pGuid, sizeof(GUID));
dwGuidLen = strlen (pszGuidString); if (dwGuidLen != 36) { TRACE0 (ANY, "GuidFromString: Guid Length != required 36"); break; } if (0 == MultiByteToWideChar( CP_ACP, 0, pszGuidString, -1, wszGuidString, dwGuidLen ) ) { dwRetCode = GetLastError();
TRACE2 (ANY, "GuidFromString: MultiByteToWideChar(%s) failed: %d", pszGuidString, dwRetCode); break; } wszGuidString[dwGuidLen] = L'\0';
// add the braces
lpwszWithBraces = (LPWSTR) MALLOC ((dwGuidLen + 1 + 2) * sizeof(WCHAR));
wsprintf (lpwszWithBraces, L"{%s}", wszGuidString);
CLSIDFromString (lpwszWithBraces, pGuid);
} while (FALSE);
return dwRetCode; }
#endif
//
// ElGetLoggedOnUserName
//
// Description:
//
// Get the Username and Domain of the currently logged in user
//
// Arguments:
// pPCB - Pointer to port on which logged-on user's name is to be
// obtained
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
//
DWORD ElGetLoggedOnUserName ( IN EAPOL_PCB *pPCB ) { HANDLE hUserToken; WCHAR *pwszUserNameBuffer = NULL; DWORD dwBufferSize = 0; BOOL fNeedToRevertToSelf = FALSE; DWORD dwRetCode = NO_ERROR;
do { hUserToken = pPCB->hUserToken;
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) { 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; } pwszUserNameBuffer[dwBufferSize]=L'\0'; TRACE1 (ANY, "ElGetLoggedOnUserName: Got User Name %S", pwszUserNameBuffer); } else { TRACE1 (ANY, "ElGetLoggedOnUserName: GetUserNameEx failed with error %ld", dwRetCode); break; } } } else { TRACE0 (ANY, "ElGetLoggedOnUserName: UserToken is NULL"); break; }
} while (FALSE);
if (pwszUserNameBuffer != NULL) { FREE (pwszUserNameBuffer); }
// Revert impersonation
if (fNeedToRevertToSelf) { if (!RevertToSelf()) { dwRetCode = GetLastError(); TRACE1 (USER, "ElGetLoggedOnUserName: Error in RevertToSelf = %ld", dwRetCode); } }
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 %S", 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 %S", 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 ) { CHAR *pszRegInterfaceList = 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++) { ZeroMemory (ucBuffer, 256); InterfaceName.Length = 0; InterfaceName.MaximumLength = 256; InterfaceName.Buffer = ucBuffer;
if (Interfaces->Interface[i].DeviceName.Buffer != NULL) { if (RtlUnicodeStringToAnsiString(&InterfaceName, &(Interfaces->Interface[i].DeviceName), FALSE) != STATUS_SUCCESS) { TRACE1 (ANY, "ElUpdateRegistryInterfaceList: Error in RtlUnicodeStringToAnsiString for DeviceName %ws", Interfaces->Interface[i].DeviceName.Buffer); }
InterfaceName.Buffer[InterfaceName.Length] = '\0';
dwSizeOfList += (strlen(InterfaceName.Buffer) + 1); } else { TRACE0(INIT, "ElUpdateRegistryInterfaceList: Device Name was NULL"); continue; }
TRACE1(INIT, "Device: %s", InterfaceName.Buffer);
}
// One extra char for terminating NULL char
pszRegInterfaceList = (CHAR *) MALLOC ( dwSizeOfList + 1 );
if ( pszRegInterfaceList == NULL ) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (ANY, "ElUpdateRegistryInterfaceList: MALLOC failed for pszRegInterfaceList"); break; }
// Start again
dwSizeOfList = 0;
// Create the string in REG_SZ format
for (i=0; i < Interfaces->TotalInterfaces; i++) { ZeroMemory (ucBuffer, 256); InterfaceName.Length = 0; InterfaceName.MaximumLength = 256; InterfaceName.Buffer = ucBuffer;
if (Interfaces->Interface[i].DeviceName.Buffer != NULL) { if (RtlUnicodeStringToAnsiString(&InterfaceName, &Interfaces->Interface[i].DeviceName, FALSE) != STATUS_SUCCESS) { TRACE0 (ANY, "ElUpdateRegistryInterfaceList: Error in RtlUnicodeStringToAnsiString for DeviceName"); }
InterfaceName.Buffer[InterfaceName.Length] = '\0';
memcpy (&pszRegInterfaceList[dwSizeOfList], InterfaceName.Buffer, (strlen(InterfaceName.Buffer) )); dwSizeOfList += (strlen(InterfaceName.Buffer)); } else { TRACE0(INIT, "ElUpdateRegistryInterfaceList: Device Name was NULL"); continue; } }
// Final NULL character
pszRegInterfaceList[dwSizeOfList++] = '\0';
// Write the string as a REG_SZ value
// Get handle to
// HKLM\Software\Microsoft\EAPOL\Parameters\General
if ((lError = RegCreateKeyExA ( HKEY_LOCAL_MACHINE, cszEapKeyEapolServiceParams, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dwDisposition)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElUpdateRegistryInterfaceList: Error in RegCreateKeyExA for base key, %ld", lError); dwRetCode = (DWORD)lError; break; }
//
// Set the value of
// ...\EAPOL\Parameters\General\InterfaceList key
//
if ((lError = RegSetValueExA ( hkey, cszInterfaceList, 0, REG_SZ, pszRegInterfaceList, dwSizeOfList)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElUpdateRegistryInterfaceList: Error in RegSetValueExA for InterfaceList, %ld", lError); dwRetCode = (DWORD)lError; break; }
TRACE0 (ANY, "ElUpdateRegistryInterfaceList: Set value succeeded");
} while (FALSE);
if (hkey != NULL) { RegCloseKey (hkey); }
if (pszRegInterfaceList != NULL) { FREE (pszRegInterfaceList); }
return dwRetCode; }
//
// ElWatchGlobalRegistryParams
//
// Description:
//
// Watch the registry for changes for global params. Update in-memory values
//
// Arguments:
// Unused
//
// Return values:
//
//
VOID ElWatchGlobalRegistryParams ( IN PVOID pvContext ) { HKEY hKey = NULL; HANDLE hRegChangeEvent = NULL; HANDLE hEvents[2]; BOOL fExitThread = FALSE; DWORD dwDisposition = 0; DWORD dwStatus = 0; LONG lError = 0; DWORD dwRetCode = NO_ERROR;
TRACE0 (ANY, "ElWatchGlobalRegistryParams: Entered");
do {
// Get handle to
// HKLM\Software\Microsoft\EAPOL\Parameters\General\Global
if ((lError = RegCreateKeyExA ( HKEY_LOCAL_MACHINE, cszEAPOLGlobalParams, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ, NULL, &hKey, &dwDisposition)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElWatchGlobalRegistryParams: Error in RegCreateKeyExA for base key, %ld", lError); dwRetCode = (DWORD)lError; break; }
// Open a handle to a event to perform wait on that event
hRegChangeEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
if (hRegChangeEvent == NULL) { dwRetCode = GetLastError (); TRACE1 (ANY, "ElWatchGlobalRegistryParams: Error in CreateEvent for hRegChangeEvent = %ld", dwRetCode); break; }
// Register to notify change in registry value
if ((lError = RegNotifyChangeKeyValue ( hKey, TRUE, // watch entire sub-tree
REG_NOTIFY_CHANGE_LAST_SET, // detect value add/delete
hRegChangeEvent, TRUE // asynchronous
)) != ERROR_SUCCESS) { dwRetCode = (DWORD)lError; TRACE1 (ANY, "ElWatchGlobalRegistryParams: RegNotifyChangeKeyValue failed with error %ld", dwRetCode); break; }
do {
// Wait for Registry changes or service termination
hEvents[0] = hRegChangeEvent; hEvents[1] = g_hEventTerminateEAPOL;
if ((dwStatus = WaitForMultipleObjects( 2, hEvents, FALSE, INFINITE )) == WAIT_FAILED) { dwRetCode = GetLastError (); TRACE1 (ANY, "ElWatchGlobalRegistryParams: WaitForMultipleObjects failed with error %ld", dwRetCode); break; } switch (dwStatus) {
case WAIT_OBJECT_0:
// Registry values changed
// Update in-memory values
if ((dwRetCode = ElReadGlobalRegistryParams ()) != NO_ERROR) { TRACE1 (ANY, "ElWatchGlobalRegistryParams: ElReadGlobalRegistryParams failed with error %ld", dwRetCode);
// continue processing since this is not a critical error
dwRetCode = NO_ERROR; }
if (!ResetEvent(hRegChangeEvent)) { dwRetCode = GetLastError (); TRACE1 (ANY, "ElWatchGlobalRegistryParams: ResetEvent failed with error %ld", dwRetCode); break; }
break;
case WAIT_OBJECT_0+1:
// Service shutdown detected
fExitThread = TRUE; break;
default:
TRACE1 (ANY, "ElWatchGlobalRegistryParams: No such event = %ld", dwStatus); break; }
if ((dwRetCode != NO_ERROR) || (fExitThread)) { break; }
} while (TRUE);
} while (FALSE);
TRACE1 (ANY, "ElWatchGlobalRegistryParams: Completed with error %ld", dwRetCode);
if (hKey != NULL) { RegCloseKey(hKey); }
return;
}
//
// 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 dwRetCode = NO_ERROR;
do {
// Get handle to
// HKLM\Software\Microsoft\EAPOL\Parameters\General\Global
if ((lError = RegCreateKeyExA ( HKEY_LOCAL_MACHINE, cszEAPOLGlobalParams, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ, NULL, &hKey, &dwDisposition)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElReadGlobalRegistryParams: Error in RegCreateKeyExA 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_dwmaxStart = EAPOL_MAX_START; g_dwstartPeriod = EAPOL_START_PERIOD; g_dwauthPeriod = EAPOL_AUTH_PERIOD; g_dwheldPeriod = EAPOL_HELD_PERIOD; }
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 = RegQueryValueExA ( hKey, cszAuthPeriod, 0, &dwType, (BYTE *)&dwauthPeriod, &dwInfoSize)) != ERROR_SUCCESS) { TRACE2 (ANY, "ElReadGlobalRegistryParams: Error in RegQueryValueExA 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 = RegQueryValueExA ( hKey, cszHeldPeriod, 0, &dwType, (BYTE *)&dwheldPeriod, &dwInfoSize)) != ERROR_SUCCESS) { TRACE2 (ANY, "ElReadGlobalRegistryParams: Error in RegQueryValueExA 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 = RegQueryValueExA ( hKey, cszStartPeriod, 0, &dwType, (BYTE *)&dwstartPeriod, &dwInfoSize)) != ERROR_SUCCESS) { TRACE2 (ANY, "ElReadGlobalRegistryParams: Error in RegQueryValueExA 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 = RegQueryValueExA ( hKey, cszMaxStart, 0, &dwType, (BYTE *)&dwmaxStart, &dwInfoSize)) != ERROR_SUCCESS) { TRACE2 (ANY, "ElReadGlobalRegistryParams: Error in RegQueryValueExA for cszMaxStart, %ld, InfoSize=%ld", lError, dwInfoSize); dwmaxStart = g_dwmaxStart; lError = ERROR_SUCCESS; }
// 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;
}
//
// ElWatchEapConfigRegistryParams
//
// Description:
//
// Watch the registry for changes in EAP config
// - HKLM - EAP type
// - HKLM - EAPOLEnabled
//
// Restart the state machine if the params change
//
// Arguments:
//
// Return values:
//
//
VOID ElWatchEapConfigRegistryParams ( IN PVOID pvContext ) { HKEY hUserKey = NULL; HKEY hWorkspaceKey = NULL; HKEY hRegChangeKey = NULL; HANDLE hRegChangeEvent = NULL; HANDLE hEvents[2]; HANDLE hUserToken = NULL; DWORD dwDisposition = 0; BOOL fExitThread = FALSE; DWORD dwStatus = 0; LONG lError = 0; DWORD dwRetCode = NO_ERROR;
TRACE0 (ANY, "ElWatchEapConfigRegistryParams: Entered");
do {
// Get handle to
// HKLM\Software\Microsoft\EAPOL\Parameters\Interfaces
if ((lError = RegCreateKeyExA ( HKEY_LOCAL_MACHINE, cszEapKeyEapolConn, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ, NULL, &hWorkspaceKey, &dwDisposition)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElWatchEapConfigRegistryParams: Error in RegCreateKeyExA for cszEapKeyEapolConn, %ld", lError); dwRetCode = (DWORD)lError; break; }
// Open a handle to a event to perform wait on that event
hRegChangeEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
if (hRegChangeEvent == NULL) { dwRetCode = GetLastError (); TRACE1 (ANY, "ElWatchEapConfigRegistryParams: Error in CreateEvent for hRegChangeEvent = %ld", dwRetCode); break; }
do { // Register to notify change in registry value
if ((lError = RegNotifyChangeKeyValue ( hWorkspaceKey, TRUE, // watch entire sub-tree
REG_NOTIFY_CHANGE_LAST_SET, // detect value add/delete
hRegChangeEvent, TRUE // asynchronous
)) != ERROR_SUCCESS) { dwRetCode = (DWORD)lError; TRACE1 (ANY, "ElWatchEapConfigRegistryParams: RegNotifyChangeKeyValue failed with error %ld", dwRetCode); break; }
// Wait for Registry changes, service termination
hEvents[0] = hRegChangeEvent; hEvents[1] = g_hEventTerminateEAPOL;
if ((dwStatus = WaitForMultipleObjects( 2, hEvents, FALSE, INFINITE )) == WAIT_FAILED) { dwRetCode = GetLastError (); TRACE1 (ANY, "ElWatchEapConfigRegistryParams: WaitForMultipleObjects failed with error %ld", dwRetCode); break; } switch (dwStatus) {
case WAIT_OBJECT_0: TRACE0 (ANY, "ElWatchEapConfigRegistryParams: Got reg change event !!! ");
// Registry values changed
// Update in memory values
if ((dwRetCode = ElProcessEapConfigChange ()) != NO_ERROR) { TRACE1 (ANY, "ElWatchEapConfigRegistryParams: ElProcessEapConfigChange failed with error %ld", dwRetCode);
// log
// continue processing since this is not a critical error
dwRetCode = NO_ERROR; }
if (!ResetEvent(hRegChangeEvent)) { dwRetCode = GetLastError (); TRACE1 (ANY, "ElWatchEapConfigRegistryParams: ResetEvent failed with error %ld", dwRetCode); break; }
break;
case WAIT_OBJECT_0+1:
// Service shutdown detected
fExitThread = TRUE; TRACE0 (ANY, "ElWatchEapConfigRegistryParams: Service shutdonw"); break;
default:
TRACE1 (ANY, "ElWatchEapConfigRegistryParams: No such event = %ld", dwStatus); break; }
if ((dwRetCode != NO_ERROR) || (fExitThread)) { break; }
TRACE0 (ANY, "ElWatchEapConfigRegistryParams: RegNotifyChangeKeyValue being reposted !!!");
} while (TRUE);
} while (FALSE);
TRACE1 (ANY, "ElWatchEapConfigRegistryParams: Completed with error %ld", dwRetCode);
if (hUserKey != NULL) { RegCloseKey(hUserKey); }
if (hWorkspaceKey != NULL) { RegCloseKey(hWorkspaceKey); }
if (!CloseHandle(hRegChangeEvent)) { TRACE1 (ANY, "ElWatchEapConfigRegistryParams: Error in closing event handle", (dwRetCode = GetLastError())); }
return;
}
//
// ElProcessEapConfigChange
//
// Description:
//
// Read EAP config changes made in registry. Restart EAPOL on the particular
// interface or stop EAPOL
//
// Arguments:
//
// Return values:
//
// NO_ERROR - success
// non-zero - error
//
DWORD ElProcessEapConfigChange () { DWORD dwEapolEnabled = 0; DWORD dwDefaultEAPType = 0; CHAR szLastUsedSSID[256]; HKEY hWorkspaceKey = NULL; HKEY hKey = NULL, hKey1 = NULL; DWORD dwType = 0; DWORD dwInfoSize = 0; DWORD dwDisposition = 0; CHAR *pszLastModifiedGUID = NULL; DWORD dwbData = 0; PBYTE pbAuthData = NULL; EAPOL_PCB *pPCB = NULL; BOOL fReStartAuthentication = FALSE; LONG lError = 0; DWORD dwRetCode = NO_ERROR;
do { // Get the GUID for the interface for which EAP config was modified
// Get handle to
// HKLM\Software\Microsoft\EAPOL\Parameters\General\EAPOLGlobal
if ((lError = RegCreateKeyExA ( HKEY_LOCAL_MACHINE, cszEAPOLWorkspace, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ, NULL, &hWorkspaceKey, &dwDisposition)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElProcessEapConfigChange: Error in RegCreateKeyExA for cszEAPOLWorkspace key, %ld", lError); dwRetCode = (DWORD)lError; break; }
// Get the value of ..\General\EAPOLGlobal\LastModifiedGUID
dwInfoSize = 0; if ((lError = RegQueryValueExA ( hWorkspaceKey, cszLastModifiedGUID, 0, &dwType, NULL, &dwInfoSize)) == ERROR_SUCCESS) { if ((pszLastModifiedGUID = (CHAR *) MALLOC ( dwInfoSize )) == NULL) { TRACE0 (ANY, "ElProcessEapConfigChange: Error in MALLOC for pszLastModifiedGUID"); lError = (ULONG) ERROR_NOT_ENOUGH_MEMORY; dwRetCode = (DWORD)lError; break; }
if ((lError = RegQueryValueExA ( hWorkspaceKey, cszLastModifiedGUID, 0, &dwType, pszLastModifiedGUID, &dwInfoSize)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElProcessEapConfigChange: RegQueryValueExA failed for pszLastModifiedGUID with error %ld", lError); dwRetCode = (DWORD)lError; break; } } else { TRACE1 (ANY, "ElProcessEapConfigChange: Error in estimating size fo cszLastModifiedGUID = %ld", lError); break; }
// Check the value of EAPOLEnabled for that interface
// Get handle to HKLM\Software\Microsoft\EAPOL\Parameters\Interfaces
if ((lError = RegOpenKeyExA ( HKEY_LOCAL_MACHINE, cszEapKeyEapolConn, 0, KEY_READ, &hKey )) != ERROR_SUCCESS) { TRACE1 (ANY, "ElProcessEapConfigChange: Error in RegOpenKeyExA for base key, %ld", lError); dwRetCode = (DWORD)lError; break; }
// Get handle to HKLM\Software\...\Interfaces\<GUID>
if ((lError = RegOpenKeyExA ( hKey, pszLastModifiedGUID, 0, KEY_READ, &hKey1 )) != ERROR_SUCCESS) { TRACE1 (ANY, "ElProcessEapConfigChange: Error in RegOpenKeyExA for GUID, %ld", lError); dwRetCode = (DWORD)lError; break; }
// Get the value of ..\Interfaces\GUID\EapolEnabled
// This value should exist since it will always be set from UI
dwInfoSize = sizeof(DWORD); if ((lError = RegQueryValueExA ( hKey1, cszEapolEnabled, 0, &dwType, (BYTE *)&dwEapolEnabled, &dwInfoSize)) != ERROR_SUCCESS) { TRACE2 (ANY, "ElProcessEapConfigChange: Error in RegQueryValueExA for EapolEnabled, %ld, InfoSize=%ld", lError, dwInfoSize); dwRetCode = (DWORD)lError; break; }
TRACE1 (ANY, "ElProcessEapConfigChange: Got EapolEnabled = %ld", dwEapolEnabled);
// Get the value of ..\Interfaces\GUID\DefaultEAPType
// This value should exist since it will always be set from UI
dwInfoSize = sizeof(DWORD); if ((lError = RegQueryValueExA ( hKey1, cszDefaultEAPType, 0, &dwType, (BYTE *)&dwDefaultEAPType, &dwInfoSize)) != ERROR_SUCCESS) { TRACE2 (ANY, "ElProcessEapConfigChange: Error in RegQueryValueExA for DefaultEAPType, %ld, InfoSize=%ld", lError, dwInfoSize); dwRetCode = (DWORD)lError; break; }
// Get the value of ..\Interfaces\GUID\LastUsedSSID
dwInfoSize = 256; ZeroMemory ((BYTE *)szLastUsedSSID, 256); if ((lError = RegQueryValueExA ( hKey1, cszLastUsedSSID, 0, &dwType, (PUCHAR)szLastUsedSSID, &dwInfoSize)) != ERROR_SUCCESS) { TRACE1 (ANY, "ElProcessEapConfigChange: Error in RegQueryValueExA for LastUsedSSID, %ld", lError); dwRetCode = (DWORD)lError; if (dwRetCode == ERROR_FILE_NOT_FOUND) { // SSID may not be received as yet from AP/switch
// Changes will be made stored for "Default" SSID
dwRetCode = NO_ERROR; } else { break; } }
// Check existence/absence of PCB i.e. if EAPOL state machine was
// started on the interface, and take appropriate action based on
// EAPOLEnabled value
if (dwEapolEnabled == 0) { ACQUIRE_WRITE_LOCK (&(g_PCBLock));
if ((pPCB = ElGetPCBPointerFromPortGUID (pszLastModifiedGUID)) != NULL) { RELEASE_WRITE_LOCK (&(g_PCBLock));
// Found PCB for interface, where EAPOLEnabled = 0
// Stop EAPOL on the port and remove the port from the module
if ((dwRetCode = ElShutdownInterface (pszLastModifiedGUID)) != NO_ERROR) { TRACE1 (ANY, "ElProcessEapConfigChange: ElShutdownInterface failed with error %ld", dwRetCode); break; } } else { // No PCB found for interface, valid condition,
// continue processing
RELEASE_WRITE_LOCK (&(g_PCBLock)); } } else { ACQUIRE_WRITE_LOCK (&(g_PCBLock));
if ((pPCB = ElGetPCBPointerFromPortGUID (pszLastModifiedGUID)) == NULL) { RELEASE_WRITE_LOCK (&(g_PCBLock));
// Did not find PCB for interface, where EAPOLEnabled = 1
// Start EAPOL on the port
ACQUIRE_WRITE_LOCK (&g_ITFLock);
if ((dwRetCode = ElEnumAndOpenInterfaces (NULL, pszLastModifiedGUID)) != NO_ERROR) { RELEASE_WRITE_LOCK (&g_ITFLock); TRACE1 (ANY, "ElProcessEapConfigChange: ElEnumAndOpenInterfaces returned error %ld", dwRetCode); break; }
RELEASE_WRITE_LOCK (&g_ITFLock); } else { ACQUIRE_WRITE_LOCK (&(pPCB->rwLock));
if (pPCB->dwEapTypeToBeUsed != dwDefaultEAPType) {
// Default EAP Type has changed
fReStartAuthentication = TRUE;
} else { // Default EAP Type is the same
// Check if the CustomAuthData is the same
// If not the same, do further processing
// Else, no change occured, same config was reapplied
// Get the size of the EAP blob
if ((dwRetCode = ElGetCustomAuthData ( pszLastModifiedGUID, dwDefaultEAPType, szLastUsedSSID, NULL, &dwbData )) != NO_ERROR) { if (dwRetCode == ERROR_BUFFER_TOO_SMALL) { if (dwbData <= 0) { if (pPCB->pCustomAuthConnData->pbCustomAuthData) { // No EAP blob stored in the registry
RELEASE_WRITE_LOCK (&(pPCB->rwLock)); RELEASE_WRITE_LOCK (&(g_PCBLock)); TRACE0 (ANY, "ElProcessEapConfigChange: NULL sized EAP blob, cannot continue"); pbAuthData = NULL; dwRetCode = ERROR_CAN_NOT_COMPLETE; break; } } else { // Allocate memory to hold the blob
pbAuthData = MALLOC (dwbData); if (pbAuthData == NULL) { RELEASE_WRITE_LOCK (&(pPCB->rwLock)); RELEASE_WRITE_LOCK (&(g_PCBLock)); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (ANY, "ElProcessEapConfigChange: Error in memory allocation for EAP blob"); break; } if ((dwRetCode = ElGetCustomAuthData ( pszLastModifiedGUID, dwDefaultEAPType, szLastUsedSSID, pbAuthData, &dwbData )) != NO_ERROR) { RELEASE_WRITE_LOCK (&(pPCB->rwLock)); RELEASE_WRITE_LOCK (&(g_PCBLock)); TRACE1 (ANY, "ElProcessEapConfigChange: ElGetCustomAuthData failed with %ld", dwRetCode); break; } } } else { RELEASE_WRITE_LOCK (&(pPCB->rwLock)); RELEASE_WRITE_LOCK (&(g_PCBLock)); TRACE1 (ANY, "ElProcessEapConfigChange: ElGetCustomAuthData failed in size estimation with error %ld", dwRetCode); break; } }
if (pPCB->pCustomAuthConnData == NULL) { if (dwbData > 0) { fReStartAuthentication = TRUE; } } else { if (pPCB->pCustomAuthConnData->dwSizeOfCustomAuthData != dwbData) { // Same EAP Type, but different lengths
fReStartAuthentication = TRUE; } else { if (memcmp ( pPCB->pCustomAuthConnData->pbCustomAuthData, pbAuthData, dwbData) != 0) { // Same EAP Type, same data length, but
// different contents
fReStartAuthentication = TRUE; } else { // No change in EAP config data for this
// interface
} } }
} RELEASE_WRITE_LOCK (&(pPCB->rwLock));
if (fReStartAuthentication) { if ((dwRetCode = ElReStartPort (pPCB)) != NO_ERROR) { RELEASE_WRITE_LOCK (&(g_PCBLock)); TRACE1 (ANY, "ElProcessEapConfigChange: Error in ElReStartPort = %d", dwRetCode); break; } }
RELEASE_WRITE_LOCK (&(g_PCBLock));
} }
} while (FALSE); if (hWorkspaceKey != NULL) { RegCloseKey(hWorkspaceKey); }
if (hKey != NULL) { RegCloseKey(hKey); }
if (hKey1 != NULL) { RegCloseKey(hKey1); }
if (pszLastModifiedGUID != NULL) { FREE (pszLastModifiedGUID); }
if (pbAuthData != NULL) { FREE (pbAuthData); }
return dwRetCode; }
//
// 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 CHAR * psGuid, OUT LPGUID pGuid ) { CHAR c; DWORD i=0;
//
// If the first character is a '{', skip it.
//
if ( psGuid[0] == L'{' ) psGuid++;
//
// Convert string to guid
// (since psGuid may be used again below, no permanent modification to
// it may be made)
//
c = psGuid[8]; psGuid[8] = 0; pGuid->Data1 = strtoul ( &psGuid[0], 0, 16 ); psGuid[8] = c; c = psGuid[13]; psGuid[13] = 0; pGuid->Data2 = (USHORT)strtoul ( &psGuid[9], 0, 16 ); psGuid[13] = c; c = psGuid[18]; psGuid[18] = 0; pGuid->Data3 = (USHORT)strtoul ( &psGuid[14], 0, 16 ); psGuid[18] = c;
c = psGuid[21]; psGuid[21] = 0; pGuid->Data4[0] = (unsigned char)strtoul ( &psGuid[19], 0, 16 ); psGuid[21] = c; c = psGuid[23]; psGuid[23] = 0; pGuid->Data4[1] = (unsigned char)strtoul ( &psGuid[21], 0, 16 ); psGuid[23] = c;
for ( i=0; i < 6; i++ ) { c = psGuid[26+i*2]; psGuid[26+i*2] = 0; pGuid->Data4[2+i] = (unsigned char)strtoul ( &psGuid[24+i*2], 0, 16 ); psGuid[26+i*2] = c; }
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 ) { DWORD dwRetCode = NO_ERROR;
do {
// Get user's identity if it has not been obtained till now
if ((g_fUserLoggedOn) && (pPCB->dwAuthFailCount <= EAPOL_MAX_AUTH_FAIL_COUNT) && (pPCB->PreviousAuthenticationType != EAPOL_MACHINE_AUTHENTICATION)) { TRACE0 (ANY, "ElGetIdentity: Userlogged, <Maxauth, Prev !Machine auth"); if (!(pPCB->fGotUserIdentity)) {
// NOTE: Hardcoding for now
// Needs to be solved
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, "ElEapMakeMessage: 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, "ElEapMakeMessage: Error in ElGetUserIdentity %ld", dwRetCode); } }
if (dwRetCode == NO_ERROR) { TRACE0 (ANY, "ElGetIdentity: Userlogged, <Maxauth, Prev !Machine auth: No Error: User Auth fine"); pPCB->PreviousAuthenticationType = EAPOL_USER_AUTHENTICATION; } else { TRACE0 (ANY, "ElGetIdentity: Userlogged, <Maxauth, Prev !Machine auth: Error");
// No UI required
if ((pPCB->dwEapTypeToBeUsed != EAP_TYPE_MD5) && (g_dwMachineAuthEnabled)) { TRACE0 (ANY, "ElGetIdentity: Userlogged, <Maxauth, Prev !Machine auth: Error: !MD5, Machine Auth");
// Get Machine name
dwRetCode = NO_ERROR; pPCB->PreviousAuthenticationType = EAPOL_MACHINE_AUTHENTICATION; dwRetCode = ElGetUserIdentity (pPCB); if (dwRetCode != NO_ERROR) { TRACE1 (ANY, "ElGetIdentity: ElGetUserIdentity failed with error %ld", dwRetCode); } }
if ((dwRetCode != NO_ERROR) || (!g_dwMachineAuthEnabled) || (pPCB->dwEapTypeToBeUsed == EAP_TYPE_MD5)) { TRACE3 (ANY, "ElGetIdentity: Userlogged, <Maxauth, !Machine auth: Error: Error=%ld, Machauth=%ld, MD5=%ld", dwRetCode?1:0, g_dwMachineAuthEnabled?1:0, (pPCB->dwEapTypeToBeUsed == EAP_TYPE_MD5)?1:0);
if (pPCB->pszIdentity != NULL) { FREE (pPCB->pszIdentity); pPCB->pszIdentity = NULL; }
pPCB->PreviousAuthenticationType = EAPOL_UNAUTHENTICATED_ACCESS; dwRetCode = NO_ERROR; } } } } else { TRACE2 (ANY, "ElGetIdentity: Userlogged=%ld, auth>max, Machine auth=%ld", g_fUserLoggedOn?1:0, (pPCB->PreviousAuthenticationType==EAPOL_MACHINE_AUTHENTICATION)?1:0 );
// No UI required
if ((pPCB->dwEapTypeToBeUsed != EAP_TYPE_MD5) && (g_dwMachineAuthEnabled)) {
TRACE0 (ANY, "ElGetIdentity: !MD5, Machine auth");
pPCB->PreviousAuthenticationType = EAPOL_MACHINE_AUTHENTICATION;
// Get Machine credentials
dwRetCode = ElGetUserIdentity (pPCB);
if (dwRetCode != NO_ERROR) { TRACE1 (ANY, "ElGetIdentity: ElGetUserIdentity failed with error %ld", dwRetCode); } }
if ((dwRetCode != NO_ERROR) || (!g_dwMachineAuthEnabled) || (pPCB->dwEapTypeToBeUsed == EAP_TYPE_MD5)) { TRACE3 (ANY, "ElGetIdentity: Error=%ld, Machine auth=%ld, MD5=%ld", dwRetCode?1:0, g_dwMachineAuthEnabled?1:0, (pPCB->dwEapTypeToBeUsed == EAP_TYPE_MD5)?1:0);
if (pPCB->pszIdentity != NULL) { FREE (pPCB->pszIdentity); pPCB->pszIdentity = NULL; }
pPCB->PreviousAuthenticationType = EAPOL_UNAUTHENTICATED_ACCESS; dwRetCode = NO_ERROR; } }
} 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); ASSERT (h == NULL); }
} 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) { 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) { 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 CHAR *pszInterfaceName, IN OUT NIC_STATISTICS *pStats ) { WCHAR *pwszInterfaceName = NULL; UNICODE_STRING UInterfaceName; DWORD dwRetCode = NO_ERROR;
do { pwszInterfaceName = MALLOC ((strlen (pszInterfaceName)+12)*sizeof(WCHAR)); if (pwszInterfaceName == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (ANY, "ElGetInterfaceNdisStatistics: MALLOC failed for pwszInterfaceName"); break; }
wcscpy (pwszInterfaceName, L"\\Device\\{");
if (0 == MultiByteToWideChar( CP_ACP, 0, pszInterfaceName, -1, &pwszInterfaceName[9], (strlen(pszInterfaceName)+12)*sizeof(WCHAR))) { dwRetCode = GetLastError(); TRACE2 (ANY, "ElGetInterfaceNdisStatistics: MultiByteToWideChar(%s) failed: %ld", pszInterfaceName, dwRetCode); break; }
pwszInterfaceName[strlen(pszInterfaceName) + 9] = L'\0';
wcscat (pwszInterfaceName, L"}");
TRACE1 (ANY, "ElGetInterfaceNdisStatistics: pwszInterfaceName = (%ws)", pwszInterfaceName);
RtlInitUnicodeString (&UInterfaceName, pwszInterfaceName); 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 (pwszInterfaceName != NULL) { FREE (pwszInterfaceName); }
return dwRetCode; }
|