/*++ 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\ 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\ 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\ 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\ 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\ 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\ 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\ 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\ 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, PreviousAuthenticationType = EAPOL_UNAUTHENTICATED_ACCESS; 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, 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; dwIndexNumberOfItems; 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\ 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\ 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; }