|
|
/*++
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
//
// Test code declarations for EAP-MD5CHAP
//
// This function is not defined in any header file. Located in
// $(SDK_LIB_PATH)\irnotif.lib
extern HANDLE GetCurrentUserTokenW ( WCHAR Winsta[], DWORD DesiredAccess );
extern BOOL GetWinStationUserToken(ULONG, PHANDLE);
extern ULONG GetClientLogonId ();
#define cszEapKeyRas TEXT("Software\\Microsoft\\RAS EAP\\UserEapInfo")
#define cszEapValue TEXT("EapInfo")
#ifndef EAPOL_SERVICE
#define cszModuleName TEXT("netman.dll")
#else
#define cszModuleName TEXT("eapol.exe")
#endif
//
// 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 hUserToken; HANDLE hLib = NULL; EAPOLEAPFREE pFreeFunc = NULL; EAPOLEAPGETIDENTITY pIdenFunc = NULL; DWORD dwIndex = -1; DWORD cbData = 0; PBYTE pbAuthData = NULL; PBYTE pbUserIn = NULL; DWORD dwInSize = 0; BYTE *pUserDataOut; DWORD dwSizeOfUserDataOut; LPWSTR lpwszIdentity = NULL; HWND hwndOwner = NULL; HWINSTA hwinstaSave; HDESK hdeskSave; HWINSTA hwinstaUser; HDESK hdeskUser; DWORD dwThreadId; UNICODE_STRING IdentityUnicodeString; ANSI_STRING IdentityAnsiString; CHAR Buffer[256]; WCHAR wszFriendlyName[256]; // Friendly name max 255 char
CHAR *pszUserName = NULL; DWORD dwFlags = 0; DWORD dwRetCode = NO_ERROR;
do { // If machine auth not enabled
TRACE0 (USER, "ElGetUserIdentity entered");
//
// NOTE:
// Optimize pPCB->rwLock lock holding time
//
ACQUIRE_WRITE_LOCK (&(pPCB->rwLock));
if (pPCB->PreviousAuthenticationType != EAPOL_MACHINE_AUTHENTICATION) {
if (!EAPOL_PORT_ACTIVE(pPCB)) { TRACE1 (PORT, "ElGetUserIdentity: Port %s not active", pPCB->pszDeviceGUID);
// Port is not active, cannot do further processing on this port
break; }
//
// Get Access Token for user logged on interactively
//
// Call Terminal Services API
if (GetWinStationUserToken (GetClientLogonId(), &hUserToken) != NO_ERROR) { TRACE0 (USER, "ElGetUserIdentity: Terminal Services API GetWinStationUserToken failed !!! ");
// Call private API
hUserToken = GetCurrentUserTokenW (L"WinSta0", TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY); if (hUserToken == NULL) { dwRetCode = GetLastError (); TRACE1 (USER, "ElGetUserIdentity: Error in GetCurrentUserTokenW = %ld", dwRetCode); dwRetCode = ERROR_NO_TOKEN; break; } } if (hUserToken == NULL) { dwRetCode = GetLastError (); TRACE0 (USER, "ElGetUserIdentity: Error in getting current user token"); dwRetCode = ERROR_NO_TOKEN; break; }
pPCB->hUserToken = hUserToken;
// Get the size of the user blob
if ((dwRetCode = ElGetEapUserInfo ( pPCB->hUserToken, pPCB->pszDeviceGUID, pPCB->dwEapTypeToBeUsed, pPCB->pszSSID, NULL, &dwInSize )) != NO_ERROR) { if (dwRetCode == ERROR_BUFFER_TOO_SMALL) { if (dwInSize <= 0) { // No blob stored in the registry
// Continue processing
TRACE0 (USER, "ElGetUserIdentity: NULL sized user data"); pbUserIn = NULL; } else { // Allocate memory to hold the blob
pbUserIn = MALLOC (dwInSize); if (pbUserIn == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (USER, "ElGetUserIdentity: Error in memory allocation for User data"); break; } if ((dwRetCode = ElGetEapUserInfo ( pPCB->hUserToken, pPCB->pszDeviceGUID, pPCB->dwEapTypeToBeUsed, pPCB->pszSSID, pbUserIn, &dwInSize )) != NO_ERROR) { TRACE1 (USER, "ElGetUserIdentity: ElGetEapUserInfo failed with %ld", dwRetCode); break; } } } else { // User info may not have been created till now
// which is valid condition to proceed
if (dwRetCode != ERROR_FILE_NOT_FOUND) { TRACE1 (USER, "ElGetUserIdentity: ElGetEapUserInfo size estimation failed with error %ld", dwRetCode); break; } } }
// 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 = (EAPOLEAPGETIDENTITY)GetProcAddress(hLib, "RasEapGetIdentity"); pFreeFunc = (EAPOLEAPFREE)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; }
// Get the size of the EAP blob
if ((dwRetCode = ElGetCustomAuthData ( pPCB->pszDeviceGUID, pPCB->dwEapTypeToBeUsed, pPCB->pszSSID, 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, cannot continue"); pbAuthData = NULL; // Every port should have connection data !!!
dwRetCode = ERROR_CAN_NOT_COMPLETE; break; } 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->pszDeviceGUID, pPCB->dwEapTypeToBeUsed, pPCB->pszSSID, 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; } }
// Save handles to service window
hwinstaSave = GetProcessWindowStation(); if (hwinstaSave == NULL) { dwRetCode = GetLastError (); TRACE1 (USER, "OpenWindowStation: GetProcessWindowStation failed with error %ld", dwRetCode); break; }
dwThreadId = GetCurrentThreadId ();
hdeskSave = GetThreadDesktop (dwThreadId); if (hdeskSave == NULL) { dwRetCode = GetLastError (); TRACE1 (USER, "OpenWindowStation: GetThreadDesktop failed with error %ld", dwRetCode); break; }
if (!ImpersonateLoggedOnUser (pPCB->hUserToken)) { dwRetCode = GetLastError(); TRACE1 (USER, "ElGetUserIdentity: ImpersonateLoggedOnUse failed with error %ld", dwRetCode); break; }
// Impersonate the client and connect to the User's window station
// and desktop. This will be the interactively logged-on user
hwinstaUser = OpenWindowStation (L"WinSta0", FALSE, MAXIMUM_ALLOWED); if (hwinstaUser == NULL) { dwRetCode = GetLastError (); TRACE1 (USER, "OpenWindowStation: OpenWindowStation failed with error %ld", dwRetCode); break; }
if (!SetProcessWindowStation(hwinstaUser)) TRACE1 (USER, "ElGetUserIdentity: SetProcessWindowStation failed with error = %ld", (dwRetCode = GetLastError())); hdeskUser = OpenDesktop (L"Default", 0, FALSE, MAXIMUM_ALLOWED); if (hdeskUser == NULL) { if (!SetProcessWindowStation (hwinstaSave)) TRACE1 (USER, "ElGetUserIdentity: SetProcessWindowStation failed with error = %ld", (dwRetCode = GetLastError())); if (!CloseWindowStation (hwinstaUser)) TRACE1 (USER, "ElGetUserIdentity: CloseWindowStation failed with error = %ld", (dwRetCode = GetLastError())); dwRetCode = ERROR_INVALID_WORKSTATION; break; }
if (!SetThreadDesktop (hdeskUser)) TRACE1 (USER, "ElGetUserIdentity: SetThreadDesktop failed with error = %ld", (dwRetCode = GetLastError()));
// Get handle to desktop window
hwndOwner = GetDesktopWindow ();
ZeroMemory (wszFriendlyName, 256*sizeof(WCHAR));
// Convert the friendly name of the adapter to a display ready
// form
if (pPCB->pszFriendlyName) { if (0 == MultiByteToWideChar( CP_ACP, 0, pPCB->pszFriendlyName, -1, wszFriendlyName, 256 ) ) { dwRetCode = GetLastError();
TRACE2 (USER, "ElGetUserIdentity: MultiByteToWideChar(%s) failed: %d", pPCB->pszFriendlyName, dwRetCode); break; } }
if (pIdenFunc) if ((dwRetCode = (*(pIdenFunc))( pPCB->dwEapTypeToBeUsed, hwndOwner, // hwndOwner
0, // dwFlags
NULL, // lpszPhonebook
wszFriendlyName, // lpszEntry
pbAuthData, // Connection data
cbData, // Count of pbAuthData
pbUserIn, // User data for port
dwInSize, // Size of user data
&pUserDataOut, &dwSizeOfUserDataOut, &lpwszIdentity )) != NO_ERROR) { TRACE1 (USER, "ElGetUserIdentity: Error in calling GetIdentity = %ld", dwRetCode); // Revert impersonation
if (!RevertToSelf()) { dwRetCode = GetLastError(); TRACE1 (USER, "ElGetUserIdentity: Error in RevertToSelf = %ld", dwRetCode); }
// Restore window station and desktop
if (!SetThreadDesktop (hdeskSave)) TRACE1 (USER, "ElGetUserIdentity: SetThreadDesktop failed with error = %ld", (dwRetCode = GetLastError())); if (!SetProcessWindowStation (hwinstaSave)) TRACE1 (USER, "ElGetUserIdentity: SetProcessWindowStation failed with error = %ld", (dwRetCode = GetLastError())); if (!CloseDesktop(hdeskUser)) TRACE1 (USER, "ElGetUserIdentity: CloseDesktop failed with error = %ld", (dwRetCode = GetLastError())); if (!CloseWindowStation(hwinstaUser)) TRACE1 (USER, "ElGetUserIdentity: CloseWindowStation failed with error = %ld", (dwRetCode = GetLastError()));
break; }
// Revert impersonation
if (!RevertToSelf()) { dwRetCode = GetLastError(); TRACE1 (USER, "ElGetUserIdentity: Error in RevertToSelf = %ld", dwRetCode); // Restore window station and desktop
if (!SetThreadDesktop (hdeskSave)) TRACE1 (USER, "ElGetUserIdentity: SetThreadDesktop failed with error = %ld", (dwRetCode = GetLastError())); if (!SetProcessWindowStation (hwinstaSave)) TRACE1 (USER, "ElGetUserIdentity: SetProcessWindowStation failed with error = %ld", (dwRetCode = GetLastError())); if (!CloseDesktop(hdeskUser)) TRACE1 (USER, "ElGetUserIdentity: CloseDesktop failed with error = %ld", (dwRetCode = GetLastError())); if (!CloseWindowStation(hwinstaUser)) TRACE1 (USER, "ElGetUserIdentity: CloseWindowStation failed with error = %ld", (dwRetCode = GetLastError())); break; }
// Restore window station and desktop settings
if (!SetThreadDesktop (hdeskSave)) TRACE1 (USER, "ElGetUserIdentity: SetThreadDesktop failed with error = %ld", (dwRetCode = GetLastError())); if (!SetProcessWindowStation (hwinstaSave)) TRACE1 (USER, "ElGetUserIdentity: SetProcessWindowStation failed with error = %ld", (dwRetCode = GetLastError())); if (!CloseDesktop(hdeskUser)) TRACE1 (USER, "ElGetUserIdentity: CloseDesktop failed with error = %ld", (dwRetCode = GetLastError())); if (!CloseWindowStation(hwinstaUser)) TRACE1 (USER, "ElGetUserIdentity: CloseWindowStation failed with error = %ld", (dwRetCode = GetLastError())); // 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) { // NOTE:
// Assuming 256 character identity maximum
// Convert wchar Identity to char string
RtlInitUnicodeString (&IdentityUnicodeString, lpwszIdentity); IdentityAnsiString.MaximumLength = sizeof(Buffer); IdentityAnsiString.Buffer = Buffer; IdentityAnsiString.Length = 0; if ((dwRetCode = RtlUnicodeStringToAnsiString ( &IdentityAnsiString, &IdentityUnicodeString, FALSE)) != NO_ERROR) { TRACE1 (USER, "ElGetUserIdentity: Error in RtlConvertUnicodeStringToAnsiString = %ld", dwRetCode); break; }
pszUserName = MALLOC (IdentityAnsiString.Length + 1); if (pszUserName == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (USER, "ElGetUserIdentity: MALLOC failed for pszUserName"); break; }
memcpy (pszUserName, IdentityAnsiString.Buffer, IdentityAnsiString.Length); pszUserName[IdentityAnsiString.Length] = '\0';
if (pPCB->pszIdentity != NULL) { FREE (pPCB->pszIdentity); pPCB->pszIdentity = NULL; }
pPCB->pszIdentity = MALLOC (IdentityAnsiString.Length + 1); if (pPCB->pszIdentity == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (USER, "ElGetUserIdentity: MALLOC failed for pPCB->pszIdentity"); break; }
memcpy (pPCB->pszIdentity, IdentityAnsiString.Buffer, IdentityAnsiString.Length); pPCB->pszIdentity[IdentityAnsiString.Length] = '\0';
TRACE1 (USER, "ElGetUserIdentity: Got username = %s", pszUserName); }
if (pPCB->pCustomAuthConnData != NULL) { FREE (pPCB->pCustomAuthConnData); pPCB->pCustomAuthConnData = NULL; }
// Memory for pCustomAuthConnData and pCustomAuthUserData
// is released from the PCB when user logs off and during
// port deletion
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;
} else // MACHINE_AUTHENTICATION
{
TRACE0 (USER, "ElGetUserIdentity entered");
if (!EAPOL_PORT_ACTIVE(pPCB)) { TRACE1 (PORT, "ElGetUserIdentity: Port %s not active", pPCB->pszDeviceGUID);
// Port is not active, cannot do further processing on this port
break; }
// 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 = (EAPOLEAPGETIDENTITY)GetProcAddress(hLib, "RasEapGetIdentity"); pFreeFunc = (EAPOLEAPFREE)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; }
// Get the size of the EAP blob
if ((dwRetCode = ElGetCustomAuthData ( pPCB->pszDeviceGUID, pPCB->dwEapTypeToBeUsed, pPCB->pszSSID, 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, cannot continue"); pbAuthData = NULL; // Every port should have connection data !!!
dwRetCode = ERROR_CAN_NOT_COMPLETE; break; } 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->pszDeviceGUID, pPCB->dwEapTypeToBeUsed, pPCB->pszSSID, 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
wszFriendlyName, // lpszEntry
pbAuthData, // Connection data
cbData, // Count of pbAuthData
pbUserIn, // User data for port
dwInSize, // Size of user data
&pUserDataOut, &dwSizeOfUserDataOut, &lpwszIdentity )) != NO_ERROR) { 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) { // NOTE:
// Assuming 256 character identity maximum
// Convert wchar Identity to char string
RtlInitUnicodeString (&IdentityUnicodeString, lpwszIdentity); IdentityAnsiString.MaximumLength = sizeof(Buffer); IdentityAnsiString.Buffer = Buffer; IdentityAnsiString.Length = 0; if ((dwRetCode = RtlUnicodeStringToAnsiString ( &IdentityAnsiString, &IdentityUnicodeString, FALSE)) != NO_ERROR) { TRACE1 (USER, "ElGetUserIdentity: Error in RtlConvertUnicodeStringToAnsiString = %ld", dwRetCode); break; }
TRACE1 (USER, "lpwszIdentity = %ws", lpwszIdentity);
pszUserName = MALLOC (IdentityAnsiString.Length + 1); if (pszUserName == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (USER, "ElGetUserIdentity: MALLOC failed for pszUserName"); break; }
memcpy (pszUserName, IdentityAnsiString.Buffer, IdentityAnsiString.Length); pszUserName[IdentityAnsiString.Length] = '\0';
TRACE1 (USER, "pszUserName = %s", pszUserName);
if (pPCB->pszIdentity != NULL) { FREE (pPCB->pszIdentity); pPCB->pszIdentity = NULL; }
pPCB->pszIdentity = MALLOC (IdentityAnsiString.Length + 1); if (pPCB->pszIdentity == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (USER, "ElGetUserIdentity: MALLOC failed for pPCB->pszIdentity"); break; }
memcpy (pPCB->pszIdentity, IdentityAnsiString.Buffer, IdentityAnsiString.Length); pPCB->pszIdentity[IdentityAnsiString.Length] = '\0';
TRACE1 (USER, "ElGetUserIdentity: Got username = %s", pszUserName); }
if (pPCB->pCustomAuthConnData != NULL) { FREE (pPCB->pCustomAuthConnData); pPCB->pCustomAuthConnData = NULL; }
// Memory for pCustomAuthConnData and pCustomAuthUserData
// is released from the PCB when user logs off and during
// port deletion
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;
}
// Release the per-interface lock
RELEASE_WRITE_LOCK (&(pPCB->rwLock));
} while (FALSE);
// Cleanup
if (dwRetCode != NO_ERROR) { // Release the per-interface lock
RELEASE_WRITE_LOCK (&(pPCB->rwLock));
if (pPCB->pCustomAuthUserData != NULL) { FREE (pPCB->pCustomAuthUserData); pPCB->pCustomAuthUserData = NULL; }
if (pPCB->pCustomAuthConnData != NULL) { FREE (pPCB->pCustomAuthConnData); pPCB->pCustomAuthConnData = NULL; }
if (pPCB->pszIdentity != NULL) { FREE (pPCB->pszIdentity); pPCB->pszIdentity = NULL; }
}
if (pbUserIn != NULL) { FREE (pbUserIn); }
if (pbAuthData != NULL) { FREE (pbAuthData); }
if (pszUserName != NULL) { FREE (pszUserName); }
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;
}
//
// 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.
//
VOID ElUserLogonCallback ( PVOID pvContext, BOOLEAN fTimerOfWaitFired ) {
DWORD dwIndex = 0; EAPOL_PCB *pPCB = NULL; BOOL fSetCONNECTINGState = FALSE; DWORD dwRetCode = NO_ERROR;
// Set global flag to indicate the user logged on
TRACE1 (USER, "ElUserLogonCallback: UserloggedOn = %ld", g_fUserLoggedOn);
g_fUserLoggedOn = InterlockedIncrement (&(g_fUserLoggedOn));
do { 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) {
#ifdef DRAFT7
if (g_dwMachineAuthEnabled) { #endif
fSetCONNECTINGState = FALSE;
ACQUIRE_WRITE_LOCK (&(pPCB->rwLock));
switch (pPCB->State) { case EAPOLSTATE_CONNECTING: case EAPOLSTATE_ACQUIRED: case EAPOLSTATE_AUTHENTICATING:
// Reset AuthFailCount conditionally
pPCB->dwAuthFailCount = 0; // fall through
case EAPOLSTATE_HELD:
// End EAP session
(VOID) ElEapEnd (pPCB);
fSetCONNECTINGState = TRUE;
break;
case EAPOLSTATE_AUTHENTICATED: if (pPCB->PreviousAuthenticationType == EAPOL_UNAUTHENTICATED_ACCESS) { // Reset AuthFailCount
pPCB->dwAuthFailCount = 0; fSetCONNECTINGState = TRUE; }
break;
default: break;
}
if (!EAPOL_PORT_ACTIVE(pPCB)) { TRACE1 (USER, "ElUserLogonCallback: Port %s not active", pPCB->pszDeviceGUID); fSetCONNECTINGState = FALSE; }
// Set port to EAPOLSTATE_CONNECTING
if (fSetCONNECTINGState) { 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)) != NO_ERROR) { TRACE1 (USER, "ElUserLogonCallback: MachineAuth: Error in ElReStartPort = %ld", dwRetCode); continue; } } else { RELEASE_WRITE_LOCK (&(pPCB->rwLock)); continue; }
#ifdef DRAFT7
} else { ACQUIRE_WRITE_LOCK (&(pPCB->rwLock));
// If the port is already authenticated due to non-secure
// LAN, authentication can be skipped for this port
if (pPCB->State == EAPOLSTATE_AUTHENTICATED) { RELEASE_WRITE_LOCK (&(pPCB->rwLock)); TRACE0 (USER, "ElUserLogonCallback: Port already authenticated, continuing with next port"); continue; } RELEASE_WRITE_LOCK (&(pPCB->rwLock)); // Restart authentication on the port
if ((dwRetCode = ElReStartPort (pPCB)) != NO_ERROR) { TRACE1 (USER, "ElUserLogonCallback: Error in ElReStartPort = %ld", dwRetCode); break; } TRACE1 (USER, "ElUserLogonCallback: = Authentication restarted on port %p", pPCB);
} // g_dwMachineAuthEnabled
#endif
} } RELEASE_WRITE_LOCK (&(g_PCBLock)); if (dwRetCode != NO_ERROR) { break; } } while (FALSE); TRACE1 (USER, "ElUserLogonCallback: completed with error %ld", dwRetCode); return;
}
//
// ElUserLogoffCallback
//
// Description:
//
// Callback function invoked whenever a user logs off
// Will logoff from all ports which have authentication enabled
//
// Arguments:
// None.
//
VOID ElUserLogoffCallback ( PVOID pvContext, BOOLEAN fTimerOfWaitFired ) { DWORD dwIndex = 0; EAPOL_PCB *pPCB = NULL; BOOL fSetCONNECTINGState = FALSE; DWORD dwRetCode = NO_ERROR;
// Reset global flag to indicate the user logged on
g_fUserLoggedOn = 0;
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) {
#ifdef DRAFT7
if (g_dwMachineAuthEnabled) { #endif
fSetCONNECTINGState = FALSE;
ACQUIRE_WRITE_LOCK (&(pPCB->rwLock));
switch (pPCB->State) { case EAPOLSTATE_CONNECTING: case EAPOLSTATE_ACQUIRED: case EAPOLSTATE_AUTHENTICATING: // Reset AuthFailCount conditionally
pPCB->dwAuthFailCount = 0;
// fall through
case EAPOLSTATE_HELD:
// End EAP session
(VOID) ElEapEnd (pPCB);
fSetCONNECTINGState = TRUE;
break;
case EAPOLSTATE_AUTHENTICATED: if (pPCB->PreviousAuthenticationType == EAPOL_USER_AUTHENTICATION) { // Reset AuthFailCount
pPCB->dwAuthFailCount = 0; fSetCONNECTINGState = TRUE; } break;
default: break;
}
// Set port to EAPOLSTATE_CONNECTING
if (fSetCONNECTINGState) { 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)) != NO_ERROR) { TRACE1 (USER, "ElUserLogoffCallback: MachineAuth: Error in ElReStartPort = %ld", dwRetCode); continue; } } else { RELEASE_WRITE_LOCK (&(pPCB->rwLock)); continue; }
#ifdef DRAFT7
} else {
ACQUIRE_WRITE_LOCK (&(pPCB->rwLock));
// If remote end has sent responses earlier and if EAPOL_Logoff
// was not sent out on this port, send out EAPOL_Logoff
if ((pPCB->fIsRemoteEndEAPOLAware) && (!(pPCB->dwLogoffSent))) {
// End EAP session
// Will always return NO_ERROR, so no check on return value
(VOID) ElEapEnd (pPCB);
// Send out EAPOL_Logoff on the port
if ((dwRetCode = FSMLogoff (pPCB)) != NO_ERROR) { RELEASE_WRITE_LOCK (&(pPCB->rwLock)); TRACE1 (USER, "ElUserLogoffCallback: Error in FSMLogoff = %ld", dwRetCode); continue; }
}
RELEASE_WRITE_LOCK (&(pPCB->rwLock)); TRACE1 (USER, "ElUserLogoffCallback: = Logoff sent out on port %p", pPCB);
} // g_dwMachineAuthEnabled
#endif
} }
RELEASE_WRITE_LOCK (&(g_PCBLock));
TRACE0 (USER, "ElUserLogonCallback: completed");
return; }
//
// 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
//
//
// NOTE: Could be done in a better way. Require EAP config structures
// as in ..\ras\ui\rasdlg\dial.c
//
DWORD ElGetUserNamePassword ( IN EAPOL_PCB *pPCB ) { HANDLE hUserToken; DWORD dwIndex = -1; DWORD dwInSize = 0; HWND hwndOwner = NULL; HWINSTA hwinstaSave; HDESK hdeskSave; HWINSTA hwinstaUser; HDESK hdeskUser; DWORD dwThreadId; DWORD dwRetCode = NO_ERROR;
do { TRACE0 (USER, "ElGetUserNamePassword entered");
//
// NOTE:
// Optimize pPCB->rwLock lock holding time
//
ACQUIRE_WRITE_LOCK (&(pPCB->rwLock));
if (!EAPOL_PORT_ACTIVE(pPCB)) { TRACE1 (PORT, "ElGetUserNamePassword: Port %s not active", pPCB->pszDeviceGUID); // Port is not active, cannot do further processing on this port
break; }
//
// Get Access Token for user logged on interactively
//
// Call Terminal Services API
if (GetWinStationUserToken (GetClientLogonId(), &hUserToken) != NO_ERROR) { TRACE0 (USER, "ElGetUserNamePassword: Terminal Services API GetWinStationUserToken failed !!! "); // Call private API
hUserToken = GetCurrentUserTokenW (L"WinSta0", TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY); if (hUserToken == NULL) { dwRetCode = GetLastError (); TRACE1 (USER, "ElGetUserNamePassword: Error in GetCurrentUserTokenW = %ld", dwRetCode); dwRetCode = ERROR_NO_TOKEN; break; } } if (hUserToken == NULL) { dwRetCode = GetLastError (); TRACE0 (USER, "ElGetUserNamePassword: Error in getting current user token"); dwRetCode = ERROR_NO_TOKEN; break; }
pPCB->hUserToken = hUserToken;
// 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, "ElGetUserNamePassword: ElGetEapTypeIndex finds no dll for EAP index %ld", pPCB->dwEapTypeToBeUsed); dwRetCode = ERROR_CAN_NOT_COMPLETE; break; }
// Save handles to service window
hwinstaSave = GetProcessWindowStation(); if (hwinstaSave == NULL) { dwRetCode = GetLastError (); TRACE1 (USER, "ElGetUserNamePassword: GetProcessWindowStation failed with error %ld", dwRetCode); break; }
dwThreadId = GetCurrentThreadId ();
hdeskSave = GetThreadDesktop (dwThreadId); if (hdeskSave == NULL) { dwRetCode = GetLastError (); TRACE1 (USER, "ElGetUserNamePassword: GetThreadDesktop failed with error %ld", dwRetCode); break; }
if (!ImpersonateLoggedOnUser (pPCB->hUserToken)) { dwRetCode = GetLastError(); TRACE1 (USER, "ElGetUserNamePassword: ImpersonateLoggedOnUse failed with error %ld", dwRetCode); break; }
// Impersonate the client and connect to the User's window station
// and desktop. This will be the interactively logged-on user
hwinstaUser = OpenWindowStation (L"WinSta0", FALSE, MAXIMUM_ALLOWED); if (hwinstaUser == NULL) { dwRetCode = GetLastError (); TRACE1 (USER, "ElGetUserNamePassword: OpenWindowStation failed with error %ld", dwRetCode); break; }
SetProcessWindowStation(hwinstaUser); hdeskUser = OpenDesktop (L"Default", 0, FALSE, MAXIMUM_ALLOWED); if (hdeskUser == NULL) { SetProcessWindowStation (hwinstaSave); CloseWindowStation (hwinstaUser); dwRetCode = ERROR_INVALID_WORKSTATION; break; }
SetThreadDesktop (hdeskUser);
// Get handle to desktop window
hwndOwner = GetDesktopWindow ();
//
// Call the user dialog for obtaining the username and password
//
if ((dwRetCode = ElUserDlg (hwndOwner, pPCB)) != NO_ERROR) { TRACE0 (USER, "ElGetUserNamePassword: ElUserDlg failed");
RevertToSelf();
// Restore window station and desktop
SetThreadDesktop (hdeskSave); SetProcessWindowStation (hwinstaSave); CloseDesktop(hdeskUser); CloseWindowStation(hwinstaUser); break; }
// Revert impersonation
if (!RevertToSelf()) { dwRetCode = GetLastError(); TRACE1 (USER, "ElGetUserNamePassword: Error in RevertToSelf = %ld", dwRetCode); // Restore window station and desktop
SetThreadDesktop (hdeskSave); SetProcessWindowStation (hwinstaSave); CloseDesktop(hdeskUser); CloseWindowStation(hwinstaUser); break; }
// Restore window station and desktop settings
SetThreadDesktop (hdeskSave); SetProcessWindowStation (hwinstaSave); CloseDesktop(hdeskUser); CloseWindowStation(hwinstaUser);
// Mark the identity has been obtained for this PCB
pPCB->fGotUserIdentity = TRUE;
// Release the per-interface lock
RELEASE_WRITE_LOCK (&(pPCB->rwLock));
} while (FALSE);
// Cleanup
if (dwRetCode != NO_ERROR) { // Release the per-interface lock
RELEASE_WRITE_LOCK (&(pPCB->rwLock));
if (pPCB->pCustomAuthUserData != NULL) { FREE (pPCB->pCustomAuthUserData); }
if (pPCB->pCustomAuthConnData != NULL) { FREE (pPCB->pCustomAuthConnData); }
}
TRACE1 (USER, "ElGetUserNamePassword completed with error %ld", dwRetCode);
return dwRetCode; }
//
// ElUserDlg
//
// Description:
//
// Function called to pop dialog box to user to enter username, password,
// domainname etc.
//
// Arguments:
// hwndOwner - handle to user desktop
// pPCB - Pointer to PCB for the port/interface on which credentials
// are to be obtained
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
DWORD ElUserDlg ( IN HWND hwndOwner, IN EAPOL_PCB *pPCB ) { USERDLGARGS args; DWORD dwRetCode = NO_ERROR;
TRACE0 (USER, "ElUserDlg: Entered");
args.pPCB = pPCB;
if ( DialogBoxParam ( GetModuleHandle(cszModuleName), MAKEINTRESOURCE (DID_DR_DialerUD), hwndOwner, ElUserDlgProc, (LPARAM)&args ) == -1) { dwRetCode = GetLastError (); TRACE1 (USER, "ElUserDlg: DialogBoxParam failed with error %ld", dwRetCode); }
return dwRetCode; }
//
// ElUserDlgProc
//
// Description:
//
// Function handling all events for username/password/... dialog box
//
// Arguments:
// hwnd -
// unMsg -
// wparam -
// lparam -
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
INT_PTR ElUserDlgProc ( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ) { switch (unMsg) { case WM_INITDIALOG: { return ElUserDlgInit( hwnd, (USERDLGARGS* )lparam ); break; } case WM_HELP: case WM_CONTEXTMENU: { break; } case WM_COMMAND: { USERDLGINFO* pInfo = (USERDLGINFO* )GetWindowLongPtr( hwnd, DWLP_USER ); ASSERT( pInfo ); return ElUserDlgCommand ( pInfo, HIWORD(wparam), LOWORD(wparam), (HWND)lparam );
break; } case WM_DESTROY: { USERDLGINFO* pInfo = (USERDLGINFO* )GetWindowLongPtr( hwnd, DWLP_USER ); ElUserDlgTerm (hwnd, pInfo); break; } }
return FALSE; }
BOOL ElUserDlgInit ( IN HWND hwndDlg, IN USERDLGARGS *pArgs ) { USERDLGINFO *pInfo = NULL; WCHAR wszFriendlyName[256]; DWORD dwRetCode = NO_ERROR;
TRACE0 (USER, "ElUserDlgInit entered");
do { pInfo = MALLOC (sizeof (USERDLGINFO)); if (pInfo == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (USER, "ElUserDlgInit: MALLOC failed for pInfo"); break; } pInfo->pArgs = pArgs; pInfo->hwndDlg = hwndDlg; SetWindowLongPtr (hwndDlg, DWLP_USER, (ULONG_PTR)pInfo); #if 0
if (!SetWindowLongPtr (hwndDlg, DWLP_USER, (ULONG_PTR)pInfo)) { dwRetCode = GetLastError (); TRACE1 (USER, "ElUserDlgInit: SetWindowLongPtr failed with error %ld", dwRetCode); break; } #endif
TRACE0 (USER, "ElUserDlgInit: Context Set"); //
// Set the title
//
ZeroMemory (wszFriendlyName, 256*sizeof(WCHAR)); // Convert the friendly name of the adapter to a display ready
// form
if (pArgs->pPCB->pszFriendlyName) { if (0 == MultiByteToWideChar( CP_ACP, 0, pArgs->pPCB->pszFriendlyName, -1, wszFriendlyName, 256 ) ) { dwRetCode = GetLastError(); TRACE2 (USER, "ElUserDlgInit: MultiByteToWideChar(%s) failed: %d", pArgs->pPCB->pszFriendlyName, dwRetCode); } if (!SetWindowText (hwndDlg, wszFriendlyName)) { dwRetCode = GetLastError (); TRACE1 (USER, "ElUserDlgInit: SetWindowText failed with error %ld", dwRetCode); break; } } else { if (!SetWindowText (hwndDlg, NULL)) { dwRetCode = GetLastError (); TRACE1 (USER, "ElUserDlgInit: SetWindowText - NULL failed with error %ld", dwRetCode); break; } } pInfo->hwndEbUser = GetDlgItem( hwndDlg, CID_DR_EB_User ); ASSERT (pInfo->hwndEbUser); pInfo->hwndEbPw = GetDlgItem( hwndDlg, CID_DR_EB_Password ); ASSERT (pInfo->hwndEbPw); pInfo->hwndEbDomain = GetDlgItem( hwndDlg, CID_DR_EB_Domain ); ASSERT (pInfo->hwndEbDomain); } while (FALSE);
if (dwRetCode != NO_ERROR) { return FALSE; } else { return TRUE; } }
//
// ElUserDlgCommand
//
// Description:
//
// Function called on WM_COMMAND
// domainname etc.
//
// Arguments:
// PInfo - dialog context
// WNotification - notification code of the command
// wId - control/menu identifier of the command
// HwndCtrl - control window handle the command.
//
// Return values:
// TRUE - success
// FALSE - error
//
BOOL ElUserDlgCommand ( IN USERDLGINFO *pInfo, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl ) { TRACE3 (USER, "ElUserDlgCommand: n=%d, i=%d, c=%x", (DWORD)wNotification, (DWORD)wId, (ULONG_PTR)hwndCtrl);
switch (wId) { case IDOK: case CID_DR_PB_DialConnect: { ElUserDlgSave (pInfo); EndDialog (pInfo->hwndDlg, TRUE); return TRUE; } case IDCANCEL: case CID_DR_PB_Cancel: { EndDialog (pInfo->hwndDlg, TRUE); return TRUE; } default: { TRACE0 (USER, "ElUserDlgCommand: Got something we are not interested in"); break; } }
return FALSE; }
VOID ElUserDlgSave ( IN USERDLGINFO *pInfo ) { EAPOL_PCB *pPCB = NULL; int iError; CHAR szUserName[UNLEN + 1]; CHAR szDomain[DNLEN + 1]; CHAR szPassword[DNLEN + 1]; DWORD dwRetCode = NO_ERROR;
pPCB = (EAPOL_PCB *)pInfo->pArgs->pPCB;
do {
// Username
if ((iError = GetWindowTextA( pInfo->hwndEbUser, &(szUserName[0]), UNLEN + 1 )) == 0) { dwRetCode = GetLastError (); TRACE1 (USER, "ElUserDlgSave: GetWindowText - Username failed with error %ld", dwRetCode); } szUserName[iError] = '\0'; TRACE1 (USER, "ElUserDlgSave: Get Username %s", szUserName); // Password
if ((iError = GetWindowTextA( pInfo->hwndEbPw, &(szPassword[0]), PWLEN + 1 )) == 0) { dwRetCode = GetLastError (); TRACE1 (USER, "ElUserDlgSave: GetWindowText - Password failed with error %ld", dwRetCode); } szPassword[iError] = '\0'; if (pPCB->pszPassword != NULL) { FREE (pPCB->pszPassword); pPCB->pszPassword = NULL; }
pPCB->pszPassword = MALLOC (strlen(szPassword) + 1); if (pPCB->pszPassword == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (USER, "ElUserDlgSave: MALLOC failed for pPCB->pszPassword"); break; }
memcpy (pPCB->pszPassword, szPassword, strlen(szPassword) + 1);
// Uncomment only if absolutely required
// Security issue, since we are writing trace to file
// TRACE1 (USER, "ElUserDlgSave: Got Password %s", pPCB->pszPassword);
// Domain
if ((iError = GetWindowTextA( pInfo->hwndEbDomain, &(szDomain[0]), DNLEN + 1 )) == 0) { dwRetCode = GetLastError (); TRACE1 (USER, "ElUserDlgSave: GetWindowText - Domain failed with error %ld", dwRetCode); } szDomain[iError] = '\0'; TRACE1 (USER, "ElUserDlgSave: Got Domain %s", szDomain); if (pPCB->pszIdentity != NULL) { FREE (pPCB->pszIdentity); pPCB->pszIdentity = NULL; }
if ((szDomain != NULL) && (szDomain[0] != (CHAR)NULL)) { pPCB->pszIdentity = MALLOC (strlen(szDomain)+strlen(szUserName)+2); if (pPCB->pszIdentity == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (USER, "ElUserDlgSave: MALLOC failed for pPCB->pszIdentity 1"); break; }
strcpy (pPCB->pszIdentity, szDomain); strcat( pPCB->pszIdentity, "\\" ); strcat (pPCB->pszIdentity, szUserName); } else { pPCB->pszIdentity = MALLOC (strlen(szUserName)+1); if (pPCB->pszIdentity == NULL) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; TRACE0 (USER, "ElUserDlgSave: MALLOC failed for pPCB->pszIdentity 2"); break; }
strcpy (pPCB->pszIdentity, szUserName); }
TRACE1 (USER, "ElUserDlgSave: Got identity %s", pPCB->pszIdentity); TRACE1 (USER, "ElUserDlgSave: PCB->GUID = %s", pPCB->pszDeviceGUID);
// Hash-up password while storing locally
ElEncodePw (pPCB->pszPassword);
} while (FALSE);
if (dwRetCode != NO_ERROR) { if (pPCB->pszIdentity != NULL) { FREE (pPCB->pszIdentity); pPCB->pszIdentity = NULL; } if (pPCB->pszPassword != NULL) { FREE (pPCB->pszPassword); pPCB->pszPassword = NULL; } }
return;
}
VOID ElUserDlgTerm ( IN HWND hwndDlg, IN USERDLGINFO *pInfo ) { EndDialog (hwndDlg, TRUE); FREE (pInfo); }
//
// 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 ) { HANDLE hUserToken = NULL; HANDLE hLib = NULL; EAPOLEAPFREE pFreeFunc = NULL; EAPOLEAPINVOKEINTERACTIVEUI pEapInvokeUI = NULL; DWORD dwIndex = -1; BYTE *pUIDataOut = NULL; DWORD dwSizeOfUIDataOut; HWND hwndOwner = NULL; HWINSTA hwinstaSave = NULL; HDESK hdeskSave = NULL; HWINSTA hwinstaUser = NULL; HDESK hdeskUser = NULL; DWORD dwThreadId = 0; DWORD dwRetCode = NO_ERROR;
do { TRACE0 (USER, "ElInvokeInteractiveUI entered");
// 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, "ElInvokeInteractiveUI: ElGetEapTypeIndex finds no dll for EAP index %ld", pPCB->dwEapTypeToBeUsed); dwRetCode = ERROR_CAN_NOT_COMPLETE; break; }
hLib = g_pEapTable[dwIndex].hInstance;
pEapInvokeUI = (EAPOLEAPINVOKEINTERACTIVEUI) GetProcAddress (hLib, "RasEapInvokeInteractiveUI"); pFreeFunc = (EAPOLEAPFREE) GetProcAddress (hLib, "RasEapFreeMemory");
if ((pFreeFunc == NULL) || (pEapInvokeUI == NULL)) { TRACE0 (USER, "ElInvokeInteractiveUI: pEapInvokeUI or pFreeFunc does not exist in the EAP implementation"); dwRetCode = ERROR_CAN_NOT_COMPLETE; break; }
// Get Access Token for user logged on interactively
// Call Terminal Services API
if (GetWinStationUserToken (GetClientLogonId(), &hUserToken) != NO_ERROR) { TRACE0 (USER, "ElInvokeInteractiveUI: Terminal Services API GetWinStationUserToken failed !!! ");
// Call private API
hUserToken = GetCurrentUserTokenW (L"WinSta0", TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY); if (hUserToken == NULL) { dwRetCode = GetLastError (); TRACE1 (USER, "ElInvokeInteractiveUI: Error in GetCurrentUserTokenW = %ld", dwRetCode); dwRetCode = ERROR_NO_TOKEN; break; } } if (hUserToken == NULL) { dwRetCode = GetLastError (); TRACE0 (USER, "ElInvokeInteractiveUI: Error in getting current user token"); dwRetCode = ERROR_NO_TOKEN; break; }
pPCB->hUserToken = hUserToken;
// Save handles to service window
hwinstaSave = GetProcessWindowStation(); if (hwinstaSave == NULL) { dwRetCode = GetLastError (); TRACE1 (USER, "ElInvokeInteractiveUI: GetProcessWindowStation failed with error %ld", dwRetCode); break; }
dwThreadId = GetCurrentThreadId ();
hdeskSave = GetThreadDesktop (dwThreadId); if (hdeskSave == NULL) { dwRetCode = GetLastError (); TRACE1 (USER, "ElInvokeInteractiveUI: GetThreadDesktop failed with error %ld", dwRetCode); break; }
if (!ImpersonateLoggedOnUser (pPCB->hUserToken)) { dwRetCode = GetLastError(); TRACE1 (USER, "ElInvokeInteractiveUI: ImpersonateLoggedOnUse failed with error %ld", dwRetCode); break; }
// Impersonate the client and connect to the User's window station
// and desktop. This will be the interactively logged-on user
hwinstaUser = OpenWindowStation (L"WinSta0", FALSE, MAXIMUM_ALLOWED); if (hwinstaUser == NULL) { dwRetCode = GetLastError (); TRACE1 (USER, "OpenWindowStation: OpenWindowStation failed with error %ld", dwRetCode); break; }
SetProcessWindowStation(hwinstaUser); hdeskUser = OpenDesktop (L"Default", 0, FALSE, MAXIMUM_ALLOWED); if (hdeskUser == NULL) { SetProcessWindowStation (hwinstaSave); CloseWindowStation (hwinstaUser); dwRetCode = ERROR_INVALID_WORKSTATION; break; }
SetThreadDesktop (hdeskUser);
// Get handle to desktop window
hwndOwner = GetDesktopWindow ();
if ((dwRetCode = (*(pEapInvokeUI))( pPCB->dwEapTypeToBeUsed, hwndOwner, // hwndOwner
// Context data from EAP
pInvokeEapUIIn->pbUIContextData, // Size of context data
pInvokeEapUIIn->dwSizeOfUIContextData, &pUIDataOut, &dwSizeOfUIDataOut )) != NO_ERROR) { TRACE1 (USER, "ElInvokeInteractiveUI: Error in calling InvokeInteractiveUI = %ld", dwRetCode); // Revert impersonation
if (!RevertToSelf()) { dwRetCode = GetLastError(); TRACE1 (USER, "ElInvokeInteractiveUI: Error in RevertToSelf = %ld", dwRetCode); }
// Restore window station and desktop
SetThreadDesktop (hdeskSave); SetProcessWindowStation (hwinstaSave); CloseDesktop(hdeskUser); CloseWindowStation(hwinstaUser);
break; }
// Revert impersonation
if (!RevertToSelf()) { dwRetCode = GetLastError(); TRACE1 (USER, "ElInvokeInteractiveUI: Error in RevertToSelf = %ld", dwRetCode); // Restore window station and desktop
SetThreadDesktop (hdeskSave); SetProcessWindowStation (hwinstaSave); CloseDesktop(hdeskUser); CloseWindowStation(hwinstaUser); break; }
// Restore window station and desktop settings
SetThreadDesktop (hdeskSave); SetProcessWindowStation (hwinstaSave); CloseDesktop(hdeskUser); CloseWindowStation(hwinstaUser); // Free the context we passed to the dll
if (pInvokeEapUIIn->pbUIContextData != NULL) { FREE (pInvokeEapUIIn->pbUIContextData); pInvokeEapUIIn->pbUIContextData = NULL; pInvokeEapUIIn->dwSizeOfUIContextData = 0; } // Fill in the returned information into the PCB fields for
// later authentication
if (pPCB->EapUIData.pEapUIData != NULL) { FREE (pPCB->EapUIData.pEapUIData); pPCB->EapUIData.pEapUIData = NULL; pPCB->EapUIData.dwSizeOfEapUIData = 0; }
pPCB->EapUIData.pEapUIData = MALLOC (dwSizeOfUIDataOut + sizeof (DWORD)); if (pPCB->EapUIData.pEapUIData == NULL) { TRACE1 (USER, "ElInvokeInteractiveUI: Error in allocating memory for UIData = %ld", dwRetCode); dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; }
pPCB->EapUIData.dwSizeOfEapUIData = dwSizeOfUIDataOut;
if ((dwSizeOfUIDataOut != 0) && (pUIDataOut != NULL)) { memcpy ((BYTE *)pPCB->EapUIData.pEapUIData, (BYTE *)pUIDataOut, dwSizeOfUIDataOut); }
pPCB->fEapUIDataReceived = TRUE;
TRACE0 (USER, "ElInvokeInteractiveUI: 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, "ElInvokeInteractiveUI: ElEapWork failed with error = %ld", dwRetCode); break; } TRACE0 (USER, "ElInvokeInteractiveUI: 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 (pInvokeEapUIIn->pbUIContextData != NULL) { FREE (pInvokeEapUIIn->pbUIContextData); pInvokeEapUIIn->pbUIContextData = NULL; pInvokeEapUIIn->dwSizeOfUIContextData = 0; }
if (pFreeFunc != NULL) { if (pUIDataOut != NULL) { if (( dwRetCode = (*(pFreeFunc)) ((BYTE *)pUIDataOut)) != NO_ERROR) { TRACE1 (USER, "ElInvokeInteractiveUI: Error in pFreeFunc = %ld", dwRetCode); } } }
TRACE1 (USER, "ElInvokeInteractiveUI completed with error %ld", dwRetCode);
return dwRetCode; }
|