2082 lines
56 KiB
C
2082 lines
56 KiB
C
/********************************************************************/
|
||
/** Copyright(c) 1985-1997 Microsoft Corporation. **/
|
||
/********************************************************************/
|
||
|
||
//***
|
||
//
|
||
// Filename: raseap.c
|
||
//
|
||
// Description: Main module that will do interfacing between the PPP engine
|
||
// and the various EAP modules.
|
||
//
|
||
// History: May 11,1997 NarenG Created original version.
|
||
//
|
||
#define UNICODE
|
||
#include <nt.h>
|
||
#include <ntrtl.h>
|
||
#include <nturtl.h>
|
||
#include <ntlsa.h>
|
||
#include <ntmsv1_0.h>
|
||
#include <ntsamp.h>
|
||
#include <crypt.h>
|
||
#include <windows.h>
|
||
#include <lmcons.h>
|
||
#include <string.h>
|
||
#include <stdlib.h>
|
||
#include <rasman.h>
|
||
#include <pppcp.h>
|
||
#include <mprlog.h>
|
||
#include <mprerror.h>
|
||
#include <raserror.h>
|
||
#include <rtutils.h>
|
||
#include <rasauth.h>
|
||
#include <raseapif.h>
|
||
#define INCL_PWUTIL
|
||
#define INCL_HOSTWIRE
|
||
#define INCL_RASAUTHATTRIBUTES
|
||
#include <ppputil.h>
|
||
#include <raseapif.h>
|
||
#define RASEAPGLOBALS
|
||
#include "raseap.h"
|
||
#include "bltincps.h"
|
||
|
||
//**
|
||
//
|
||
// Call: LoadEapDlls
|
||
//
|
||
// Returns: NO_ERROR - Success
|
||
// Non-zero returns - Failure
|
||
//
|
||
// Description: Will load all the EAP dlls installed.
|
||
//
|
||
DWORD
|
||
LoadEapDlls(
|
||
VOID
|
||
)
|
||
{
|
||
HKEY hKeyEap = (HKEY)NULL;
|
||
LPWSTR pEapDllPath = (LPWSTR)NULL;
|
||
LPWSTR pEapDllExpandedPath = (LPWSTR)NULL;
|
||
HKEY hKeyEapDll = (HKEY)NULL;
|
||
DWORD dwRetCode;
|
||
DWORD dwNumSubKeys;
|
||
DWORD dwMaxSubKeySize;
|
||
DWORD dwNumValues;
|
||
DWORD cbMaxValNameLen;
|
||
DWORD cbMaxValueDataSize;
|
||
DWORD dwKeyIndex;
|
||
WCHAR wchSubKeyName[200];
|
||
HINSTANCE hInstance;
|
||
FARPROC pRasEapGetInfo;
|
||
DWORD cbSubKeyName;
|
||
DWORD dwSecDescLen;
|
||
DWORD cbSize;
|
||
DWORD dwType;
|
||
DWORD dwEapTypeId;
|
||
|
||
//
|
||
// Open the EAP key
|
||
//
|
||
|
||
dwRetCode = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
||
RAS_EAP_REGISTRY_LOCATION,
|
||
0,
|
||
KEY_READ,
|
||
&hKeyEap );
|
||
|
||
if ( dwRetCode != NO_ERROR )
|
||
{
|
||
EapLogErrorString( ROUTERLOG_CANT_OPEN_PPP_REGKEY,0,NULL, dwRetCode,0);
|
||
|
||
return( dwRetCode );
|
||
}
|
||
|
||
//
|
||
// Find out how many EAP DLLs there are
|
||
//
|
||
|
||
dwRetCode = RegQueryInfoKey(
|
||
hKeyEap,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
&dwNumSubKeys,
|
||
&dwMaxSubKeySize,
|
||
NULL,
|
||
&dwNumValues,
|
||
&cbMaxValNameLen,
|
||
&cbMaxValueDataSize,
|
||
NULL,
|
||
NULL );
|
||
|
||
if ( dwRetCode != NO_ERROR )
|
||
{
|
||
EapLogErrorString(ROUTERLOG_CANT_OPEN_PPP_REGKEY,0,NULL, dwRetCode,0);
|
||
|
||
RegCloseKey( hKeyEap );
|
||
|
||
return( dwRetCode );
|
||
}
|
||
|
||
//
|
||
// Allocate space in the table to hold information for each one
|
||
//
|
||
|
||
gblpEapTable=(EAP_INFO*)LocalAlloc(LPTR,sizeof(EAP_INFO)*dwNumSubKeys);
|
||
|
||
if ( gblpEapTable == NULL )
|
||
{
|
||
RegCloseKey( hKeyEap );
|
||
|
||
return( GetLastError() );
|
||
}
|
||
|
||
//
|
||
// Read the registry to find out the various EAPs to load.
|
||
//
|
||
|
||
for ( dwKeyIndex = 0; dwKeyIndex < dwNumSubKeys; dwKeyIndex++ )
|
||
{
|
||
cbSubKeyName = sizeof( wchSubKeyName ) / sizeof(TCHAR);
|
||
|
||
dwRetCode = RegEnumKeyEx(
|
||
hKeyEap,
|
||
dwKeyIndex,
|
||
wchSubKeyName,
|
||
&cbSubKeyName,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL );
|
||
|
||
if ( ( dwRetCode != NO_ERROR ) &&
|
||
( dwRetCode != ERROR_MORE_DATA ) &&
|
||
( dwRetCode != ERROR_NO_MORE_ITEMS ) )
|
||
{
|
||
EapLogErrorString(ROUTERLOG_CANT_ENUM_REGKEYVALUES,0,
|
||
NULL,dwRetCode,0);
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
if ( dwRetCode == ERROR_NO_MORE_ITEMS )
|
||
{
|
||
dwRetCode = NO_ERROR;
|
||
|
||
break;
|
||
}
|
||
}
|
||
|
||
dwRetCode = RegOpenKeyEx(
|
||
hKeyEap,
|
||
wchSubKeyName,
|
||
0,
|
||
KEY_QUERY_VALUE,
|
||
&hKeyEapDll );
|
||
|
||
|
||
if ( dwRetCode != NO_ERROR )
|
||
{
|
||
EapLogErrorString( ROUTERLOG_CANT_OPEN_PPP_REGKEY,0,NULL,
|
||
dwRetCode,0);
|
||
break;
|
||
}
|
||
|
||
dwEapTypeId = _wtol( wchSubKeyName );
|
||
|
||
//
|
||
// Find out the size of the path value.
|
||
//
|
||
|
||
dwRetCode = RegQueryInfoKey(
|
||
hKeyEapDll,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
&cbMaxValNameLen,
|
||
&cbMaxValueDataSize,
|
||
NULL,
|
||
NULL
|
||
);
|
||
|
||
if ( dwRetCode != NO_ERROR )
|
||
{
|
||
EapLogErrorString(ROUTERLOG_CANT_OPEN_PPP_REGKEY,0,NULL,
|
||
dwRetCode,0);
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Allocate space for path and add one for NULL terminator
|
||
//
|
||
|
||
cbMaxValueDataSize += sizeof( WCHAR );
|
||
|
||
pEapDllPath = (LPWSTR)LocalAlloc( LPTR, cbMaxValueDataSize );
|
||
|
||
if ( pEapDllPath == (LPWSTR)NULL )
|
||
{
|
||
dwRetCode = GetLastError();
|
||
EapLogError( ROUTERLOG_NOT_ENOUGH_MEMORY, 0, NULL, dwRetCode);
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Read in the path
|
||
//
|
||
|
||
dwRetCode = RegQueryValueEx(
|
||
hKeyEapDll,
|
||
RAS_EAP_VALUENAME_PATH,
|
||
NULL,
|
||
&dwType,
|
||
(LPBYTE)pEapDllPath,
|
||
&cbMaxValueDataSize );
|
||
|
||
if ( dwRetCode != NO_ERROR )
|
||
{
|
||
EapLogError(ROUTERLOG_CANT_GET_REGKEYVALUES, 0, NULL, dwRetCode );
|
||
break;
|
||
}
|
||
|
||
if ( ( dwType != REG_EXPAND_SZ ) && ( dwType != REG_SZ ) )
|
||
{
|
||
dwRetCode = ERROR_REGISTRY_CORRUPT;
|
||
EapLogError( ROUTERLOG_CANT_GET_REGKEYVALUES, 0, NULL, dwRetCode );
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Replace the %SystemRoot% with the actual path.
|
||
//
|
||
|
||
cbSize = ExpandEnvironmentStrings( pEapDllPath, NULL, 0 );
|
||
|
||
if ( cbSize == 0 )
|
||
{
|
||
dwRetCode = GetLastError();
|
||
EapLogError( ROUTERLOG_CANT_GET_REGKEYVALUES, 0, NULL, dwRetCode );
|
||
break;
|
||
}
|
||
|
||
pEapDllExpandedPath = (LPWSTR)LocalAlloc( LPTR, cbSize*sizeof(WCHAR) );
|
||
|
||
if ( pEapDllExpandedPath == (LPWSTR)NULL )
|
||
{
|
||
dwRetCode = GetLastError();
|
||
EapLogError( ROUTERLOG_NOT_ENOUGH_MEMORY, 0, NULL, dwRetCode);
|
||
break;
|
||
}
|
||
|
||
cbSize = ExpandEnvironmentStrings( pEapDllPath,
|
||
pEapDllExpandedPath,
|
||
cbSize*sizeof(WCHAR) );
|
||
if ( cbSize == 0 )
|
||
{
|
||
dwRetCode = GetLastError();
|
||
EapLogError(ROUTERLOG_CANT_GET_REGKEYVALUES,0,NULL,dwRetCode);
|
||
break;
|
||
}
|
||
|
||
hInstance = LoadLibrary( pEapDllExpandedPath );
|
||
|
||
if ( hInstance == (HINSTANCE)NULL )
|
||
{
|
||
dwRetCode = GetLastError();
|
||
EapLogErrorString( ROUTERLOG_PPP_CANT_LOAD_DLL,1,
|
||
&pEapDllExpandedPath,dwRetCode, 1);
|
||
break;
|
||
}
|
||
|
||
gblpEapTable[dwKeyIndex].hInstance = hInstance;
|
||
|
||
gbldwNumEapProtocols++;
|
||
|
||
pRasEapGetInfo = GetProcAddress( hInstance, "RasEapGetInfo" );
|
||
|
||
if ( pRasEapGetInfo == (FARPROC)NULL )
|
||
{
|
||
dwRetCode = GetLastError();
|
||
|
||
EapLogErrorString( ROUTERLOG_PPPCP_DLL_ERROR, 1,
|
||
&pEapDllExpandedPath, dwRetCode, 1);
|
||
break;
|
||
}
|
||
|
||
gblpEapTable[dwKeyIndex].RasEapInfo.dwSizeInBytes =
|
||
sizeof( PPP_EAP_INFO );
|
||
|
||
dwRetCode = (DWORD) (*pRasEapGetInfo)( dwEapTypeId,
|
||
&(gblpEapTable[dwKeyIndex].RasEapInfo));
|
||
|
||
if ( dwRetCode != NO_ERROR )
|
||
{
|
||
EapLogErrorString(ROUTERLOG_PPPCP_DLL_ERROR, 1,
|
||
&pEapDllExpandedPath, dwRetCode, 1);
|
||
break;
|
||
|
||
}
|
||
|
||
//
|
||
// Also initialize the GetCredentials entrypoint if available.
|
||
//
|
||
gblpEapTable[dwKeyIndex].RasEapGetCredentials = (DWORD (*) (
|
||
DWORD,VOID *, VOID **)) GetProcAddress(
|
||
hInstance,
|
||
"RasEapGetCredentials");
|
||
#if DBG
|
||
if(NULL != gblpEapTable[dwKeyIndex].RasEapGetCredentials)
|
||
{
|
||
EAP_TRACE1("GetCredentials entry point found for typeid %d",
|
||
dwEapTypeId);
|
||
}
|
||
#endif
|
||
|
||
if ( gblpEapTable[dwKeyIndex].RasEapInfo.RasEapInitialize != NULL )
|
||
{
|
||
dwRetCode = gblpEapTable[dwKeyIndex].RasEapInfo.RasEapInitialize(
|
||
TRUE );
|
||
|
||
if ( dwRetCode != NO_ERROR )
|
||
{
|
||
EapLogErrorString(ROUTERLOG_PPPCP_DLL_ERROR, 1,
|
||
&pEapDllExpandedPath, dwRetCode, 1);
|
||
break;
|
||
}
|
||
}
|
||
|
||
EAP_TRACE1("Successfully loaded EAP DLL type id = %d", dwEapTypeId );
|
||
|
||
RegCloseKey( hKeyEapDll );
|
||
|
||
hKeyEapDll = (HKEY)NULL;
|
||
|
||
LocalFree( pEapDllExpandedPath );
|
||
|
||
pEapDllExpandedPath = NULL;
|
||
|
||
LocalFree( pEapDllPath );
|
||
|
||
pEapDllPath = (LPWSTR)NULL;
|
||
}
|
||
|
||
if ( hKeyEap != (HKEY)NULL )
|
||
{
|
||
RegCloseKey( hKeyEap );
|
||
}
|
||
|
||
if ( hKeyEapDll == (HKEY)NULL )
|
||
{
|
||
RegCloseKey( hKeyEapDll );
|
||
}
|
||
|
||
if ( pEapDllPath != (LPWSTR)NULL )
|
||
{
|
||
LocalFree( pEapDllPath );
|
||
}
|
||
|
||
if ( pEapDllExpandedPath != NULL )
|
||
{
|
||
LocalFree( pEapDllExpandedPath );
|
||
}
|
||
|
||
return( dwRetCode );
|
||
}
|
||
|
||
//**
|
||
//
|
||
// Call: EapInit
|
||
//
|
||
// Returns: NO_ERROR - Success
|
||
// Non-zero returns - Failure
|
||
//
|
||
// Description: Called to initialize/uninitialize this CP. In the former case,
|
||
// fInitialize will be TRUE; in the latter case, it will be FALSE.
|
||
//
|
||
DWORD
|
||
EapInit(
|
||
IN BOOL fInitialize
|
||
)
|
||
{
|
||
DWORD dwError;
|
||
|
||
if ( fInitialize )
|
||
{
|
||
g_dwTraceIdEap = TraceRegister( TEXT("RASEAP") );
|
||
|
||
g_hLogEvents = RouterLogRegister( TEXT("RemoteAccess") );
|
||
|
||
if ( ( dwError = LoadEapDlls() ) != NO_ERROR )
|
||
{
|
||
if ( g_dwTraceIdEap != INVALID_TRACEID )
|
||
{
|
||
TraceDeregister( g_dwTraceIdEap );
|
||
|
||
g_dwTraceIdEap = INVALID_TRACEID;
|
||
}
|
||
|
||
if ( g_hLogEvents != NULL )
|
||
{
|
||
RouterLogDeregister( g_hLogEvents );
|
||
|
||
g_hLogEvents = NULL;
|
||
}
|
||
|
||
if ( gblpEapTable != NULL )
|
||
{
|
||
LocalFree( gblpEapTable );
|
||
|
||
gblpEapTable = NULL;
|
||
}
|
||
|
||
gbldwNumEapProtocols = 0;
|
||
|
||
return( dwError );
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if ( g_dwTraceIdEap != INVALID_TRACEID )
|
||
{
|
||
TraceDeregister( g_dwTraceIdEap );
|
||
|
||
g_dwTraceIdEap = INVALID_TRACEID;
|
||
}
|
||
|
||
if ( g_hLogEvents != NULL )
|
||
{
|
||
RouterLogDeregister( g_hLogEvents );
|
||
|
||
g_hLogEvents = NULL;
|
||
}
|
||
|
||
if ( gblpEapTable != NULL )
|
||
{
|
||
DWORD dwIndex;
|
||
|
||
//
|
||
// Unload loaded DLLs
|
||
//
|
||
|
||
for ( dwIndex = 0; dwIndex < gbldwNumEapProtocols; dwIndex++ )
|
||
{
|
||
if ( gblpEapTable[dwIndex].hInstance != NULL )
|
||
{
|
||
if ( gblpEapTable[dwIndex].RasEapInfo.RasEapInitialize !=
|
||
NULL )
|
||
{
|
||
dwError = gblpEapTable[dwIndex].RasEapInfo.
|
||
RasEapInitialize(
|
||
FALSE );
|
||
|
||
if ( dwError != NO_ERROR )
|
||
{
|
||
EAP_TRACE2(
|
||
"RasEapInitialize(%d) failed and returned %d",
|
||
gblpEapTable[dwIndex].RasEapInfo.dwEapTypeId,
|
||
dwError );
|
||
}
|
||
}
|
||
|
||
FreeLibrary( gblpEapTable[dwIndex].hInstance );
|
||
gblpEapTable[dwIndex].hInstance = NULL;
|
||
}
|
||
}
|
||
|
||
LocalFree( gblpEapTable );
|
||
|
||
gblpEapTable = NULL;
|
||
}
|
||
|
||
gbldwNumEapProtocols = 0;
|
||
}
|
||
|
||
return(NO_ERROR);
|
||
}
|
||
|
||
//**
|
||
//
|
||
// Call: EapGetInfo
|
||
//
|
||
// Returns: NO_ERROR - Success
|
||
// Non-zero returns - Failure
|
||
//
|
||
// Description: Called to get information for all protocols supported in this
|
||
// module
|
||
//
|
||
LONG_PTR
|
||
EapGetInfo(
|
||
IN DWORD dwProtocolId,
|
||
OUT PPPCP_INFO* pInfo
|
||
)
|
||
{
|
||
ZeroMemory( pInfo, sizeof( PPPCP_INFO ) );
|
||
|
||
pInfo->Protocol = (DWORD )PPP_EAP_PROTOCOL;
|
||
lstrcpyA(pInfo->SzProtocolName, "EAP");
|
||
pInfo->Recognize = MAXEAPCODE + 1;
|
||
pInfo->RasCpInit = EapInit;
|
||
pInfo->RasCpBegin = EapBegin;
|
||
pInfo->RasCpEnd = EapEnd;
|
||
pInfo->RasApMakeMessage = EapMakeMessage;
|
||
|
||
return( 0 );
|
||
}
|
||
|
||
//**
|
||
//
|
||
// Call: EapBegin
|
||
//
|
||
// Returns: NO_ERROR - Success
|
||
// Non-zero returns - Failure
|
||
//
|
||
// Description: Called by the engine to begin a EAP PPP session.
|
||
//
|
||
DWORD
|
||
EapBegin(
|
||
OUT VOID** ppWorkBuf,
|
||
IN VOID* pInfo
|
||
)
|
||
{
|
||
DWORD dwRetCode;
|
||
PPPAP_INPUT* pInput = (PPPAP_INPUT* )pInfo;
|
||
EAPCB* pEapCb;
|
||
|
||
EAP_TRACE1("EapBegin(fServer=%d)",pInput->fServer );
|
||
|
||
|
||
if ( pInput->dwEapTypeToBeUsed != -1 )
|
||
{
|
||
//
|
||
// First check if we support this EAP type
|
||
//
|
||
|
||
if ( GetEapTypeIndex( (BYTE)(pInput->dwEapTypeToBeUsed) ) == -1 )
|
||
{
|
||
return( ERROR_NOT_SUPPORTED );
|
||
}
|
||
}
|
||
|
||
//
|
||
// Allocate work buffer.
|
||
//
|
||
|
||
if ( ( pEapCb = (EAPCB* )LocalAlloc( LPTR, sizeof( EAPCB ) ) ) == NULL )
|
||
{
|
||
return( ERROR_NOT_ENOUGH_MEMORY );
|
||
}
|
||
|
||
pEapCb->hPort = pInput->hPort;
|
||
pEapCb->fAuthenticator = pInput->fServer;
|
||
pEapCb->fRouter = pInput->fRouter;
|
||
pEapCb->fLogon = pInput->fLogon;
|
||
pEapCb->fNonInteractive = pInput->fNonInteractive;
|
||
pEapCb->fPortWillBeBundled = pInput->fPortWillBeBundled;
|
||
pEapCb->fThisIsACallback = pInput->fThisIsACallback;
|
||
pEapCb->hTokenImpersonateUser = pInput->hTokenImpersonateUser;
|
||
pEapCb->pCustomAuthConnData = pInput->pCustomAuthConnData;
|
||
pEapCb->pCustomAuthUserData = pInput->pCustomAuthUserData;
|
||
pEapCb->EapState = EAPSTATE_Initial;
|
||
pEapCb->dwEapIndex = (DWORD)-1;
|
||
pEapCb->dwEapTypeToBeUsed = pInput->dwEapTypeToBeUsed;
|
||
pEapCb->chSeed = GEN_RAND_ENCODE_SEED;
|
||
|
||
if ( !pEapCb->fAuthenticator )
|
||
{
|
||
if ( ( pInput->pszDomain != NULL ) &&
|
||
( pInput->pszDomain[0] != (CHAR)NULL ) )
|
||
{
|
||
strcpy( pEapCb->szIdentity, pInput->pszDomain );
|
||
strcat( pEapCb->szIdentity, "\\" );
|
||
strcat( pEapCb->szIdentity, pInput->pszUserName );
|
||
}
|
||
else
|
||
{
|
||
strcpy( pEapCb->szIdentity, pInput->pszUserName );
|
||
}
|
||
|
||
strcpy( pEapCb->szPassword, pInput->pszPassword );
|
||
EncodePw( pEapCb->chSeed, pEapCb->szPassword );
|
||
|
||
if ( pInput->EapUIData.pEapUIData != NULL )
|
||
{
|
||
PPP_EAP_UI_DATA EapUIData;
|
||
|
||
EapUIData.dwSizeOfEapUIData = pInput->EapUIData.dwSizeOfEapUIData;
|
||
EapUIData.dwContextId = pInput->EapUIData.dwContextId;
|
||
|
||
EapUIData.pEapUIData = LocalAlloc( LPTR,
|
||
EapUIData.dwSizeOfEapUIData );
|
||
|
||
if ( NULL == EapUIData.pEapUIData )
|
||
{
|
||
LocalFree( pEapCb );
|
||
|
||
return( ERROR_NOT_ENOUGH_MEMORY );
|
||
}
|
||
|
||
CopyMemory( EapUIData.pEapUIData, pInput->EapUIData.pEapUIData,
|
||
EapUIData.dwSizeOfEapUIData );
|
||
|
||
pEapCb->EapUIData = EapUIData;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Register work buffer with engine.
|
||
//
|
||
|
||
*ppWorkBuf = pEapCb;
|
||
|
||
EAP_TRACE("EapBegin done");
|
||
|
||
return( NO_ERROR );
|
||
}
|
||
|
||
//**
|
||
//
|
||
// Call: EapEnd
|
||
//
|
||
// Returns: NO_ERROR - Success
|
||
// Non-zero returns - Failure
|
||
//
|
||
// Description: Called to end the Eap session initiated by an EapBegin
|
||
//
|
||
DWORD
|
||
EapEnd(
|
||
IN VOID* pWorkBuf
|
||
)
|
||
{
|
||
EAPCB* pEapCb = (EAPCB* )pWorkBuf;
|
||
|
||
EAP_TRACE("EapEnd");
|
||
|
||
if ( pEapCb == NULL )
|
||
{
|
||
return( NO_ERROR );
|
||
}
|
||
|
||
EapDllEnd( pEapCb );
|
||
|
||
if ( pEapCb->pUserAttributes != NULL )
|
||
{
|
||
RasAuthAttributeDestroy( pEapCb->pUserAttributes );
|
||
}
|
||
|
||
LocalFree( pEapCb->EapUIData.pEapUIData );
|
||
|
||
//
|
||
// Nuke any credentials in memory.
|
||
//
|
||
|
||
ZeroMemory( pEapCb, sizeof(EAPCB) );
|
||
|
||
LocalFree( pEapCb );
|
||
|
||
return( NO_ERROR );
|
||
}
|
||
|
||
//**
|
||
//
|
||
// Call: EapExtractMessage
|
||
//
|
||
// Returns: VOID
|
||
//
|
||
// Description: If there is any message in the Request/Notification packet, then
|
||
// save the string in pResult->szReplyMessage
|
||
//
|
||
VOID
|
||
EapExtractMessage(
|
||
IN PPP_CONFIG* pReceiveBuf,
|
||
OUT PPPAP_RESULT* pResult )
|
||
{
|
||
DWORD dwNumBytes;
|
||
CHAR* szReplyMessage = NULL;
|
||
WORD cbPacket;
|
||
|
||
cbPacket = WireToHostFormat16( pReceiveBuf->Length );
|
||
|
||
if ( PPP_CONFIG_HDR_LEN + 1 >= cbPacket )
|
||
{
|
||
goto LDone;
|
||
}
|
||
|
||
dwNumBytes = cbPacket - PPP_CONFIG_HDR_LEN - 1;
|
||
|
||
//
|
||
// One more for the terminating NULL.
|
||
//
|
||
|
||
szReplyMessage = LocalAlloc( LPTR, dwNumBytes + 1 );
|
||
|
||
if ( NULL == szReplyMessage )
|
||
{
|
||
EAP_TRACE( "LocalAlloc failed. Cannot extract server's message." );
|
||
goto LDone;
|
||
}
|
||
|
||
CopyMemory( szReplyMessage, pReceiveBuf->Data + 1, dwNumBytes );
|
||
|
||
LocalFree( pResult->szReplyMessage );
|
||
|
||
pResult->szReplyMessage = szReplyMessage;
|
||
|
||
szReplyMessage = NULL;
|
||
|
||
LDone:
|
||
|
||
LocalFree( szReplyMessage );
|
||
|
||
return;
|
||
}
|
||
|
||
//**
|
||
//
|
||
// Call: EapMakeMessage
|
||
//
|
||
// Returns: NO_ERROR - Success
|
||
// Non-zero returns - Failure
|
||
//
|
||
// Description: Called to process and/or to send an EAP packet.
|
||
//
|
||
DWORD
|
||
EapMakeMessage(
|
||
IN VOID* pWorkBuf,
|
||
IN PPP_CONFIG* pReceiveBuf,
|
||
OUT PPP_CONFIG* pSendBuf,
|
||
IN DWORD cbSendBuf,
|
||
OUT PPPAP_RESULT* pResult,
|
||
IN PPPAP_INPUT* pInput
|
||
)
|
||
{
|
||
EAPCB* pEapCb = (EAPCB* )pWorkBuf;
|
||
|
||
EAP_TRACE1("EapMakeMessage,RBuf=%x",pReceiveBuf);
|
||
|
||
if ( ( pReceiveBuf != NULL ) && ( pReceiveBuf->Code == EAPCODE_Request ) )
|
||
{
|
||
//
|
||
// Always respond to notitication request, with a notification response
|
||
//
|
||
|
||
if ( pReceiveBuf->Data[0] == EAPTYPE_Notification )
|
||
{
|
||
pSendBuf->Code = EAPCODE_Response;
|
||
pSendBuf->Id = pReceiveBuf->Id;
|
||
|
||
HostToWireFormat16( PPP_CONFIG_HDR_LEN + 1, pSendBuf->Length );
|
||
|
||
pSendBuf->Data[0] = EAPTYPE_Notification;
|
||
|
||
pResult->Action = APA_Send;
|
||
|
||
EapExtractMessage( pReceiveBuf, pResult );
|
||
|
||
return( NO_ERROR );
|
||
}
|
||
|
||
//
|
||
// Always respond to Identity request, with an Identity response
|
||
//
|
||
|
||
if ( pReceiveBuf->Data[0] == EAPTYPE_Identity )
|
||
{
|
||
pSendBuf->Code = EAPCODE_Response;
|
||
pSendBuf->Id = pReceiveBuf->Id;
|
||
|
||
if ( !pEapCb->fAuthenticator )
|
||
{
|
||
HostToWireFormat16(
|
||
(WORD)(PPP_CONFIG_HDR_LEN+1+strlen(pEapCb->szIdentity)),
|
||
pSendBuf->Length );
|
||
|
||
strcpy( pSendBuf->Data+1, pEapCb->szIdentity );
|
||
}
|
||
else
|
||
{
|
||
HostToWireFormat16( (WORD)(PPP_CONFIG_HDR_LEN+1),
|
||
pSendBuf->Length );
|
||
}
|
||
|
||
pSendBuf->Data[0] = EAPTYPE_Identity;
|
||
|
||
pResult->Action = APA_Send;
|
||
|
||
return( NO_ERROR );
|
||
}
|
||
}
|
||
|
||
return
|
||
(pEapCb->fAuthenticator)
|
||
? MakeAuthenticatorMessage(
|
||
pEapCb, pReceiveBuf, pSendBuf, cbSendBuf, pResult, pInput )
|
||
: MakeAuthenticateeMessage(
|
||
pEapCb, pReceiveBuf, pSendBuf, cbSendBuf, pResult, pInput );
|
||
}
|
||
|
||
//**
|
||
//
|
||
// Call: MakeAuthenticateeMessage
|
||
//
|
||
// Returns: NO_ERROR - Success
|
||
// Non-zero returns - Failure
|
||
//
|
||
// Description: EAP Authenticatee engine
|
||
//
|
||
DWORD
|
||
MakeAuthenticateeMessage(
|
||
IN EAPCB* pEapCb,
|
||
IN PPP_CONFIG* pReceiveBuf,
|
||
OUT PPP_CONFIG* pSendBuf,
|
||
IN DWORD cbSendBuf,
|
||
OUT PPPAP_RESULT* pResult,
|
||
IN PPPAP_INPUT* pInput
|
||
)
|
||
{
|
||
DWORD dwEapIndex;
|
||
DWORD dwRetCode = NO_ERROR;
|
||
|
||
EAP_TRACE("MakeAuthenticateeMessage...");
|
||
|
||
switch( pEapCb->EapState )
|
||
{
|
||
case EAPSTATE_Initial:
|
||
|
||
EAP_TRACE("EAPSTATE_Initial");
|
||
|
||
if ( pReceiveBuf == NULL )
|
||
{
|
||
//
|
||
// Do nothing. Wait for request from authenticator
|
||
//
|
||
|
||
pResult->Action = APA_NoAction;
|
||
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
if ( pReceiveBuf->Code != EAPCODE_Request )
|
||
{
|
||
//
|
||
// We are authenticatee side so drop everything other than
|
||
// requests, since we do not send requests
|
||
//
|
||
|
||
pResult->Action = APA_NoAction;
|
||
|
||
break;
|
||
}
|
||
|
||
//
|
||
// We got a packet, see if we support this EAP type, also that
|
||
// we are authorized to use it
|
||
//
|
||
|
||
dwEapIndex = GetEapTypeIndex( pReceiveBuf->Data[0] );
|
||
|
||
if (( dwEapIndex == -1 ) ||
|
||
( ( pEapCb->dwEapTypeToBeUsed != -1 ) &&
|
||
( dwEapIndex != GetEapTypeIndex( pEapCb->dwEapTypeToBeUsed))))
|
||
{
|
||
//
|
||
// We do not support this type or we are not authorized to use
|
||
// it so we NAK with a type we support
|
||
//
|
||
|
||
pSendBuf->Code = EAPCODE_Response;
|
||
pSendBuf->Id = pReceiveBuf->Id;
|
||
|
||
HostToWireFormat16( PPP_CONFIG_HDR_LEN + 2, pSendBuf->Length );
|
||
|
||
pSendBuf->Data[0] = EAPTYPE_Nak;
|
||
|
||
if ( pEapCb->dwEapTypeToBeUsed != -1 )
|
||
{
|
||
pSendBuf->Data[1] = (BYTE)pEapCb->dwEapTypeToBeUsed;
|
||
}
|
||
else
|
||
{
|
||
pSendBuf->Data[1] =
|
||
(BYTE)gblpEapTable[0].RasEapInfo.dwEapTypeId;
|
||
}
|
||
|
||
pResult->Action = APA_Send;
|
||
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// The EAP type is acceptable to us so we begin authentication
|
||
//
|
||
|
||
if ( (dwRetCode = EapDllBegin(pEapCb, dwEapIndex)) != NO_ERROR )
|
||
{
|
||
break;
|
||
}
|
||
|
||
pEapCb->EapState = EAPSTATE_Working;
|
||
|
||
//
|
||
// Fall thru
|
||
//
|
||
}
|
||
}
|
||
|
||
case EAPSTATE_Working:
|
||
|
||
EAP_TRACE("EAPSTATE_Working");
|
||
|
||
if ( pReceiveBuf != NULL )
|
||
{
|
||
if ( ( pReceiveBuf->Code != EAPCODE_Request ) &&
|
||
( pReceiveBuf->Code != EAPCODE_Success ) &&
|
||
( pReceiveBuf->Code != EAPCODE_Failure ) )
|
||
{
|
||
//
|
||
// We are authenticatee side so drop everything other than
|
||
// request/success/failure
|
||
//
|
||
|
||
EAP_TRACE("Dropping invlid packet not request/success/failure");
|
||
|
||
pResult->Action = APA_NoAction;
|
||
|
||
break;
|
||
}
|
||
|
||
if ( ( pReceiveBuf->Code == EAPCODE_Request ) &&
|
||
( pReceiveBuf->Data[0] !=
|
||
gblpEapTable[pEapCb->dwEapIndex].RasEapInfo.dwEapTypeId ) )
|
||
{
|
||
EAP_TRACE("Dropping invalid request packet with unknown Id");
|
||
|
||
pResult->Action = APA_NoAction;
|
||
|
||
break;
|
||
}
|
||
}
|
||
|
||
dwRetCode = EapDllWork( pEapCb,
|
||
pReceiveBuf,
|
||
pSendBuf,
|
||
cbSendBuf,
|
||
pResult,
|
||
pInput );
|
||
|
||
break;
|
||
|
||
default:
|
||
|
||
RTASSERT( FALSE );
|
||
|
||
break;
|
||
}
|
||
|
||
return( dwRetCode );
|
||
}
|
||
|
||
//**
|
||
//
|
||
// Call: MakeAuthenticatorMessage
|
||
//
|
||
// Returns: NO_ERROR - Success
|
||
// Non-zero returns - Failure
|
||
//
|
||
// Description: EAP Authenticator engine
|
||
//
|
||
DWORD
|
||
MakeAuthenticatorMessage(
|
||
IN EAPCB* pEapCb,
|
||
IN PPP_CONFIG* pReceiveBuf,
|
||
OUT PPP_CONFIG* pSendBuf,
|
||
IN DWORD cbSendBuf,
|
||
OUT PPPAP_RESULT* pResult,
|
||
IN PPPAP_INPUT* pInput
|
||
)
|
||
{
|
||
DWORD dwRetCode = NO_ERROR;
|
||
DWORD dwEapTypeIndex;
|
||
CHAR * pszReplyMessage;
|
||
DWORD dwNumBytes;
|
||
WORD wLength;
|
||
BYTE bCode;
|
||
RAS_AUTH_ATTRIBUTE * pAttribute;
|
||
|
||
EAP_TRACE("MakeAuthenticatorMessage...");
|
||
|
||
pResult->dwEapTypeId = pEapCb->dwEapTypeToBeUsed;
|
||
|
||
switch( pEapCb->EapState )
|
||
{
|
||
case EAPSTATE_IdentityRequestSent:
|
||
|
||
EAP_TRACE("EAPSTATE_IdentityRequestSent");
|
||
|
||
if ( pReceiveBuf != NULL )
|
||
{
|
||
//
|
||
// If we received a response to our identity request, then process
|
||
// it.
|
||
//
|
||
|
||
if ( ( pReceiveBuf->Code == EAPCODE_Response ) &&
|
||
( pReceiveBuf->Data[0] == EAPTYPE_Identity ) )
|
||
{
|
||
DWORD dwIdentityLength=WireToHostFormat16(pReceiveBuf->Length);
|
||
|
||
dwIdentityLength -= ( PPP_CONFIG_HDR_LEN + 1 );
|
||
|
||
//
|
||
// Truncate the identity length if it is greater than UNLEN
|
||
//
|
||
|
||
if ( dwIdentityLength > UNLEN+DNLEN+1 )
|
||
{
|
||
dwIdentityLength = UNLEN+DNLEN+1;
|
||
}
|
||
|
||
CopyMemory( pEapCb->szIdentity,
|
||
pReceiveBuf->Data+1,
|
||
dwIdentityLength );
|
||
|
||
pEapCb->szIdentity[dwIdentityLength] = (CHAR)NULL;
|
||
|
||
dwRetCode = MakeRequestAttributes( pEapCb, pReceiveBuf );
|
||
|
||
if ( dwRetCode == NO_ERROR )
|
||
{
|
||
pResult->pUserAttributes = pEapCb->pUserAttributes;
|
||
|
||
pEapCb->EapState = EAPSTATE_EapPacketSentToAuthServer;
|
||
|
||
pResult->Action = APA_Authenticate;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// Otherwise drop the packet
|
||
//
|
||
|
||
EAP_TRACE("Dropping invalid packet");
|
||
|
||
pResult->Action = APA_NoAction;
|
||
}
|
||
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Else if If timed out, fallthru and resend
|
||
//
|
||
|
||
case EAPSTATE_Initial:
|
||
|
||
EAP_TRACE("EAPSTATE_Initial");
|
||
|
||
pEapCb->dwIdExpected = bNextId++;
|
||
|
||
//
|
||
// Create Identity request packet
|
||
//
|
||
|
||
pSendBuf->Code = EAPCODE_Request;
|
||
pSendBuf->Id = (BYTE)pEapCb->dwIdExpected;
|
||
|
||
HostToWireFormat16( PPP_CONFIG_HDR_LEN + 1, pSendBuf->Length );
|
||
|
||
pSendBuf->Data[0] = EAPTYPE_Identity;
|
||
pResult->Action = APA_SendWithTimeout;
|
||
pResult->bIdExpected = (BYTE)pEapCb->dwIdExpected;
|
||
pEapCb->EapState = EAPSTATE_IdentityRequestSent;
|
||
|
||
break;
|
||
|
||
case EAPSTATE_EapPacketSentToAuthServer:
|
||
|
||
//
|
||
// Wait for response from RADIUS authentication provider
|
||
// drop all other packets received in the mean time.
|
||
//
|
||
|
||
if ( pInput == NULL )
|
||
{
|
||
pResult->Action = APA_NoAction;
|
||
|
||
break;
|
||
}
|
||
|
||
if ( !pInput->fAuthenticationComplete )
|
||
{
|
||
//
|
||
// If authentication was not complete then we do nothing
|
||
//
|
||
|
||
pResult->Action = APA_NoAction;
|
||
|
||
break;
|
||
}
|
||
|
||
strcpy( pResult->szUserName, pEapCb->szIdentity );
|
||
|
||
//
|
||
// If authentication completed with an error, then we error out
|
||
// now, otherwise we process the authentication completion
|
||
// event below
|
||
//
|
||
|
||
if ( pInput->dwAuthError != NO_ERROR )
|
||
{
|
||
EAP_TRACE1("Error %d while processing Access-Request",
|
||
pInput->dwAuthError );
|
||
|
||
return( pInput->dwAuthError );
|
||
}
|
||
|
||
//
|
||
// If we got here then the authentication completed successfully,
|
||
// ie the RADIUS server returned attributes. First save the state
|
||
// attribute from the access challenge if there was one.
|
||
//
|
||
|
||
if ( pEapCb->pStateAttribute != NULL )
|
||
{
|
||
LocalFree( pEapCb->pStateAttribute );
|
||
|
||
pEapCb->pStateAttribute = NULL;
|
||
}
|
||
|
||
pAttribute = RasAuthAttributeGet(
|
||
raatState,
|
||
pInput->pAttributesFromAuthenticator );
|
||
|
||
if ( pAttribute != NULL )
|
||
{
|
||
pEapCb->pStateAttribute =
|
||
(PBYTE)LocalAlloc(LPTR, pAttribute->dwLength);
|
||
|
||
if ( pEapCb->pStateAttribute == NULL )
|
||
{
|
||
return( GetLastError() );
|
||
}
|
||
|
||
CopyMemory( pEapCb->pStateAttribute,
|
||
(PBYTE)(pAttribute->Value),
|
||
pAttribute->dwLength );
|
||
|
||
pEapCb->cbStateAttribute = pAttribute->dwLength;
|
||
}
|
||
|
||
//
|
||
// Try to get the EAP Message if there is one
|
||
//
|
||
|
||
pAttribute = RasAuthAttributeGet(
|
||
raatEAPMessage,
|
||
pInput->pAttributesFromAuthenticator );
|
||
|
||
if ( pAttribute != NULL )
|
||
{
|
||
//
|
||
// Save the send buffer in case we have to resend
|
||
//
|
||
|
||
if ( pEapCb->pEAPSendBuf != NULL )
|
||
{
|
||
LocalFree( pEapCb->pEAPSendBuf );
|
||
pEapCb->cbEAPSendBuf = 0;
|
||
}
|
||
|
||
pszReplyMessage = RasAuthAttributeGetConcatString(
|
||
raatReplyMessage,
|
||
pInput->pAttributesFromAuthenticator,
|
||
&dwNumBytes );
|
||
|
||
wLength = (USHORT) (PPP_CONFIG_HDR_LEN + 1 + dwNumBytes);
|
||
bCode = ((PPP_CONFIG*)(pAttribute->Value))->Code;
|
||
|
||
if ( ( NULL != pszReplyMessage ) &&
|
||
( wLength <= cbSendBuf ) &&
|
||
( ( bCode == EAPCODE_Success ) ||
|
||
( bCode == EAPCODE_Failure ) ) )
|
||
{
|
||
pEapCb->pEAPSendBuf = (PBYTE)LocalAlloc( LPTR, wLength );
|
||
|
||
if ( pEapCb->pEAPSendBuf == NULL )
|
||
{
|
||
LocalFree( pszReplyMessage );
|
||
|
||
return( GetLastError() );
|
||
}
|
||
|
||
pEapCb->cbEAPSendBuf = wLength;
|
||
|
||
pSendBuf->Code = EAPCODE_Request;
|
||
pSendBuf->Id = ++((PPP_CONFIG*)(pAttribute->Value))->Id;
|
||
HostToWireFormat16( wLength, pSendBuf->Length );
|
||
|
||
pSendBuf->Data[0] = EAPTYPE_Notification;
|
||
|
||
CopyMemory( pSendBuf->Data + 1, pszReplyMessage, dwNumBytes );
|
||
|
||
LocalFree( pszReplyMessage );
|
||
|
||
CopyMemory( pEapCb->pEAPSendBuf, pSendBuf, wLength );
|
||
|
||
pResult->Action = APA_SendWithTimeout;
|
||
pResult->bIdExpected = pSendBuf->Id;
|
||
|
||
pEapCb->fSendWithTimeoutInteractive = FALSE;
|
||
pEapCb->dwIdExpected = pSendBuf->Id;
|
||
pEapCb->EapState = EAPSTATE_NotificationSentToClient;
|
||
|
||
pEapCb->pSavedAttributesFromAuthenticator =
|
||
pInput->pAttributesFromAuthenticator;
|
||
pEapCb->dwSavedAuthResultCode = pInput->dwAuthResultCode;
|
||
|
||
EAP_TRACE("Sending notification to client");
|
||
|
||
break;
|
||
}
|
||
|
||
LocalFree( pszReplyMessage );
|
||
|
||
if ( pAttribute->dwLength > cbSendBuf )
|
||
{
|
||
EAP_TRACE( "Need a larger buffer to construct reply" );
|
||
// return( ERROR_BUFFER_TOO_SMALL );
|
||
}
|
||
|
||
pEapCb->pEAPSendBuf = (PBYTE)LocalAlloc(LPTR, pAttribute->dwLength);
|
||
|
||
if ( pEapCb->pEAPSendBuf == NULL )
|
||
{
|
||
return( GetLastError() );
|
||
}
|
||
|
||
EAP_TRACE("Sending packet to client");
|
||
|
||
pEapCb->cbEAPSendBuf = pAttribute->dwLength;
|
||
|
||
CopyMemory( pEapCb->pEAPSendBuf,
|
||
pAttribute->Value,
|
||
pAttribute->dwLength );
|
||
|
||
CopyMemory( pSendBuf, pAttribute->Value, pAttribute->dwLength );
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// No EAP Message attribute returned so fail the authentication
|
||
//
|
||
|
||
EAP_TRACE("No EAP Message attribute received, failing auth");
|
||
|
||
if ( pInput->dwAuthResultCode == NO_ERROR )
|
||
{
|
||
pInput->dwAuthResultCode = ERROR_AUTHENTICATION_FAILURE;
|
||
}
|
||
}
|
||
|
||
if ( pInput->dwAuthResultCode != NO_ERROR )
|
||
{
|
||
//
|
||
// If we failed authentication
|
||
//
|
||
|
||
pResult->dwError = pInput->dwAuthResultCode;
|
||
|
||
if ( pAttribute == NULL )
|
||
{
|
||
//
|
||
// If there was no EAP packet then we are done
|
||
//
|
||
|
||
pResult->Action = APA_Done;
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// If there was an EAP packet returned then simply send it
|
||
//
|
||
|
||
pResult->Action = APA_SendAndDone;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// Otherwise either we succeeded or for some reason, we don't have
|
||
// a success or failure packet.
|
||
//
|
||
|
||
if ( pAttribute == NULL )
|
||
{
|
||
//
|
||
// We succeeded but there was no packet to send, so we are
|
||
// done
|
||
//
|
||
|
||
pResult->Action = APA_Done;
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// If we succeeded and there is a packet to send and that
|
||
// packet is a success packet, then send it and we are done
|
||
//
|
||
|
||
if ( pSendBuf->Code == EAPCODE_Success )
|
||
{
|
||
pResult->Action = APA_SendAndDone;
|
||
}
|
||
else
|
||
{
|
||
pResult->Action = APA_SendWithTimeout;
|
||
|
||
pEapCb->fSendWithTimeoutInteractive = FALSE;
|
||
|
||
pAttribute = RasAuthAttributeGet(
|
||
raatSessionTimeout,
|
||
pInput->pAttributesFromAuthenticator );
|
||
|
||
if ( pAttribute != NULL )
|
||
{
|
||
//
|
||
// If session timeout in Access-Challenge is
|
||
// greater then 10 then send with interactive
|
||
// timeout.
|
||
//
|
||
|
||
if ( PtrToUlong(pAttribute->Value) > 10 )
|
||
{
|
||
pResult->Action = APA_SendWithTimeout2;
|
||
|
||
pEapCb->fSendWithTimeoutInteractive = TRUE;
|
||
}
|
||
}
|
||
|
||
pEapCb->dwIdExpected = pSendBuf->Id;
|
||
pResult->bIdExpected = (BYTE)pEapCb->dwIdExpected;
|
||
pEapCb->EapState = EAPSTATE_EapPacketSentToClient;
|
||
}
|
||
}
|
||
|
||
pResult->dwError = NO_ERROR;
|
||
}
|
||
|
||
break;
|
||
|
||
case EAPSTATE_NotificationSentToClient:
|
||
|
||
if ( pReceiveBuf != NULL )
|
||
{
|
||
//
|
||
// Make sure the packet IDs match
|
||
//
|
||
|
||
if ( pReceiveBuf->Id != ((PPP_CONFIG*)(pEapCb->pEAPSendBuf))->Id )
|
||
{
|
||
EAP_TRACE("Id of packet recvd doesn't match one sent");
|
||
|
||
pResult->Action = APA_NoAction;
|
||
|
||
break;
|
||
}
|
||
|
||
strcpy( pResult->szUserName, pEapCb->szIdentity );
|
||
|
||
pAttribute = RasAuthAttributeGet(
|
||
raatEAPMessage,
|
||
pEapCb->pSavedAttributesFromAuthenticator );
|
||
|
||
if ( pAttribute != NULL )
|
||
{
|
||
//
|
||
// Save the send buffer in case we have to resend
|
||
//
|
||
|
||
if ( pEapCb->pEAPSendBuf != NULL )
|
||
{
|
||
LocalFree( pEapCb->pEAPSendBuf );
|
||
pEapCb->cbEAPSendBuf = 0;
|
||
}
|
||
|
||
if ( pAttribute->dwLength > cbSendBuf )
|
||
{
|
||
EAP_TRACE( "Need a larger buffer to construct reply" );
|
||
// return( ERROR_BUFFER_TOO_SMALL );
|
||
}
|
||
|
||
pEapCb->pEAPSendBuf = (PBYTE)LocalAlloc(LPTR, pAttribute->dwLength);
|
||
|
||
if ( pEapCb->pEAPSendBuf == NULL )
|
||
{
|
||
return( GetLastError() );
|
||
}
|
||
|
||
EAP_TRACE("Sending packet to client");
|
||
|
||
pEapCb->cbEAPSendBuf = pAttribute->dwLength;
|
||
|
||
CopyMemory( pEapCb->pEAPSendBuf,
|
||
pAttribute->Value,
|
||
pAttribute->dwLength );
|
||
|
||
CopyMemory( pSendBuf, pAttribute->Value, pAttribute->dwLength );
|
||
|
||
if ( pEapCb->dwSavedAuthResultCode != NO_ERROR )
|
||
{
|
||
//
|
||
// If we failed authentication
|
||
//
|
||
|
||
pResult->dwError = pEapCb->dwSavedAuthResultCode;
|
||
pResult->Action = APA_SendAndDone;
|
||
break;
|
||
}
|
||
else if ( EAPCODE_Success == pSendBuf->Code )
|
||
{
|
||
pResult->dwError = NO_ERROR;
|
||
pResult->Action = APA_SendAndDone;
|
||
break;
|
||
}
|
||
}
|
||
|
||
pResult->dwError = ERROR_AUTHENTICATION_FAILURE;
|
||
pResult->Action = APA_Done;
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Fall thru
|
||
//
|
||
|
||
case EAPSTATE_EapPacketSentToClient:
|
||
|
||
//
|
||
// If we did not get any input structure, then we either received
|
||
// a packet or we timed out.
|
||
//
|
||
|
||
if ( pReceiveBuf != NULL )
|
||
{
|
||
//
|
||
// Make sure the packet IDs match
|
||
//
|
||
|
||
if ( pReceiveBuf->Id != ((PPP_CONFIG*)(pEapCb->pEAPSendBuf))->Id )
|
||
{
|
||
EAP_TRACE("Id of packet recvd doesn't match one sent");
|
||
|
||
pResult->Action = APA_NoAction;
|
||
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Save the Eap Type. Make sure that the response from the client
|
||
// contains an authentication Type code, and not something like
|
||
// a Nak.
|
||
//
|
||
|
||
if ( ( pReceiveBuf->Code == EAPCODE_Response ) &&
|
||
( pReceiveBuf->Data[0] > EAPTYPE_Nak ) )
|
||
{
|
||
pEapCb->dwEapTypeToBeUsed = pReceiveBuf->Data[0];
|
||
}
|
||
|
||
//
|
||
// We received a packet so simply send it to the RADIUS server
|
||
//
|
||
|
||
dwRetCode = MakeRequestAttributes( pEapCb, pReceiveBuf );
|
||
|
||
if ( dwRetCode == NO_ERROR )
|
||
{
|
||
pResult->pUserAttributes = pEapCb->pUserAttributes;
|
||
pResult->Action = APA_Authenticate;
|
||
pEapCb->EapState = EAPSTATE_EapPacketSentToAuthServer;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// We timed out and have to resend
|
||
//
|
||
|
||
EAP_TRACE("Timed out, resending packet to client");
|
||
|
||
CopyMemory(pSendBuf, pEapCb->pEAPSendBuf, pEapCb->cbEAPSendBuf);
|
||
|
||
if ( pEapCb->fSendWithTimeoutInteractive )
|
||
{
|
||
pResult->Action = APA_SendWithTimeout2;
|
||
}
|
||
else
|
||
{
|
||
pResult->Action = APA_SendWithTimeout;
|
||
}
|
||
|
||
pResult->bIdExpected = (BYTE)pEapCb->dwIdExpected;
|
||
}
|
||
|
||
break;
|
||
|
||
default:
|
||
|
||
RTASSERT( FALSE );
|
||
break;
|
||
}
|
||
|
||
return( dwRetCode );
|
||
}
|
||
|
||
//**
|
||
//
|
||
// Call: EapDllBegin
|
||
//
|
||
// Returns: NO_ERROR - Success
|
||
// Non-zero returns - Failure
|
||
//
|
||
// Description: Called to initiate an EAP session for a certain type
|
||
//
|
||
//
|
||
DWORD
|
||
EapDllBegin(
|
||
IN EAPCB * pEapCb,
|
||
IN DWORD dwEapIndex
|
||
)
|
||
{
|
||
PPP_EAP_INPUT PppEapInput;
|
||
WCHAR awszIdentity[DNLEN+UNLEN+2];
|
||
WCHAR awszPassword[PWLEN+1];
|
||
DWORD dwRetCode;
|
||
|
||
EAP_TRACE1("EapDllBegin called for EAP Type %d",
|
||
gblpEapTable[dwEapIndex].RasEapInfo.dwEapTypeId);
|
||
|
||
if (0 == MultiByteToWideChar(
|
||
CP_ACP,
|
||
0,
|
||
pEapCb->szIdentity,
|
||
-1,
|
||
awszIdentity,
|
||
DNLEN+UNLEN+2 ) )
|
||
{
|
||
dwRetCode = GetLastError();
|
||
|
||
EAP_TRACE2("MultiByteToWideChar(%s) failed: %d",
|
||
pEapCb->szIdentity,
|
||
dwRetCode);
|
||
|
||
return( dwRetCode );
|
||
}
|
||
|
||
ZeroMemory( &PppEapInput, sizeof( PppEapInput ) );
|
||
|
||
PppEapInput.dwSizeInBytes = sizeof( PPP_EAP_INPUT );
|
||
PppEapInput.fFlags = ( pEapCb->fRouter ?
|
||
RAS_EAP_FLAG_ROUTER : 0 );
|
||
PppEapInput.fFlags |= ( pEapCb->fLogon ?
|
||
RAS_EAP_FLAG_LOGON : 0 );
|
||
PppEapInput.fFlags |= ( pEapCb->fNonInteractive ?
|
||
RAS_EAP_FLAG_NON_INTERACTIVE : 0 );
|
||
|
||
if ( !pEapCb->fThisIsACallback && !pEapCb->fPortWillBeBundled )
|
||
{
|
||
PppEapInput.fFlags |= RAS_EAP_FLAG_FIRST_LINK;
|
||
}
|
||
|
||
PppEapInput.fAuthenticator = pEapCb->fAuthenticator;
|
||
PppEapInput.pwszIdentity = awszIdentity;
|
||
PppEapInput.pwszPassword = awszPassword;
|
||
PppEapInput.hTokenImpersonateUser = pEapCb->hTokenImpersonateUser;
|
||
PppEapInput.fAuthenticationComplete = FALSE;
|
||
PppEapInput.dwAuthResultCode = NO_ERROR;
|
||
|
||
if ( NULL != pEapCb->pCustomAuthConnData )
|
||
{
|
||
PppEapInput.pConnectionData =
|
||
pEapCb->pCustomAuthConnData->abCustomAuthData;
|
||
PppEapInput.dwSizeOfConnectionData =
|
||
pEapCb->pCustomAuthConnData->cbCustomAuthData;
|
||
}
|
||
|
||
if ( NULL != pEapCb->pCustomAuthUserData )
|
||
{
|
||
PppEapInput.pUserData =
|
||
pEapCb->pCustomAuthUserData->abCustomAuthData;
|
||
PppEapInput.dwSizeOfUserData =
|
||
pEapCb->pCustomAuthUserData->cbCustomAuthData;
|
||
}
|
||
|
||
if ( NULL != pEapCb->EapUIData.pEapUIData )
|
||
{
|
||
PppEapInput.pDataFromInteractiveUI =
|
||
pEapCb->EapUIData.pEapUIData;
|
||
PppEapInput.dwSizeOfDataFromInteractiveUI =
|
||
pEapCb->EapUIData.dwSizeOfEapUIData;
|
||
}
|
||
|
||
DecodePw( pEapCb->chSeed, pEapCb->szPassword );
|
||
|
||
MultiByteToWideChar(
|
||
CP_ACP,
|
||
0,
|
||
pEapCb->szPassword,
|
||
-1,
|
||
awszPassword,
|
||
PWLEN+1 );
|
||
|
||
awszPassword[PWLEN] = 0;
|
||
|
||
dwRetCode = gblpEapTable[dwEapIndex].RasEapInfo.RasEapBegin(
|
||
&pEapCb->pWorkBuffer,
|
||
&PppEapInput );
|
||
EncodePw( pEapCb->chSeed, pEapCb->szPassword );
|
||
ZeroMemory( awszPassword, sizeof(awszPassword) );
|
||
|
||
if ( dwRetCode == NO_ERROR )
|
||
{
|
||
pEapCb->dwEapIndex = dwEapIndex;
|
||
}
|
||
else
|
||
{
|
||
pEapCb->dwEapIndex = (DWORD)-1;
|
||
}
|
||
|
||
return( dwRetCode );
|
||
}
|
||
|
||
//**
|
||
//
|
||
// Call: EapDllEnd
|
||
//
|
||
// Returns: NO_ERROR - Success
|
||
// Non-zero returns - Failure
|
||
//
|
||
// Description: Called to end an EAP session for a certain type
|
||
//
|
||
//
|
||
DWORD
|
||
EapDllEnd(
|
||
EAPCB * pEapCb
|
||
)
|
||
{
|
||
DWORD dwRetCode = NO_ERROR;
|
||
|
||
EAP_TRACE1("EapDllEnd called for EAP Index %d", pEapCb->dwEapIndex );
|
||
|
||
if ( pEapCb->pWorkBuffer != NULL )
|
||
{
|
||
//
|
||
// On the server, pWorkBuffer must be NULL. IAS must call RasEapEnd.
|
||
//
|
||
|
||
if ( pEapCb->dwEapIndex != (DWORD)-1 )
|
||
{
|
||
dwRetCode = gblpEapTable[pEapCb->dwEapIndex].RasEapInfo.RasEapEnd(
|
||
pEapCb->pWorkBuffer );
|
||
}
|
||
|
||
pEapCb->pWorkBuffer = NULL;
|
||
}
|
||
|
||
if ( pEapCb->pEAPSendBuf != NULL )
|
||
{
|
||
LocalFree( pEapCb->pEAPSendBuf );
|
||
|
||
pEapCb->pEAPSendBuf = NULL;
|
||
pEapCb->cbEAPSendBuf = 0;
|
||
}
|
||
|
||
if ( pEapCb->pStateAttribute != NULL )
|
||
{
|
||
LocalFree( pEapCb->pStateAttribute );
|
||
|
||
pEapCb->pStateAttribute = NULL;
|
||
}
|
||
|
||
pEapCb->dwEapIndex = (DWORD)-1;
|
||
|
||
return( dwRetCode );
|
||
}
|
||
|
||
//**
|
||
//
|
||
// Call: EapDllWork
|
||
//
|
||
// Returns: NO_ERROR - Success
|
||
// Non-zero returns - Failure
|
||
//
|
||
// Description: Called to process an incomming packet or timeout etc
|
||
//
|
||
DWORD
|
||
EapDllWork(
|
||
IN EAPCB * pEapCb,
|
||
IN PPP_CONFIG* pReceiveBuf,
|
||
OUT PPP_CONFIG* pSendBuf,
|
||
IN DWORD cbSendBuf,
|
||
OUT PPPAP_RESULT* pResult,
|
||
IN PPPAP_INPUT* pInput
|
||
)
|
||
{
|
||
PPP_EAP_OUTPUT PppEapOutput;
|
||
PPP_EAP_INPUT PppEapInput;
|
||
DWORD dwRetCode;
|
||
CHAR * pChar = NULL;
|
||
|
||
EAP_TRACE1("EapDllWork called for EAP Type %d",
|
||
gblpEapTable[pEapCb->dwEapIndex].RasEapInfo.dwEapTypeId);
|
||
|
||
ZeroMemory( &PppEapOutput, sizeof( PppEapOutput ) );
|
||
PppEapOutput.dwSizeInBytes = sizeof( PppEapOutput );
|
||
|
||
ZeroMemory( &PppEapInput, sizeof( PppEapInput ) );
|
||
PppEapInput.dwSizeInBytes = sizeof( PPP_EAP_INPUT );
|
||
PppEapInput.fAuthenticator = pEapCb->fAuthenticator;
|
||
PppEapInput.hTokenImpersonateUser = pEapCb->hTokenImpersonateUser;
|
||
|
||
if ( pInput != NULL )
|
||
{
|
||
PppEapInput.fAuthenticationComplete = pInput->fAuthenticationComplete;
|
||
PppEapInput.dwAuthResultCode = pInput->dwAuthResultCode;
|
||
PppEapInput.fSuccessPacketReceived = pInput->fSuccessPacketReceived;
|
||
|
||
if ( pInput->fEapUIDataReceived )
|
||
{
|
||
//
|
||
// EapUIData.pEapUIData is allocated by rasman and freed by engine.
|
||
// raseap.c must not free it.
|
||
//
|
||
|
||
if ( pInput->EapUIData.dwContextId != pEapCb->dwUIInvocationId )
|
||
{
|
||
//
|
||
// Ignore this data received
|
||
//
|
||
|
||
EAP_TRACE("Out of date data received from UI" );
|
||
|
||
return( NO_ERROR );
|
||
}
|
||
|
||
PppEapInput.fDataReceivedFromInteractiveUI = TRUE;
|
||
|
||
PppEapInput.pDataFromInteractiveUI =
|
||
pInput->EapUIData.pEapUIData;
|
||
PppEapInput.dwSizeOfDataFromInteractiveUI =
|
||
pInput->EapUIData.dwSizeOfEapUIData;
|
||
|
||
}
|
||
}
|
||
|
||
dwRetCode = gblpEapTable[pEapCb->dwEapIndex].RasEapInfo.RasEapMakeMessage(
|
||
pEapCb->pWorkBuffer,
|
||
(PPP_EAP_PACKET *)pReceiveBuf,
|
||
(PPP_EAP_PACKET *)pSendBuf,
|
||
cbSendBuf,
|
||
&PppEapOutput,
|
||
&PppEapInput );
|
||
|
||
if ( dwRetCode != NO_ERROR )
|
||
{
|
||
switch( dwRetCode )
|
||
{
|
||
case ERROR_PPP_INVALID_PACKET:
|
||
|
||
EAP_TRACE("Silently discarding invalid EAP packet");
|
||
|
||
pResult->Action = APA_NoAction;
|
||
|
||
return( NO_ERROR );
|
||
|
||
default:
|
||
|
||
EAP_TRACE2("EapDLLMakeMessage for type %d returned %d",
|
||
gblpEapTable[pEapCb->dwEapIndex].RasEapInfo.dwEapTypeId,
|
||
dwRetCode );
|
||
break;
|
||
}
|
||
|
||
return( dwRetCode );
|
||
}
|
||
|
||
switch( PppEapOutput.Action )
|
||
{
|
||
case EAPACTION_NoAction:
|
||
|
||
pResult->Action = APA_NoAction;
|
||
EAP_TRACE( "EAP Dll returned Action=EAPACTION_NoAction" );
|
||
break;
|
||
|
||
case EAPACTION_Send:
|
||
|
||
pResult->Action = APA_Send;
|
||
EAP_TRACE( "EAP Dll returned Action=EAPACTION_Send" );
|
||
break;
|
||
|
||
case EAPACTION_Done:
|
||
case EAPACTION_SendAndDone:
|
||
|
||
if ( PppEapOutput.Action == EAPACTION_SendAndDone )
|
||
{
|
||
pResult->Action = APA_SendAndDone;
|
||
EAP_TRACE( "EAP Dll returned Action=EAPACTION_SendAndDone" );
|
||
}
|
||
else
|
||
{
|
||
pResult->Action = APA_Done;
|
||
EAP_TRACE( "EAP Dll returned Action=EAPACTION_Done" );
|
||
}
|
||
|
||
pResult->dwError = PppEapOutput.dwAuthResultCode;
|
||
pResult->pUserAttributes = PppEapOutput.pUserAttributes;
|
||
|
||
strcpy( pResult->szUserName, pEapCb->szIdentity );
|
||
|
||
break;
|
||
|
||
case EAPACTION_SendWithTimeout:
|
||
case EAPACTION_SendWithTimeoutInteractive:
|
||
case EAPACTION_Authenticate:
|
||
|
||
EAP_TRACE1( "EAP Dll returned disallowed Action=%d",
|
||
PppEapOutput.Action );
|
||
break;
|
||
|
||
default:
|
||
|
||
RTASSERT( FALSE );
|
||
EAP_TRACE1( "EAP Dll returned unknown Action=%d", PppEapOutput.Action );
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Check to see if EAP dll wants to bring up UI
|
||
//
|
||
|
||
if ( PppEapOutput.fInvokeInteractiveUI )
|
||
{
|
||
if ( pEapCb->fAuthenticator )
|
||
{
|
||
EAP_TRACE( "EAP Dll wants to bring up UI on the server side" );
|
||
|
||
return( ERROR_INTERACTIVE_MODE );
|
||
}
|
||
|
||
if ( PppEapOutput.pUIContextData != NULL )
|
||
{
|
||
pResult->InvokeEapUIData.dwSizeOfUIContextData =
|
||
PppEapOutput.dwSizeOfUIContextData;
|
||
|
||
pResult->InvokeEapUIData.pUIContextData
|
||
= LocalAlloc(LPTR, PppEapOutput.dwSizeOfUIContextData);
|
||
|
||
if ( pResult->InvokeEapUIData.pUIContextData == NULL )
|
||
{
|
||
return( ERROR_NOT_ENOUGH_MEMORY );
|
||
}
|
||
|
||
CopyMemory( pResult->InvokeEapUIData.pUIContextData,
|
||
PppEapOutput.pUIContextData,
|
||
pResult->InvokeEapUIData.dwSizeOfUIContextData );
|
||
}
|
||
else
|
||
{
|
||
pResult->InvokeEapUIData.pUIContextData = NULL;
|
||
pResult->InvokeEapUIData.dwSizeOfUIContextData = 0;
|
||
}
|
||
|
||
pResult->fInvokeEapUI = TRUE;
|
||
pEapCb->dwUIInvocationId = gbldwGuid++;
|
||
pResult->InvokeEapUIData.dwContextId = pEapCb->dwUIInvocationId;
|
||
pResult->InvokeEapUIData.dwEapTypeId =
|
||
gblpEapTable[pEapCb->dwEapIndex].RasEapInfo.dwEapTypeId;
|
||
|
||
EAP_TRACE( "EAP Dll wants to invoke interactive UI" );
|
||
}
|
||
|
||
pResult->dwEapTypeId = pEapCb->dwEapTypeToBeUsed;
|
||
pResult->fSaveUserData = PppEapOutput.fSaveUserData;
|
||
pResult->pUserData = PppEapOutput.pUserData;
|
||
pResult->dwSizeOfUserData = PppEapOutput.dwSizeOfUserData;
|
||
|
||
pResult->fSaveConnectionData = PppEapOutput.fSaveConnectionData;
|
||
pResult->SetCustomAuthData.pConnectionData =
|
||
PppEapOutput.pConnectionData;
|
||
pResult->SetCustomAuthData.dwSizeOfConnectionData =
|
||
PppEapOutput.dwSizeOfConnectionData;
|
||
|
||
return( dwRetCode );
|
||
}
|
||
|
||
//**
|
||
//
|
||
// Call: GetEapIndex
|
||
//
|
||
// Returns: NO_ERROR - Success
|
||
// Non-zero returns - Failure
|
||
//
|
||
// Description: Will return the index into gblpEapTable of the specified
|
||
// EAP type
|
||
//
|
||
DWORD
|
||
GetEapTypeIndex(
|
||
IN DWORD dwEapTypeId
|
||
)
|
||
{
|
||
DWORD dwIndex;
|
||
|
||
for ( dwIndex = 0; dwIndex < gbldwNumEapProtocols; dwIndex++ )
|
||
{
|
||
if ( gblpEapTable[dwIndex].RasEapInfo.dwEapTypeId == dwEapTypeId )
|
||
{
|
||
return( dwIndex );
|
||
}
|
||
}
|
||
|
||
return( (DWORD)-1 );
|
||
}
|
||
|
||
//**
|
||
//
|
||
// Call: MakeRequestAttributes
|
||
//
|
||
// Returns: NO_ERROR - Success
|
||
// Non-zero returns - Failure
|
||
//
|
||
// Description: Will begin the RADIUS/EAP dialog by sending the caller's
|
||
// identity to the RADIUS server.
|
||
//
|
||
DWORD
|
||
MakeRequestAttributes(
|
||
IN EAPCB * pEapCb,
|
||
IN PPP_CONFIG * pReceiveBuf
|
||
)
|
||
{
|
||
DWORD dwIndex = 0;
|
||
DWORD dwRetCode;
|
||
|
||
EAP_TRACE("Sending EAP packet to RADIUS/IAS");
|
||
|
||
if ( pEapCb->pUserAttributes != NULL )
|
||
{
|
||
RasAuthAttributeDestroy( pEapCb->pUserAttributes );
|
||
|
||
pEapCb->pUserAttributes = NULL;
|
||
}
|
||
|
||
//
|
||
// Allocate the appropriate amount + 1 for Identity + 1 more for EAP packet
|
||
// +1 for State attribute (if any).
|
||
//
|
||
|
||
if ( ( pEapCb->pUserAttributes = RasAuthAttributeCreate(
|
||
( pEapCb->pStateAttribute != NULL )
|
||
? 3
|
||
: 2 ) ) == NULL )
|
||
{
|
||
return( GetLastError() );
|
||
}
|
||
|
||
//
|
||
// Insert EAP Message
|
||
//
|
||
|
||
dwRetCode = RasAuthAttributeInsert( dwIndex++,
|
||
pEapCb->pUserAttributes,
|
||
raatEAPMessage,
|
||
FALSE,
|
||
WireToHostFormat16(pReceiveBuf->Length),
|
||
pReceiveBuf );
|
||
if ( dwRetCode != NO_ERROR )
|
||
{
|
||
RasAuthAttributeDestroy( pEapCb->pUserAttributes );
|
||
|
||
pEapCb->pUserAttributes = NULL;
|
||
|
||
return( dwRetCode );
|
||
}
|
||
|
||
//
|
||
// Insert username
|
||
//
|
||
|
||
dwRetCode = RasAuthAttributeInsert( dwIndex++,
|
||
pEapCb->pUserAttributes,
|
||
raatUserName,
|
||
FALSE,
|
||
strlen( pEapCb->szIdentity ),
|
||
pEapCb->szIdentity );
|
||
if ( dwRetCode != NO_ERROR )
|
||
{
|
||
RasAuthAttributeDestroy( pEapCb->pUserAttributes );
|
||
|
||
pEapCb->pUserAttributes = NULL;
|
||
|
||
return( dwRetCode );
|
||
}
|
||
|
||
//
|
||
// Insert State attribute if we have one
|
||
//
|
||
|
||
if ( pEapCb->pStateAttribute != NULL )
|
||
{
|
||
dwRetCode = RasAuthAttributeInsert(
|
||
dwIndex++,
|
||
pEapCb->pUserAttributes,
|
||
raatState,
|
||
FALSE,
|
||
pEapCb->cbStateAttribute,
|
||
pEapCb->pStateAttribute );
|
||
if ( dwRetCode != NO_ERROR )
|
||
{
|
||
RasAuthAttributeDestroy( pEapCb->pUserAttributes );
|
||
|
||
pEapCb->pUserAttributes = NULL;
|
||
|
||
return( dwRetCode );
|
||
}
|
||
}
|
||
|
||
return( NO_ERROR );
|
||
}
|
||
|
||
DWORD
|
||
EapGetCredentials(
|
||
VOID * pWorkBuf,
|
||
VOID ** ppCredentials)
|
||
{
|
||
EAPCB *pEapCb = (EAPCB *) pWorkBuf;
|
||
DWORD dwRetCode = ERROR_SUCCESS;
|
||
|
||
if( (NULL == pEapCb)
|
||
|| (NULL == ppCredentials))
|
||
{
|
||
return E_INVALIDARG;
|
||
}
|
||
|
||
if(NULL != gblpEapTable[pEapCb->dwEapIndex].RasEapGetCredentials)
|
||
{
|
||
//
|
||
// Invoke appropriate eap dll for credentials
|
||
//
|
||
dwRetCode =
|
||
gblpEapTable[pEapCb->dwEapIndex].RasEapGetCredentials(
|
||
pEapCb->dwEapTypeToBeUsed,
|
||
pEapCb->pWorkBuffer,
|
||
ppCredentials);
|
||
}
|
||
|
||
return dwRetCode;
|
||
}
|