|
|
/*++
Copyright (c) 2000, Microsoft Corporation
Module Name: eluser.c
Abstract:
The module deals with functions related to user interaction, user logon
Revision History:
sachins, Apr 23 2000, Created
--*/
#include "pcheapol.h"
#pragma hdrstop
#define cszEapKeyRas TEXT("Software\\Microsoft\\RAS EAP\\UserEapInfo")
#define cszEapValue TEXT("EapInfo")
#ifndef EAPOL_SERVICE
#define cszModuleName TEXT("wzcsvc.dll")
#else
#define cszModuleName TEXT("eapol.exe")
#endif
//
// ElSessionChangeHandler
//
// Description:
//
// Function called to handle user session login/logoff/user-switching
//
// Arguments:
// pEventData - SCM event data
// dwEventType - SCM event type
//
VOID ElSessionChangeHandler ( PVOID pEventData, DWORD dwEventType ) { DWORD dwEventStatus = 0; BOOLEAN fDecrWorkerThreadCount = FALSE; LPTHREAD_START_ROUTINE pUserRoutine = NULL; PVOID pvBuffer = NULL; EAPOL_ZC_INTF ZCData; 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; } if (!(g_dwModulesStarted & LOGON_MODULE_STARTED)) { break; }
InterlockedIncrement (&g_lWorkerThreads);
fDecrWorkerThreadCount = TRUE;
if (pEventData) { WTSSESSION_NOTIFICATION* pswtsi = (WTSSESSION_NOTIFICATION*)pEventData; DWORD dwSessionId = pswtsi->dwSessionId; switch (dwEventType) { case WTS_CONSOLE_CONNECT: case WTS_REMOTE_CONNECT: { TRACE1 (USER,"ElSessionChangeHandler: CONNECT for session = (%ld)\n", dwSessionId); pUserRoutine = ElUserLogonCallback; break; } case WTS_CONSOLE_DISCONNECT: case WTS_REMOTE_DISCONNECT: { TRACE1 (USER,"ElSessionChangeHandler: DISCONNECT for session = (%ld)\n", dwSessionId); pUserRoutine = ElUserLogoffCallback; break; } case WTS_SESSION_LOGON: { TRACE1 (USER,"ElSessionChangeHandler: LOGON for session = (%ld)", dwSessionId); pUserRoutine = ElUserLogonCallback; break; } case WTS_SESSION_LOGOFF: { TRACE1 (USER,"ElSessionChangeHandler: LOGOFF for session=(%ld)", dwSessionId); pUserRoutine = ElUserLogoffCallback; break; } default: break; }
if (pUserRoutine == NULL) { break; }
if ((pvBuffer = MALLOC (sizeof(DWORD))) == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; }
*((DWORD *)pvBuffer) = dwSessionId;
if (!QueueUserWorkItem ( (LPTHREAD_START_ROUTINE)pUserRoutine, pvBuffer, WT_EXECUTELONGFUNCTION)) { dwRetCode = GetLastError(); TRACE1 (DEVICE, "ElSessionChangeHandler: QueueUserWorkItem failed with error %ld", dwRetCode); break; } else { fDecrWorkerThreadCount = FALSE; }
} } while (FALSE);
if (fDecrWorkerThreadCount) { InterlockedDecrement (&g_lWorkerThreads); }
if (dwRetCode != NO_ERROR) { if (pvBuffer != NULL) { FREE (pvBuffer); } } }
//
// ElUserLogonCallback
//
// Description:
//
// Callback function invoked whenever a user logs in
// Will initiate authentication process on all ports of LAN class
// Credentials for the user in case of EAP-TLS can be obtained by
// acquiring user token
// For EAP-CHAP, WinLogon cerdentials will need to be supplied
//
// Arguments:
// None.
//
DWORD WINAPI ElUserLogonCallback ( IN PVOID pvContext ) {
DWORD dwIndex = 0; EAPOL_PCB *pPCB = NULL; BOOL fSetCONNECTINGState = FALSE; EAPOL_ZC_INTF ZCData; DWORD dwRetCode = NO_ERROR;
TRACE1 (USER, "ElUserLogonCallback: UserloggedOn = %ld", g_fUserLoggedOn);
do { if (g_fUserLoggedOn) { TRACE0 (USER, "ElUserLogonCallback: User logon already detected, returning without processing"); break; }
if (pvContext == NULL) { break; }
if (*((DWORD *)pvContext) != USER_SHARED_DATA->ActiveConsoleId) { TRACE1 (USER, "ElUserLogonCallback: Not active console id (%ld)", *((DWORD *)pvContext)); break; }
// Check if UserModule is ready for notifications
if (!g_fTrayIconReady) { if ((dwRetCode = ElCheckUserModuleReady ()) != NO_ERROR) { TRACE1 (USER, "ElUserLogonCallback: ElCheckUserModuleReady failed with error %ld", dwRetCode); if (dwRetCode == ERROR_BAD_IMPERSONATION_LEVEL) { break; } } }
// Set global flag to indicate the user logged on
g_fUserLoggedOn = TRUE; g_dwCurrentSessionId = *((DWORD *)pvContext);
ACQUIRE_WRITE_LOCK (&(g_PCBLock));
for (dwIndex = 0; dwIndex < PORT_TABLE_BUCKETS; dwIndex++) { for (pPCB = g_PCBTable.pPCBBuckets[dwIndex].pPorts; pPCB != NULL; pPCB = pPCB->pNext) { fSetCONNECTINGState = FALSE; ACQUIRE_WRITE_LOCK (&(pPCB->rwLock));
switch (pPCB->dwEAPOLAuthMode) { case EAPOL_AUTH_MODE_0:
if (pPCB->State == EAPOLSTATE_AUTHENTICATED) { if (pPCB->PreviousAuthenticationType == EAPOL_UNAUTHENTICATED_ACCESS) { fSetCONNECTINGState = TRUE; } } else { (VOID) ElEapEnd (pPCB); fSetCONNECTINGState = TRUE; }
break;
case EAPOL_AUTH_MODE_1:
(VOID) ElEapEnd (pPCB); fSetCONNECTINGState = TRUE;
break;
case EAPOL_AUTH_MODE_2:
// Do nothing
break; }
if (!EAPOL_PORT_ACTIVE(pPCB)) { TRACE1 (USER, "ElUserLogonCallback: Port %ws not active", pPCB->pwszDeviceGUID); fSetCONNECTINGState = FALSE; }
// Set port to EAPOLSTATE_CONNECTING
if (fSetCONNECTINGState) { DbLogPCBEvent (DBLOG_CATEG_INFO, pPCB, EAPOL_USER_LOGON, pPCB->pwszFriendlyName);
// First send out EAPOL_Logoff message
if ((dwRetCode = FSMLogoff (pPCB, NULL)) != NO_ERROR) { TRACE1 (USER, "ElUserLogonCallback: Error in FSMLogoff = %ld", dwRetCode); dwRetCode = NO_ERROR; }
pPCB->dwAuthFailCount = 0;
// With unauthenticated access flag set, port will always
// reauthenticate for logged on user
pPCB->PreviousAuthenticationType = EAPOL_UNAUTHENTICATED_ACCESS;
RELEASE_WRITE_LOCK (&(pPCB->rwLock));
// Restart authentication on the port
if ((dwRetCode = ElReStartPort (pPCB, 0, NULL)) != NO_ERROR) { TRACE1 (USER, "ElUserLogonCallback: MachineAuth: Error in ElReStartPort = %ld", dwRetCode); continue; } } else { RELEASE_WRITE_LOCK (&(pPCB->rwLock)); continue; } } } RELEASE_WRITE_LOCK (&(g_PCBLock)); if (dwRetCode != NO_ERROR) { break; } } while (FALSE);
TRACE1 (USER, "ElUserLogonCallback: completed with error %ld", dwRetCode); if (pvContext != NULL) { FREE (pvContext); }
InterlockedDecrement (&g_lWorkerThreads);
return 0; }
//
// ElUserLogoffCallback
//
// Description:
//
// Callback function invoked whenever a user logs off
// Will logoff from all ports which have authentication enabled
//
// Arguments:
// None.
//
DWORD WINAPI ElUserLogoffCallback ( IN PVOID pvContext ) { DWORD dwIndex = 0; EAPOL_PCB *pPCB = NULL; BOOL fSetCONNECTINGState = FALSE; EAPOL_ZC_INTF ZCData; DWORD dwRetCode = NO_ERROR;
do { if (!g_fUserLoggedOn) { TRACE0 (USER, "ElUserLogoffCallback: User logoff already called, returning without processing"); break; }
if (pvContext == NULL) { break; }
if (g_dwCurrentSessionId != *((DWORD *)pvContext)) { TRACE1 (USER, "ElUserLogoffCallback: Not active console id (%ld)", *((DWORD *)pvContext)); break; }
// Reset global flag to indicate the user logged off
g_fUserLoggedOn = FALSE; g_dwCurrentSessionId = 0xffffffff;
// Reset User Module ready flag
g_fTrayIconReady = FALSE; TRACE1 (USER, "ElUserLogoffCallback: UserloggedOff = %ld", g_fUserLoggedOn);
ACQUIRE_WRITE_LOCK (&(g_PCBLock));
for (dwIndex = 0; dwIndex < PORT_TABLE_BUCKETS; dwIndex++) { for (pPCB = g_PCBTable.pPCBBuckets[dwIndex].pPorts; pPCB != NULL; pPCB = pPCB->pNext) { fSetCONNECTINGState = FALSE; ACQUIRE_WRITE_LOCK (&(pPCB->rwLock));
switch (pPCB->dwEAPOLAuthMode) { case EAPOL_AUTH_MODE_0:
if (pPCB->State == EAPOLSTATE_AUTHENTICATED) { if (pPCB->PreviousAuthenticationType != EAPOL_MACHINE_AUTHENTICATION) { fSetCONNECTINGState = TRUE; } } else { (VOID) ElEapEnd (pPCB); fSetCONNECTINGState = TRUE; }
break;
case EAPOL_AUTH_MODE_1:
(VOID) ElEapEnd (pPCB); fSetCONNECTINGState = TRUE;
break;
case EAPOL_AUTH_MODE_2:
// Do nothing
break; }
if (!EAPOL_PORT_ACTIVE(pPCB)) { TRACE1 (USER, "ElUserLogoffCallback: Port %ws not active", pPCB->pwszDeviceGUID); fSetCONNECTINGState = FALSE; }
// Set port to EAPOLSTATE_CONNECTING
if (fSetCONNECTINGState) { DbLogPCBEvent (DBLOG_CATEG_INFO, pPCB, EAPOL_USER_LOGOFF, pPCB->pwszFriendlyName);
// First send out EAPOL_Logoff message
if ((dwRetCode = FSMLogoff (pPCB, NULL)) != NO_ERROR) { TRACE1 (USER, "ElUserLogoffCallback: Error in FSMLogoff = %ld", dwRetCode); dwRetCode = NO_ERROR; }
pPCB->dwAuthFailCount = 0;
// With Unauthenticated_access, port will always
// reauthenticate
pPCB->PreviousAuthenticationType = EAPOL_UNAUTHENTICATED_ACCESS;
RELEASE_WRITE_LOCK (&(pPCB->rwLock));
// Restart authentication on the port
if ((dwRetCode = ElReStartPort (pPCB, 0, NULL)) != NO_ERROR) { TRACE1 (USER, "ElUserLogoffCallback: Error in ElReStartPort = %ld", dwRetCode); continue; } } else { RELEASE_WRITE_LOCK (&(pPCB->rwLock)); continue; } } } RELEASE_WRITE_LOCK (&(g_PCBLock)); } while (FALSE); TRACE0 (USER, "ElUserLogoffCallback: completed");
if (pvContext != NULL) { FREE (pvContext); }
InterlockedDecrement (&g_lWorkerThreads); return 0; }
//
// ElGetUserIdentity
//
// Description:
//
// Function called to initiate and get user identity on a particular
// interface. The RasEapGetIdentity in the appropriate DLL is called
// with the necessary arguments.
//
// Arguments:
// pPCB - Pointer to PCB for the specific port/interface
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
DWORD ElGetUserIdentity ( IN EAPOL_PCB *pPCB ) { HANDLE hLib = NULL; RASEAPFREE pFreeFunc = NULL; RASEAPGETIDENTITY pIdenFunc = NULL; DWORD dwIndex = -1; DWORD cbData = 0; PBYTE pbAuthData = NULL; PBYTE pbUserIn = NULL; DWORD dwInSize = 0; BYTE *pUserDataOut; DWORD dwSizeOfUserDataOut; LPWSTR lpwszIdentity = NULL; CHAR *pszIdentity = NULL; HWND hwndOwner = NULL; DWORD dwFlags = 0; BYTE *pbSSID = NULL; DWORD dwSizeOfSSID = 0; EAPOL_STATE TmpEAPOLState; EAPOL_EAP_UI_CONTEXT *pEAPUIContext = NULL; DWORD dwRetCode = NO_ERROR;
do { TRACE0 (USER, "ElGetUserIdentity entered");
if (!EAPOL_PORT_ACTIVE(pPCB)) { TRACE1 (PORT, "ElGetUserIdentity: Port %ws not active", pPCB->pwszDeviceGUID); // Port is not active, cannot do further processing on this port
break; }
if (pPCB->PreviousAuthenticationType != EAPOL_MACHINE_AUTHENTICATION) { // Get Access Token for user logged on interactively
if (pPCB->hUserToken != NULL) { if (!CloseHandle (pPCB->hUserToken)) { dwRetCode = GetLastError (); TRACE1 (USER, "ElGetUserIdentity: CloseHandle failed with error %ld", dwRetCode); break; } } pPCB->hUserToken = NULL;
if ((dwRetCode = ElGetWinStationUserToken (g_dwCurrentSessionId, &pPCB->hUserToken)) != NO_ERROR) { TRACE1 (USER, "ElGetUserIdentity: ElGetWinStationUserToken failed with error (%ld)", dwRetCode); dwRetCode = ERROR_NO_TOKEN; break; }
//
// Try to fetch user identity without sending request to
// user module. If not possible, send request to user module
//
if ((dwRetCode = ElGetUserIdentityOptimized (pPCB)) != ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION) { TRACE0 (USER, "ElGetUserIdentity: ElGetUserIdentityOptimized got identity without user module intervention"); break; }
if (!g_fTrayIconReady) { if ((dwRetCode = ElCheckUserModuleReady ()) != NO_ERROR) { TRACE1 (USER, "ElGetUserIdentity: ElCheckUserModuleReady failed with error %ld", dwRetCode); break; } }
if (!g_fTrayIconReady) { DbLogPCBEvent (DBLOG_CATEG_WARN, pPCB, EAPOL_WAITING_FOR_DESKTOP_LOAD); dwRetCode = ERROR_IO_PENDING; TRACE0 (USER, "ElGetUserIdentity: TrayIcon NOT ready"); break; }
//
// Call GetUserIdentityDlgWorker
//
pEAPUIContext = MALLOC (sizeof(EAPOL_EAP_UI_CONTEXT)); if (pEAPUIContext == NULL) { TRACE0 (USER, "ElGetUserIdentity: MALLOC failed for pEAPUIContext"); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; }
pEAPUIContext->dwEAPOLUIMsgType = EAPOLUI_GET_USERIDENTITY; wcscpy (pEAPUIContext->wszGUID, pPCB->pwszDeviceGUID); pPCB->dwUIInvocationId = InterlockedIncrement(&(g_dwEAPUIInvocationId)); pEAPUIContext->dwSessionId = g_dwCurrentSessionId; pEAPUIContext->dwContextId = pPCB->dwUIInvocationId; pEAPUIContext->dwEapId = pPCB->bCurrentEAPId; pEAPUIContext->dwEapTypeId = pPCB->dwEapTypeToBeUsed; pEAPUIContext->dwEapFlags = pPCB->dwEapFlags; 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)); }
// Have to notify state change before we post balloon
TmpEAPOLState = pPCB->State; pPCB->State = EAPOLSTATE_ACQUIRED; ElNetmanNotify (pPCB, EAPOL_NCS_CRED_REQUIRED, NULL); // State is changed only in FSMAcquired
// Revert to original
pPCB->State = TmpEAPOLState;
// Post the message to netman
if ((dwRetCode = ElPostShowBalloonMessage ( pPCB, sizeof(EAPOL_EAP_UI_CONTEXT), (BYTE *)pEAPUIContext, 0, NULL )) != NO_ERROR) { TRACE1 (USER, "ElGetUserIdentity: ElPostShowBalloonMessage failed with error %ld", dwRetCode); break; }
// Restart PCB timer since UI may take longer time than required
RESTART_TIMER (pPCB->hTimer, INFINITE_SECONDS, "PCB", &dwRetCode); if (dwRetCode != NO_ERROR) { break; }
pPCB->EapUIState = EAPUISTATE_WAITING_FOR_IDENTITY; DbLogPCBEvent (DBLOG_CATEG_INFO, pPCB, EAPOL_WAITING_FOR_DESKTOP_IDENTITY);
// Return error code as pending, since credentials have still not
// been acquired
dwRetCode = ERROR_IO_PENDING;
} else // MACHINE_AUTHENTICATION
{
pPCB->hUserToken = NULL;
// The EAP dll will have already been loaded by the state machine
// Retrieve the handle to the dll from the global EAP table
if ((dwIndex = ElGetEapTypeIndex (pPCB->dwEapTypeToBeUsed)) == -1) { TRACE1 (USER, "ElGetUserIdentity: ElGetEapTypeIndex finds no dll for EAP index %ld", pPCB->dwEapTypeToBeUsed); dwRetCode = ERROR_CAN_NOT_COMPLETE; break; }
hLib = g_pEapTable[dwIndex].hInstance;
pIdenFunc = (RASEAPGETIDENTITY)GetProcAddress(hLib, "RasEapGetIdentity"); pFreeFunc = (RASEAPFREE)GetProcAddress(hLib, "RasEapFreeMemory");
if ((pFreeFunc == NULL) || (pIdenFunc == NULL)) { TRACE0 (USER, "ElGetUserIdentity: pIdenFunc or pFreeFunc does not exist in the EAP implementation"); dwRetCode = ERROR_CAN_NOT_COMPLETE; break; }
if (pPCB->pSSID) { pbSSID = pPCB->pSSID->Ssid; dwSizeOfSSID = pPCB->pSSID->SsidLength; }
// Get the size of the EAP blob
if ((dwRetCode = ElGetCustomAuthData ( pPCB->pwszDeviceGUID, pPCB->dwEapTypeToBeUsed, dwSizeOfSSID, pbSSID, NULL, &cbData )) != NO_ERROR) { if (dwRetCode == ERROR_BUFFER_TOO_SMALL) { if (cbData <= 0) { // No EAP blob stored in the registry
TRACE0 (USER, "ElGetUserIdentity: NULL sized EAP blob: continue"); pbAuthData = NULL; // Every port should have connection data !!!
dwRetCode = NO_ERROR; } else { // Allocate memory to hold the blob
pbAuthData = MALLOC (cbData); if (pbAuthData == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (USER, "ElGetUserIdentity: Error in memory allocation for EAP blob"); break; } if ((dwRetCode = ElGetCustomAuthData ( pPCB->pwszDeviceGUID, pPCB->dwEapTypeToBeUsed, dwSizeOfSSID, pbSSID, pbAuthData, &cbData )) != NO_ERROR) { TRACE1 (USER, "ElGetUserIdentity: ElGetCustomAuthData failed with %ld", dwRetCode); break; } } } else { // CustomAuthData for "Default" is always created for an
// interface when EAPOL starts up
TRACE1 (USER, "ElGetUserIdentity: ElGetCustomAuthData size estimation failed with error %ld", dwRetCode); break; } }
if (pIdenFunc) if ((dwRetCode = (*(pIdenFunc))( pPCB->dwEapTypeToBeUsed, hwndOwner, // hwndOwner
RAS_EAP_FLAG_MACHINE_AUTH, // dwFlags
NULL, // lpszPhonebook
pPCB->pwszFriendlyName, // lpszEntry
pbAuthData, // Connection data
cbData, // Count of pbAuthData
pbUserIn, // User data for port
dwInSize, // Size of user data
&pUserDataOut, &dwSizeOfUserDataOut, &lpwszIdentity )) != NO_ERROR) { if (dwRetCode == ERROR_NO_EAPTLS_CERTIFICATE) { DbLogPCBEvent (DBLOG_CATEG_ERR, pPCB, EAPOL_NO_CERTIFICATE_MACHINE); } else { DbLogPCBEvent (DBLOG_CATEG_ERR, pPCB, EAPOL_ERROR_GET_IDENTITY, EAPOLAuthTypes[EAPOL_MACHINE_AUTHENTICATION], dwRetCode); } TRACE1 (USER, "ElGetUserIdentity: Error in calling GetIdentity = %ld", dwRetCode); break; }
// Fill in the returned information into the PCB fields for
// later authentication
if (pPCB->pCustomAuthUserData != NULL) { FREE (pPCB->pCustomAuthUserData); pPCB->pCustomAuthUserData = NULL; }
pPCB->pCustomAuthUserData = MALLOC (dwSizeOfUserDataOut + sizeof (DWORD)); if (pPCB->pCustomAuthUserData == NULL) { TRACE1 (USER, "ElGetUserIdentity: Error in allocating memory for UserInfo = %ld", dwRetCode); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; }
pPCB->pCustomAuthUserData->dwSizeOfCustomAuthData = dwSizeOfUserDataOut;
if ((dwSizeOfUserDataOut != 0) && (pUserDataOut != NULL)) { memcpy ((BYTE *)pPCB->pCustomAuthUserData->pbCustomAuthData, (BYTE *)pUserDataOut, dwSizeOfUserDataOut); }
if (lpwszIdentity != NULL) { pszIdentity = MALLOC (wcslen(lpwszIdentity)*sizeof(CHAR) + sizeof(CHAR)); if (pszIdentity == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (USER, "ElGetUserIdentity: MALLOC failed for pszIdentity"); break; }
if (0 == WideCharToMultiByte ( CP_ACP, 0, lpwszIdentity, -1, pszIdentity, wcslen(lpwszIdentity)*sizeof(CHAR)+sizeof(CHAR), NULL, NULL )) { dwRetCode = GetLastError(); TRACE2 (USER, "ElGetUserIdentity: WideCharToMultiByte (%ws) failed: %ld", lpwszIdentity, dwRetCode); break; }
TRACE1 (USER, "ElGetUserIdentity: Got identity = %s", pszIdentity);
if (pPCB->pszIdentity != NULL) { FREE (pPCB->pszIdentity); pPCB->pszIdentity = NULL; } pPCB->pszIdentity = MALLOC (strlen(pszIdentity) + sizeof(CHAR)); if (pPCB->pszIdentity == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (USER, "ElGetUserIdentity: MALLOC failed for pPCB->pszIdentity"); break; } memcpy (pPCB->pszIdentity, pszIdentity, strlen (pszIdentity)); pPCB->pszIdentity[strlen(pszIdentity)] = '\0'; }
if (pPCB->pCustomAuthConnData != NULL) { FREE (pPCB->pCustomAuthConnData); pPCB->pCustomAuthConnData = NULL; }
pPCB->pCustomAuthConnData = MALLOC (cbData + sizeof (DWORD)); if (pPCB->pCustomAuthConnData == NULL) { TRACE1 (USER, "ElGetUserIdentity: Error in allocating memory for AuthInfo = %ld", dwRetCode); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; }
pPCB->pCustomAuthConnData->dwSizeOfCustomAuthData = cbData;
if ((cbData != 0) && (pbAuthData != NULL)) { memcpy ((BYTE *)pPCB->pCustomAuthConnData->pbCustomAuthData, (BYTE *)pbAuthData, cbData); }
// Mark the identity has been obtained for this PCB
pPCB->fGotUserIdentity = TRUE;
}
} while (FALSE);
// Cleanup
if ((dwRetCode != NO_ERROR) && (dwRetCode != ERROR_IO_PENDING)) { if (pPCB->pCustomAuthUserData != NULL) { FREE (pPCB->pCustomAuthUserData); pPCB->pCustomAuthUserData = NULL; }
if (pPCB->pszIdentity != NULL) { FREE (pPCB->pszIdentity); pPCB->pszIdentity = NULL; } }
if (pEAPUIContext != NULL) { FREE (pEAPUIContext); }
if (pbUserIn != NULL) { FREE (pbUserIn); }
if (pbAuthData != NULL) { FREE (pbAuthData); }
if (pFreeFunc != NULL) { if (lpwszIdentity != NULL) { if (( dwRetCode = (*(pFreeFunc)) ((BYTE *)lpwszIdentity)) != NO_ERROR) { TRACE1 (USER, "ElGetUserIdentity: Error in pFreeFunc = %ld", dwRetCode); } } if (pUserDataOut != NULL) { if (( dwRetCode = (*(pFreeFunc)) ((BYTE *)pUserDataOut)) != NO_ERROR) { TRACE1 (USER, "ElGetUserIdentity: Error in pFreeFunc = %ld", dwRetCode); } } }
TRACE1 (USER, "ElGetUserIdentity completed with error %ld", dwRetCode);
return dwRetCode;
}
//
// ElProcessUserIdentityResponse
//
// Description:
//
// Function to handle UI response for ElGetUserIdentityResponse
//
// Arguments:
//
// Return values:
//
//
DWORD ElProcessUserIdentityResponse ( IN EAPOL_EAP_UI_CONTEXT EapolUIContext, IN EAPOLUI_RESP EapolUIResp ) { DWORD dwSizeOfIdentity = 0; BYTE *pbIdentity = NULL; DWORD dwSizeOfUserData = 0; BYTE *pbUserData = NULL; DWORD dwSizeofConnData = 0; BYTE *pbConnData = NULL; EAPOL_PCB *pPCB = NULL; EAPOL_EAP_UI_CONTEXT *pEAPUIContext = NULL; BOOLEAN fPortReferenced = FALSE; BOOLEAN fPCBLocked = FALSE; BOOLEAN fBlobCopyIncomplete = FALSE; DWORD dwRetCode = NO_ERROR;
do { pEAPUIContext = (EAPOL_EAP_UI_CONTEXT *)&EapolUIContext;
ACQUIRE_WRITE_LOCK (&g_PCBLock);
if ((pPCB = ElGetPCBPointerFromPortGUID (pEAPUIContext->wszGUID)) != 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 (!EAPOL_PORT_ACTIVE(pPCB)) { TRACE1 (USER, "ElProcessUserIdentityResponse: Port %ws not active", pPCB->pwszDeviceGUID);
// Port is not active, cannot do further processing on this port
break; }
if (pEAPUIContext->dwRetCode != NO_ERROR) { DbLogPCBEvent (DBLOG_CATEG_ERR, pPCB, EAPOL_ERROR_DESKTOP_IDENTITY, dwRetCode); TRACE1 (USER, "ElProcessUserIdentityResponse: Error in Dialog function (%ld)", pEAPUIContext->dwRetCode); break; }
if (pPCB->EapUIState != EAPUISTATE_WAITING_FOR_IDENTITY) { TRACE2 (USER, "ElProcessUserIdentityResponse: PCB EapUIState has changed to (%ld), expected = (%ld)", pPCB->EapUIState, EAPUISTATE_WAITING_FOR_IDENTITY); break; }
if (pPCB->dwUIInvocationId != pEAPUIContext->dwContextId) { TRACE2 (USER, "ElProcessUserIdentityResponse: PCB UI Id has changed to (%ld), expected = (%ld)", pPCB->dwUIInvocationId, pEAPUIContext->dwContextId); // break;
}
if (pPCB->bCurrentEAPId != pEAPUIContext->dwEapId) { TRACE2 (USER, "ElProcessUserIdentityResponse: PCB EAP Id has changed to (%ld), expected = (%ld)", pPCB->bCurrentEAPId, pEAPUIContext->dwEapId); // break;
}
// Since the PCB context is right, restart PCB timer to timeout
// in authPeriod seconds
RESTART_TIMER (pPCB->hTimer, pPCB->EapolConfig.dwauthPeriod, "PCB", &dwRetCode); if (dwRetCode != NO_ERROR) { TRACE1 (USER, "ElProcessUserIdentityResponse: Error in RESTART_TIMER %ld", dwRetCode); break; }
DbLogPCBEvent (DBLOG_CATEG_INFO, pPCB, EAPOL_PROCESSING_DESKTOP_RESPONSE);
if ((EapolUIResp.rdData0.dwDataLen != 0) && (EapolUIResp.rdData0.pData != NULL)) { dwSizeOfIdentity = EapolUIResp.rdData0.dwDataLen; pbIdentity = EapolUIResp.rdData0.pData; }
if ((EapolUIResp.rdData1.dwDataLen != 0) && (EapolUIResp.rdData1.pData != NULL)) { dwSizeOfUserData = EapolUIResp.rdData1.dwDataLen; pbUserData = EapolUIResp.rdData1.pData; }
if ((EapolUIResp.rdData2.dwDataLen != 0) && (EapolUIResp.rdData2.pData != NULL)) { dwSizeofConnData = EapolUIResp.rdData2.dwDataLen; pbConnData = EapolUIResp.rdData2.pData; }
fBlobCopyIncomplete = TRUE;
if (pPCB->pszIdentity != NULL) { FREE (pPCB->pszIdentity); pPCB->pszIdentity = NULL; } if (pbIdentity != NULL) { pPCB->pszIdentity = MALLOC (dwSizeOfIdentity + sizeof(CHAR)); if (pPCB->pszIdentity == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (USER, "ElProcessUserIdentityResponse: MALLOC failed for pPCB->pszIdentity"); break; } memcpy (pPCB->pszIdentity, pbIdentity, dwSizeOfIdentity); pPCB->pszIdentity[dwSizeOfIdentity] = '\0'; TRACE1 (USER, "ElProcessUserIdentityResponse: Got username = %s", pPCB->pszIdentity); }
if (pPCB->pCustomAuthUserData != NULL) { FREE (pPCB->pCustomAuthUserData); pPCB->pCustomAuthUserData = NULL; } pPCB->pCustomAuthUserData = MALLOC (dwSizeOfUserData + sizeof (DWORD)); if (pPCB->pCustomAuthUserData == NULL) { TRACE1 (USER, "ElProcessUserIdentityResponse: Error in allocating memory for UserInfo = %ld", dwRetCode); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; } pPCB->pCustomAuthUserData->dwSizeOfCustomAuthData = dwSizeOfUserData; if ((dwSizeOfUserData != 0) && (pbUserData != NULL)) { memcpy ((BYTE *)pPCB->pCustomAuthUserData->pbCustomAuthData, (BYTE *)pbUserData, dwSizeOfUserData); }
if (pPCB->pCustomAuthConnData != NULL) { FREE (pPCB->pCustomAuthConnData); pPCB->pCustomAuthConnData = NULL; } pPCB->pCustomAuthConnData = MALLOC (dwSizeofConnData + sizeof (DWORD)); if (pPCB->pCustomAuthConnData == NULL) { TRACE1 (USER, "ElProcessUserIdentityResponse: Error in allocating memory for AuthInfo = %ld", dwRetCode); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; } pPCB->pCustomAuthConnData->dwSizeOfCustomAuthData = dwSizeofConnData; if ((dwSizeofConnData != 0) && (pbConnData != NULL)) { memcpy ((BYTE *)pPCB->pCustomAuthConnData->pbCustomAuthData, (BYTE *)pbConnData, dwSizeofConnData); }
fBlobCopyIncomplete = FALSE;
if ((dwRetCode = ElCreateAndSendIdentityResponse ( pPCB, pEAPUIContext)) != NO_ERROR) { TRACE1 (USER, "ElProcessUserIdentityResponse: ElCreateAndSendIdentityResponse failed with error %ld", dwRetCode); break; }
// Mark the identity has been obtained for this PCB
pPCB->fGotUserIdentity = TRUE;
// Reset the state if identity was obtained, else port will
// recover by itself
pPCB->EapUIState &= ~EAPUISTATE_WAITING_FOR_IDENTITY;
} while (FALSE);
// Cleanup
if (dwRetCode != NO_ERROR) { if (fPCBLocked && fBlobCopyIncomplete) { if (pPCB->pCustomAuthUserData != NULL) { FREE (pPCB->pCustomAuthUserData); pPCB->pCustomAuthUserData = NULL; }
if (pPCB->pszIdentity != NULL) { FREE (pPCB->pszIdentity); pPCB->pszIdentity = NULL; } } }
if (fPCBLocked) { RELEASE_WRITE_LOCK (&(pPCB->rwLock)); }
if (fPortReferenced) { EAPOL_DEREFERENCE_PORT (pPCB); }
return dwRetCode; }
//
// ElGetUserNamePassword
//
// Description:
//
// Function called to get username, domain (if any) and password using
// an interactive dialog. Called if EAP-type is MD5
//
// Arguments:
// pPCB - Pointer to PCB for the port/interface on which credentials
// are to be obtained
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
DWORD ElGetUserNamePassword ( IN EAPOL_PCB *pPCB ) { EAPOL_EAP_UI_CONTEXT *pEAPUIContext = NULL; DWORD dwRetCode = NO_ERROR;
do { TRACE0 (USER, "ElGetUserNamePassword entered");
if (!EAPOL_PORT_ACTIVE(pPCB)) { TRACE1 (PORT, "ElGetUserNamePassword: Port %ws not active", pPCB->pwszDeviceGUID); // Port is not active, cannot do further processing on this port
break; }
// Get Access Token for user logged on interactively
if (pPCB->hUserToken != NULL) { if (!CloseHandle (pPCB->hUserToken)) { dwRetCode = GetLastError (); TRACE1 (USER, "ElGetUserNamePassword: CloseHandle failed with error %ld", dwRetCode); break; } } pPCB->hUserToken = NULL;
if ((dwRetCode = ElGetWinStationUserToken (g_dwCurrentSessionId, &pPCB->hUserToken)) != NO_ERROR) { TRACE1 (USER, "ElGetUserNamePassword: ElGetWinStationUserToken failed with error (%ld)", dwRetCode); dwRetCode = ERROR_NO_TOKEN; break; }
if (!g_fTrayIconReady) { if ((dwRetCode = ElCheckUserModuleReady ()) != NO_ERROR) { TRACE1 (USER, "ElGetUserNamePassword: ElCheckUserModuleReady failed with error %ld", dwRetCode); break; } }
if (!g_fTrayIconReady) { DbLogPCBEvent (DBLOG_CATEG_WARN, pPCB, EAPOL_WAITING_FOR_DESKTOP_LOAD); dwRetCode = ERROR_IO_PENDING; TRACE0 (USER, "ElGetUserNamePassword: TrayIcon NOT ready"); break; }
//
// Call ElGetUserNamePasswordDlgWorker
//
pEAPUIContext = MALLOC (sizeof(EAPOL_EAP_UI_CONTEXT)); if (pEAPUIContext == NULL) { TRACE0 (USER, "ElGetUserNamePassword: MALLOC failed for pEAPUIContext"); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; }
pEAPUIContext->dwEAPOLUIMsgType = EAPOLUI_GET_USERNAMEPASSWORD; wcscpy (pEAPUIContext->wszGUID, pPCB->pwszDeviceGUID); pPCB->dwUIInvocationId = InterlockedIncrement(&(g_dwEAPUIInvocationId)); pEAPUIContext->dwSessionId = g_dwCurrentSessionId; pEAPUIContext->dwContextId = pPCB->dwUIInvocationId; pEAPUIContext->dwEapId = pPCB->bCurrentEAPId; pEAPUIContext->dwEapTypeId = pPCB->dwEapTypeToBeUsed; pEAPUIContext->dwEapFlags = pPCB->dwEapFlags; if (pPCB->pSSID) { memcpy ((BYTE *)pEAPUIContext->bSSID, (BYTE *)pPCB->pSSID->Ssid, NDIS_802_11_SSID_LEN-sizeof(ULONG)); pEAPUIContext->dwSizeOfSSID = pPCB->pSSID->SsidLength; } if (pPCB->pwszSSID) { wcscpy (pEAPUIContext->wszSSID, pPCB->pwszSSID); }
// Post the message to netman
if ((dwRetCode = ElPostShowBalloonMessage ( pPCB, sizeof(EAPOL_EAP_UI_CONTEXT), (BYTE *)pEAPUIContext, 0, NULL )) != NO_ERROR) { TRACE1 (USER, "ElGetUserNamePassword: ElPostShowBalloonMessage failed with error %ld", dwRetCode); break; }
// Restart PCB timer since UI may take longer time than required
RESTART_TIMER (pPCB->hTimer, INFINITE_SECONDS, "PCB", &dwRetCode); if (dwRetCode != NO_ERROR) { break; }
pPCB->EapUIState = EAPUISTATE_WAITING_FOR_IDENTITY; DbLogPCBEvent (DBLOG_CATEG_INFO, pPCB, EAPOL_WAITING_FOR_DESKTOP_IDENTITY);
// Return error code as pending, since credentials have still not
// been acquired
dwRetCode = ERROR_IO_PENDING;
} while (FALSE);
if ((dwRetCode != NO_ERROR) && (dwRetCode != ERROR_IO_PENDING)) { }
if (pEAPUIContext) { FREE (pEAPUIContext); }
TRACE1 (USER, "ElGetUserNamePassword completed with error %ld", dwRetCode);
return dwRetCode; }
//
// ElProcessUserNamePasswordResponse
//
// Description:
//
// UI Response handler function for ElGetUserNamePassword
//
// Arguments:
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
DWORD ElProcessUserNamePasswordResponse ( IN EAPOL_EAP_UI_CONTEXT EapolUIContext, IN EAPOLUI_RESP EapolUIResp ) { DWORD dwSizeOfIdentity = 0; BYTE *pbIdentity = NULL; DWORD dwSizeOfPassword = 0; BYTE *pbPassword = NULL; HWND hwndOwner = NULL; BOOLEAN fPCBLocked = FALSE; BOOLEAN fPortReferenced = FALSE; BOOLEAN fBlobCopyIncomplete = FALSE; EAPOL_PCB *pPCB = NULL; EAPOL_EAP_UI_CONTEXT *pEAPUIContext = NULL; DWORD dwRetCode = NO_ERROR;
do { TRACE0 (USER, "ElProcessUserNamePasswordResponse entered");
pEAPUIContext = (EAPOL_EAP_UI_CONTEXT *)&EapolUIContext;
ACQUIRE_WRITE_LOCK (&g_PCBLock);
if ((pPCB = ElGetPCBPointerFromPortGUID (pEAPUIContext->wszGUID)) != 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 (!EAPOL_PORT_ACTIVE(pPCB)) { TRACE1 (PORT, "ElProcessUserNamePasswordResponse: Port %ws not active", pPCB->pwszDeviceGUID); // Port is not active, cannot do further processing on this port
break; } if (pEAPUIContext->dwRetCode != NO_ERROR) { DbLogPCBEvent (DBLOG_CATEG_ERR, pPCB, EAPOL_ERROR_DESKTOP_IDENTITY, dwRetCode); TRACE1 (USER, "ElProcessUserNamePasswordResponse: Error in Dialog function (%ld)", pEAPUIContext->dwRetCode); break; }
if (pPCB->EapUIState != EAPUISTATE_WAITING_FOR_IDENTITY) { TRACE2 (USER, "ElProcessUserNamePasswordResponse: PCB EapUIState has changed to (%ld), expected = (%ld)", pPCB->EapUIState, EAPUISTATE_WAITING_FOR_IDENTITY); break; }
if (pPCB->dwUIInvocationId != pEAPUIContext->dwContextId) { TRACE2 (USER, "ElProcessUserNamePasswordResponse: PCB UI Id has changed to (%ld), expected = (%ld)", pPCB->dwUIInvocationId, pEAPUIContext->dwContextId); // break;
}
if (pPCB->bCurrentEAPId != pEAPUIContext->dwEapId) { TRACE2 (USER, "ElProcessUserNamePasswordResponse: PCB EAP Id has changed to (%ld), expected = (%ld)", pPCB->bCurrentEAPId, pEAPUIContext->dwEapId); // break;
}
// Since the PCB context is right, restart PCB timer to timeout
// in authPeriod seconds
RESTART_TIMER (pPCB->hTimer, pPCB->EapolConfig.dwauthPeriod, "PCB", &dwRetCode); if (dwRetCode != NO_ERROR) { TRACE1 (USER, "ElProcessUserNamePasswordResponse: Error in RESTART_TIMER %ld", dwRetCode); break; }
DbLogPCBEvent (DBLOG_CATEG_INFO, pPCB, EAPOL_PROCESSING_DESKTOP_RESPONSE);
if ((EapolUIResp.rdData0.dwDataLen != 0) && (EapolUIResp.rdData0.pData != NULL)) { dwSizeOfIdentity = EapolUIResp.rdData0.dwDataLen; pbIdentity = EapolUIResp.rdData0.pData; }
if ((EapolUIResp.rdData1.dwDataLen != 0) && (EapolUIResp.rdData1.pData != NULL)) { dwSizeOfPassword = EapolUIResp.rdData1.dwDataLen; pbPassword = EapolUIResp.rdData1.pData; }
fBlobCopyIncomplete = TRUE;
if (pPCB->pszIdentity != NULL) { FREE (pPCB->pszIdentity); pPCB->pszIdentity = NULL; }
if (pPCB->PasswordBlob.pbData != NULL) { FREE (pPCB->PasswordBlob.pbData); pPCB->PasswordBlob.pbData = NULL; pPCB->PasswordBlob.cbData = 0; }
if (pbIdentity != NULL) { pPCB->pszIdentity = MALLOC (dwSizeOfIdentity + sizeof(CHAR)); if (pPCB->pszIdentity == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (USER, "ElProcessUserNamePasswordResponse: MALLOC failed for pPCB->pszIdentity"); break; } memcpy (pPCB->pszIdentity, pbIdentity, dwSizeOfIdentity); pPCB->pszIdentity[dwSizeOfIdentity] = '\0'; TRACE1 (USER, "ElProcessUserNamePasswordResponse: Got username = %s", pPCB->pszIdentity); }
if (pbPassword != 0) { if ((pPCB->PasswordBlob.pbData = MALLOC (dwSizeOfPassword)) == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; } memcpy (pPCB->PasswordBlob.pbData, pbPassword, dwSizeOfPassword); pPCB->PasswordBlob.cbData = dwSizeOfPassword; }
fBlobCopyIncomplete = FALSE;
if ((dwRetCode = ElCreateAndSendIdentityResponse ( pPCB, pEAPUIContext)) != NO_ERROR) { TRACE1 (USER, "ElProcessUserNamePasswordResponse: ElCreateAndSendIdentityResponse failed with error %ld", dwRetCode); break; }
// Mark the identity has been obtained for this PCB
pPCB->fGotUserIdentity = TRUE;
// Reset the state if identity was obtained, else the port will recover
// by itself
pPCB->EapUIState &= ~EAPUISTATE_WAITING_FOR_IDENTITY; } while (FALSE);
if (dwRetCode != NO_ERROR) { if (fPCBLocked && fBlobCopyIncomplete) { if (pPCB->pszIdentity) { FREE (pPCB->pszIdentity); pPCB->pszIdentity = NULL; } if (pPCB->PasswordBlob.pbData) { FREE (pPCB->PasswordBlob.pbData); pPCB->PasswordBlob.pbData = NULL; pPCB->PasswordBlob.cbData = 0; } } }
if (fPCBLocked) { RELEASE_WRITE_LOCK (&(pPCB->rwLock)); }
if (fPortReferenced) { EAPOL_DEREFERENCE_PORT (pPCB); }
TRACE1 (USER, "ElProcessUserNamePasswordResponse completed with error %ld", dwRetCode);
return dwRetCode; }
//
// ElInvokeInteractiveUI
//
// Description:
//
// Function called to invoke RasEapInvokeInteractiveUI for an EAP on a
// particular interface
//
// Arguments:
// pPCB - Pointer to PCB for the specific interface
// pInvokeEapUIIn - Data to be supplied to the InvokeInteractiveUI entrypoint
// provided by the EAP dll through PPP_EAP_OUTPUT structure
//
DWORD ElInvokeInteractiveUI ( IN EAPOL_PCB *pPCB, IN ELEAP_INVOKE_EAP_UI *pInvokeEapUIIn ) { EAPOL_EAP_UI_CONTEXT *pEAPUIContext = NULL; DWORD dwRetCode = NO_ERROR;
do { if (pInvokeEapUIIn == NULL) { dwRetCode = ERROR_INVALID_PARAMETER; return dwRetCode; }
if (pPCB->PreviousAuthenticationType == EAPOL_MACHINE_AUTHENTICATION) { TRACE0 (USER, "ElInvokeInteractiveUI: Cannot popup UI during machine authentication"); DbLogPCBEvent (DBLOG_CATEG_ERR, pPCB, EAPOL_CANNOT_DESKTOP_MACHINE_AUTH); dwRetCode = ERROR_CAN_NOT_COMPLETE; break; } if (!g_fTrayIconReady) { if ((dwRetCode = ElCheckUserModuleReady ()) != NO_ERROR) { TRACE1 (USER, "ElInvokeInteractiveUI: ElCheckUserModuleReady failed with error %ld", dwRetCode); break; } }
if (!g_fTrayIconReady) { DbLogPCBEvent (DBLOG_CATEG_WARN, pPCB, EAPOL_WAITING_FOR_DESKTOP_LOAD); dwRetCode = ERROR_IO_PENDING; TRACE0 (USER, "ElInvokeInteractiveUI: TrayIcon NOT ready"); break; }
TRACE0 (USER, "ElInvokeInteractiveUI entered");
//
// Call ElInvokeInteractiveUIDlgWorker
//
pEAPUIContext = MALLOC (sizeof(EAPOL_EAP_UI_CONTEXT) + pInvokeEapUIIn->dwSizeOfUIContextData); if (pEAPUIContext == NULL) { TRACE0 (USER, "ElInvokeInteractiveUI: MALLOC failed for pEAPUIContext"); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; }
pEAPUIContext->dwEAPOLUIMsgType = EAPOLUI_INVOKEINTERACTIVEUI; wcscpy (pEAPUIContext->wszGUID, pPCB->pwszDeviceGUID); pPCB->dwUIInvocationId = InterlockedIncrement(&(g_dwEAPUIInvocationId)); pEAPUIContext->dwSessionId = g_dwCurrentSessionId; pEAPUIContext->dwContextId = pPCB->dwUIInvocationId; pEAPUIContext->dwEapId = pPCB->bCurrentEAPId; pEAPUIContext->dwEapTypeId = pPCB->dwEapTypeToBeUsed; pEAPUIContext->dwEapFlags = pPCB->dwEapFlags; if (pPCB->pSSID) { pEAPUIContext->dwSizeOfSSID = pPCB->pSSID->SsidLength; memcpy ((BYTE *)pEAPUIContext->bSSID, (BYTE *)pPCB->pSSID->Ssid, NDIS_802_11_SSID_LEN-sizeof(ULONG)); } if (pPCB->pwszSSID) { wcscpy (pEAPUIContext->wszSSID, pPCB->pwszSSID); } pEAPUIContext->dwSizeOfEapUIData = pInvokeEapUIIn->dwSizeOfUIContextData; memcpy (pEAPUIContext->bEapUIData, pInvokeEapUIIn->pbUIContextData, pInvokeEapUIIn->dwSizeOfUIContextData);
// Post the message to netman
if ((dwRetCode = ElPostShowBalloonMessage ( pPCB, sizeof(EAPOL_EAP_UI_CONTEXT)+pInvokeEapUIIn->dwSizeOfUIContextData, (BYTE *)pEAPUIContext, 0, NULL )) != NO_ERROR) { TRACE1 (USER, "ElInvokeInteractiveUI: ElPostShowBalloonMessage failed with error %ld", dwRetCode); break; }
// Restart PCB timer since UI may take longer time than required
RESTART_TIMER (pPCB->hTimer, INFINITE_SECONDS, "PCB", &dwRetCode); if (dwRetCode != NO_ERROR) { break; }
pPCB->EapUIState = EAPUISTATE_WAITING_FOR_UI_RESPONSE; DbLogPCBEvent (DBLOG_CATEG_INFO, pPCB, EAPOL_WAITING_FOR_DESKTOP_LOGON);
TRACE0 (USER, "ElInvokeInteractiveUI: ElEapWork completed successfully");
} while (FALSE);
if (pInvokeEapUIIn->pbUIContextData != NULL) { FREE (pInvokeEapUIIn->pbUIContextData); pInvokeEapUIIn->pbUIContextData = NULL; pInvokeEapUIIn->dwSizeOfUIContextData = 0; }
if (pEAPUIContext != NULL) { FREE (pEAPUIContext); }
TRACE1 (USER, "ElInvokeInteractiveUI completed with error %ld", dwRetCode);
return dwRetCode; }
//
// ElProcessInvokeInteractiveUIResponse
//
// Description:
//
// Worker function for ElInvokeInteractiveUI
//
// Arguments:
//
DWORD ElProcessInvokeInteractiveUIResponse ( IN EAPOL_EAP_UI_CONTEXT EapolUIContext, IN EAPOLUI_RESP EapolUIResp ) { BYTE *pbUIData = NULL; DWORD dwSizeOfUIData = 0; EAPOL_PCB *pPCB = NULL; EAPOL_EAP_UI_CONTEXT *pEAPUIContext = NULL; BOOLEAN fPortReferenced = FALSE; BOOLEAN fPCBLocked = FALSE; DWORD dwRetCode = NO_ERROR;
do { TRACE0 (USER, "ElProcessInvokeInteractiveUIResponse entered");
pEAPUIContext = (EAPOL_EAP_UI_CONTEXT *)&EapolUIContext;
ACQUIRE_WRITE_LOCK (&g_PCBLock);
if ((pPCB = ElGetPCBPointerFromPortGUID (pEAPUIContext->wszGUID)) != 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 (!EAPOL_PORT_ACTIVE(pPCB)) { TRACE1 (PORT, "ElProcessInvokeInteractiveUIResponse: Port %ws not active", pPCB->pwszDeviceGUID); break; }
if (pEAPUIContext->dwRetCode != NO_ERROR) { DbLogPCBEvent (DBLOG_CATEG_ERR, pPCB, EAPOL_ERROR_DESKTOP_LOGON, dwRetCode); TRACE1 (USER, "ElProcessInvokeInteractiveUIResponse: Error in Dialog function (%ld)", pEAPUIContext->dwRetCode); break; }
if (pPCB->EapUIState != EAPUISTATE_WAITING_FOR_UI_RESPONSE) { TRACE2 (USER, "ElProcessInvokeInteractiveUIResponse: PCB EapUIState has changed to (%ld), expected = (%ld)", pPCB->EapUIState, EAPUISTATE_WAITING_FOR_UI_RESPONSE); break; }
if (pPCB->dwUIInvocationId != pEAPUIContext->dwContextId) { TRACE2 (USER, "ElProcessInvokeInteractiveUIResponse: PCB UI Id has changed to (%ld), expected = (%ld)", pPCB->dwUIInvocationId, pEAPUIContext->dwContextId); // break;
}
if (pPCB->bCurrentEAPId != pEAPUIContext->dwEapId) { TRACE2 (USER, "ElProcessInvokeInteractiveUIResponse: PCB EAP Id has changed to (%ld), expected = (%ld)", pPCB->bCurrentEAPId, pEAPUIContext->dwEapId); // break;
}
// Since the PCB context is right, restart PCB timer to timeout
// in authPeriod seconds
RESTART_TIMER (pPCB->hTimer, pPCB->EapolConfig.dwauthPeriod, "PCB", &dwRetCode); if (dwRetCode != NO_ERROR) { TRACE1 (USER, "ElProcessInvokeInteractiveUIResponse: Error in RESTART_TIMER %ld", dwRetCode); break; }
DbLogPCBEvent (DBLOG_CATEG_INFO, pPCB, EAPOL_PROCESSING_DESKTOP_RESPONSE);
if ((EapolUIResp.rdData0.dwDataLen != 0) && (EapolUIResp.rdData0.pData != NULL)) { dwSizeOfUIData = EapolUIResp.rdData0.dwDataLen; pbUIData = EapolUIResp.rdData0.pData; }
if (pPCB->EapUIData.pEapUIData != NULL) { FREE (pPCB->EapUIData.pEapUIData); pPCB->EapUIData.pEapUIData = NULL; pPCB->EapUIData.dwSizeOfEapUIData = 0; } pPCB->EapUIData.pEapUIData = MALLOC (dwSizeOfUIData); if (pPCB->EapUIData.pEapUIData == NULL) { TRACE1 (USER, "ElProcessInvokeInteractiveUIResponse: Error in allocating memory for UIData = %ld", dwRetCode); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; }
pPCB->EapUIData.dwSizeOfEapUIData = dwSizeOfUIData; if ((dwSizeOfUIData != 0) && (pbUIData != NULL)) { memcpy ((BYTE *)pPCB->EapUIData.pEapUIData, (BYTE *)pbUIData, dwSizeOfUIData); }
pPCB->EapUIData.dwContextId = pPCB->dwUIInvocationId;
pPCB->fEapUIDataReceived = TRUE;
TRACE0 (USER, "ElProcessInvokeInteractiveUIResponse: Calling ElEapWork");
// Provide UI data to EAP Dll for processing
// EAP will send out response if required
if ((dwRetCode = ElEapWork ( pPCB, NULL)) != NO_ERROR) { TRACE1 (USER, "ElProcessInvokeInteractiveUIResponse: ElEapWork failed with error = %ld", dwRetCode); break; } // Reset the state
pPCB->EapUIState &= ~EAPUISTATE_WAITING_FOR_UI_RESPONSE;
TRACE0 (USER, "ElProcessInvokeInteractiveUIResponse: ElEapWork completed successfully");
} while (FALSE);
// Cleanup
if (dwRetCode != NO_ERROR) { if (pPCB->EapUIData.pEapUIData != NULL) { FREE (pPCB->EapUIData.pEapUIData); pPCB->EapUIData.pEapUIData = NULL; pPCB->EapUIData.dwSizeOfEapUIData = 0; } }
if (fPCBLocked) { RELEASE_WRITE_LOCK (&(pPCB->rwLock)); }
if (fPortReferenced) { EAPOL_DEREFERENCE_PORT (pPCB); }
TRACE1 (USER, "ElProcessInvokeInteractiveUIResponse completed with error %ld", dwRetCode);
return dwRetCode; }
//
// ElCreateAndSendIdentityResponse
//
// Description:
//
// Function called send out Identity Response packet
//
// Arguments:
// pPCB - Port Control Block for appropriate interface
// pEAPUIContext - UI context blob
//
// Return values:
// NO_ERROR - success
// !NO_ERROR - error
//
//
DWORD ElCreateAndSendIdentityResponse ( IN EAPOL_PCB *pPCB, IN EAPOL_EAP_UI_CONTEXT *pEAPUIContext ) { PPP_EAP_PACKET *pSendBuf = NULL; EAPOL_PACKET *pEapolPkt = NULL; WORD wSizeOfEapPkt = 0; DWORD dwIdentityLength = 0; DWORD dwRetCode = NO_ERROR;
do { // Create buffer for EAPOL + EAP and pass pointer to EAP header
pEapolPkt = (EAPOL_PACKET *) MALLOC (MAX_EAPOL_BUFFER_SIZE);
TRACE1 (EAPOL, "ElCreateAndSendIdResp: EapolPkt created at %p", pEapolPkt);
if (pEapolPkt == NULL) { TRACE0 (EAPOL, "ElCreateAndSendIdResp: Error allocating EAP buffer"); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; }
// Point to EAP header
pSendBuf = (PPP_EAP_PACKET *)((PBYTE)pEapolPkt + sizeof (EAPOL_PACKET) - 1);
pSendBuf->Code = EAPCODE_Response; pSendBuf->Id = (BYTE)pPCB->bCurrentEAPId;
if (pPCB->pszIdentity != NULL) { dwIdentityLength = strlen (pPCB->pszIdentity); } else { dwIdentityLength = 0; }
HostToWireFormat16 ( (WORD)(PPP_EAP_PACKET_HDR_LEN+1+dwIdentityLength), pSendBuf->Length );
strncpy ((CHAR *)pSendBuf->Data+1, (CHAR *)pPCB->pszIdentity, dwIdentityLength);
TRACE1 (EAPOL, "ElCreateAndSendIdResp: Identity sent out = %s", pPCB->pszIdentity);
pSendBuf->Data[0] = EAPTYPE_Identity;
// Indicate to EAPOL what is length of the EAP packet
wSizeOfEapPkt = (WORD)(PPP_EAP_PACKET_HDR_LEN+ 1+dwIdentityLength);
// Send out EAPOL packet
memcpy ((BYTE *)pEapolPkt->EthernetType, (BYTE *)pPCB->bEtherType, SIZE_ETHERNET_TYPE); pEapolPkt->ProtocolVersion = pPCB->bProtocolVersion; pEapolPkt->PacketType = EAP_Packet;
HostToWireFormat16 ((WORD) wSizeOfEapPkt, (BYTE *)pEapolPkt->PacketBodyLength);
// Make a copy of the EAPOL packet in the PCB
// Will be used during retransmission
if (pPCB->pbPreviousEAPOLPkt != NULL) { FREE (pPCB->pbPreviousEAPOLPkt); } pPCB->pbPreviousEAPOLPkt = MALLOC (sizeof (EAPOL_PACKET)+wSizeOfEapPkt-1);
if (pPCB->pbPreviousEAPOLPkt == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; }
memcpy (pPCB->pbPreviousEAPOLPkt, pEapolPkt, sizeof (EAPOL_PACKET)+wSizeOfEapPkt-1);
pPCB->dwSizeOfPreviousEAPOLPkt = sizeof (EAPOL_PACKET)+wSizeOfEapPkt-1;
pPCB->dwPreviousId = pPCB->bCurrentEAPId;
// Send packet out on the port
dwRetCode = ElWriteToPort (pPCB, (CHAR *)pEapolPkt, sizeof (EAPOL_PACKET)+wSizeOfEapPkt-1); if (dwRetCode != NO_ERROR) { TRACE1 (EAPOL, "ElCreateAndSendIdResp: Error in writing EAP_Packet to port %ld", dwRetCode); break; }
} while (FALSE);
if (pEapolPkt != NULL) { FREE (pEapolPkt); }
return dwRetCode; }
//
// ElSendGuestIdentityResponse
//
// Description:
//
// Function called send out Guest Identity Response packet
//
// Arguments:
// pEAPUIContext - UI context blob
//
// Return values:
// NO_ERROR - success
// !NO_ERROR - failure
//
DWORD ElSendGuestIdentityResponse ( IN EAPOL_EAP_UI_CONTEXT *pEAPUIContext ) { EAPOL_PCB *pPCB = NULL; BOOLEAN fPortReferenced = FALSE; BOOLEAN fPCBLocked = FALSE; DWORD dwRetCode = NO_ERROR;
do { ACQUIRE_WRITE_LOCK (&g_PCBLock);
if ((pPCB = ElGetPCBPointerFromPortGUID (pEAPUIContext->wszGUID)) != 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;
// Send the identity out as a EAP-Response packet
if (pPCB->EapUIState != EAPUISTATE_WAITING_FOR_IDENTITY) { TRACE2 (USER, "ElSendGuestIdentityResponse: PCB EapUIState has changed to (%ld), expected = (%ld)", pPCB->EapUIState, EAPUISTATE_WAITING_FOR_IDENTITY); dwRetCode = ERROR_CAN_NOT_COMPLETE; break; }
if (pPCB->dwUIInvocationId != pEAPUIContext->dwContextId) { TRACE2 (USER, "ElSendGuestIdentityResponse: PCB UI Id has changed to (%ld), expected = (%ld)", pPCB->dwUIInvocationId, pEAPUIContext->dwContextId); dwRetCode = ERROR_CAN_NOT_COMPLETE; break; }
if (pPCB->bCurrentEAPId != pEAPUIContext->dwEapId) { TRACE2 (USER, "ElSendGuestIdentityResponse: PCB EAP Id has changed to (%ld), expected = (%ld)", pPCB->bCurrentEAPId, pEAPUIContext->dwEapId); dwRetCode = ERROR_CAN_NOT_COMPLETE; break; }
if (pPCB->pszIdentity != NULL) { FREE (pPCB->pszIdentity); pPCB->pszIdentity = NULL; }
// Do not flag that identity was received
// Reset the UI state though for state machine to proceed
pPCB->EapUIState &= ~EAPUISTATE_WAITING_FOR_IDENTITY; pPCB->PreviousAuthenticationType = EAPOL_UNAUTHENTICATED_ACCESS;
if ((dwRetCode = ElCreateAndSendIdentityResponse ( pPCB, pEAPUIContext)) != NO_ERROR) { TRACE1 (USER, "ElSendGuestIdentityResponse: ElCreateAndSendIdentityResponse failed with error %ld", dwRetCode); break; } } while (FALSE);
if (fPCBLocked) { RELEASE_WRITE_LOCK (&(pPCB->rwLock)); }
if (fPortReferenced) { EAPOL_DEREFERENCE_PORT (pPCB); }
return dwRetCode; }
|