2206 lines
66 KiB
C
2206 lines
66 KiB
C
|
/*++
|
||
|
|
||
|
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;
|
||
|
}
|