You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
5602 lines
168 KiB
5602 lines
168 KiB
/********************************************************************/
|
|
/** Copyright(c) 1985-1997 Microsoft Corporation. **/
|
|
/********************************************************************/
|
|
|
|
//***
|
|
//
|
|
// Filename: eapchap.c
|
|
//
|
|
// Description: Will do MD5 CHAP for EAP. This module is a EAP wrapper
|
|
// around CHAP
|
|
//
|
|
// History: May 11,1997 NarenG Created original version.
|
|
//
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <ntlsa.h>
|
|
#include <ntmsv1_0.h>
|
|
#include <ntsamp.h>
|
|
#define SECURITY_WIN32
|
|
#include <security.h> // For GetUserNameExW
|
|
#include <crypt.h>
|
|
#include <windows.h>
|
|
#include <lmcons.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <rasman.h>
|
|
#include <pppcp.h>
|
|
#include <raserror.h>
|
|
#include <rtutils.h>
|
|
#include <md5.h>
|
|
#include <raseapif.h>
|
|
#include <eaptypeid.h>
|
|
#include <pppcp.h>
|
|
#define INCL_RASAUTHATTRIBUTES
|
|
#define INCL_PWUTIL
|
|
#define INCL_HOSTWIRE
|
|
#include <ppputil.h>
|
|
#include <raschap.h>
|
|
#include <wincrypt.h>
|
|
#include <wintrust.h>
|
|
#include <softpub.h>
|
|
#include <mscat.h>
|
|
#include <ezlogon.h>
|
|
#include "resource.h"
|
|
|
|
#define STRSAFE_NO_DEPRECATE
|
|
#include <strsafe.h>
|
|
|
|
|
|
|
|
#define EAPTYPE_MD5Challenge 4
|
|
//
|
|
// We need to move this definition to pppcp.h
|
|
//
|
|
#define VENDOR_MICROSOFT 311
|
|
|
|
|
|
//
|
|
// Various states that EAPMSCHAPv2 can be in.
|
|
//
|
|
#define EAPMSCHAPv2STATE enum tagEAPMSCHAPv2STATE
|
|
EAPMSCHAPv2STATE
|
|
{
|
|
EMV2_Initial,
|
|
EMV2_RequestSend,
|
|
EMV2_ResponseSend,
|
|
EMV2_CHAPAuthSuccess,
|
|
EMV2_CHAPAuthFail,
|
|
EMV2_Success,
|
|
EMV2_Failure
|
|
};
|
|
|
|
|
|
//
|
|
// These ids are pulled in from rasdlg. Need them for the
|
|
// change password dialog in case of winlogon scenario
|
|
//
|
|
#define DID_CP_ChangePassword2 109
|
|
#define CID_CP_EB_ConfirmPassword_RASDLG 1058
|
|
#define CID_CP_EB_OldPassword_RASDLG 1059
|
|
#define CID_CP_EB_Password_RASDLG 1060
|
|
|
|
|
|
//
|
|
// Reg Key for EAPMSCHAPv2
|
|
//
|
|
|
|
#define EAPMSCHAPv2_KEY "System\\CurrentControlSet\\Services\\Rasman\\PPP\\EAP\\26"
|
|
#define EAPMSCHAPv2_VAL_SERVER_CONFIG_DATA "ServerConfigData"
|
|
|
|
//
|
|
//
|
|
// Flags for EAPMSChapv2
|
|
//
|
|
//
|
|
|
|
/*
|
|
** SaveUid and password
|
|
*/
|
|
#define EAPMSCHAPv2_FLAG_SAVE_UID_PWD 0x00000001
|
|
/*
|
|
** Use Winlogon Credentials
|
|
*/
|
|
#define EAPMSCHAPv2_FLAG_USE_WINLOGON_CREDS 0x00000002
|
|
/*
|
|
** Allow Change password - server side only.
|
|
*/
|
|
#define EAPMSCHAPv2_FLAG_ALLOW_CHANGEPWD 0x00000004
|
|
/*
|
|
** MACHINE Auth is happening
|
|
*/
|
|
#define EAPMSCHAPv2_FLAG_MACHINE_AUTH 0x00000008
|
|
|
|
#define EAPMSCHAPv2_FLAG_CALLED_WITHIN_WINLOGON 0x00000010
|
|
|
|
#define EAPMSCHAPv2_FLAG_8021x 0x00000020
|
|
|
|
|
|
typedef struct _EAPMSCHAPv2_USER_PROPERTIES
|
|
{
|
|
DWORD dwVersion; //Version = 2
|
|
DWORD fFlags;
|
|
//This is a server config property. Tells the server
|
|
//how many retris are allowed
|
|
DWORD dwMaxRetries;
|
|
CHAR szUserName[UNLEN+1];
|
|
CHAR szPassword[PWLEN+1];
|
|
CHAR szDomain[DNLEN+1];
|
|
DWORD cbEncPassword; //Number of bytes in encrypted password
|
|
BYTE bEncPassword[1]; //Encrypted Password if any ...
|
|
}EAPMSCHAPv2_USER_PROPERTIES, *PEAPMSCHAPv2_USER_PROPERTIES;
|
|
//
|
|
// USER properties for EAPMSCHAPv2
|
|
//
|
|
typedef struct _EAPMSCHAPv2_USER_PROPERTIES_v1
|
|
{
|
|
DWORD dwVersion;
|
|
DWORD fFlags;
|
|
//This is a server config property. Tells the server
|
|
//how many retris are allowed
|
|
DWORD dwMaxRetries;
|
|
CHAR szUserName[UNLEN+1];
|
|
CHAR szPassword[PWLEN+1];
|
|
CHAR szDomain[DNLEN+1];
|
|
}EAPMSCHAPv2_USER_PROPERTIES_v1, *PEAPMSCHAPv2_USER_PROPERTIES_v1;
|
|
|
|
|
|
|
|
//
|
|
// CONNECTION properties for EAPMSCHAPv2
|
|
//
|
|
|
|
typedef struct _EAPMSCHAPv2_CONN_PROPERTIES
|
|
{
|
|
DWORD dwVersion;
|
|
//This is the only field for now. Maybe more will come in later.
|
|
DWORD fFlags;
|
|
}EAPMSCHAPv2_CONN_PROPERTIES, * PEAPMSCHAPv2_CONN_PROPERTIES;
|
|
|
|
|
|
//
|
|
// Interactive UI for EAPMSCHAPv2
|
|
//
|
|
|
|
// Flag for retry password ui
|
|
|
|
#define EAPMSCHAPv2_INTERACTIVE_UI_FLAG_RETRY 0x00000001
|
|
//
|
|
// flag indicating show the change password in case
|
|
// the old password is provided
|
|
#define EAPMSCHAPv2_INTERACTIVE_UI_FLAG_CHANGE_PWD 0x00000002
|
|
//
|
|
// flag indicating that change password was invoked in
|
|
// winlogon context
|
|
//
|
|
#define EAPMSCHAPv2_INTERACTIVE_UI_FLAG_CHANGE_PWD_WINLOGON 0x00000004
|
|
|
|
typedef struct _EAPMSCHAPv2_INTERACTIVE_UI
|
|
{
|
|
DWORD dwVersion;
|
|
DWORD fFlags;
|
|
EAPMSCHAPv2_USER_PROPERTIES UserProp;
|
|
CHAR szNewPassword[PWLEN+1];
|
|
}EAPMSCHAPv2_INTERACTIVE_UI, * PEAPMSCHAPv2_INTERACTIVE_UI;
|
|
|
|
|
|
#define EAPMSCHAPv2WB struct tagEAPMSCHAPv2WB
|
|
EAPMSCHAPv2WB
|
|
{
|
|
EAPMSCHAPv2STATE EapState;
|
|
DWORD fFlags;
|
|
DWORD dwInteractiveUIOperation;
|
|
BYTE IdToSend;
|
|
BYTE IdToExpect;
|
|
PEAPMSCHAPv2_INTERACTIVE_UI pUIContextData;
|
|
PEAPMSCHAPv2_USER_PROPERTIES pUserProp;
|
|
CHAR szOldPassword[PWLEN+1];
|
|
//We need to save this for auth purposes.
|
|
WCHAR wszRadiusUserName[UNLEN+DNLEN+1];
|
|
PEAPMSCHAPv2_CONN_PROPERTIES pConnProp;
|
|
CHAPWB * pwb;
|
|
RAS_AUTH_ATTRIBUTE * pUserAttributes;
|
|
DWORD dwAuthResultCode;
|
|
DWORD dwLSARetCode; //Return value from LSA
|
|
};
|
|
|
|
//
|
|
// This structure is shared between retry and
|
|
// logon dialog
|
|
//
|
|
typedef struct _EAPMSCHAPv2_LOGON_DIALOG
|
|
{
|
|
PEAPMSCHAPv2_USER_PROPERTIES pUserProp;
|
|
HWND hWndUserName;
|
|
HWND hWndPassword;
|
|
HWND hWndDomain;
|
|
HWND hWndSavePassword;
|
|
}EAPMSCHAPv2_LOGON_DIALOG, * PEAPMSCHAPv2_LOGON_DIALOG;
|
|
|
|
|
|
//
|
|
// This stuct is used for client config UI.
|
|
//
|
|
typedef struct _EAPMSCHAPv2_CLIENTCONFIG_DIALOG
|
|
{
|
|
PEAPMSCHAPv2_CONN_PROPERTIES pConnProp;
|
|
}EAPMSCHAPv2_CLIENTCONFIG_DIALOG, * PEAPMSCHAPv2_CLIENTCONFIG_DIALOG;
|
|
|
|
typedef struct _EAPMSCHAPv2_SERVERCONFIG_DIALOG
|
|
{
|
|
PEAPMSCHAPv2_USER_PROPERTIES pUserProp;
|
|
HWND hWndRetries;
|
|
}EAPMSCHAPv2_SERVERCONFIG_DIALOG, *PEAPMSCHAPv2_SERVERCONFIG_DIALOG;
|
|
|
|
typedef struct _EAPMSCHAPv2_CHANGEPWD_DIALOG
|
|
{
|
|
PEAPMSCHAPv2_INTERACTIVE_UI pInteractiveUIData;
|
|
HWND hWndNewPassword;
|
|
HWND hWndConfirmNewPassword;
|
|
HWND hWndOldPassword;
|
|
}EAPMSCHAPv2_CHANGEPWD_DIALOG, *PEAPMSCHAPv2_CHANGEPWD_DIALOG;
|
|
|
|
|
|
DWORD
|
|
AllocateUserDataWithEncPwd ( EAPMSCHAPv2WB * pEapwb, DATA_BLOB * pDBPassword );
|
|
|
|
DWORD
|
|
EapMSCHAPv2Initialize(
|
|
IN BOOL fInitialize
|
|
);
|
|
|
|
INT_PTR CALLBACK
|
|
LogonDialogProc(
|
|
IN HWND hWnd,
|
|
IN UINT unMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam
|
|
);
|
|
|
|
INT_PTR CALLBACK
|
|
RetryDialogProc(
|
|
IN HWND hWnd,
|
|
IN UINT unMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam
|
|
);
|
|
|
|
INT_PTR CALLBACK
|
|
ClientConfigDialogProc(
|
|
IN HWND hWnd,
|
|
IN UINT unMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam
|
|
);
|
|
|
|
INT_PTR CALLBACK
|
|
ServerConfigDialogProc(
|
|
IN HWND hWnd,
|
|
IN UINT unMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam
|
|
);
|
|
|
|
INT_PTR CALLBACK
|
|
ChangePasswordDialogProc(
|
|
IN HWND hWnd,
|
|
IN UINT unMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam
|
|
);
|
|
|
|
HINSTANCE
|
|
GetHInstance(
|
|
VOID
|
|
);
|
|
|
|
HINSTANCE
|
|
GetRasDlgDLLHInstance(
|
|
VOID
|
|
);
|
|
|
|
extern DWORD g_dwTraceIdChap;
|
|
|
|
|
|
DWORD
|
|
ReadUserData(
|
|
IN BYTE* pUserDataIn,
|
|
IN DWORD dwSizeOfUserDataIn,
|
|
OUT PEAPMSCHAPv2_USER_PROPERTIES* ppUserProp
|
|
);
|
|
|
|
|
|
DWORD
|
|
ReadConnectionData(
|
|
IN BOOL fWirelessConnection,
|
|
IN BYTE* pConnectionDataIn,
|
|
IN DWORD dwSizeOfConnectionDataIn,
|
|
OUT PEAPMSCHAPv2_CONN_PROPERTIES* ppConnProp
|
|
);
|
|
|
|
|
|
DWORD
|
|
ServerConfigDataIO(
|
|
IN BOOL fRead,
|
|
IN CHAR* pszMachineName,
|
|
IN OUT BYTE** ppData,
|
|
IN DWORD dwNumBytes
|
|
);
|
|
|
|
|
|
//**
|
|
//
|
|
// Call: MapEapInputToApInput
|
|
//
|
|
// Returns: NO_ERROR - Success
|
|
// Non-zero returns - Failure
|
|
//
|
|
// Description:
|
|
//
|
|
VOID
|
|
MapEapInputToApInput(
|
|
IN PPP_EAP_INPUT* pPppEapInput,
|
|
OUT PPPAP_INPUT * pInput
|
|
)
|
|
{
|
|
pInput->fServer = pPppEapInput->fAuthenticator;
|
|
pInput->APDataSize = 1;
|
|
pInput->fAuthenticationComplete = pPppEapInput->fAuthenticationComplete;
|
|
pInput->dwAuthResultCode = pPppEapInput->dwAuthResultCode;
|
|
pInput->dwAuthError = NO_ERROR;
|
|
pInput->pUserAttributes = NULL;
|
|
pInput->pAttributesFromAuthenticator= pPppEapInput->pUserAttributes;
|
|
pInput->fSuccessPacketReceived = pPppEapInput->fSuccessPacketReceived;
|
|
pInput->dwInitialPacketId = pPppEapInput->bInitialId;
|
|
|
|
//
|
|
// These are used only for MS-CHAP
|
|
//
|
|
|
|
pInput->pszOldPassword = "";
|
|
pInput->dwRetries = 0;
|
|
}
|
|
|
|
|
|
|
|
//**
|
|
//
|
|
// Call: MapApInputToEapInput
|
|
//
|
|
// Returns: NONE
|
|
//
|
|
//
|
|
// Description: $TODO: Put in the correct mapping here
|
|
//
|
|
VOID
|
|
MapApResultToEapOutput(
|
|
IN PPPAP_RESULT * pApResult,
|
|
OUT PPP_EAP_OUTPUT* pPppEapOutput
|
|
)
|
|
{
|
|
//
|
|
//Action is already taken care of. So dont set it here
|
|
//
|
|
pPppEapOutput->dwAuthResultCode = pApResult->dwError;
|
|
pPppEapOutput->pUserAttributes = pApResult->pUserAttributes;
|
|
}
|
|
|
|
|
|
|
|
//**
|
|
//
|
|
// Call: EapChapBeginCommon
|
|
//
|
|
// Returns: NO_ERROR - Success
|
|
// Non-zero returns - Failure
|
|
//
|
|
// Description: Wrapper around ChapBegin
|
|
//
|
|
DWORD
|
|
EapChapBeginCommon(
|
|
IN DWORD dwEapType,
|
|
IN BOOL fUseWinLogon,
|
|
IN DWORD dwRetries,
|
|
IN EAPMSCHAPv2WB * pWB,
|
|
OUT VOID ** ppWorkBuffer,
|
|
IN PPP_EAP_INPUT * pPppEapInput
|
|
)
|
|
{
|
|
PPPAP_INPUT Input;
|
|
DWORD dwRetCode;
|
|
PPP_EAP_INPUT* pInput = (PPP_EAP_INPUT* )pPppEapInput;
|
|
BYTE bMD5 = 0x05;
|
|
BYTE bMSChapNew = 0x81;
|
|
BYTE bInvalid = 0xFF;
|
|
WCHAR * pWchar = NULL;
|
|
CHAR szDomain[DNLEN+1];
|
|
CHAR szUserName[UNLEN+1];
|
|
CHAR szPassword[PWLEN+1];
|
|
PPPAP_RESULT ApResult;
|
|
|
|
|
|
|
|
TRACE("EapChapBeginCommon");
|
|
|
|
ZeroMemory( &Input, sizeof( PPPAP_INPUT ) );
|
|
ZeroMemory( szDomain, sizeof( szDomain ) );
|
|
ZeroMemory( szUserName, sizeof( szUserName ) );
|
|
ZeroMemory( szPassword, sizeof( szPassword ) );
|
|
ZeroMemory( &ApResult, sizeof(ApResult) );
|
|
|
|
MapEapInputToApInput( pPppEapInput, &Input );
|
|
|
|
if ( dwEapType == EAPTYPE_MD5Challenge )
|
|
{
|
|
Input.pAPData = &bMD5;
|
|
}
|
|
else if ( dwEapType == PPP_EAP_MSCHAPv2 )
|
|
{
|
|
Input.pAPData = &bMSChapNew;
|
|
}
|
|
else
|
|
//Set the value to invalid type and let ChapBegin Fail
|
|
Input.pAPData = &bInvalid;
|
|
|
|
//
|
|
// If we dont have to use winlogon or we have to do machine auth
|
|
//
|
|
|
|
if ( !fUseWinLogon ||
|
|
( pPppEapInput->fFlags & RAS_EAP_FLAG_MACHINE_AUTH )
|
|
)
|
|
{
|
|
if ( NULL != pPppEapInput->pwszIdentity )
|
|
{
|
|
pWchar = wcschr( pPppEapInput->pwszIdentity, L'\\' );
|
|
|
|
if ( pWchar == NULL )
|
|
{
|
|
if ( 0 == WideCharToMultiByte(
|
|
CP_ACP,
|
|
0,
|
|
pPppEapInput->pwszIdentity,
|
|
-1,
|
|
szUserName,
|
|
UNLEN + 1,
|
|
NULL,
|
|
NULL ) )
|
|
{
|
|
return( GetLastError() );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*pWchar = 0;
|
|
|
|
if ( 0 == WideCharToMultiByte(
|
|
CP_ACP,
|
|
0,
|
|
pPppEapInput->pwszIdentity,
|
|
-1,
|
|
szDomain,
|
|
DNLEN + 1,
|
|
NULL,
|
|
NULL ) )
|
|
{
|
|
return( GetLastError() );
|
|
}
|
|
|
|
*pWchar = L'\\';
|
|
|
|
if ( 0 == WideCharToMultiByte(
|
|
CP_ACP,
|
|
0,
|
|
pWchar + 1,
|
|
-1,
|
|
szUserName,
|
|
UNLEN + 1,
|
|
NULL,
|
|
NULL ) )
|
|
{
|
|
return( GetLastError() );
|
|
}
|
|
}
|
|
}
|
|
if ( dwEapType == EAPTYPE_MD5Challenge )
|
|
{
|
|
if ( NULL != pPppEapInput->pwszPassword )
|
|
{
|
|
if ( 0 == WideCharToMultiByte(
|
|
CP_ACP,
|
|
0,
|
|
pPppEapInput->pwszPassword,
|
|
-1,
|
|
szPassword,
|
|
PWLEN + 1,
|
|
NULL,
|
|
NULL ) )
|
|
{
|
|
return( GetLastError() );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// if this is not a server then copy the user props
|
|
if ( !pPppEapInput->fAuthenticator )
|
|
{
|
|
strncpy( szPassword, pWB->pUserProp->szPassword, PWLEN );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
if ( !pPppEapInput->fAuthenticator &&
|
|
!(pPppEapInput->fFlags & RAS_EAP_FLAG_MACHINE_AUTH )
|
|
)
|
|
{
|
|
//Set up the Luid for the logged on user
|
|
TOKEN_STATISTICS TokenStats;
|
|
DWORD TokenStatsSize;
|
|
if (!GetTokenInformation(pPppEapInput->hTokenImpersonateUser,
|
|
TokenStatistics,
|
|
&TokenStats,
|
|
sizeof(TOKEN_STATISTICS),
|
|
&TokenStatsSize))
|
|
{
|
|
dwRetCode = GetLastError();
|
|
return dwRetCode;
|
|
}
|
|
//
|
|
// "This will tell us if there was an API failure
|
|
// (means our buffer wasn't big enough)"
|
|
//
|
|
if (TokenStatsSize > sizeof(TOKEN_STATISTICS))
|
|
{
|
|
dwRetCode = GetLastError();
|
|
return dwRetCode;
|
|
}
|
|
|
|
Input.Luid = TokenStats.AuthenticationId;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
Input.dwRetries = dwRetries;
|
|
Input.pszDomain = szDomain;
|
|
Input.pszUserName = szUserName;
|
|
Input.pszPassword = szPassword;
|
|
|
|
if ( (pPppEapInput->fFlags & RAS_EAP_FLAG_MACHINE_AUTH) )
|
|
Input.fConfigInfo |= PPPCFG_MachineAuthentication;
|
|
|
|
|
|
dwRetCode = ChapBegin( ppWorkBuffer, &Input );
|
|
if ( NO_ERROR != dwRetCode )
|
|
return dwRetCode;
|
|
|
|
RtlSecureZeroMemory( szPassword, sizeof( szPassword ) );
|
|
if ( ! (Input.fServer) )
|
|
{
|
|
//if this is a client then call ChapMakeMessage to
|
|
//move the state from Initial to WaitForChallange
|
|
dwRetCode = ChapMakeMessage(
|
|
*ppWorkBuffer,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
&ApResult,
|
|
&Input );
|
|
}
|
|
|
|
|
|
return( dwRetCode );
|
|
}
|
|
|
|
DWORD EapMSChapv2Begin (
|
|
OUT VOID ** ppWorkBuffer,
|
|
IN PPP_EAP_INPUT * pPppEapInput
|
|
)
|
|
{
|
|
DWORD dwRetCode = NO_ERROR;
|
|
EAPMSCHAPv2WB * pWB = NULL;
|
|
|
|
TRACE("EapChapBeginMSChapV2");
|
|
|
|
//
|
|
// Allocate a work buffer here and send it back as our
|
|
// work buffer.
|
|
//
|
|
pWB = (EAPMSCHAPv2WB *)LocalAlloc(LPTR, sizeof(EAPMSCHAPv2WB) );
|
|
if ( NULL == pWB )
|
|
{
|
|
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto done;
|
|
}
|
|
|
|
if ( (pPppEapInput->fFlags & RAS_EAP_FLAG_MACHINE_AUTH) )
|
|
{
|
|
pWB->fFlags |= EAPMSCHAPv2_FLAG_MACHINE_AUTH;
|
|
}
|
|
if ( pPppEapInput->fAuthenticator )
|
|
{
|
|
#if 0
|
|
dwRetCode = ServerConfigDataIO(
|
|
TRUE /* fRead */,
|
|
NULL /* pwszMachineName */,
|
|
(BYTE**)&(pWB->pUserProp),
|
|
0);
|
|
#endif
|
|
|
|
//
|
|
// pConnectionData should have the config data which
|
|
// was supplied in InvokeConfigUI2 routine.
|
|
//
|
|
if( (NULL == pPppEapInput->pConnectionData)
|
|
|| (pPppEapInput->dwSizeOfConnectionData <
|
|
sizeof(EAPMSCHAPv2_USER_PROPERTIES)))
|
|
{
|
|
pWB->pUserProp = LocalAlloc(LPTR,
|
|
sizeof(EAPMSCHAPv2_USER_PROPERTIES));
|
|
|
|
if(NULL == pWB->pUserProp)
|
|
{
|
|
dwRetCode = E_OUTOFMEMORY;
|
|
goto done;
|
|
}
|
|
|
|
pWB->pUserProp->dwVersion = 1;
|
|
//Set Defaults here
|
|
pWB->pUserProp->dwMaxRetries = 2;
|
|
pWB->pUserProp->fFlags |= EAPMSCHAPv2_FLAG_ALLOW_CHANGEPWD;
|
|
|
|
}
|
|
else
|
|
{
|
|
pWB->pUserProp = (EAPMSCHAPv2_USER_PROPERTIES *)
|
|
LocalAlloc(LPTR, pPppEapInput->dwSizeOfConnectionData);
|
|
|
|
if(NULL == pWB->pUserProp)
|
|
{
|
|
dwRetCode = E_OUTOFMEMORY;
|
|
goto done;
|
|
}
|
|
|
|
CopyMemory(pWB->pUserProp,
|
|
pPppEapInput->pConnectionData,
|
|
pPppEapInput->dwSizeOfConnectionData);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
dwRetCode = ReadUserData( pPppEapInput->pUserData,
|
|
pPppEapInput->dwSizeOfUserData,
|
|
&(pWB->pUserProp)
|
|
);
|
|
}
|
|
|
|
if ( ERROR_SUCCESS != dwRetCode )
|
|
{
|
|
goto done;
|
|
}
|
|
//
|
|
// Check to see if we got password field set. If so, we use that password
|
|
// It means that the user has chosen to save the password. If not,
|
|
// szpassword field should be empty.
|
|
if ( !( pPppEapInput->fFlags & RAS_EAP_FLAG_8021X_AUTH ) )
|
|
{
|
|
|
|
if ( pPppEapInput->pwszPassword &&
|
|
*(pPppEapInput->pwszPassword) &&
|
|
wcscmp (pPppEapInput->pwszPassword, L"****************")
|
|
)
|
|
{
|
|
WideCharToMultiByte( CP_ACP,
|
|
0,
|
|
pPppEapInput->pwszPassword ,
|
|
-1,
|
|
pWB->pUserProp->szPassword,
|
|
PWLEN+1,
|
|
NULL,
|
|
NULL );
|
|
|
|
}
|
|
}
|
|
dwRetCode = ReadConnectionData ( ( pPppEapInput->fFlags & RAS_EAP_FLAG_8021X_AUTH ),
|
|
pPppEapInput->pConnectionData,
|
|
pPppEapInput->dwSizeOfConnectionData,
|
|
&(pWB->pConnProp )
|
|
);
|
|
if ( ERROR_SUCCESS != dwRetCode )
|
|
{
|
|
goto done;
|
|
}
|
|
|
|
|
|
dwRetCode = EapChapBeginCommon( PPP_EAP_MSCHAPv2,
|
|
(pWB->pConnProp->fFlags & EAPMSCHAPv2_FLAG_USE_WINLOGON_CREDS ),
|
|
(pWB->pUserProp->dwMaxRetries ),
|
|
pWB,
|
|
&pWB->pwb,
|
|
pPppEapInput
|
|
);
|
|
if ( NO_ERROR != dwRetCode )
|
|
{
|
|
goto done;
|
|
}
|
|
if ( pPppEapInput->pwszIdentity )
|
|
{
|
|
wcsncpy ( pWB->wszRadiusUserName, pPppEapInput->pwszIdentity, UNLEN+DNLEN );
|
|
}
|
|
|
|
*ppWorkBuffer = (PVOID)pWB;
|
|
|
|
done:
|
|
if ( NO_ERROR != dwRetCode )
|
|
{
|
|
if ( pWB )
|
|
{
|
|
LocalFree(pWB->pUserProp);
|
|
LocalFree(pWB->pConnProp);
|
|
LocalFree(pWB);
|
|
}
|
|
}
|
|
|
|
return dwRetCode;
|
|
}
|
|
|
|
|
|
DWORD CheckCallerIdentity ( HANDLE hWVTStateData )
|
|
{
|
|
DWORD dwRetCode = ERROR_ACCESS_DENIED;
|
|
PCRYPT_PROVIDER_DATA pProvData = NULL;
|
|
PCCERT_CHAIN_CONTEXT pChainContext = NULL;
|
|
PCRYPT_PROVIDER_SGNR pProvSigner = NULL;
|
|
CERT_CHAIN_POLICY_PARA chainpolicyparams;
|
|
CERT_CHAIN_POLICY_STATUS chainpolicystatus;
|
|
|
|
if (!(pProvData = WTHelperProvDataFromStateData(hWVTStateData)))
|
|
{
|
|
goto done;
|
|
}
|
|
|
|
if (!(pProvSigner = WTHelperGetProvSignerFromChain(pProvData, 0, FALSE, 0)))
|
|
{
|
|
goto done;
|
|
}
|
|
|
|
chainpolicyparams.cbSize = sizeof(CERT_CHAIN_POLICY_PARA);
|
|
|
|
//
|
|
//
|
|
// We do want to test for microsoft test root flags. and dont care
|
|
// for revocation flags...
|
|
//
|
|
chainpolicyparams.dwFlags = CERT_CHAIN_POLICY_ALLOW_TESTROOT_FLAG |
|
|
CERT_CHAIN_POLICY_TRUST_TESTROOT_FLAG |
|
|
CERT_CHAIN_POLICY_IGNORE_ALL_REV_UNKNOWN_FLAGS;
|
|
|
|
pChainContext = pProvSigner->pChainContext;
|
|
|
|
|
|
if (!CertVerifyCertificateChainPolicy (
|
|
CERT_CHAIN_POLICY_MICROSOFT_ROOT,
|
|
pChainContext,
|
|
&chainpolicyparams,
|
|
&chainpolicystatus))
|
|
{
|
|
goto done;
|
|
}
|
|
else
|
|
{
|
|
if ( S_OK == chainpolicystatus.dwError )
|
|
{
|
|
dwRetCode = NO_ERROR;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Check the base policy to see if this
|
|
// is a Microsoft test root
|
|
//
|
|
if (!CertVerifyCertificateChainPolicy (
|
|
CERT_CHAIN_POLICY_BASE,
|
|
pChainContext,
|
|
&chainpolicyparams,
|
|
&chainpolicystatus))
|
|
{
|
|
goto done;
|
|
}
|
|
else
|
|
{
|
|
if ( S_OK == chainpolicystatus.dwError )
|
|
{
|
|
dwRetCode = NO_ERROR;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
done:
|
|
return dwRetCode;
|
|
}
|
|
|
|
|
|
DWORD VerifyCallerTrust ( LPWSTR lpszCaller )
|
|
{
|
|
DWORD dwRetCode = NO_ERROR;
|
|
HRESULT hr = S_OK;
|
|
WINTRUST_DATA wtData;
|
|
WINTRUST_FILE_INFO wtFileInfo;
|
|
WINTRUST_CATALOG_INFO wtCatalogInfo;
|
|
BOOL fRet = FALSE;
|
|
HCATADMIN hCATAdmin = NULL;
|
|
|
|
GUID guidPublishedSoftware = WINTRUST_ACTION_GENERIC_VERIFY_V2;
|
|
//
|
|
// Following GUID is Mirosoft's Catalog System Root
|
|
//
|
|
GUID guidCatSystemRoot = { 0xf750e6c3, 0x38ee, 0x11d1,{ 0x85, 0xe5, 0x0, 0xc0, 0x4f, 0xc2, 0x95, 0xee } };
|
|
HCATINFO hCATInfo = NULL;
|
|
CATALOG_INFO CatInfo;
|
|
HANDLE hFile = INVALID_HANDLE_VALUE;
|
|
BYTE bHash[40];
|
|
DWORD cbHash = 40;
|
|
|
|
if ( NULL == lpszCaller )
|
|
{
|
|
dwRetCode = ERROR_INVALID_PARAMETER;
|
|
goto done;
|
|
}
|
|
|
|
//
|
|
//
|
|
// Try and see if WinVerifyTrust will verify
|
|
// the signature as a standalone file
|
|
//
|
|
//
|
|
|
|
ZeroMemory ( &wtData, sizeof(wtData) );
|
|
ZeroMemory ( &wtFileInfo, sizeof(wtFileInfo) );
|
|
|
|
|
|
wtData.cbStruct = sizeof(wtData);
|
|
wtData.dwUIChoice = WTD_UI_NONE;
|
|
wtData.fdwRevocationChecks = WTD_REVOKE_NONE;
|
|
wtData.dwStateAction = WTD_STATEACTION_VERIFY;
|
|
wtData.dwUnionChoice = WTD_CHOICE_FILE;
|
|
wtData.pFile = &wtFileInfo;
|
|
|
|
wtFileInfo.cbStruct = sizeof( wtFileInfo );
|
|
wtFileInfo.pcwszFilePath = lpszCaller;
|
|
|
|
hr = WinVerifyTrust ( NULL,
|
|
&guidPublishedSoftware,
|
|
&wtData
|
|
);
|
|
|
|
if ( ERROR_SUCCESS == hr )
|
|
{
|
|
//
|
|
// Check to see if this is indeed microsoft
|
|
// signed caller
|
|
//
|
|
dwRetCode = CheckCallerIdentity( wtData.hWVTStateData);
|
|
wtData.dwStateAction = WTD_STATEACTION_CLOSE;
|
|
WinVerifyTrust(NULL, &guidPublishedSoftware, &wtData);
|
|
goto done;
|
|
|
|
}
|
|
|
|
wtData.dwStateAction = WTD_STATEACTION_CLOSE;
|
|
WinVerifyTrust(NULL, &guidPublishedSoftware, &wtData);
|
|
|
|
//
|
|
// We did not find the file was signed.
|
|
// So check the system catalog to see if
|
|
// the file is in the catalog and the catalog
|
|
// is signed
|
|
//
|
|
|
|
//
|
|
// Open the file
|
|
//
|
|
hFile = CreateFileW ( lpszCaller,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
|
|
|
|
if ( INVALID_HANDLE_VALUE == hFile )
|
|
{
|
|
dwRetCode = GetLastError();
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
fRet = CryptCATAdminAcquireContext( &hCATAdmin,
|
|
&guidCatSystemRoot,
|
|
0
|
|
);
|
|
if ( !fRet )
|
|
{
|
|
dwRetCode = GetLastError();
|
|
goto done;
|
|
}
|
|
|
|
//
|
|
// Get the hash of the file here
|
|
//
|
|
|
|
fRet = CryptCATAdminCalcHashFromFileHandle ( hFile,
|
|
&cbHash,
|
|
bHash,
|
|
0
|
|
);
|
|
|
|
if ( !fRet )
|
|
{
|
|
dwRetCode = GetLastError();
|
|
goto done;
|
|
}
|
|
|
|
ZeroMemory(&CatInfo, sizeof(CatInfo));
|
|
CatInfo.cbStruct = sizeof(CatInfo);
|
|
|
|
ZeroMemory( &wtCatalogInfo, sizeof(wtCatalogInfo) );
|
|
|
|
wtData.dwUnionChoice = WTD_CHOICE_CATALOG;
|
|
wtData.dwStateAction = WTD_STATEACTION_VERIFY;
|
|
wtData.pCatalog = &wtCatalogInfo;
|
|
|
|
wtCatalogInfo.cbStruct = sizeof(wtCatalogInfo);
|
|
|
|
wtCatalogInfo.hMemberFile = hFile;
|
|
|
|
wtCatalogInfo.pbCalculatedFileHash = bHash;
|
|
wtCatalogInfo.cbCalculatedFileHash = cbHash;
|
|
|
|
|
|
while ( ( hCATInfo = CryptCATAdminEnumCatalogFromHash ( hCATAdmin,
|
|
bHash,
|
|
cbHash,
|
|
0,
|
|
&hCATInfo
|
|
)
|
|
)
|
|
)
|
|
{
|
|
if (!(CryptCATCatalogInfoFromContext(hCATInfo, &CatInfo, 0)))
|
|
{
|
|
// should do something (??)
|
|
continue;
|
|
}
|
|
|
|
wtCatalogInfo.pcwszCatalogFilePath = CatInfo.wszCatalogFile;
|
|
|
|
hr = WinVerifyTrust ( NULL,
|
|
&guidPublishedSoftware,
|
|
&wtData
|
|
);
|
|
|
|
if ( ERROR_SUCCESS == hr )
|
|
{
|
|
//
|
|
// Verify that this file is trusted
|
|
//
|
|
|
|
dwRetCode = CheckCallerIdentity( wtData.hWVTStateData);
|
|
wtData.dwStateAction = WTD_STATEACTION_CLOSE;
|
|
WinVerifyTrust(NULL, &guidPublishedSoftware, &wtData);
|
|
|
|
goto done;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// File not found in any of the catalogs
|
|
//
|
|
dwRetCode = ERROR_ACCESS_DENIED;
|
|
|
|
|
|
|
|
|
|
done:
|
|
|
|
if ( hCATInfo )
|
|
{
|
|
CryptCATAdminReleaseCatalogContext( hCATAdmin, hCATInfo, 0 );
|
|
}
|
|
if ( hCATAdmin )
|
|
{
|
|
CryptCATAdminReleaseContext( hCATAdmin, 0 );
|
|
}
|
|
if ( hFile )
|
|
{
|
|
CloseHandle(hFile);
|
|
}
|
|
return dwRetCode;
|
|
}
|
|
|
|
#define TEST_VIVEKK_PRIVATE 0
|
|
DWORD
|
|
EapChapBegin(
|
|
OUT VOID ** ppWorkBuffer,
|
|
IN PPP_EAP_INPUT * pPppEapInput
|
|
)
|
|
{
|
|
void* callersAddress;
|
|
DWORD dwRetCode;
|
|
MEMORY_BASIC_INFORMATION mbi;
|
|
SIZE_T nbyte;
|
|
DWORD nchar;
|
|
wchar_t callersModule[MAX_PATH + 1];
|
|
#ifdef TEST_VIVEKK_PRIVATE
|
|
static BOOL fCallerTrusted = TRUE;
|
|
#else
|
|
static BOOL fCallerTrusted = FALSE;
|
|
#endif
|
|
//
|
|
//Verify the caller first and then proceed with
|
|
//other business
|
|
//
|
|
|
|
if ( !fCallerTrusted )
|
|
{
|
|
//
|
|
//First Verify the caller and then
|
|
//proceed with initialization
|
|
//
|
|
|
|
callersAddress = _ReturnAddress();
|
|
|
|
nbyte = VirtualQuery(
|
|
callersAddress,
|
|
&mbi,
|
|
sizeof(mbi)
|
|
);
|
|
|
|
if (nbyte < sizeof(mbi))
|
|
{
|
|
dwRetCode = ERROR_ACCESS_DENIED;
|
|
goto done;
|
|
}
|
|
|
|
nchar = GetModuleFileNameW(
|
|
(HMODULE)(mbi.AllocationBase),
|
|
callersModule,
|
|
MAX_PATH
|
|
);
|
|
|
|
if (nchar == 0)
|
|
{
|
|
dwRetCode = GetLastError();
|
|
goto done;
|
|
}
|
|
dwRetCode = VerifyCallerTrust(callersModule);
|
|
if ( NO_ERROR != dwRetCode )
|
|
{
|
|
goto done;
|
|
}
|
|
fCallerTrusted = TRUE;
|
|
}
|
|
|
|
|
|
dwRetCode = EapChapBeginCommon( EAPTYPE_MD5Challenge,
|
|
FALSE,
|
|
0,
|
|
NULL,
|
|
ppWorkBuffer,
|
|
pPppEapInput
|
|
);
|
|
done:
|
|
return dwRetCode;
|
|
}
|
|
|
|
DWORD
|
|
EapMSChapv2End ( IN VOID * pWorkBuf )
|
|
{
|
|
DWORD dwRetCode = NO_ERROR;
|
|
EAPMSCHAPv2WB * pWB = (EAPMSCHAPv2WB *)pWorkBuf;
|
|
|
|
TRACE("EapMSChapv2End");
|
|
|
|
if ( pWB )
|
|
{
|
|
dwRetCode = ChapEnd( pWB->pwb );
|
|
|
|
LocalFree ( pWB->pUIContextData );
|
|
LocalFree ( pWB->pUserProp );
|
|
LocalFree ( pWB->pConnProp );
|
|
if ( pWB->pUserAttributes )
|
|
RasAuthAttributeDestroy(pWB->pUserAttributes);
|
|
LocalFree( pWB );
|
|
}
|
|
|
|
return dwRetCode;
|
|
}
|
|
|
|
//**
|
|
//
|
|
// Call: EapChapEnd
|
|
//
|
|
// Returns: NO_ERROR - Success
|
|
// Non-zero returns - Failure
|
|
//
|
|
// Description: Wrapper around ChapEnd.
|
|
//
|
|
DWORD
|
|
EapChapEnd(
|
|
IN VOID* pWorkBuf
|
|
)
|
|
{
|
|
|
|
return( ChapEnd( pWorkBuf ) );
|
|
}
|
|
|
|
DWORD
|
|
GetIdentityFromUserName (
|
|
LPSTR lpszUserName,
|
|
LPSTR lpszDomain,
|
|
LPWSTR * ppwszIdentity
|
|
)
|
|
{
|
|
DWORD dwRetCode = NO_ERROR;
|
|
DWORD dwNumBytes;
|
|
|
|
//domain+ user + '\' + null
|
|
dwNumBytes = (strlen(lpszUserName) + strlen(lpszDomain) + 1 + 1) * sizeof(WCHAR);
|
|
*ppwszIdentity = LocalAlloc ( LPTR, dwNumBytes);
|
|
if ( NULL == *ppwszIdentity )
|
|
{
|
|
dwRetCode = ERROR_OUTOFMEMORY;
|
|
goto LDone;
|
|
}
|
|
|
|
if ( *lpszDomain )
|
|
{
|
|
MultiByteToWideChar( CP_ACP,
|
|
0,
|
|
lpszDomain,
|
|
-1,
|
|
*ppwszIdentity,
|
|
dwNumBytes/sizeof(WCHAR) );
|
|
|
|
wcscat( *ppwszIdentity, L"\\");
|
|
}
|
|
|
|
MultiByteToWideChar( CP_ACP,
|
|
0,
|
|
lpszUserName,
|
|
-1,
|
|
*lpszDomain? *ppwszIdentity + strlen(lpszDomain) + 1:*ppwszIdentity,
|
|
dwNumBytes/sizeof(WCHAR) - strlen(lpszDomain) );
|
|
|
|
LDone:
|
|
return dwRetCode;
|
|
}
|
|
// Convert a number to a hex representation.
|
|
BYTE num2Digit(BYTE num)
|
|
{
|
|
return (num < 10) ? num + '0' : num + ('A' - 10);
|
|
}
|
|
//
|
|
DWORD
|
|
ChangePassword ( IN OUT EAPMSCHAPv2WB * pEapwb,
|
|
PPP_EAP_OUTPUT* pEapOutput,
|
|
PPPAP_INPUT* pApInput)
|
|
{
|
|
DWORD dwRetCode = NO_ERROR;
|
|
RAS_AUTH_ATTRIBUTE * pAttribute = NULL;
|
|
WCHAR wszUserName[UNLEN + DNLEN +1] = {0};
|
|
LPWSTR lpwszHashUserName = NULL;
|
|
CHAR szHashUserName[UNLEN+1] = {0};
|
|
WCHAR wszDomainName[DNLEN +1] = {0};
|
|
PBYTE pbEncHash = NULL;
|
|
BYTE bEncPassword[550] = {0};
|
|
HANDLE hAttribute;
|
|
int i;
|
|
|
|
|
|
//
|
|
// check to see if change password attribute is present in
|
|
// User Attributes
|
|
//
|
|
|
|
pAttribute = RasAuthAttributeGetVendorSpecific(
|
|
VENDOR_MICROSOFT,
|
|
MS_VSA_CHAP2_CPW,
|
|
pEapOutput->pUserAttributes );
|
|
|
|
if ( NULL == pAttribute )
|
|
{
|
|
TRACE ( "no change password attribute");
|
|
|
|
goto LDone;
|
|
}
|
|
|
|
//Get encrypted Hash
|
|
pbEncHash = (PBYTE)pAttribute->Value + 8;
|
|
|
|
//
|
|
// Get the user name and domain name
|
|
//
|
|
|
|
pAttribute = RasAuthAttributeGet ( raatUserName,
|
|
pEapOutput->pUserAttributes
|
|
);
|
|
|
|
if ( NULL == pAttribute )
|
|
{
|
|
//Need a better way of sending error
|
|
TRACE ( "UserName missing");
|
|
dwRetCode = ERROR_AUTHENTICATION_FAILURE;
|
|
goto LDone;
|
|
}
|
|
|
|
//
|
|
// Convert the username to unicode
|
|
//
|
|
|
|
MultiByteToWideChar( CP_ACP,
|
|
0,
|
|
pAttribute->Value,
|
|
pAttribute->dwLength,
|
|
wszUserName,
|
|
UNLEN + DNLEN + 1 );
|
|
|
|
|
|
//
|
|
// Get the hash user name and domain name
|
|
//
|
|
|
|
lpwszHashUserName = wcschr ( wszUserName, '\\' );
|
|
if ( lpwszHashUserName )
|
|
{
|
|
wcsncpy ( wszDomainName, wszUserName, lpwszHashUserName - wszUserName );
|
|
|
|
lpwszHashUserName ++;
|
|
}
|
|
else
|
|
{
|
|
lpwszHashUserName = wszUserName;
|
|
}
|
|
/*
|
|
//Convert hash user name to multibyte
|
|
WideCharToMultiByte( CP_ACP,
|
|
0,
|
|
lpwszHashUserName,
|
|
-1,
|
|
szHashUserName,
|
|
DNLEN+1,
|
|
NULL,
|
|
NULL );
|
|
*/
|
|
//
|
|
// Get encrypted password
|
|
//
|
|
|
|
pAttribute = RasAuthAttributeGetFirst( raatVendorSpecific,
|
|
pEapOutput->pUserAttributes,
|
|
&hAttribute );
|
|
|
|
while ( pAttribute )
|
|
{
|
|
if ( *((PBYTE)pAttribute->Value + 4) == MS_VSA_CHAP_NT_Enc_PW )
|
|
{
|
|
//
|
|
// check to see the sequence number and copy it
|
|
// proper place in our buffer.
|
|
//
|
|
switch ( WireToHostFormat16 ( (PBYTE) pAttribute->Value + 8 ) )
|
|
{
|
|
case 1:
|
|
CopyMemory( bEncPassword,
|
|
(PBYTE)pAttribute->Value + 10,
|
|
243
|
|
);
|
|
break;
|
|
case 2:
|
|
CopyMemory( bEncPassword+ 243,
|
|
(PBYTE)pAttribute->Value + 10,
|
|
243
|
|
);
|
|
|
|
break;
|
|
case 3:
|
|
CopyMemory( bEncPassword+ 486,
|
|
(PBYTE)pAttribute->Value + 10,
|
|
30
|
|
);
|
|
break;
|
|
default:
|
|
TRACE("Invalid enc password attribute");
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
// Check to see if this is enc password
|
|
// and also get the sequence number.
|
|
//
|
|
pAttribute = RasAuthAttributeGetNext( &hAttribute,
|
|
raatVendorSpecific );
|
|
}
|
|
//
|
|
// Call Change password function
|
|
//
|
|
|
|
dwRetCode = IASChangePassword3( lpwszHashUserName,
|
|
wszDomainName,
|
|
pbEncHash,
|
|
bEncPassword
|
|
);
|
|
pEapwb->dwLSARetCode = dwRetCode;
|
|
LDone:
|
|
return dwRetCode;
|
|
}
|
|
|
|
DWORD
|
|
AuthenticateUser ( IN OUT EAPMSCHAPv2WB * pEapwb,
|
|
IN PPP_EAP_OUTPUT* pEapOutput,
|
|
PPPAP_INPUT * pApInput
|
|
)
|
|
{
|
|
|
|
DWORD dwRetCode = NO_ERROR;
|
|
RAS_AUTH_ATTRIBUTE * pAttribute = NULL;
|
|
WCHAR wszUserName[UNLEN + DNLEN +1] = {0};
|
|
WCHAR wszHashUserName[UNLEN+DNLEN+1] = {0};
|
|
|
|
//Hash user name is taken from chapwb
|
|
CHAR szHashUserName[UNLEN+1] = {0};
|
|
|
|
WCHAR* lpszRover = NULL;
|
|
|
|
WCHAR wszDomainName[DNLEN +1] = {0};
|
|
//Format is Type + Length + identity + "S=" + 40 bytes response
|
|
UCHAR szAuthSuccessResponse[1+1+1+2+40] ={0};
|
|
//Domain Name Type + Length+Domainname
|
|
CHAR szDomainName[1+1+1+DNLEN+1] ={0};
|
|
//MPPE Keys Type+Length+Salt+KeyLength+NTkey(16)+PAdding(15)
|
|
BYTE bMPPEKey[1+1+2+1+16+15]={0};
|
|
PBYTE pbChapChallenge = NULL;
|
|
DWORD cbChallenge = 0;
|
|
PBYTE pbResponse = NULL;
|
|
PBYTE pbPeerChallenge = NULL;
|
|
IAS_MSCHAP_V2_PROFILE Profile;
|
|
HANDLE hToken = INVALID_HANDLE_VALUE;
|
|
DWORD dwCurAttr = 0;
|
|
DWORD dwCount=0;
|
|
DWORD dwChapRetCode = NO_ERROR;
|
|
//Type +
|
|
CHAR szChapError[64] = {0};
|
|
|
|
TRACE("Authenticate User");
|
|
//
|
|
// Authenticate the user by calling the IASLogonUser function here
|
|
// This is stolen from IAS.
|
|
//
|
|
|
|
|
|
//Extract the attribs from pUserAttributes
|
|
//
|
|
// We need following attribs
|
|
// raatUserName,
|
|
// MS_VSA_CHAP_Challenge
|
|
// MS_VSA_CHAP2_Response
|
|
//
|
|
//We dont use the user name got from EAP for auth. We use the one got from
|
|
//Radius
|
|
#if 0
|
|
pAttribute = RasAuthAttributeGet ( raatUserName,
|
|
pEapOutput->pUserAttributes
|
|
);
|
|
|
|
if ( NULL == pAttribute )
|
|
{
|
|
//Need a better way of sending error
|
|
TRACE ( "UserName missing");
|
|
dwRetCode = ERROR_AUTHENTICATION_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Convert the username to unicode
|
|
//
|
|
|
|
MultiByteToWideChar( CP_ACP,
|
|
0,
|
|
pAttribute->Value,
|
|
pAttribute->dwLength,
|
|
wszUserName,
|
|
UNLEN + DNLEN + 1 );
|
|
|
|
#endif
|
|
//Get the chap challenge and chap response
|
|
|
|
pAttribute = RasAuthAttributeGetVendorSpecific(
|
|
VENDOR_MICROSOFT,
|
|
MS_VSA_CHAP_Challenge,
|
|
pEapOutput->pUserAttributes );
|
|
|
|
if ( NULL == pAttribute )
|
|
{
|
|
TRACE ( "Challenge missing");
|
|
dwRetCode = ERROR_AUTHENTICATION_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
pbChapChallenge = (PBYTE)pAttribute->Value + 6;
|
|
cbChallenge = ((DWORD)(*((PBYTE)pAttribute->Value + 5))) - 2;
|
|
|
|
pAttribute = RasAuthAttributeGetVendorSpecific(
|
|
VENDOR_MICROSOFT,
|
|
MS_VSA_CHAP2_Response,
|
|
pEapOutput->pUserAttributes );
|
|
|
|
|
|
|
|
if ( NULL == pAttribute )
|
|
{
|
|
//
|
|
// Try and see if this is a change password response
|
|
//
|
|
pAttribute = RasAuthAttributeGetVendorSpecific(
|
|
VENDOR_MICROSOFT,
|
|
MS_VSA_CHAP2_CPW,
|
|
pEapOutput->pUserAttributes );
|
|
|
|
if ( NULL == pAttribute )
|
|
{
|
|
TRACE("Response missing");
|
|
dwRetCode = ERROR_AUTHENTICATION_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
//
|
|
// Setup response and peer challenge here
|
|
//
|
|
pbPeerChallenge = (PBYTE)pAttribute->Value + 8 + 16;
|
|
pbResponse = (PBYTE)pAttribute->Value + 8 + 16 + 24;
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
//
|
|
// Get the peer challenge and response from
|
|
// the VSA
|
|
//
|
|
pbPeerChallenge = (PBYTE)pAttribute->Value + 8;
|
|
pbResponse = (PBYTE)pAttribute->Value + 8 + 16 + 8;
|
|
}
|
|
|
|
|
|
//
|
|
// Get the hash user name and domain name
|
|
//
|
|
MultiByteToWideChar( CP_ACP,
|
|
0,
|
|
pEapwb->pwb->szUserName,
|
|
-1,
|
|
wszHashUserName,
|
|
UNLEN+DNLEN );
|
|
|
|
|
|
//
|
|
// Get the domain if any
|
|
//
|
|
|
|
lpszRover = wcschr ( wszHashUserName, '\\' );
|
|
if ( lpszRover )
|
|
{
|
|
lpszRover++;
|
|
}
|
|
else
|
|
{
|
|
lpszRover = wszHashUserName;
|
|
}
|
|
|
|
|
|
//Convert hash user name to multibyte
|
|
WideCharToMultiByte( CP_ACP,
|
|
0,
|
|
lpszRover,
|
|
-1,
|
|
szHashUserName,
|
|
UNLEN+1,
|
|
NULL,
|
|
NULL );
|
|
|
|
|
|
|
|
lpszRover = wcschr ( pEapwb->wszRadiusUserName, '\\');
|
|
if ( lpszRover )
|
|
{
|
|
wcsncpy ( wszDomainName, pEapwb->wszRadiusUserName, lpszRover - pEapwb->wszRadiusUserName );
|
|
lpszRover++;
|
|
}
|
|
else
|
|
{
|
|
lpszRover = pEapwb->wszRadiusUserName;
|
|
}
|
|
|
|
|
|
dwRetCode = IASLogonMSCHAPv2( (PCWSTR)lpszRover,
|
|
(PCWSTR)wszDomainName,
|
|
szHashUserName,
|
|
pbChapChallenge,
|
|
cbChallenge,
|
|
pbResponse,
|
|
pbPeerChallenge,
|
|
&Profile,
|
|
&hToken
|
|
);
|
|
|
|
//
|
|
// Map the return errors to correct errors
|
|
// create a set of attributes to be sent back to raschap
|
|
//
|
|
|
|
if ( NO_ERROR == dwRetCode )
|
|
{
|
|
|
|
//
|
|
// Setup the authenticator attributes here
|
|
// Following attributes will be send back.
|
|
// 1. SendKey
|
|
// 2. RecvKey
|
|
// 3. AuthResponse
|
|
// 4. MSCHAPDomain
|
|
//
|
|
pApInput->dwAuthResultCode = NO_ERROR;
|
|
pApInput->fAuthenticationComplete = TRUE;
|
|
|
|
pAttribute = RasAuthAttributeCreate ( 4 );
|
|
if ( NULL == pAttribute )
|
|
{
|
|
TRACE("RasAuthAttributeCreate failed");
|
|
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto done;
|
|
}
|
|
|
|
for ( dwCurAttr = 0; dwCurAttr < 4; dwCurAttr ++ )
|
|
{
|
|
switch ( dwCurAttr )
|
|
{
|
|
case 0:
|
|
{
|
|
|
|
CHAR * p = szDomainName;
|
|
|
|
//
|
|
// Setup MSCHAP Domain name here
|
|
//
|
|
*p++ = (BYTE)MS_VSA_CHAP_Domain;
|
|
*p++ = (BYTE)wcslen(Profile.LogonDomainName)+1+1;
|
|
*p++ = 1;
|
|
WideCharToMultiByte( CP_ACP,
|
|
0,
|
|
Profile.LogonDomainName,
|
|
-1,
|
|
p,
|
|
DNLEN+1,
|
|
NULL,
|
|
NULL );
|
|
dwRetCode = RasAuthAttributeInsertVSA(
|
|
dwCurAttr,
|
|
pAttribute,
|
|
VENDOR_MICROSOFT,
|
|
(DWORD)szDomainName[1],
|
|
szDomainName );
|
|
|
|
break;
|
|
|
|
}
|
|
case 1:
|
|
case 2:
|
|
{
|
|
//SEtup MPPE SEnd Key attributes here
|
|
PBYTE p = bMPPEKey;
|
|
|
|
ZeroMemory(bMPPEKey, sizeof(bMPPEKey) );
|
|
|
|
if ( dwCurAttr == 1 )
|
|
*p++ = (BYTE)MS_VSA_MPPE_Send_Key; //Type
|
|
else
|
|
*p++ = (BYTE)MS_VSA_MPPE_Recv_Key; //Type
|
|
*p++ = (BYTE)36; //Length
|
|
p++;p++; //Salt is 0
|
|
*p++ = 16; //Key Length
|
|
|
|
if ( dwCurAttr == 1 )
|
|
CopyMemory(p, Profile.SendSessionKey, 16 );
|
|
else
|
|
CopyMemory(p, Profile.RecvSessionKey, 16 );
|
|
|
|
dwRetCode = RasAuthAttributeInsertVSA(
|
|
dwCurAttr,
|
|
pAttribute,
|
|
VENDOR_MICROSOFT,
|
|
36,
|
|
bMPPEKey );
|
|
|
|
break;
|
|
}
|
|
case 3:
|
|
{
|
|
UCHAR * p = szAuthSuccessResponse;
|
|
*p++ = (BYTE)MS_VSA_CHAP2_Success; //Type of attr
|
|
*p++ = (BYTE)45; //Length of the VSA
|
|
*p++ = (BYTE)1; //ID ignored by out implementation of MSCHAPv2
|
|
*p++ = 'S';
|
|
*p++ = '=';
|
|
|
|
for ( dwCount = 0; dwCount < 20; dwCount++ )
|
|
{
|
|
*p++ = num2Digit(Profile.AuthResponse[dwCount] >> 4);
|
|
*p++ = num2Digit(Profile.AuthResponse[dwCount] & 0xF);
|
|
}
|
|
//
|
|
// Setup the value field here
|
|
//
|
|
dwRetCode = RasAuthAttributeInsertVSA(
|
|
dwCurAttr,
|
|
pAttribute,
|
|
VENDOR_MICROSOFT,
|
|
45,
|
|
szAuthSuccessResponse );
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
break;
|
|
|
|
}
|
|
if ( NO_ERROR != dwRetCode )
|
|
{
|
|
TRACE("RasAuthAttributeInsetVSA failed");
|
|
goto done;
|
|
}
|
|
|
|
}
|
|
|
|
pApInput->pAttributesFromAuthenticator = pAttribute;
|
|
//
|
|
// Also save the attributes in the WB to send across later.
|
|
//
|
|
pEapwb->pUserAttributes = pAttribute;
|
|
pEapwb->dwAuthResultCode = NO_ERROR;
|
|
pEapwb->dwLSARetCode = NO_ERROR;
|
|
pApInput->fAuthenticationComplete = TRUE;
|
|
pApInput->dwAuthResultCode = pApInput->dwAuthError = NO_ERROR;
|
|
|
|
}
|
|
else
|
|
{
|
|
pEapwb->dwLSARetCode = dwRetCode;
|
|
//
|
|
// Handle the failure by sending
|
|
//
|
|
|
|
switch ( dwRetCode )
|
|
{
|
|
case ERROR_INVALID_LOGON_HOURS:
|
|
dwChapRetCode = ERROR_RESTRICTED_LOGON_HOURS;
|
|
|
|
break;
|
|
|
|
case ERROR_ACCOUNT_DISABLED:
|
|
dwChapRetCode = ERROR_ACCT_DISABLED;
|
|
|
|
break;
|
|
|
|
case ERROR_PASSWORD_EXPIRED:
|
|
case ERROR_PASSWORD_MUST_CHANGE:
|
|
dwChapRetCode = ERROR_PASSWD_EXPIRED;
|
|
break;
|
|
|
|
case ERROR_ILL_FORMED_PASSWORD:
|
|
case ERROR_PASSWORD_RESTRICTION:
|
|
dwChapRetCode = ERROR_CHANGING_PASSWORD;
|
|
break;
|
|
|
|
default:
|
|
dwChapRetCode = ERROR_AUTHENTICATION_FAILURE;
|
|
}
|
|
pAttribute = RasAuthAttributeCreate ( 1 );
|
|
if ( NULL == pAttribute )
|
|
{
|
|
TRACE("RasAuthAttributeCreate failed");
|
|
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto done;
|
|
}
|
|
//Make a VSA out of this and send it back
|
|
wsprintf ( &szChapError[3], "E=%lu R=0 V=3", dwChapRetCode );
|
|
szChapError[0] = MS_VSA_CHAP_Error;
|
|
szChapError[1] = 3 + strlen(&szChapError[3]);
|
|
szChapError[2] = pEapwb->IdToExpect;
|
|
dwRetCode = RasAuthAttributeInsertVSA(
|
|
0,
|
|
pAttribute,
|
|
VENDOR_MICROSOFT,
|
|
szChapError[1],
|
|
szChapError );
|
|
pApInput->fAuthenticationComplete = TRUE;
|
|
|
|
pApInput->pAttributesFromAuthenticator = pAttribute;
|
|
pApInput->dwAuthError = NO_ERROR;
|
|
pApInput->dwAuthResultCode = dwChapRetCode;
|
|
}
|
|
|
|
|
|
|
|
|
|
done:
|
|
if ( INVALID_HANDLE_VALUE != hToken )
|
|
CloseHandle(hToken);
|
|
if ( NO_ERROR != dwRetCode )
|
|
{
|
|
RasAuthAttributeDestroy(pAttribute);
|
|
pApInput->pAttributesFromAuthenticator = NULL;
|
|
}
|
|
return dwRetCode;
|
|
}
|
|
|
|
|
|
DWORD
|
|
CallMakeMessageAndSetEAPState(
|
|
IN PVOID pWorkBuf,
|
|
IN PPP_CONFIG* pReceiveBuf,
|
|
IN OUT PPP_CONFIG* pSendBuf,
|
|
IN DWORD cbSendBuf,
|
|
PPPAP_RESULT * pApResult,
|
|
PPPAP_INPUT * pApInput,
|
|
OUT PPP_EAP_OUTPUT* pEapOutput
|
|
)
|
|
{
|
|
DWORD dwRetCode = NO_ERROR;
|
|
CHAPWB * pwb = (CHAPWB *)pWorkBuf;
|
|
|
|
dwRetCode = ChapMakeMessage(
|
|
pWorkBuf,
|
|
pReceiveBuf,
|
|
pSendBuf,
|
|
cbSendBuf,
|
|
pApResult,
|
|
pApInput );
|
|
|
|
if ( dwRetCode != NO_ERROR )
|
|
{
|
|
goto done;
|
|
}
|
|
|
|
|
|
switch( pApResult->Action )
|
|
{
|
|
case APA_NoAction:
|
|
pEapOutput->Action = EAPACTION_NoAction;
|
|
break;
|
|
|
|
case APA_Done:
|
|
pEapOutput->Action = EAPACTION_Done;
|
|
break;
|
|
|
|
case APA_SendAndDone:
|
|
case APA_Send:
|
|
pEapOutput->Action = EAPACTION_Send;
|
|
break;
|
|
|
|
case APA_SendWithTimeout:
|
|
|
|
pEapOutput->Action = ( pwb->fServer )
|
|
? EAPACTION_SendWithTimeout
|
|
: EAPACTION_Send;
|
|
break;
|
|
|
|
case APA_SendWithTimeout2:
|
|
|
|
pEapOutput->Action = ( pwb->fServer )
|
|
? EAPACTION_SendWithTimeoutInteractive
|
|
: EAPACTION_Send;
|
|
break;
|
|
|
|
case APA_Authenticate:
|
|
pEapOutput->pUserAttributes = pApResult->pUserAttributes;
|
|
pEapOutput->Action = EAPACTION_Authenticate;
|
|
break;
|
|
|
|
default:
|
|
RTASSERT(FALSE);
|
|
break;
|
|
}
|
|
|
|
done:
|
|
return dwRetCode;
|
|
}
|
|
|
|
|
|
DWORD
|
|
EapMSChapv2SMakeMessage(
|
|
IN VOID* pWorkBuf,
|
|
IN PPP_EAP_PACKET* pReceivePacket,
|
|
OUT PPP_EAP_PACKET* pSendPacket,
|
|
IN DWORD cbSendPacket,
|
|
OUT PPP_EAP_OUTPUT* pEapOutput,
|
|
IN PPP_EAP_INPUT* pEapInput
|
|
)
|
|
{
|
|
DWORD dwRetCode = NO_ERROR;
|
|
PPP_CONFIG * pReceiveBuf = NULL;
|
|
PPP_CONFIG * pSendBuf = NULL;
|
|
DWORD cbSendBuf = 1500;
|
|
PPPAP_INPUT ApInput;
|
|
PPPAP_RESULT ApResult;
|
|
WORD cbPacket = 0;
|
|
EAPMSCHAPv2WB * pEapwb = (EAPMSCHAPv2WB * ) pWorkBuf;
|
|
TRACE("EapMSChapv2SMakeMessage");
|
|
//
|
|
//Do default processing here.
|
|
//
|
|
ZeroMemory( &ApResult, sizeof(ApResult) );
|
|
|
|
if ( ( pSendBuf = LocalAlloc( LPTR, cbSendBuf ) ) == NULL )
|
|
{
|
|
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto done;
|
|
}
|
|
|
|
|
|
if ( pEapInput != NULL )
|
|
{
|
|
MapEapInputToApInput( pEapInput, &ApInput );
|
|
}
|
|
|
|
switch ( pEapwb->EapState )
|
|
{
|
|
case EMV2_Initial:
|
|
TRACE("EMV2_Initial");
|
|
//
|
|
// This is the first time this has been invoked.
|
|
// So we make a MACHAPv2 chap challenge and send
|
|
// back a response
|
|
//
|
|
dwRetCode = CallMakeMessageAndSetEAPState(
|
|
pEapwb->pwb,
|
|
pReceiveBuf,
|
|
pSendBuf,
|
|
cbSendBuf,
|
|
&ApResult,
|
|
( pEapInput ? &ApInput : NULL ),
|
|
pEapOutput
|
|
);
|
|
//
|
|
// We got the CHAP Challenge now. If all's fine
|
|
// package the result back and send it to the client
|
|
//
|
|
//
|
|
// Translate MSCHAPv2 packet to EAP packet
|
|
//
|
|
if ( NO_ERROR == dwRetCode && pSendBuf )
|
|
{
|
|
pSendPacket->Code = EAPCODE_Request;
|
|
pEapwb->IdToExpect = pEapwb->IdToSend =
|
|
pSendPacket->Id = pEapwb->pwb->bIdToSend;
|
|
//
|
|
// Length = sizeof Header + sizeof MSCHAP packet to send
|
|
// This includes the first byte of
|
|
cbPacket = WireToHostFormat16( pSendBuf->Length );
|
|
|
|
CopyMemory ( pSendPacket->Data+1, pSendBuf, cbPacket);
|
|
|
|
cbPacket += sizeof(PPP_EAP_PACKET);
|
|
|
|
HostToWireFormat16( cbPacket, pSendPacket->Length );
|
|
|
|
pSendPacket->Data[0] = (BYTE)PPP_EAP_MSCHAPv2;
|
|
|
|
pEapwb->EapState = EMV2_RequestSend;
|
|
}
|
|
|
|
break;
|
|
case EMV2_RequestSend:
|
|
TRACE("EMV2_RequestSend");
|
|
//
|
|
// We should only get a response here.
|
|
// If not discard this packet.
|
|
//
|
|
|
|
if ( NULL != pReceivePacket )
|
|
{
|
|
if ( pReceivePacket->Code != EAPCODE_Response )
|
|
{
|
|
TRACE("Got unexpected packet. Does not have response");
|
|
dwRetCode = ERROR_PPP_INVALID_PACKET;
|
|
break;
|
|
}
|
|
if ( pReceivePacket->Id != pEapwb->IdToExpect )
|
|
{
|
|
TRACE("received packet id does not match");
|
|
dwRetCode = ERROR_PPP_INVALID_PACKET;
|
|
break;
|
|
}
|
|
//
|
|
// Translate the packet received to
|
|
// MSCHAP v2 format
|
|
//
|
|
cbPacket = WireToHostFormat16(pReceivePacket->Length);
|
|
|
|
if ( cbPacket > sizeof( PPP_EAP_PACKET ) )
|
|
{
|
|
pReceiveBuf = (PPP_CONFIG *)( pReceivePacket->Data + 1);
|
|
|
|
dwRetCode = CallMakeMessageAndSetEAPState(
|
|
pEapwb->pwb,
|
|
pReceiveBuf,
|
|
pSendBuf,
|
|
cbSendBuf,
|
|
&ApResult,
|
|
( pEapInput ? &ApInput : NULL ),
|
|
pEapOutput
|
|
);
|
|
if ( NO_ERROR == dwRetCode )
|
|
{
|
|
//Check to see if we are asked to authenticate
|
|
if ( pEapOutput->Action == EAPACTION_Authenticate )
|
|
{
|
|
//
|
|
// If we have come this far pEapInput cannot be NULL
|
|
// Or else it is a bug in the client.
|
|
//
|
|
|
|
//
|
|
// Check to see if this is a change password request
|
|
// If so first change tha password and then authenticate.
|
|
//
|
|
|
|
dwRetCode = ChangePassword (pEapwb, pEapOutput, &ApInput);
|
|
if ( NO_ERROR == dwRetCode )
|
|
{
|
|
//
|
|
// Now authenticate user
|
|
//
|
|
dwRetCode = AuthenticateUser (pEapwb, pEapOutput, &ApInput );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Change password operation failed.
|
|
//
|
|
|
|
pSendPacket->Code = EAPCODE_Failure;
|
|
HostToWireFormat16 ( (WORD)4, pSendPacket->Length );
|
|
pEapwb->EapState = EMV2_Failure;
|
|
//pEapOutput->dwAuthResultCode = pEapwb->pwb->result.dwError;
|
|
pEapOutput->dwAuthResultCode = pEapwb->dwLSARetCode;
|
|
pEapOutput->Action = EAPACTION_SendAndDone;
|
|
dwRetCode = NO_ERROR;
|
|
break;
|
|
}
|
|
//
|
|
// We will get a set of auth attributes back
|
|
// that we need to send back to the mschap
|
|
// protocol.
|
|
//
|
|
|
|
dwRetCode = CallMakeMessageAndSetEAPState
|
|
(
|
|
pEapwb->pwb,
|
|
pReceiveBuf,
|
|
pSendBuf,
|
|
cbSendBuf,
|
|
&ApResult,
|
|
&ApInput,
|
|
pEapOutput
|
|
|
|
);
|
|
}
|
|
|
|
//
|
|
// Check to see if auth was success or fail.
|
|
// If Auth was success then set state to EMV2_CHAPAuthSuccess
|
|
//
|
|
|
|
if ( NO_ERROR == dwRetCode && pSendBuf )
|
|
{
|
|
pSendPacket->Code = EAPCODE_Request;
|
|
pEapwb->IdToSend ++;
|
|
pEapwb->IdToExpect = pSendPacket->Id = pEapwb->IdToSend;
|
|
//
|
|
// Length = sizeof Header + sizeof MSCHAP packet to send
|
|
// This includes the first byte of
|
|
cbPacket = WireToHostFormat16( pSendBuf->Length );
|
|
|
|
CopyMemory ( pSendPacket->Data+1, pSendBuf, cbPacket);
|
|
|
|
cbPacket += sizeof(PPP_EAP_PACKET);
|
|
|
|
HostToWireFormat16( cbPacket, pSendPacket->Length );
|
|
|
|
pSendPacket->Data[0] = (BYTE)PPP_EAP_MSCHAPv2;
|
|
|
|
if ( pEapwb->pwb->result.dwError == NO_ERROR )
|
|
{
|
|
//
|
|
// We succeeded in auth
|
|
//
|
|
pEapwb->EapState = EMV2_CHAPAuthSuccess;
|
|
pEapOutput->Action = EAPACTION_SendWithTimeout;
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Could be a retryable failure. So we need to send
|
|
// with interactive timeout.
|
|
//
|
|
if ( pEapwb->pwb->result.fRetry )
|
|
{
|
|
pEapwb->EapState = EMV2_RequestSend;
|
|
pEapOutput->Action = EAPACTION_SendWithTimeoutInteractive;
|
|
}
|
|
else if ( pEapwb->pwb->result.dwError == ERROR_PASSWD_EXPIRED )
|
|
{
|
|
if ( pEapwb->pUserProp->fFlags & EAPMSCHAPv2_FLAG_ALLOW_CHANGEPWD )
|
|
{
|
|
//
|
|
// Check to see if this is allowed
|
|
//
|
|
pEapwb->EapState = EMV2_RequestSend;
|
|
pEapOutput->Action = EAPACTION_SendWithTimeoutInteractive;
|
|
}
|
|
else
|
|
{
|
|
pSendPacket->Code = EAPCODE_Failure;
|
|
HostToWireFormat16 ( (WORD)4, pSendPacket->Length );
|
|
pEapwb->EapState = EMV2_Failure;
|
|
//pEapOutput->dwAuthResultCode = pEapwb->pwb->result.dwError;
|
|
pEapOutput->dwAuthResultCode = pEapwb->dwLSARetCode;
|
|
pEapOutput->Action = EAPACTION_SendAndDone;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pSendPacket->Code = EAPCODE_Failure;
|
|
HostToWireFormat16 ( (WORD)4, pSendPacket->Length );
|
|
pEapwb->EapState = EMV2_Failure;
|
|
//pEapOutput->dwAuthResultCode = pEapwb->pwb->result.dwError;
|
|
pEapOutput->dwAuthResultCode = pEapwb->dwLSARetCode;
|
|
pEapOutput->Action = EAPACTION_SendAndDone;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We should never get an empty response in
|
|
//
|
|
dwRetCode = ERROR_PPP_INVALID_PACKET;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
dwRetCode = ERROR_PPP_INVALID_PACKET;
|
|
}
|
|
break;
|
|
case EMV2_CHAPAuthSuccess:
|
|
TRACE("EMV2_CHAPAuthSuccess");
|
|
//
|
|
// We should only get an response here indicating
|
|
// if the client could validate the server successfully.
|
|
// Then we can send back a EAP_SUCCESS or EAP_FAIL.
|
|
//
|
|
if ( NULL != pReceivePacket )
|
|
{
|
|
if ( pReceivePacket->Code != EAPCODE_Response )
|
|
{
|
|
dwRetCode = ERROR_PPP_INVALID_PACKET;
|
|
break;
|
|
}
|
|
|
|
if ( pReceivePacket->Id != pEapwb->IdToExpect )
|
|
{
|
|
//Invalid packet id
|
|
dwRetCode = ERROR_PPP_INVALID_PACKET;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Translate the packet received to
|
|
// MSCHAP v2 format
|
|
//
|
|
cbPacket = WireToHostFormat16(pReceivePacket->Length);
|
|
if ( cbPacket == sizeof( PPP_EAP_PACKET ) + 1 )
|
|
{
|
|
//
|
|
// Check to see if the data is CHAPCODE_Success
|
|
// or CHAPCode Fail and send appropriate packet
|
|
//
|
|
if ( *(pReceivePacket->Data+1) == CHAPCODE_Success )
|
|
{
|
|
//
|
|
//peer could auth successfully
|
|
//
|
|
pSendPacket->Code = EAPCODE_Success;
|
|
}
|
|
else
|
|
{
|
|
pSendPacket->Code = EAPCODE_Failure;
|
|
}
|
|
pEapwb->IdToSend++;
|
|
|
|
pEapwb->IdToExpect =
|
|
pSendPacket->Id = pEapwb->IdToSend;
|
|
|
|
HostToWireFormat16( (WORD)4, pSendPacket->Length );
|
|
|
|
pEapwb->EapState = EMV2_Success;
|
|
|
|
//Set the Out attributes here
|
|
pEapOutput->pUserAttributes = pEapwb->pUserAttributes;
|
|
pEapOutput->dwAuthResultCode = pEapwb->dwAuthResultCode;
|
|
|
|
pEapOutput->Action = EAPACTION_SendAndDone;
|
|
|
|
}
|
|
else
|
|
{
|
|
dwRetCode = ERROR_PPP_INVALID_PACKET;
|
|
}
|
|
}
|
|
|
|
break;
|
|
case EMV2_CHAPAuthFail:
|
|
TRACE("EMV2_CHAPAuthFail");
|
|
//
|
|
// We could get a retry or a change password packet here
|
|
// Again we should get only a EAPCODE_Response here...
|
|
|
|
//
|
|
//Got a response. So send it to MSCHAP and see what happens
|
|
//
|
|
|
|
break;
|
|
case EMV2_Success:
|
|
TRACE("EMV2_Success");
|
|
//
|
|
// See the CS_Done state in raschap for this state to be here.
|
|
//
|
|
|
|
break;
|
|
case EMV2_Failure:
|
|
TRACE("EMV2_Failure");
|
|
break;
|
|
|
|
case EMV2_ResponseSend:
|
|
default:
|
|
TRACE1("Why is this EAPMschapv2 in this state? %d",pEapwb->EapState );
|
|
break;
|
|
}
|
|
|
|
done:
|
|
if ( pSendBuf )
|
|
{
|
|
LocalFree(pSendBuf);
|
|
}
|
|
|
|
return dwRetCode;
|
|
}
|
|
|
|
|
|
DWORD
|
|
GetClientMPPEKeys ( EAPMSCHAPv2WB *pEapwb, PPPAP_RESULT * pApResult )
|
|
{
|
|
DWORD dwRetCode = NO_ERROR;
|
|
BYTE bRecvKey[16] = {0};
|
|
BYTE bSendKey[16] = {0};
|
|
RAS_AUTH_ATTRIBUTE * pAttribute;
|
|
RAS_AUTH_ATTRIBUTE * pSendRecvKeyAttr = NULL;
|
|
//MPPE Keys Type+Length+Salt+KeyLength+NTkey(16)+PAdding(15)
|
|
BYTE bMPPEKey[1+1+2+1+16+15]={0};
|
|
|
|
TRACE("GetClientMPPEKeys");
|
|
|
|
pEapwb->pUserAttributes = NULL;
|
|
|
|
pAttribute = RasAuthAttributeGetVendorSpecific(
|
|
311, MS_VSA_CHAP_MPPE_Keys,
|
|
pApResult->pUserAttributes);
|
|
|
|
if ( NULL == pAttribute )
|
|
{
|
|
TRACE("No User Session Key");
|
|
dwRetCode = ERROR_NOT_FOUND;
|
|
goto done;
|
|
}
|
|
|
|
dwRetCode = IASGetSendRecvSessionKeys( ((PBYTE)(pAttribute->Value))+6+8,
|
|
16,
|
|
pApResult->abResponse,
|
|
24,
|
|
bSendKey,
|
|
bRecvKey
|
|
);
|
|
|
|
if ( NO_ERROR != dwRetCode )
|
|
{
|
|
TRACE("Failed to generate send/recv keys");
|
|
goto done;
|
|
}
|
|
|
|
pSendRecvKeyAttr = RasAuthAttributeCreate ( 2 );
|
|
if ( NULL == pSendRecvKeyAttr )
|
|
{
|
|
TRACE("RasAuthAttributeCreate failed");
|
|
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto done;
|
|
}
|
|
|
|
bMPPEKey[0] = MS_VSA_MPPE_Send_Key;
|
|
bMPPEKey[1] = 36;
|
|
bMPPEKey[4] = 16;
|
|
CopyMemory(&bMPPEKey[5], bSendKey, 16 );
|
|
|
|
dwRetCode = RasAuthAttributeInsertVSA(
|
|
0,
|
|
pSendRecvKeyAttr,
|
|
VENDOR_MICROSOFT,
|
|
36,
|
|
bMPPEKey );
|
|
|
|
if ( NO_ERROR != dwRetCode )
|
|
{
|
|
TRACE("Failed to insert send key");
|
|
goto done;
|
|
}
|
|
|
|
bMPPEKey[0] = MS_VSA_MPPE_Recv_Key;
|
|
CopyMemory(&bMPPEKey[5], bRecvKey, 16 );
|
|
|
|
dwRetCode = RasAuthAttributeInsertVSA(
|
|
1,
|
|
pSendRecvKeyAttr,
|
|
VENDOR_MICROSOFT,
|
|
36,
|
|
bMPPEKey );
|
|
|
|
if ( NO_ERROR != dwRetCode )
|
|
{
|
|
TRACE("Failed to insert recv key");
|
|
goto done;
|
|
}
|
|
|
|
pEapwb->pUserAttributes = pSendRecvKeyAttr;
|
|
done:
|
|
if ( NO_ERROR != dwRetCode )
|
|
{
|
|
if ( pSendRecvKeyAttr )
|
|
RasAuthAttributeDestroy(pSendRecvKeyAttr);
|
|
}
|
|
return dwRetCode;
|
|
}
|
|
|
|
|
|
DWORD
|
|
EapMSChapv2CMakeMessage(
|
|
IN VOID* pWorkBuf,
|
|
IN PPP_EAP_PACKET* pReceivePacket,
|
|
OUT PPP_EAP_PACKET* pSendPacket,
|
|
IN DWORD cbSendPacket,
|
|
OUT PPP_EAP_OUTPUT* pEapOutput,
|
|
IN PPP_EAP_INPUT* pEapInput
|
|
)
|
|
{
|
|
DWORD dwRetCode = NO_ERROR;
|
|
PPP_CONFIG* pReceiveBuf = NULL;
|
|
PPP_CONFIG* pSendBuf = NULL;
|
|
DWORD cbSendBuf = 1500;
|
|
PPPAP_INPUT ApInput;
|
|
PPPAP_RESULT ApResult;
|
|
WORD cbPacket = 0;
|
|
EAPMSCHAPv2WB * pEapwb = (EAPMSCHAPv2WB * ) pWorkBuf;
|
|
TRACE("EapMSChapv2CMakeMessage");
|
|
//
|
|
//Do default processing here.
|
|
//
|
|
ZeroMemory( &ApResult, sizeof(ApResult) );
|
|
|
|
if ( ( pSendBuf = LocalAlloc( LPTR, cbSendBuf ) ) == NULL )
|
|
{
|
|
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto done;
|
|
}
|
|
|
|
|
|
if ( pEapInput != NULL )
|
|
{
|
|
MapEapInputToApInput( pEapInput, &ApInput );
|
|
}
|
|
switch ( pEapwb->EapState )
|
|
{
|
|
case EMV2_Initial:
|
|
TRACE("EMV2_Initial");
|
|
//
|
|
// We can oly get a request here...
|
|
//
|
|
if ( NULL != pReceivePacket )
|
|
{
|
|
if ( pReceivePacket->Code != EAPCODE_Request )
|
|
{
|
|
dwRetCode = ERROR_PPP_INVALID_PACKET;
|
|
break;
|
|
}
|
|
//
|
|
// Translate the packet received to
|
|
// MSCHAP v2 format
|
|
//
|
|
cbPacket = WireToHostFormat16(pReceivePacket->Length);
|
|
|
|
if ( cbPacket > sizeof( PPP_EAP_PACKET ) )
|
|
{
|
|
pReceiveBuf = (PPP_CONFIG *) (pReceivePacket->Data + 1);
|
|
|
|
dwRetCode = CallMakeMessageAndSetEAPState(
|
|
pEapwb->pwb,
|
|
pReceiveBuf,
|
|
pSendBuf,
|
|
cbSendBuf,
|
|
&ApResult,
|
|
( pEapInput ? &ApInput : NULL ),
|
|
pEapOutput
|
|
);
|
|
|
|
// Translate MSCHAPv2 packet to EAP packet
|
|
//
|
|
if ( NO_ERROR == dwRetCode && pSendBuf )
|
|
{
|
|
pSendPacket->Code = EAPCODE_Response;
|
|
|
|
pEapwb->IdToExpect = pEapwb->IdToSend =
|
|
pSendPacket->Id = pEapwb->pwb->bIdToSend;
|
|
//
|
|
// Length = sizeof Header + sizeof MSCHAP packet to send
|
|
// This includes the first byte of
|
|
cbPacket = WireToHostFormat16( pSendBuf->Length );
|
|
|
|
CopyMemory ( pSendPacket->Data+1, pSendBuf, cbPacket);
|
|
|
|
cbPacket += sizeof(PPP_EAP_PACKET);
|
|
|
|
HostToWireFormat16( cbPacket, pSendPacket->Length );
|
|
|
|
pSendPacket->Data[0] = (BYTE)PPP_EAP_MSCHAPv2;
|
|
|
|
pEapwb->EapState = EMV2_ResponseSend;
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
case EMV2_ResponseSend:
|
|
TRACE("EMV2_ResponseSend");
|
|
//
|
|
// We should get either a CHAP auth success or CHAP Auth fail here
|
|
// for the initial challenge send out.
|
|
//
|
|
if ( NULL != pReceivePacket )
|
|
{
|
|
if ( pReceivePacket->Code != EAPCODE_Request &&
|
|
pReceivePacket->Code != EAPCODE_Failure
|
|
)
|
|
{
|
|
dwRetCode = ERROR_PPP_INVALID_PACKET;
|
|
break;
|
|
}
|
|
if ( pReceivePacket->Code == EAPCODE_Failure )
|
|
{
|
|
TRACE("Got a Code Failure when expecting Response. Failing Auth");
|
|
pEapwb->EapState = EMV2_Failure;
|
|
pEapOutput->Action = EAPACTION_Done;
|
|
pEapOutput->fSaveUserData = FALSE;
|
|
ZeroMemory ( pEapwb->pUserProp->szPassword, sizeof( pEapwb->pUserProp->szPassword ) );
|
|
pEapOutput->dwAuthResultCode = ERROR_AUTHENTICATION_FAILURE;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Translate the packet received to
|
|
// MSCHAP v2 format
|
|
//
|
|
cbPacket = WireToHostFormat16(pReceivePacket->Length);
|
|
|
|
if ( cbPacket > sizeof( PPP_EAP_PACKET ) )
|
|
{
|
|
pReceiveBuf = (PPP_CONFIG *) (pReceivePacket->Data + 1);
|
|
|
|
dwRetCode = CallMakeMessageAndSetEAPState(
|
|
pEapwb->pwb,
|
|
pReceiveBuf,
|
|
pSendBuf,
|
|
cbSendBuf,
|
|
&ApResult,
|
|
( pEapInput ? &ApInput : NULL ),
|
|
pEapOutput
|
|
);
|
|
//
|
|
// Translate MSCHAPv2 packet to EAP packet
|
|
//
|
|
if ( NO_ERROR == dwRetCode && pSendBuf )
|
|
{
|
|
if ( ApResult.dwError == NO_ERROR )
|
|
{
|
|
if ( ApResult.Action == APA_NoAction )
|
|
{
|
|
pEapOutput->Action = EAPACTION_NoAction;
|
|
|
|
pEapOutput->dwAuthResultCode = NO_ERROR;
|
|
break;
|
|
}
|
|
//
|
|
// We need to change MSCHAP keys to MPPE send recv keys
|
|
// This is needed because there is no way to pass the
|
|
// MSCHAP challenge response back
|
|
//
|
|
dwRetCode = GetClientMPPEKeys ( pEapwb, &ApResult );
|
|
if ( NO_ERROR != dwRetCode )
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
//Client could successfully validate the server
|
|
//
|
|
pSendPacket->Code = EAPCODE_Response;
|
|
pEapwb->IdToSend ++;
|
|
//send the same id as received packet back
|
|
pEapwb->IdToExpect = pSendPacket->Id = pReceivePacket->Id;
|
|
//
|
|
// Length = sizeof Header + sizeof MSCHAP packet to send
|
|
// This includes the first byte of
|
|
|
|
|
|
* (pSendPacket->Data+1) = CHAPCODE_Success;
|
|
|
|
cbPacket = sizeof(PPP_EAP_PACKET) + 1;
|
|
|
|
HostToWireFormat16( cbPacket, pSendPacket->Length );
|
|
|
|
pSendPacket->Data[0] = (BYTE)PPP_EAP_MSCHAPv2;
|
|
|
|
pEapwb->EapState = EMV2_CHAPAuthSuccess;
|
|
//
|
|
// Set the out attributes and the response
|
|
//
|
|
pEapOutput->Action = EAPACTION_Send;
|
|
|
|
pEapwb->dwAuthResultCode = ApResult.dwError;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Based on what MSCHAPV2 has send back
|
|
// we need to Invoke appropriate interactive UI
|
|
// Retry password or change password here.
|
|
// If both retry and change pwd are not
|
|
// applicable then just send a fail message.
|
|
// and wait for EAP_Failure message from server.
|
|
// And Auth state goes to CHAPAuthFailed
|
|
//
|
|
// If this is a failure with rety then show
|
|
// interactive UI.
|
|
if ( pEapwb->fFlags & EAPMSCHAPv2_FLAG_MACHINE_AUTH )
|
|
{
|
|
//
|
|
// This is a machine auth. So we dont to show any
|
|
// retry or any of that stuff even though the server
|
|
// might have send such things back.
|
|
//
|
|
pEapOutput->dwAuthResultCode = ERROR_AUTHENTICATION_FAILURE;
|
|
pEapOutput->Action = EAPACTION_Done;
|
|
pEapwb->EapState = EMV2_Failure;
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
if ( ApResult.fRetry )
|
|
{
|
|
pEapOutput->fInvokeInteractiveUI = TRUE;
|
|
//
|
|
// Setup the UI Context data
|
|
//
|
|
pEapwb->pUIContextData =
|
|
(PEAPMSCHAPv2_INTERACTIVE_UI) LocalAlloc ( LPTR,
|
|
sizeof(EAPMSCHAPv2_INTERACTIVE_UI) );
|
|
|
|
if ( NULL == pEapwb->pUIContextData )
|
|
{
|
|
TRACE ("Error allocating memory for UI context data");
|
|
dwRetCode = ERROR_OUTOFMEMORY;
|
|
goto done;
|
|
}
|
|
pEapwb->pUIContextData->dwVersion = 1;
|
|
pEapwb->pUIContextData->fFlags |= EAPMSCHAPv2_INTERACTIVE_UI_FLAG_RETRY;
|
|
pEapwb->dwInteractiveUIOperation |= EAPMSCHAPv2_INTERACTIVE_UI_FLAG_RETRY;
|
|
|
|
if ( pEapwb->pUserProp )
|
|
{
|
|
CopyMemory( &(pEapwb->pUIContextData->UserProp),
|
|
pEapwb->pUserProp,
|
|
sizeof(EAPMSCHAPv2_USER_PROPERTIES)
|
|
);
|
|
}
|
|
if ( pEapwb->pConnProp->fFlags & EAPMSCHAPv2_FLAG_USE_WINLOGON_CREDS )
|
|
{
|
|
//We are using winlogon creds
|
|
// and this is a retryable failure
|
|
// so copy over the username and domain
|
|
// from chap wb to eapchap wb
|
|
WCHAR * pWchar = NULL;
|
|
pWchar = wcschr( pEapwb->wszRadiusUserName, L'\\' );
|
|
|
|
if ( pWchar == NULL )
|
|
{
|
|
WideCharToMultiByte(
|
|
CP_ACP,
|
|
0,
|
|
pEapwb->wszRadiusUserName,
|
|
-1,
|
|
pEapwb->pUIContextData->UserProp.szUserName,
|
|
UNLEN + 1,
|
|
NULL,
|
|
NULL );
|
|
}
|
|
else
|
|
{
|
|
*pWchar = 0;
|
|
|
|
WideCharToMultiByte(
|
|
CP_ACP,
|
|
0,
|
|
pEapwb->wszRadiusUserName,
|
|
-1,
|
|
pEapwb->pUIContextData->UserProp.szDomain,
|
|
DNLEN + 1,
|
|
NULL,
|
|
NULL );
|
|
|
|
*pWchar = L'\\';
|
|
|
|
WideCharToMultiByte(
|
|
CP_ACP,
|
|
0,
|
|
pWchar + 1,
|
|
-1,
|
|
pEapwb->pUIContextData->UserProp.szUserName,
|
|
UNLEN + 1,
|
|
NULL,
|
|
NULL );
|
|
}
|
|
|
|
}
|
|
pEapOutput->Action = EAPACTION_NoAction;
|
|
pEapOutput->pUIContextData = (PBYTE)pEapwb->pUIContextData;
|
|
pEapOutput->dwSizeOfUIContextData = sizeof(EAPMSCHAPv2_INTERACTIVE_UI);
|
|
pEapwb->EapState = EMV2_CHAPAuthFail;
|
|
}
|
|
else if ( ApResult.dwError == ERROR_PASSWD_EXPIRED )
|
|
{
|
|
//
|
|
// show the change password GUI.
|
|
//
|
|
|
|
pEapOutput->fInvokeInteractiveUI = TRUE;
|
|
//
|
|
// Setup the UI Context data
|
|
//
|
|
pEapwb->pUIContextData =
|
|
(PEAPMSCHAPv2_INTERACTIVE_UI) LocalAlloc ( LPTR,
|
|
sizeof(EAPMSCHAPv2_INTERACTIVE_UI) );
|
|
|
|
if ( NULL == pEapwb->pUIContextData )
|
|
{
|
|
TRACE ("Error allocating memory for UI context data");
|
|
dwRetCode = ERROR_OUTOFMEMORY;
|
|
goto done;
|
|
}
|
|
pEapwb->pUIContextData->dwVersion = 1;
|
|
if ( pEapwb->pConnProp->fFlags & EAPMSCHAPv2_FLAG_USE_WINLOGON_CREDS )
|
|
{
|
|
//
|
|
// Show the dialog with old pwd, new pwd and conf pwd
|
|
//
|
|
pEapwb->pUIContextData->fFlags |= EAPMSCHAPv2_INTERACTIVE_UI_FLAG_CHANGE_PWD_WINLOGON;
|
|
pEapwb->dwInteractiveUIOperation |= EAPMSCHAPv2_INTERACTIVE_UI_FLAG_CHANGE_PWD_WINLOGON;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We have the old password. So show the dialog with new pwd and conf pwd.
|
|
//
|
|
|
|
pEapwb->pUIContextData->fFlags |= EAPMSCHAPv2_INTERACTIVE_UI_FLAG_CHANGE_PWD;
|
|
pEapwb->dwInteractiveUIOperation |= EAPMSCHAPv2_INTERACTIVE_UI_FLAG_CHANGE_PWD;
|
|
}
|
|
|
|
if ( pEapwb->pUserProp )
|
|
{
|
|
CopyMemory( &(pEapwb->pUIContextData->UserProp),
|
|
pEapwb->pUserProp,
|
|
sizeof(EAPMSCHAPv2_USER_PROPERTIES)
|
|
);
|
|
}
|
|
pEapOutput->Action = EAPACTION_NoAction;
|
|
pEapOutput->pUIContextData = (PBYTE)pEapwb->pUIContextData;
|
|
pEapOutput->dwSizeOfUIContextData = sizeof(EAPMSCHAPv2_INTERACTIVE_UI);
|
|
pEapwb->EapState = EMV2_CHAPAuthFail;
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// this is not a retryable failure
|
|
// So we are done with Auth and failed.
|
|
//
|
|
pEapOutput->dwAuthResultCode = ApResult.dwError;
|
|
pEapOutput->Action = EAPACTION_Done;
|
|
pEapwb->EapState = EMV2_Failure;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Something went wrong here.
|
|
TRACE1("Error returned by MSCHAPv2 protocol 0x%x", dwRetCode);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwRetCode = ERROR_PPP_INVALID_PACKET;
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwRetCode = ERROR_PPP_INVALID_PACKET;
|
|
}
|
|
break;
|
|
case EMV2_CHAPAuthFail:
|
|
TRACE("EMV2_CHAPAuthFail");
|
|
//
|
|
// We come here in case of a retryable
|
|
// failure from chap and after we have popped
|
|
// interactive UI.
|
|
//
|
|
//
|
|
// Check to see if we have got data from user
|
|
//
|
|
if ( pEapInput->fDataReceivedFromInteractiveUI )
|
|
{
|
|
//
|
|
// Copy the new uid/pwd and then call chap make message again.
|
|
// adjust our state
|
|
LocalFree(pEapwb->pUIContextData);
|
|
pEapwb->pUIContextData = NULL;
|
|
LocalFree(pEapwb->pUserProp);
|
|
pEapwb->pUserProp = (PEAPMSCHAPv2_USER_PROPERTIES)LocalAlloc(LPTR,
|
|
sizeof(EAPMSCHAPv2_USER_PROPERTIES) );
|
|
if (NULL == pEapwb->pUserProp )
|
|
{
|
|
TRACE("Failed to allocate memory for user props.");
|
|
dwRetCode = ERROR_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
CopyMemory( pEapwb->pUserProp,
|
|
&(((PEAPMSCHAPv2_INTERACTIVE_UI)(pEapInput->pDataFromInteractiveUI))->UserProp),
|
|
sizeof(EAPMSCHAPv2_USER_PROPERTIES)
|
|
);
|
|
|
|
//
|
|
// Call into mschap here
|
|
//
|
|
ApInput.pszDomain = pEapwb->pUserProp->szDomain;
|
|
if ( ((PEAPMSCHAPv2_INTERACTIVE_UI)(pEapInput->pDataFromInteractiveUI))->fFlags &
|
|
EAPMSCHAPv2_INTERACTIVE_UI_FLAG_RETRY
|
|
)
|
|
{
|
|
ApInput.pszUserName = pEapwb->pUserProp->szUserName;
|
|
ApInput.pszPassword = pEapwb->pUserProp->szPassword;
|
|
}
|
|
else
|
|
{
|
|
if ( pEapwb->pConnProp->fFlags & EAPMSCHAPv2_FLAG_USE_WINLOGON_CREDS )
|
|
{
|
|
CopyMemory ( pEapwb->pUserProp->szPassword,
|
|
((PEAPMSCHAPv2_INTERACTIVE_UI)(pEapInput->pDataFromInteractiveUI))->UserProp.szPassword,
|
|
PWLEN
|
|
);
|
|
}
|
|
|
|
|
|
CopyMemory ( pEapwb->szOldPassword,
|
|
pEapwb->pUserProp->szPassword,
|
|
PWLEN
|
|
|
|
);
|
|
|
|
CopyMemory ( pEapwb->pUserProp->szPassword,
|
|
((PEAPMSCHAPv2_INTERACTIVE_UI)(pEapInput->pDataFromInteractiveUI))->szNewPassword,
|
|
PWLEN
|
|
);
|
|
|
|
ApInput.pszUserName = pEapwb->pUserProp->szUserName;
|
|
ApInput.pszPassword = pEapwb->pUserProp->szPassword;
|
|
ApInput.pszOldPassword = pEapwb->szOldPassword;
|
|
}
|
|
dwRetCode = CallMakeMessageAndSetEAPState(
|
|
pEapwb->pwb,
|
|
pReceiveBuf,
|
|
pSendBuf,
|
|
cbSendBuf,
|
|
&ApResult,
|
|
( pEapInput ? &ApInput : NULL ),
|
|
pEapOutput
|
|
);
|
|
if ( NO_ERROR == dwRetCode && pSendBuf )
|
|
{
|
|
pSendPacket->Code = EAPCODE_Response;
|
|
|
|
|
|
pSendPacket->Id = pEapwb->pwb->bIdToSend;
|
|
//
|
|
// Length = sizeof Header + sizeof MSCHAP packet to send
|
|
// This includes the first byte of
|
|
cbPacket = WireToHostFormat16( pSendBuf->Length );
|
|
|
|
CopyMemory ( pSendPacket->Data+1, pSendBuf, cbPacket);
|
|
|
|
cbPacket += sizeof(PPP_EAP_PACKET);
|
|
|
|
HostToWireFormat16( cbPacket, pSendPacket->Length );
|
|
|
|
pSendPacket->Data[0] = (BYTE)PPP_EAP_MSCHAPv2;
|
|
|
|
pEapwb->EapState = EMV2_ResponseSend;
|
|
pEapOutput->dwAuthResultCode = ApResult.dwError;
|
|
pEapOutput->Action = EAPACTION_Send;
|
|
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
TRACE("No Data received from interactive UI when expecting some");
|
|
//Work around for PPP misbehavior. We have invoked
|
|
//interactive UI and ppp is sending stuff to us all the time...
|
|
|
|
if ( !pEapwb->pUIContextData )
|
|
{
|
|
pEapOutput->dwAuthResultCode = ApResult.dwError;
|
|
pEapOutput->Action = EAPACTION_Done;
|
|
pEapwb->EapState = EMV2_Failure;
|
|
}
|
|
}
|
|
|
|
break;
|
|
case EMV2_CHAPAuthSuccess:
|
|
TRACE("EMV2_CHAPAuthSuccess");
|
|
//We should get an EAPSUCCESS here
|
|
if ( NULL != pReceivePacket )
|
|
{
|
|
if ( pReceivePacket->Code != EAPCODE_Success )
|
|
{
|
|
dwRetCode = ERROR_PPP_INVALID_PACKET;
|
|
pEapwb->EapState = EMV2_Failure;
|
|
break;
|
|
}
|
|
if ( ( pEapwb->dwInteractiveUIOperation &
|
|
EAPMSCHAPv2_INTERACTIVE_UI_FLAG_CHANGE_PWD_WINLOGON
|
|
) ||
|
|
( ( pEapwb->dwInteractiveUIOperation &
|
|
EAPMSCHAPv2_INTERACTIVE_UI_FLAG_RETRY ) &&
|
|
( pEapwb->pConnProp->fFlags &
|
|
EAPMSCHAPv2_FLAG_USE_WINLOGON_CREDS
|
|
)
|
|
)
|
|
)
|
|
{
|
|
//
|
|
// We need to plumb creds in winlogon.
|
|
//
|
|
dwRetCode = RasSetCachedCredentials ( pEapwb->pUserProp->szUserName,
|
|
pEapwb->pUserProp->szDomain,
|
|
pEapwb->pUserProp->szPassword
|
|
);
|
|
if ( NO_ERROR != dwRetCode )
|
|
{
|
|
TRACE1("RasSetCachedCredentials failed with error 0x%x", dwRetCode);
|
|
TRACE("Change password operation could not apply changes to winlogon.");
|
|
dwRetCode = NO_ERROR;
|
|
}
|
|
//since we entered this mode in winlogon mode
|
|
//wipe out the uid pwd if set
|
|
//
|
|
ZeroMemory ( pEapwb->pUserProp->szUserName, sizeof(pEapwb->pUserProp->szUserName) );
|
|
ZeroMemory ( pEapwb->pUserProp->szDomain, sizeof(pEapwb->pUserProp->szDomain) );
|
|
|
|
}
|
|
pEapwb->EapState = EMV2_Success;
|
|
pEapOutput->Action = EAPACTION_Done;
|
|
pEapOutput->fSaveUserData = TRUE;
|
|
|
|
if ( pEapwb->pUserProp->szPassword[0] )
|
|
{
|
|
DATA_BLOB DBPassword;
|
|
//Encode the password to send back.
|
|
dwRetCode = EncodePassword( strlen(pEapwb->pUserProp->szPassword) + 1,
|
|
pEapwb->pUserProp->szPassword,
|
|
&(DBPassword)
|
|
);
|
|
|
|
if ( NO_ERROR == dwRetCode )
|
|
{
|
|
AllocateUserDataWithEncPwd ( pEapwb, &DBPassword );
|
|
FreePassword ( &DBPassword );
|
|
}
|
|
else
|
|
{
|
|
TRACE1("EncodePassword failed with errror 0x%x.", dwRetCode);
|
|
dwRetCode = NO_ERROR;
|
|
}
|
|
|
|
}
|
|
RtlSecureZeroMemory ( pEapwb->pUserProp->szPassword, sizeof( pEapwb->pUserProp->szPassword ) );
|
|
LocalFree ( pEapOutput->pUserData );
|
|
pEapOutput->pUserData = (PBYTE)pEapwb->pUserProp;
|
|
pEapOutput->dwSizeOfUserData =
|
|
sizeof( EAPMSCHAPv2_USER_PROPERTIES) + pEapwb->pUserProp->cbEncPassword -1 ;
|
|
pEapOutput->pUserAttributes = pEapwb->pUserAttributes;
|
|
pEapOutput->dwAuthResultCode = pEapwb->dwAuthResultCode;
|
|
}
|
|
else
|
|
{
|
|
dwRetCode = ERROR_PPP_INVALID_PACKET;
|
|
}
|
|
break;
|
|
case EMV2_Success:
|
|
TRACE("EMV2_Success");
|
|
break;
|
|
case EMV2_Failure:
|
|
TRACE("EMV2_Failure");
|
|
break;
|
|
case EMV2_RequestSend:
|
|
default:
|
|
TRACE1("Why is this EAPMschapv2 in this state? %d", pEapwb->EapState);
|
|
break;
|
|
}
|
|
|
|
done:
|
|
if ( pSendBuf )
|
|
{
|
|
LocalFree(pSendBuf);
|
|
}
|
|
|
|
return dwRetCode;
|
|
}
|
|
|
|
|
|
//**
|
|
//
|
|
// Call: EapMSChapv2MakeMessage
|
|
//
|
|
// Returns: NO_ERROR - Success
|
|
// Non-zero returns - Failure
|
|
//
|
|
// Description:
|
|
//
|
|
|
|
DWORD
|
|
EapMSChapv2MakeMessage(
|
|
IN VOID* pWorkBuf,
|
|
IN PPP_EAP_PACKET* pReceivePacket,
|
|
OUT PPP_EAP_PACKET* pSendPacket,
|
|
IN DWORD cbSendPacket,
|
|
OUT PPP_EAP_OUTPUT* pEapOutput,
|
|
IN PPP_EAP_INPUT* pEapInput
|
|
)
|
|
{
|
|
DWORD dwRetCode = NO_ERROR;
|
|
EAPMSCHAPv2WB * pwb = (EAPMSCHAPv2WB *)pWorkBuf;
|
|
|
|
TRACE("EapMSChapv2MakeMessage");
|
|
//
|
|
// There may not be a real pressing need to split
|
|
// this function but it is just cleaner.
|
|
|
|
if ( pwb->pwb->fServer )
|
|
{
|
|
dwRetCode = EapMSChapv2SMakeMessage ( pWorkBuf,
|
|
pReceivePacket,
|
|
pSendPacket,
|
|
cbSendPacket,
|
|
pEapOutput,
|
|
pEapInput
|
|
);
|
|
|
|
}
|
|
else
|
|
{
|
|
dwRetCode = EapMSChapv2CMakeMessage ( pWorkBuf,
|
|
pReceivePacket,
|
|
pSendPacket,
|
|
cbSendPacket,
|
|
pEapOutput,
|
|
pEapInput
|
|
);
|
|
}
|
|
|
|
return dwRetCode;
|
|
|
|
}
|
|
|
|
|
|
|
|
//**
|
|
//
|
|
// Call: EapChapMakeMessage
|
|
//
|
|
// Returns: NO_ERROR - Success
|
|
// Non-zero returns - Failure
|
|
//
|
|
// Description:
|
|
//
|
|
DWORD
|
|
EapChapMakeMessage(
|
|
IN VOID* pWorkBuf,
|
|
IN PPP_EAP_PACKET* pReceivePacket,
|
|
OUT PPP_EAP_PACKET* pSendPacket,
|
|
IN DWORD cbSendPacket,
|
|
OUT PPP_EAP_OUTPUT* pEapOutput,
|
|
IN PPP_EAP_INPUT* pEapInput
|
|
)
|
|
{
|
|
DWORD dwRetCode;
|
|
PPP_CONFIG* pReceiveBuf = NULL;
|
|
PPP_CONFIG* pSendBuf = NULL;
|
|
DWORD cbSendBuf = 1500;
|
|
PPPAP_INPUT ApInput;
|
|
PPPAP_RESULT ApResult;
|
|
CHAPWB * pwb = (CHAPWB *)pWorkBuf;
|
|
|
|
ZeroMemory( &ApResult, sizeof(ApResult) );
|
|
|
|
if ( ( pSendBuf = LocalAlloc( LPTR, cbSendBuf ) ) == NULL )
|
|
{
|
|
return( ERROR_NOT_ENOUGH_MEMORY );
|
|
}
|
|
|
|
//
|
|
// Convert EAP to CHAP packet.
|
|
//
|
|
|
|
if ( pReceivePacket != NULL )
|
|
{
|
|
WORD cbPacket = WireToHostFormat16( pReceivePacket->Length );
|
|
|
|
if ( ( pReceiveBuf = LocalAlloc( LPTR, cbPacket ) ) == NULL )
|
|
{
|
|
LocalFree( pSendBuf );
|
|
|
|
return( ERROR_NOT_ENOUGH_MEMORY );
|
|
}
|
|
|
|
switch( pReceivePacket->Code )
|
|
{
|
|
case EAPCODE_Request:
|
|
|
|
//
|
|
// CHAP challenge code
|
|
//
|
|
|
|
pReceiveBuf->Code = 1;
|
|
|
|
//
|
|
// Length is EAP length - 1 for type
|
|
//
|
|
|
|
cbPacket--;
|
|
|
|
break;
|
|
|
|
case EAPCODE_Response:
|
|
|
|
//
|
|
// CHAP response code
|
|
//
|
|
|
|
pReceiveBuf->Code = 2;
|
|
|
|
//
|
|
// Length is EAP length - 1 for type
|
|
//
|
|
|
|
cbPacket--;
|
|
|
|
break;
|
|
|
|
case EAPCODE_Success:
|
|
|
|
//
|
|
// CHAP success code
|
|
//
|
|
|
|
pReceiveBuf->Code = 3;
|
|
|
|
break;
|
|
|
|
case EAPCODE_Failure:
|
|
|
|
//
|
|
// CHAP failure code
|
|
//
|
|
|
|
pReceiveBuf->Code = 4;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
//
|
|
// Unknown code
|
|
//
|
|
|
|
LocalFree( pSendBuf );
|
|
|
|
LocalFree( pReceiveBuf );
|
|
|
|
return( ERROR_PPP_INVALID_PACKET );
|
|
}
|
|
|
|
//
|
|
// Set the Id
|
|
//
|
|
|
|
pReceiveBuf->Id = pReceivePacket->Id;
|
|
|
|
//
|
|
// Set the length
|
|
//
|
|
|
|
HostToWireFormat16( (WORD)cbPacket, pReceiveBuf->Length );
|
|
|
|
if ( cbPacket > PPP_EAP_PACKET_HDR_LEN )
|
|
{
|
|
if ( ( pReceivePacket->Code == EAPCODE_Request ) ||
|
|
( pReceivePacket->Code == EAPCODE_Response ) )
|
|
{
|
|
//
|
|
// Do not copy EAP type
|
|
//
|
|
|
|
CopyMemory( pReceiveBuf->Data,
|
|
pReceivePacket->Data+1,
|
|
cbPacket - PPP_EAP_PACKET_HDR_LEN );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// As per the EAP spec, there shouldn't be any data but
|
|
// copy it anyway if there is.
|
|
//
|
|
|
|
CopyMemory( pReceiveBuf->Data,
|
|
pReceivePacket->Data,
|
|
cbPacket - PPP_EAP_PACKET_HDR_LEN );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( pEapInput != NULL )
|
|
{
|
|
MapEapInputToApInput( pEapInput, &ApInput );
|
|
|
|
//
|
|
// On the client side, if we received an indication that a success
|
|
// packet was received, then simply create a success packet and
|
|
// pass it in
|
|
//
|
|
|
|
if ( pEapInput->fSuccessPacketReceived )
|
|
{
|
|
if ( ( pReceiveBuf = LocalAlloc( LPTR, 4 ) ) == NULL )
|
|
{
|
|
LocalFree( pSendBuf );
|
|
|
|
return( ERROR_NOT_ENOUGH_MEMORY );
|
|
|
|
}
|
|
|
|
pReceiveBuf->Code = 3; // CHAP success code
|
|
|
|
pReceiveBuf->Id = pwb->bIdExpected;
|
|
|
|
HostToWireFormat16( (WORD)4, pReceiveBuf->Length );
|
|
}
|
|
}
|
|
|
|
dwRetCode = ChapMakeMessage(
|
|
pWorkBuf,
|
|
pReceiveBuf,
|
|
pSendBuf,
|
|
cbSendBuf,
|
|
&ApResult,
|
|
( pEapInput == NULL ) ? NULL : &ApInput );
|
|
|
|
if ( dwRetCode != NO_ERROR )
|
|
{
|
|
LocalFree( pSendBuf );
|
|
LocalFree( pReceiveBuf );
|
|
return( dwRetCode );
|
|
}
|
|
|
|
//
|
|
// Convert ApResult to pEapOutput
|
|
//
|
|
|
|
switch( ApResult.Action )
|
|
{
|
|
case APA_NoAction:
|
|
pEapOutput->Action = EAPACTION_NoAction;
|
|
break;
|
|
|
|
case APA_Done:
|
|
pEapOutput->Action = EAPACTION_Done;
|
|
break;
|
|
|
|
case APA_SendAndDone:
|
|
pEapOutput->Action = EAPACTION_SendAndDone;
|
|
break;
|
|
|
|
case APA_Send:
|
|
pEapOutput->Action = EAPACTION_Send;
|
|
break;
|
|
|
|
case APA_SendWithTimeout:
|
|
|
|
pEapOutput->Action = ( pwb->fServer )
|
|
? EAPACTION_SendWithTimeout
|
|
: EAPACTION_Send;
|
|
break;
|
|
|
|
case APA_SendWithTimeout2:
|
|
|
|
pEapOutput->Action = ( pwb->fServer )
|
|
? EAPACTION_SendWithTimeoutInteractive
|
|
: EAPACTION_Send;
|
|
break;
|
|
|
|
case APA_Authenticate:
|
|
pEapOutput->pUserAttributes = ApResult.pUserAttributes;
|
|
pEapOutput->Action = EAPACTION_Authenticate;
|
|
break;
|
|
|
|
default:
|
|
RTASSERT(FALSE);
|
|
break;
|
|
}
|
|
|
|
switch( pEapOutput->Action )
|
|
{
|
|
case EAPACTION_SendAndDone:
|
|
case EAPACTION_Send:
|
|
case EAPACTION_SendWithTimeout:
|
|
case EAPACTION_SendWithTimeoutInteractive:
|
|
{
|
|
//
|
|
// Convert CHAP to EAP packet
|
|
// Length is CHAP length + 1 for EAP type
|
|
//
|
|
|
|
WORD cbPacket = WireToHostFormat16( pSendBuf->Length );
|
|
|
|
switch( pSendBuf->Code )
|
|
{
|
|
case 1: // CHAPCODE_Challenge
|
|
pSendPacket->Code = EAPCODE_Request;
|
|
cbPacket++; // Add one octect for EAP type
|
|
break;
|
|
|
|
case 2: // CHAPCODE_Response
|
|
pSendPacket->Code = EAPCODE_Response;
|
|
cbPacket++; // Add one octect for EAP type
|
|
break;
|
|
|
|
case 3: // CHAPCODE_Success
|
|
pSendPacket->Code = EAPCODE_Success;
|
|
break;
|
|
|
|
case 4: // CHAPCODE_Failure
|
|
pSendPacket->Code = EAPCODE_Failure;
|
|
break;
|
|
|
|
default:
|
|
RTASSERT( FALSE );
|
|
break;
|
|
}
|
|
|
|
pSendPacket->Id = pSendBuf->Id;
|
|
|
|
//
|
|
// Need to copy the payload and the EAP type in the data field
|
|
//
|
|
|
|
if ( ( pSendPacket->Code == EAPCODE_Request ) ||
|
|
( pSendPacket->Code == EAPCODE_Response ) )
|
|
{
|
|
HostToWireFormat16( (WORD)cbPacket, pSendPacket->Length );
|
|
*pSendPacket->Data = EAPTYPE_MD5Challenge; // EAPTYPE_MD5Challenge;
|
|
|
|
//
|
|
// If there is a payload, copy it
|
|
//
|
|
|
|
if ( ( cbPacket - 1 ) > PPP_CONFIG_HDR_LEN )
|
|
{
|
|
CopyMemory( pSendPacket->Data+1,
|
|
pSendBuf->Data,
|
|
cbPacket - 1 - PPP_CONFIG_HDR_LEN );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Success or failure should not have any data bytes.
|
|
//
|
|
|
|
HostToWireFormat16( (WORD)4, pSendPacket->Length );
|
|
}
|
|
|
|
//
|
|
// Fall thru...
|
|
//
|
|
}
|
|
|
|
default:
|
|
|
|
pEapOutput->dwAuthResultCode = ApResult.dwError;
|
|
|
|
break;
|
|
}
|
|
|
|
LocalFree( pSendBuf );
|
|
|
|
if ( pReceiveBuf != NULL )
|
|
{
|
|
LocalFree( pReceiveBuf );
|
|
}
|
|
|
|
return( dwRetCode );
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//**
|
|
//
|
|
// Call: EapChapInitialize
|
|
//
|
|
// Returns: NO_ERROR - Success
|
|
// Non-zero returns - Failure
|
|
//
|
|
// Description:
|
|
//
|
|
DWORD
|
|
EapChapInitialize(
|
|
IN BOOL fInitialize
|
|
)
|
|
{
|
|
|
|
return ChapInit( fInitialize );
|
|
}
|
|
|
|
//**
|
|
//
|
|
// Call: RasEapGetInfo
|
|
//
|
|
// Returns: NO_ERROR - Success
|
|
// Non-zero returns - Failure
|
|
//
|
|
// Description:
|
|
//
|
|
DWORD
|
|
RasEapGetInfo(
|
|
IN DWORD dwEapTypeId,
|
|
OUT PPP_EAP_INFO* pEapInfo
|
|
)
|
|
{
|
|
if ( dwEapTypeId != PPP_EAP_MSCHAPv2 &&
|
|
dwEapTypeId != EAPTYPE_MD5Challenge
|
|
)
|
|
{
|
|
//
|
|
// We support 4 (MD5) eap type
|
|
//
|
|
//
|
|
// and now we support MSCHAP V2 also
|
|
//
|
|
//
|
|
|
|
return( ERROR_NOT_SUPPORTED );
|
|
}
|
|
|
|
ZeroMemory( pEapInfo, sizeof( PPP_EAP_INFO ) );
|
|
|
|
//
|
|
// Fill in the required information
|
|
//
|
|
|
|
pEapInfo->dwEapTypeId = dwEapTypeId;
|
|
|
|
if ( dwEapTypeId == EAPTYPE_MD5Challenge ) //MD5 CHAP
|
|
{
|
|
pEapInfo->RasEapInitialize = EapChapInitialize;
|
|
pEapInfo->RasEapBegin = EapChapBegin;
|
|
pEapInfo->RasEapEnd = EapChapEnd;
|
|
pEapInfo->RasEapMakeMessage = EapChapMakeMessage;
|
|
}
|
|
else
|
|
{
|
|
pEapInfo->RasEapInitialize = EapMSCHAPv2Initialize;
|
|
pEapInfo->RasEapBegin = EapMSChapv2Begin;
|
|
pEapInfo->RasEapEnd = EapMSChapv2End;
|
|
pEapInfo->RasEapMakeMessage = EapMSChapv2MakeMessage;
|
|
|
|
}
|
|
|
|
return( NO_ERROR );
|
|
}
|
|
|
|
DWORD
|
|
RasEapGetCredentials(
|
|
DWORD dwTypeId,
|
|
VOID * pWorkBuf,
|
|
VOID ** ppCredentials)
|
|
{
|
|
RASMAN_CREDENTIALS *pCreds = NULL;
|
|
DWORD dwRetCode = NO_ERROR;
|
|
EAPMSCHAPv2WB *pWB = (EAPMSCHAPv2WB *)pWorkBuf;
|
|
DWORD cbPassword;
|
|
PBYTE pbPassword = NULL;
|
|
|
|
if(PPP_EAP_MSCHAPv2 != dwTypeId)
|
|
{
|
|
dwRetCode = E_NOTIMPL;
|
|
goto done;
|
|
}
|
|
|
|
if(NULL == pWorkBuf)
|
|
{
|
|
dwRetCode = E_INVALIDARG;
|
|
goto done;
|
|
}
|
|
|
|
//
|
|
// Retrieve the password and return. Its important that
|
|
// the allocation below is made from process heap.
|
|
//
|
|
pCreds = LocalAlloc(LPTR, sizeof(RASMAN_CREDENTIALS));
|
|
if(NULL == pCreds)
|
|
{
|
|
dwRetCode = GetLastError();
|
|
goto done;
|
|
}
|
|
|
|
(VOID) StringCchCopyA(pCreds->szUserName, UNLEN, pWB->pwb->szUserName);
|
|
(VOID) StringCchCopyA(pCreds->szDomain, DNLEN, pWB->pwb->szDomain);
|
|
// DecodePw( pWB->pwb->chSeed, pWB->pwb->szPassword );
|
|
|
|
dwRetCode = DecodePassword(&pWB->pwb->DBPassword, &cbPassword,
|
|
&pbPassword);
|
|
|
|
if(NO_ERROR != dwRetCode)
|
|
{
|
|
goto done;
|
|
}
|
|
|
|
//
|
|
// Convert the password to unicode
|
|
//
|
|
if(!MultiByteToWideChar(CP_ACP,
|
|
0,
|
|
pWB->pwb->szPassword,
|
|
-1,
|
|
pCreds->wszPassword,
|
|
PWLEN))
|
|
{
|
|
TRACE("RasEapGetCredentials: multibytetowidechar failed");
|
|
}
|
|
|
|
// EncodePw(pWB->pwb->chSeed, pWB->pwb->szPassword);
|
|
RtlSecureZeroMemory(pbPassword, cbPassword);
|
|
LocalFree(pbPassword);
|
|
|
|
done:
|
|
*ppCredentials = (VOID *) pCreds;
|
|
return dwRetCode;
|
|
}
|
|
|
|
DWORD
|
|
ReadConnectionData(
|
|
IN BOOL fWireless,
|
|
IN BYTE* pConnectionDataIn,
|
|
IN DWORD dwSizeOfConnectionDataIn,
|
|
OUT PEAPMSCHAPv2_CONN_PROPERTIES* ppConnProp
|
|
)
|
|
{
|
|
DWORD dwErr = NO_ERROR;
|
|
PEAPMSCHAPv2_CONN_PROPERTIES pConnProp = NULL;
|
|
|
|
TRACE("ReadConnectionData");
|
|
RTASSERT(NULL != ppConnProp);
|
|
|
|
if ( dwSizeOfConnectionDataIn < sizeof(EAPMSCHAPv2_CONN_PROPERTIES) )
|
|
{
|
|
pConnProp = LocalAlloc(LPTR, sizeof(EAPMSCHAPv2_CONN_PROPERTIES));
|
|
|
|
if (NULL == pConnProp)
|
|
{
|
|
dwErr = GetLastError();
|
|
TRACE1("LocalAlloc failed and returned %d", dwErr);
|
|
goto LDone;
|
|
}
|
|
//This is a new structure
|
|
pConnProp->dwVersion = 1;
|
|
if ( fWireless )
|
|
{
|
|
|
|
//Set the use winlogon default flag
|
|
pConnProp->fFlags = EAPMSCHAPv2_FLAG_USE_WINLOGON_CREDS;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RTASSERT(NULL != pConnectionDataIn);
|
|
|
|
//
|
|
//Check to see if this is a version 0 structure
|
|
//If it is a version 0 structure then we migrate it to version1
|
|
//
|
|
|
|
pConnProp = LocalAlloc(LPTR, dwSizeOfConnectionDataIn);
|
|
|
|
if (NULL == pConnProp)
|
|
{
|
|
dwErr = GetLastError();
|
|
TRACE1("LocalAlloc failed and returned %d", dwErr);
|
|
goto LDone;
|
|
}
|
|
|
|
// If the user has mucked with the phonebook, we mustn't be affected.
|
|
// The size must be correct.
|
|
|
|
CopyMemory(pConnProp, pConnectionDataIn, dwSizeOfConnectionDataIn);
|
|
|
|
}
|
|
|
|
*ppConnProp = pConnProp;
|
|
pConnProp = NULL;
|
|
|
|
LDone:
|
|
|
|
LocalFree(pConnProp);
|
|
|
|
return(dwErr);
|
|
}
|
|
|
|
DWORD
|
|
AllocateUserDataWithEncPwd ( EAPMSCHAPv2WB * pEapwb, DATA_BLOB * pDBPassword )
|
|
{
|
|
DWORD dwRetCode = NO_ERROR;
|
|
PEAPMSCHAPv2_USER_PROPERTIES pUserProp = NULL;
|
|
|
|
TRACE("AllocateUserDataWithEncPwd");
|
|
|
|
pUserProp = LocalAlloc ( LPTR, sizeof( EAPMSCHAPv2_USER_PROPERTIES) + pDBPassword->cbData - 1 );
|
|
if ( NULL == pUserProp )
|
|
{
|
|
TRACE("LocalAlloc failed");
|
|
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto LDone;
|
|
}
|
|
//
|
|
// Set the fields here
|
|
//
|
|
pUserProp->dwVersion = pEapwb->pUserProp->dwVersion;
|
|
pUserProp->fFlags = pEapwb->pUserProp->fFlags;
|
|
pUserProp->dwMaxRetries = pEapwb->pUserProp->dwMaxRetries;
|
|
strncpy ( pUserProp->szUserName, pEapwb->pUserProp->szUserName, UNLEN );
|
|
strncpy ( pUserProp->szPassword, pEapwb->pUserProp->szPassword, PWLEN );
|
|
strncpy ( pUserProp->szDomain, pEapwb->pUserProp->szDomain, DNLEN );
|
|
pUserProp->cbEncPassword = pDBPassword->cbData;
|
|
CopyMemory (pUserProp->bEncPassword,
|
|
pDBPassword->pbData,
|
|
pDBPassword->cbData
|
|
);
|
|
LocalFree ( pEapwb->pUserProp );
|
|
pEapwb->pUserProp = pUserProp;
|
|
|
|
LDone:
|
|
return dwRetCode;
|
|
}
|
|
|
|
DWORD
|
|
ReadUserData(
|
|
IN BYTE* pUserDataIn,
|
|
IN DWORD dwSizeOfUserDataIn,
|
|
OUT PEAPMSCHAPv2_USER_PROPERTIES* ppUserProp
|
|
)
|
|
{
|
|
DWORD dwRetCode = NO_ERROR;
|
|
PEAPMSCHAPv2_USER_PROPERTIES pUserProp = NULL;
|
|
DATA_BLOB DBPassword;
|
|
DWORD cbPassword = 0;
|
|
PBYTE pbPassword = NULL;
|
|
TRACE("ReadUserData");
|
|
|
|
RTASSERT(NULL != ppUserProp);
|
|
if (dwSizeOfUserDataIn < sizeof(EAPMSCHAPv2_USER_PROPERTIES_v1))
|
|
{
|
|
pUserProp = LocalAlloc(LPTR, sizeof(EAPMSCHAPv2_USER_PROPERTIES));
|
|
|
|
if (NULL == pUserProp)
|
|
{
|
|
dwRetCode = GetLastError();
|
|
TRACE1("LocalAlloc failed and returned %d", dwRetCode);
|
|
goto LDone;
|
|
}
|
|
|
|
pUserProp->dwVersion = 2;
|
|
//Set Defaults here
|
|
pUserProp->dwMaxRetries = 2;
|
|
pUserProp->fFlags |= EAPMSCHAPv2_FLAG_ALLOW_CHANGEPWD;
|
|
|
|
}
|
|
else
|
|
{
|
|
DWORD dwSizeToAllocate = dwSizeOfUserDataIn;
|
|
RTASSERT(NULL != pUserDataIn);
|
|
if ( dwSizeOfUserDataIn == sizeof( EAPMSCHAPv2_USER_PROPERTIES_v1 ) )
|
|
{
|
|
//This is the old struct so allocation new number of bytes.
|
|
dwSizeToAllocate = sizeof( EAPMSCHAPv2_USER_PROPERTIES );
|
|
}
|
|
pUserProp = LocalAlloc(LPTR, dwSizeToAllocate);
|
|
|
|
if (NULL == pUserProp)
|
|
{
|
|
dwRetCode = GetLastError();
|
|
TRACE1("LocalAlloc failed and returned %d", dwRetCode);
|
|
goto LDone;
|
|
}
|
|
|
|
CopyMemory(pUserProp, pUserDataIn, dwSizeOfUserDataIn);
|
|
pUserProp->dwVersion = 2;
|
|
if ( pUserProp->cbEncPassword )
|
|
{
|
|
|
|
// We have the encrypted password.
|
|
DBPassword.cbData = pUserProp->cbEncPassword;
|
|
DBPassword.pbData = pUserProp->bEncPassword;
|
|
|
|
DecodePassword( &(DBPassword),
|
|
&cbPassword,
|
|
&pbPassword
|
|
);
|
|
if ( cbPassword )
|
|
{
|
|
CopyMemory ( pUserProp->szPassword,
|
|
pbPassword,
|
|
cbPassword
|
|
);
|
|
RtlSecureZeroMemory(pbPassword, cbPassword);
|
|
LocalFree(pbPassword);
|
|
}
|
|
}
|
|
}
|
|
|
|
*ppUserProp = pUserProp;
|
|
pUserProp = NULL;
|
|
|
|
LDone:
|
|
|
|
LocalFree(pUserProp);
|
|
|
|
return dwRetCode;
|
|
}
|
|
|
|
DWORD
|
|
OpenEapEAPMschapv2RegistryKey(
|
|
IN LPSTR pszMachineName,
|
|
IN REGSAM samDesired,
|
|
OUT HKEY* phKeyEapMschapv2
|
|
)
|
|
{
|
|
HKEY hKeyLocalMachine = NULL;
|
|
BOOL fHKeyLocalMachineOpened = FALSE;
|
|
BOOL fHKeyEapMschapv2Opened = FALSE;
|
|
|
|
LONG lRet;
|
|
DWORD dwErr = NO_ERROR;
|
|
|
|
RTASSERT(NULL != phKeyEapMschapv2);
|
|
|
|
lRet = RegConnectRegistry(pszMachineName, HKEY_LOCAL_MACHINE,
|
|
&hKeyLocalMachine);
|
|
if (ERROR_SUCCESS != lRet)
|
|
{
|
|
dwErr = lRet;
|
|
TRACE2("RegConnectRegistry(%s) failed and returned %d",
|
|
pszMachineName ? pszMachineName : "NULL", dwErr);
|
|
goto LDone;
|
|
}
|
|
fHKeyLocalMachineOpened = TRUE;
|
|
|
|
lRet = RegOpenKeyEx(hKeyLocalMachine, EAPMSCHAPv2_KEY, 0, samDesired,
|
|
phKeyEapMschapv2);
|
|
if (ERROR_SUCCESS != lRet)
|
|
{
|
|
dwErr = lRet;
|
|
TRACE2("RegOpenKeyEx(%s) failed and returned %d",
|
|
EAPMSCHAPv2_KEY, dwErr);
|
|
goto LDone;
|
|
}
|
|
fHKeyEapMschapv2Opened = TRUE;
|
|
|
|
LDone:
|
|
|
|
if ( fHKeyEapMschapv2Opened
|
|
&& (ERROR_SUCCESS != dwErr))
|
|
{
|
|
RegCloseKey(*phKeyEapMschapv2);
|
|
}
|
|
|
|
if (fHKeyLocalMachineOpened)
|
|
{
|
|
RegCloseKey(hKeyLocalMachine);
|
|
|
|
}
|
|
|
|
return(dwErr);
|
|
}
|
|
|
|
DWORD
|
|
ServerConfigDataIO(
|
|
IN BOOL fRead,
|
|
IN CHAR* pszMachineName,
|
|
IN OUT BYTE** ppData,
|
|
IN DWORD dwNumBytes
|
|
)
|
|
{
|
|
HKEY hKeyEapMschapv2;
|
|
PEAPMSCHAPv2_USER_PROPERTIES pUserProp;
|
|
BOOL fHKeyEapMsChapv2Opened = FALSE;
|
|
BYTE* pData = NULL;
|
|
DWORD dwSize = 0;
|
|
|
|
LONG lRet;
|
|
DWORD dwType;
|
|
DWORD dwErr = NO_ERROR;
|
|
|
|
RTASSERT(NULL != ppData);
|
|
|
|
dwErr = OpenEapEAPMschapv2RegistryKey(pszMachineName,
|
|
fRead ? KEY_READ : KEY_WRITE, &hKeyEapMschapv2);
|
|
if (ERROR_SUCCESS != dwErr)
|
|
{
|
|
goto LDone;
|
|
}
|
|
fHKeyEapMsChapv2Opened = TRUE;
|
|
|
|
if (fRead)
|
|
{
|
|
lRet = RegQueryValueEx(hKeyEapMschapv2, EAPMSCHAPv2_VAL_SERVER_CONFIG_DATA, NULL,
|
|
&dwType, NULL, &dwSize);
|
|
|
|
if ( (ERROR_SUCCESS != lRet)
|
|
|| (REG_BINARY != dwType)
|
|
|| (sizeof(EAPMSCHAPv2_USER_PROPERTIES) != dwSize))
|
|
{
|
|
pData = LocalAlloc(LPTR, sizeof(EAPMSCHAPv2_USER_PROPERTIES));
|
|
|
|
if (NULL == pData)
|
|
{
|
|
dwErr = GetLastError();
|
|
TRACE1("LocalAlloc failed and returned %d", dwErr);
|
|
goto LDone;
|
|
}
|
|
|
|
pUserProp = (EAPMSCHAPv2_USER_PROPERTIES*)pData;
|
|
pUserProp->dwVersion = 1;
|
|
}
|
|
else
|
|
{
|
|
pData = LocalAlloc(LPTR, dwSize);
|
|
|
|
if (NULL == pData)
|
|
{
|
|
dwErr = GetLastError();
|
|
TRACE1("LocalAlloc failed and returned %d", dwErr);
|
|
goto LDone;
|
|
}
|
|
|
|
lRet = RegQueryValueEx(hKeyEapMschapv2, EAPMSCHAPv2_VAL_SERVER_CONFIG_DATA,
|
|
NULL, &dwType, pData, &dwSize);
|
|
|
|
if (ERROR_SUCCESS != lRet)
|
|
{
|
|
dwErr = lRet;
|
|
TRACE2("RegQueryValueEx(%s) failed and returned %d",
|
|
EAPMSCHAPv2_VAL_SERVER_CONFIG_DATA, dwErr);
|
|
goto LDone;
|
|
}
|
|
|
|
}
|
|
|
|
pUserProp = (EAPMSCHAPv2_USER_PROPERTIES*)pData;
|
|
|
|
*ppData = pData;
|
|
pData = NULL;
|
|
}
|
|
else
|
|
{
|
|
lRet = RegSetValueEx(hKeyEapMschapv2, EAPMSCHAPv2_VAL_SERVER_CONFIG_DATA, 0,
|
|
REG_BINARY, *ppData, dwNumBytes);
|
|
|
|
if (ERROR_SUCCESS != lRet)
|
|
{
|
|
dwErr = lRet;
|
|
TRACE2("RegSetValueEx(%s) failed and returned %d",
|
|
EAPMSCHAPv2_VAL_SERVER_CONFIG_DATA, dwErr);
|
|
goto LDone;
|
|
}
|
|
}
|
|
|
|
LDone:
|
|
|
|
if (fHKeyEapMsChapv2Opened)
|
|
{
|
|
RegCloseKey(hKeyEapMschapv2);
|
|
}
|
|
|
|
LocalFree(pData);
|
|
|
|
return(dwErr);
|
|
}
|
|
|
|
|
|
DWORD
|
|
InvokeServerConfigUI (
|
|
HWND hWnd,
|
|
LPSTR pszMachineName,
|
|
BOOL fConfigDataInRegistry,
|
|
const BYTE* pConfigDataIn,
|
|
DWORD dwSizeofConfigDataIn,
|
|
BYTE** ppConfigDataOut,
|
|
DWORD* pdwSizeofConfigDataOut
|
|
)
|
|
{
|
|
DWORD dwRetCode = NO_ERROR;
|
|
INT_PTR nRet = 0;
|
|
EAPMSCHAPv2_SERVERCONFIG_DIALOG EapServerConfig;
|
|
|
|
BOOL fLocal = FALSE;
|
|
|
|
if (0 == *pszMachineName)
|
|
{
|
|
fLocal = TRUE;
|
|
}
|
|
|
|
if(fConfigDataInRegistry)
|
|
{
|
|
//Read the information from registry here
|
|
dwRetCode = ServerConfigDataIO(
|
|
TRUE /* fRead */,
|
|
fLocal ? NULL : pszMachineName,
|
|
(BYTE**)&(EapServerConfig.pUserProp), 0);
|
|
|
|
if (NO_ERROR != dwRetCode)
|
|
{
|
|
goto LDone;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(dwSizeofConfigDataIn < sizeof(EAPMSCHAPv2_USER_PROPERTIES))
|
|
{
|
|
dwRetCode = ReadUserData(NULL,0,
|
|
&EapServerConfig.pUserProp);
|
|
}
|
|
else
|
|
{
|
|
EapServerConfig.pUserProp = LocalAlloc(LPTR, dwSizeofConfigDataIn);
|
|
if(NULL == EapServerConfig.pUserProp)
|
|
{
|
|
dwRetCode = E_OUTOFMEMORY;
|
|
goto LDone;
|
|
}
|
|
|
|
CopyMemory(EapServerConfig.pUserProp, pConfigDataIn,
|
|
dwSizeofConfigDataIn);
|
|
}
|
|
|
|
if(NO_ERROR != dwRetCode)
|
|
{
|
|
goto LDone;
|
|
}
|
|
}
|
|
|
|
//Show the server config UI here
|
|
nRet = DialogBoxParam(
|
|
GetHInstance(),
|
|
MAKEINTRESOURCE(IDD_DIALOG_SERVER_CONFIG),
|
|
hWnd,
|
|
ServerConfigDialogProc,
|
|
(LPARAM)&EapServerConfig);
|
|
|
|
if (-1 == nRet)
|
|
{
|
|
dwRetCode = GetLastError();
|
|
goto LDone;
|
|
}
|
|
else if (IDOK != nRet)
|
|
{
|
|
dwRetCode = ERROR_CANCELLED;
|
|
goto LDone;
|
|
}
|
|
|
|
if(fConfigDataInRegistry)
|
|
{
|
|
//Read the information from registry here
|
|
dwRetCode = ServerConfigDataIO(
|
|
FALSE/* fRead */,
|
|
fLocal ? NULL : pszMachineName,
|
|
(BYTE**)&(EapServerConfig.pUserProp),
|
|
sizeof(EAPMSCHAPv2_USER_PROPERTIES));
|
|
|
|
LocalFree(EapServerConfig.pUserProp);
|
|
}
|
|
else
|
|
{
|
|
*ppConfigDataOut = (BYTE *) EapServerConfig.pUserProp;
|
|
*pdwSizeofConfigDataOut = sizeof(EAPMSCHAPv2_USER_PROPERTIES);
|
|
}
|
|
|
|
LDone:
|
|
return dwRetCode;
|
|
}
|
|
|
|
|
|
BOOL FFormatMachineIdentity1 ( LPWSTR lpszMachineNameRaw, LPWSTR * lppszMachineNameFormatted )
|
|
{
|
|
BOOL fRetVal = FALSE;
|
|
LPWSTR lpwszPrefix = L"host/";
|
|
|
|
RTASSERT(NULL != lpszMachineNameRaw );
|
|
RTASSERT(NULL != lppszMachineNameFormatted );
|
|
|
|
//
|
|
// Prepend host/ to the UPN name
|
|
//
|
|
|
|
*lppszMachineNameFormatted =
|
|
(LPWSTR)LocalAlloc ( LPTR, ( wcslen ( lpszMachineNameRaw ) + wcslen ( lpwszPrefix ) + 2 ) * sizeof(WCHAR) );
|
|
if ( NULL == *lppszMachineNameFormatted )
|
|
{
|
|
goto done;
|
|
}
|
|
|
|
wcscpy( *lppszMachineNameFormatted, lpwszPrefix );
|
|
wcscat ( *lppszMachineNameFormatted, lpszMachineNameRaw );
|
|
|
|
fRetVal = TRUE;
|
|
|
|
done:
|
|
return fRetVal;
|
|
}
|
|
|
|
|
|
BOOL FFormatMachineIdentity ( LPWSTR lpszMachineNameRaw, LPWSTR * lppszMachineNameFormatted )
|
|
{
|
|
BOOL fRetVal = TRUE;
|
|
LPWSTR s1 = lpszMachineNameRaw;
|
|
LPWSTR s2 = NULL;
|
|
|
|
RTASSERT(NULL != lpszMachineNameRaw );
|
|
RTASSERT(NULL != lppszMachineNameFormatted );
|
|
//Need to add 2 more chars. One for NULL and other for $ sign
|
|
*lppszMachineNameFormatted = (LPWSTR )LocalAlloc ( LPTR, (wcslen(lpszMachineNameRaw) + 2)* sizeof(WCHAR) );
|
|
if ( NULL == *lppszMachineNameFormatted )
|
|
{
|
|
return FALSE;
|
|
}
|
|
//find the first "." and that is the identity of the machine.
|
|
//the second "." is the domain.
|
|
//check to see if there at least 2 dots. If not the raw string is
|
|
//the output string
|
|
|
|
while ( *s1 )
|
|
{
|
|
if ( *s1 == '.' )
|
|
{
|
|
if ( !s2 ) //First dot
|
|
s2 = s1;
|
|
else //second dot
|
|
break;
|
|
}
|
|
s1++;
|
|
}
|
|
//can perform several additional checks here
|
|
|
|
if ( *s1 != '.' ) //there are no 2 dots so raw = formatted
|
|
{
|
|
wcscpy ( *lppszMachineNameFormatted, lpszMachineNameRaw );
|
|
goto done;
|
|
}
|
|
if ( s1-s2 < 2 )
|
|
{
|
|
wcscpy ( *lppszMachineNameFormatted, lpszMachineNameRaw );
|
|
goto done;
|
|
}
|
|
memcpy ( *lppszMachineNameFormatted, s2+1, ( s1-s2-1) * sizeof(WCHAR));
|
|
memcpy ( (*lppszMachineNameFormatted) + (s1-s2-1) , L"\\", sizeof(WCHAR));
|
|
wcsncpy ( (*lppszMachineNameFormatted) + (s1-s2), lpszMachineNameRaw, s2-lpszMachineNameRaw );
|
|
|
|
|
|
|
|
|
|
done:
|
|
|
|
//Append the $ sign no matter what...
|
|
wcscat ( *lppszMachineNameFormatted, L"$" );
|
|
//upper case the identity
|
|
_wcsupr ( *lppszMachineNameFormatted );
|
|
return fRetVal;
|
|
}
|
|
|
|
DWORD
|
|
GetLocalMachineName (
|
|
OUT WCHAR ** ppLocalMachineName
|
|
)
|
|
{
|
|
DWORD dwRetCode = NO_ERROR;
|
|
WCHAR * pLocalMachineName = NULL;
|
|
DWORD dwLocalMachineNameLen = 0;
|
|
|
|
if ( !GetComputerNameExW ( ComputerNameDnsFullyQualified,
|
|
pLocalMachineName,
|
|
&dwLocalMachineNameLen
|
|
)
|
|
)
|
|
{
|
|
dwRetCode = GetLastError();
|
|
if ( ERROR_MORE_DATA != dwRetCode )
|
|
goto LDone;
|
|
dwRetCode = NO_ERROR;
|
|
}
|
|
|
|
pLocalMachineName = (WCHAR *)LocalAlloc( LPTR, (dwLocalMachineNameLen * sizeof(WCHAR)) + sizeof(WCHAR) );
|
|
if ( NULL == pLocalMachineName )
|
|
{
|
|
dwRetCode = GetLastError();
|
|
goto LDone;
|
|
}
|
|
|
|
if ( !GetComputerNameExW ( ComputerNameDnsFullyQualified,
|
|
pLocalMachineName,
|
|
&dwLocalMachineNameLen
|
|
)
|
|
)
|
|
{
|
|
dwRetCode = GetLastError();
|
|
goto LDone;
|
|
}
|
|
|
|
*ppLocalMachineName = pLocalMachineName;
|
|
|
|
pLocalMachineName = NULL;
|
|
|
|
LDone:
|
|
|
|
LocalFree(pLocalMachineName);
|
|
|
|
return dwRetCode;
|
|
}
|
|
|
|
|
|
DWORD
|
|
RasEapGetIdentity(
|
|
IN DWORD dwEapTypeId,
|
|
IN HWND hwndParent,
|
|
IN DWORD dwFlags,
|
|
IN const WCHAR* pwszPhonebook,
|
|
IN const WCHAR* pwszEntry,
|
|
IN BYTE* pConnectionDataIn,
|
|
IN DWORD dwSizeOfConnectionDataIn,
|
|
IN BYTE* pUserDataIn,
|
|
IN DWORD dwSizeOfUserDataIn,
|
|
OUT BYTE** ppUserDataOut,
|
|
OUT DWORD* pdwSizeOfUserDataOut,
|
|
OUT WCHAR** ppwszIdentityOut
|
|
)
|
|
{
|
|
DWORD dwRetCode = NO_ERROR;
|
|
PEAPMSCHAPv2_USER_PROPERTIES pUserProp = NULL;
|
|
PEAPMSCHAPv2_CONN_PROPERTIES pConnProp = NULL;
|
|
EAPMSCHAPv2_LOGON_DIALOG EapMsChapv2LogonDialog;
|
|
INT_PTR nRet = 0;
|
|
LPWSTR lpwszLocalMachineName = NULL;
|
|
RASCREDENTIALSW RasCredentials;
|
|
CHAR szOldPwd[PWLEN+1]= {0};
|
|
BOOL fShowUI = TRUE;
|
|
|
|
|
|
TRACE("RasEapGetIdentity");
|
|
|
|
RTASSERT(NULL != ppUserDataOut);
|
|
RTASSERT(NULL != pdwSizeOfUserDataOut);
|
|
|
|
|
|
|
|
*ppUserDataOut = NULL;
|
|
|
|
ZeroMemory( &EapMsChapv2LogonDialog,
|
|
sizeof(EapMsChapv2LogonDialog) );
|
|
|
|
//
|
|
// Read User data first
|
|
//
|
|
|
|
dwRetCode = ReadUserData ( pUserDataIn,
|
|
dwSizeOfUserDataIn,
|
|
&pUserProp
|
|
);
|
|
if ( NO_ERROR != dwRetCode )
|
|
{
|
|
goto LDone;
|
|
}
|
|
|
|
//
|
|
// ReadConnectionData and see if we have been setup to use winlogon
|
|
// credentials. If so, just call to get user id and send back
|
|
// information.
|
|
//
|
|
|
|
dwRetCode = ReadConnectionData ( ( dwFlags & RAS_EAP_FLAG_8021X_AUTH ),
|
|
pConnectionDataIn,
|
|
dwSizeOfConnectionDataIn,
|
|
&pConnProp
|
|
);
|
|
|
|
if ( NO_ERROR != dwRetCode )
|
|
{
|
|
TRACE("Error reading connection properties");
|
|
goto LDone;
|
|
}
|
|
|
|
//MAchine Auth
|
|
if ( (dwFlags & RAS_EAP_FLAG_MACHINE_AUTH) )
|
|
{
|
|
|
|
//Send the identity back as domain\machine$
|
|
dwRetCode = GetLocalMachineName(&lpwszLocalMachineName );
|
|
if ( NO_ERROR != dwRetCode )
|
|
{
|
|
TRACE("Failed to get computer name");
|
|
goto LDone;
|
|
}
|
|
|
|
if ( ! FFormatMachineIdentity1 ( lpwszLocalMachineName,
|
|
ppwszIdentityOut )
|
|
)
|
|
{
|
|
TRACE("Failed to format machine identity");
|
|
}
|
|
|
|
*ppUserDataOut = (PBYTE)pUserProp;
|
|
*pdwSizeOfUserDataOut = sizeof(EAPMSCHAPv2_USER_PROPERTIES);
|
|
|
|
pUserProp = NULL;
|
|
goto LDone;
|
|
}
|
|
|
|
|
|
if ( !(pConnProp->fFlags & EAPMSCHAPv2_FLAG_USE_WINLOGON_CREDS) &&
|
|
dwFlags & RAS_EAP_FLAG_NON_INTERACTIVE
|
|
)
|
|
{
|
|
if ( (dwFlags & RAS_EAP_FLAG_8021X_AUTH ) )
|
|
{
|
|
// Wireless case - If there is no username or password cached
|
|
// we need to show the interactive UI
|
|
if( !pUserProp->szUserName[0] ||
|
|
!pUserProp->cbEncPassword
|
|
)
|
|
{
|
|
TRACE("Passed non interactive mode when interactive mode expected.");
|
|
dwRetCode = ERROR_INTERACTIVE_MODE;
|
|
goto LDone;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//VPN case
|
|
dwRetCode = ERROR_INTERACTIVE_MODE;
|
|
goto LDone;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//User Auth
|
|
if ( pConnProp->fFlags & EAPMSCHAPv2_FLAG_USE_WINLOGON_CREDS )
|
|
{
|
|
WCHAR wszUserName[UNLEN + DNLEN + 2];
|
|
DWORD dwNumChars = UNLEN + DNLEN;
|
|
|
|
if ( dwFlags & RAS_EAP_FLAG_LOGON)
|
|
{
|
|
//
|
|
// This is not allowed.
|
|
//
|
|
dwRetCode = ERROR_INVALID_MSCHAPV2_CONFIG;
|
|
goto LDone;
|
|
|
|
}
|
|
|
|
//Get currently logged on user name for identity
|
|
if (!GetUserNameExW(NameSamCompatible, wszUserName, &dwNumChars))
|
|
{
|
|
dwRetCode = GetLastError();
|
|
TRACE1("GetUserNameExW failed and returned %d", dwRetCode );
|
|
goto LDone;
|
|
}
|
|
|
|
*ppwszIdentityOut = (WCHAR *)LocalAlloc(LPTR,
|
|
dwNumChars * sizeof(WCHAR) + sizeof(WCHAR) );
|
|
|
|
if ( NULL == *ppwszIdentityOut )
|
|
{
|
|
TRACE("Failed to allocate memory for identity");
|
|
dwRetCode = ERROR_OUTOFMEMORY;
|
|
goto LDone;
|
|
}
|
|
CopyMemory(*ppwszIdentityOut, wszUserName, dwNumChars * sizeof(WCHAR) );
|
|
//All other fields in user prop remains blank
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
EapMsChapv2LogonDialog.pUserProp = pUserProp;
|
|
|
|
//
|
|
// Show the logon dialog for credentials
|
|
//
|
|
// if Machine Auth flag is passed in, we dont show
|
|
// the logon dialog. If Get Credentials from winlogon
|
|
// is passed in dont show logon dialog. else show
|
|
// logon dialog.
|
|
|
|
//
|
|
// Check to see if we have the password saved in LSA
|
|
// It should not matter if it is not.
|
|
if ( !(dwFlags & RAS_EAP_FLAG_LOGON ) )
|
|
{
|
|
#if 0
|
|
ZeroMemory(&RasCredentials, sizeof(RasCredentials));
|
|
RasCredentials.dwSize = sizeof(RasCredentials);
|
|
RasCredentials.dwMask = RASCM_Password;
|
|
|
|
dwRetCode = RasGetCredentialsW(pwszPhonebook, pwszEntry,
|
|
&RasCredentials);
|
|
|
|
if ( (dwRetCode == NO_ERROR)
|
|
&& (RasCredentials.dwMask & RASCM_Password))
|
|
{
|
|
//Set the password
|
|
WideCharToMultiByte(
|
|
CP_ACP,
|
|
0,
|
|
RasCredentials.szPassword,
|
|
-1,
|
|
pUserProp->szPassword,
|
|
PWLEN + 1,
|
|
NULL,
|
|
NULL );
|
|
strncpy (szOldPwd, pUserProp->szPassword, PWLEN );
|
|
}
|
|
dwRetCode = NO_ERROR;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
EapMsChapv2LogonDialog.pUserProp->fFlags |= EAPMSCHAPv2_FLAG_CALLED_WITHIN_WINLOGON;
|
|
if ( pUserProp->fFlags & EAPMSCHAPv2_FLAG_SAVE_UID_PWD )
|
|
pUserProp->fFlags &= ~EAPMSCHAPv2_FLAG_SAVE_UID_PWD;
|
|
}
|
|
|
|
if ( dwFlags & RAS_EAP_FLAG_8021X_AUTH )
|
|
{
|
|
EapMsChapv2LogonDialog.pUserProp->fFlags |= EAPMSCHAPv2_FLAG_8021x;
|
|
}
|
|
// Check to see if our existing user props are cached? If so,
|
|
// there is no need to show the dialog
|
|
if ( (dwFlags & RAS_EAP_FLAG_8021X_AUTH ) &&
|
|
pUserProp->szUserName[0] &&
|
|
pUserProp->cbEncPassword
|
|
)
|
|
{
|
|
fShowUI = FALSE;
|
|
}
|
|
if ( fShowUI )
|
|
{
|
|
//Either we have an empty user name
|
|
//or password
|
|
|
|
nRet = DialogBoxParam(
|
|
GetHInstance(),
|
|
MAKEINTRESOURCE(IDD_DIALOG_LOGON),
|
|
hwndParent,
|
|
LogonDialogProc,
|
|
(LPARAM)&EapMsChapv2LogonDialog);
|
|
|
|
if (-1 == nRet)
|
|
{
|
|
dwRetCode = GetLastError();
|
|
goto LDone;
|
|
}
|
|
else if (IDOK != nRet)
|
|
{
|
|
dwRetCode = ERROR_CANCELLED;
|
|
goto LDone;
|
|
}
|
|
}
|
|
if ( !(dwFlags & RAS_EAP_FLAG_ROUTER ) )
|
|
{
|
|
|
|
//
|
|
// Setup the identity parameter here
|
|
//
|
|
dwRetCode = GetIdentityFromUserName ( pUserProp->szUserName,
|
|
pUserProp->szDomain,
|
|
ppwszIdentityOut
|
|
);
|
|
if ( NO_ERROR != dwRetCode )
|
|
{
|
|
goto LDone;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#if 0
|
|
if ( !(dwFlags & RAS_EAP_FLAG_LOGON ) )
|
|
{
|
|
|
|
ZeroMemory(&RasCredentials, sizeof(RasCredentials));
|
|
RasCredentials.dwSize = sizeof(RasCredentials);
|
|
RasCredentials.dwMask = RASCM_Password;
|
|
|
|
if ( pUserProp->fFlags & EAPMSCHAPv2_FLAG_SAVE_UID_PWD )
|
|
{
|
|
//
|
|
// Check to see if the new password is different from the old one
|
|
//
|
|
if ( strcmp ( szOldPwd, pUserProp->szPassword ) )
|
|
{
|
|
//
|
|
// There is a new password for us to save.
|
|
//
|
|
MultiByteToWideChar( CP_ACP,
|
|
0,
|
|
pUserProp->szPassword,
|
|
-1,
|
|
RasCredentials.szPassword,
|
|
sizeof(RasCredentials.szPassword)/sizeof(WCHAR) );
|
|
|
|
RasSetCredentialsW(pwszPhonebook, pwszEntry, &RasCredentials,
|
|
FALSE /* fClearCredentials */);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RasSetCredentialsW(pwszPhonebook, pwszEntry, &RasCredentials,
|
|
TRUE /* fClearCredentials */);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
*ppUserDataOut = (PBYTE)pUserProp;
|
|
*pdwSizeOfUserDataOut = sizeof(EAPMSCHAPv2_USER_PROPERTIES);
|
|
|
|
pUserProp = NULL;
|
|
|
|
LDone:
|
|
if ( lpwszLocalMachineName )
|
|
LocalFree(lpwszLocalMachineName);
|
|
|
|
LocalFree(pUserProp);
|
|
return dwRetCode;
|
|
}
|
|
|
|
DWORD
|
|
RasEapInvokeConfigUI(
|
|
IN DWORD dwEapTypeId,
|
|
IN HWND hwndParent,
|
|
IN DWORD dwFlags,
|
|
IN BYTE* pConnectionDataIn,
|
|
IN DWORD dwSizeOfConnectionDataIn,
|
|
OUT BYTE** ppConnectionDataOut,
|
|
OUT DWORD* pdwSizeOfConnectionDataOut
|
|
)
|
|
{
|
|
DWORD dwRetCode = NO_ERROR;
|
|
EAPMSCHAPv2_CLIENTCONFIG_DIALOG ClientConfigDialog;
|
|
INT_PTR nRet;
|
|
|
|
TRACE("RasEapInvokeConfigUI");
|
|
|
|
*ppConnectionDataOut = NULL;
|
|
*pdwSizeOfConnectionDataOut = 0;
|
|
//
|
|
// In case of Router there is nothing to configure
|
|
//
|
|
if ( dwFlags & RAS_EAP_FLAG_ROUTER )
|
|
{
|
|
CHAR szMessage[512] = {0};
|
|
CHAR szHeader[64] = {0};
|
|
//
|
|
// Load resource from res file
|
|
//
|
|
|
|
LoadString( GetHInstance(),
|
|
IDS_NO_ROUTER_CONFIG,
|
|
szMessage,
|
|
sizeof(szMessage)-1
|
|
);
|
|
LoadString( GetHInstance(),
|
|
IDS_MESSAGE_HEADER,
|
|
szHeader,
|
|
sizeof(szHeader)-1
|
|
);
|
|
|
|
MessageBox (hwndParent,
|
|
szMessage,
|
|
szHeader,
|
|
MB_OK
|
|
);
|
|
goto LDone;
|
|
}
|
|
//
|
|
// If we are a client, read connection data and call
|
|
// the dialog to do the config.
|
|
//
|
|
dwRetCode = ReadConnectionData ( ( dwFlags & RAS_EAP_FLAG_8021X_AUTH ),
|
|
pConnectionDataIn,
|
|
dwSizeOfConnectionDataIn,
|
|
&(ClientConfigDialog.pConnProp)
|
|
);
|
|
if ( NO_ERROR != dwRetCode )
|
|
{
|
|
TRACE("Error reading conn prop");
|
|
goto LDone;
|
|
}
|
|
|
|
//
|
|
// Call in the dialog to show connection props
|
|
//
|
|
|
|
nRet = DialogBoxParam(
|
|
GetHInstance(),
|
|
MAKEINTRESOURCE(IDD_DIALOG_CLEINT_CONFIG),
|
|
hwndParent,
|
|
ClientConfigDialogProc,
|
|
(LPARAM)&ClientConfigDialog);
|
|
|
|
if (-1 == nRet)
|
|
{
|
|
dwRetCode = GetLastError();
|
|
goto LDone;
|
|
}
|
|
else if (IDOK != nRet)
|
|
{
|
|
dwRetCode = ERROR_CANCELLED;
|
|
goto LDone;
|
|
}
|
|
//
|
|
// Setup the out parameters in the ppDataFromInteractiveUI
|
|
// so that we can send the new uid/pwd back
|
|
//
|
|
|
|
* ppConnectionDataOut = LocalAlloc( LPTR, sizeof(EAPMSCHAPv2_CONN_PROPERTIES) );
|
|
if ( NULL == * ppConnectionDataOut )
|
|
{
|
|
TRACE("Error allocating memory for pConnectionDataOut");
|
|
dwRetCode = ERROR_OUTOFMEMORY;
|
|
goto LDone;
|
|
}
|
|
CopyMemory( *ppConnectionDataOut,
|
|
ClientConfigDialog.pConnProp,
|
|
sizeof(EAPMSCHAPv2_CONN_PROPERTIES)
|
|
);
|
|
* pdwSizeOfConnectionDataOut = sizeof(EAPMSCHAPv2_CONN_PROPERTIES);
|
|
|
|
LDone:
|
|
LocalFree(ClientConfigDialog.pConnProp);
|
|
return dwRetCode;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
RasEapFreeMemory(
|
|
IN BYTE* pMemory
|
|
)
|
|
{
|
|
LocalFree(pMemory);
|
|
return(NO_ERROR);
|
|
}
|
|
|
|
DWORD
|
|
RasEapInvokeInteractiveUI(
|
|
IN DWORD dwEapTypeId,
|
|
IN HWND hWndParent,
|
|
IN BYTE* pUIContextData,
|
|
IN DWORD dwSizeofUIContextData,
|
|
OUT BYTE** ppDataFromInteractiveUI,
|
|
OUT DWORD* pdwSizeOfDataFromInteractiveUI
|
|
)
|
|
{
|
|
DWORD dwRetCode = NO_ERROR;
|
|
PEAPMSCHAPv2_USER_PROPERTIES pUserProp = NULL;
|
|
PEAPMSCHAPv2_INTERACTIVE_UI pEapMschapv2InteractiveUI = NULL;
|
|
EAPMSCHAPv2_CHANGEPWD_DIALOG EapMsChapv2ChangePwdDialog;
|
|
EAPMSCHAPv2_LOGON_DIALOG EapMsChapv2LogonDialog;
|
|
INT_PTR nRet = 0;
|
|
|
|
TRACE("RasEapInvokeInteractiveUI");
|
|
RTASSERT(NULL != pUIContextData);
|
|
RTASSERT(dwSizeofUIContextData == sizeof(EAPMSCHAPv2_INTERACTIVE_UI));
|
|
|
|
* ppDataFromInteractiveUI = NULL;
|
|
* pdwSizeOfDataFromInteractiveUI = 0;
|
|
|
|
pEapMschapv2InteractiveUI = (PEAPMSCHAPv2_INTERACTIVE_UI)pUIContextData;
|
|
|
|
if ( pEapMschapv2InteractiveUI->fFlags & EAPMSCHAPv2_INTERACTIVE_UI_FLAG_RETRY )
|
|
{
|
|
ZeroMemory( &EapMsChapv2LogonDialog,
|
|
sizeof(EapMsChapv2LogonDialog) );
|
|
|
|
EapMsChapv2LogonDialog.pUserProp =
|
|
&(pEapMschapv2InteractiveUI->UserProp);
|
|
|
|
//
|
|
// Show the retry dialog for credentials
|
|
//
|
|
|
|
nRet = DialogBoxParam(
|
|
GetHInstance(),
|
|
MAKEINTRESOURCE(IDD_DIALOG_RETRY_LOGON),
|
|
hWndParent,
|
|
RetryDialogProc,
|
|
(LPARAM)&EapMsChapv2LogonDialog);
|
|
|
|
if (-1 == nRet)
|
|
{
|
|
dwRetCode = GetLastError();
|
|
goto LDone;
|
|
}
|
|
else if (IDOK != nRet)
|
|
{
|
|
dwRetCode = ERROR_CANCELLED;
|
|
goto LDone;
|
|
}
|
|
//
|
|
// Setup the out parameters in the ppDataFromInteractiveUI
|
|
// so that we can send the new uid/pwd back
|
|
//
|
|
|
|
* ppDataFromInteractiveUI = LocalAlloc( LPTR, sizeof(EAPMSCHAPv2_INTERACTIVE_UI) );
|
|
if ( NULL == * ppDataFromInteractiveUI )
|
|
{
|
|
TRACE("Error allocating memory for pDataFromInteractiveUI");
|
|
dwRetCode = ERROR_OUTOFMEMORY;
|
|
goto LDone;
|
|
}
|
|
CopyMemory ( *ppDataFromInteractiveUI,
|
|
pEapMschapv2InteractiveUI,
|
|
sizeof( EAPMSCHAPv2_INTERACTIVE_UI )
|
|
);
|
|
|
|
pEapMschapv2InteractiveUI = (PEAPMSCHAPv2_INTERACTIVE_UI)*ppDataFromInteractiveUI;
|
|
|
|
CopyMemory( &(pEapMschapv2InteractiveUI->UserProp),
|
|
EapMsChapv2LogonDialog.pUserProp,
|
|
sizeof(EAPMSCHAPv2_USER_PROPERTIES)
|
|
);
|
|
* pdwSizeOfDataFromInteractiveUI = sizeof(EAPMSCHAPv2_INTERACTIVE_UI);
|
|
|
|
}
|
|
else if ( ( pEapMschapv2InteractiveUI->fFlags & EAPMSCHAPv2_INTERACTIVE_UI_FLAG_CHANGE_PWD )||
|
|
( pEapMschapv2InteractiveUI->fFlags & EAPMSCHAPv2_INTERACTIVE_UI_FLAG_CHANGE_PWD_WINLOGON )
|
|
)
|
|
{
|
|
//
|
|
// Change password
|
|
//
|
|
ZeroMemory( &EapMsChapv2ChangePwdDialog,
|
|
sizeof(EapMsChapv2ChangePwdDialog)
|
|
);
|
|
|
|
EapMsChapv2ChangePwdDialog.pInteractiveUIData = (PEAPMSCHAPv2_INTERACTIVE_UI)pUIContextData;
|
|
//
|
|
// Show the retry dialog for credentials
|
|
//
|
|
if ( pEapMschapv2InteractiveUI->fFlags & EAPMSCHAPv2_INTERACTIVE_UI_FLAG_CHANGE_PWD )
|
|
{
|
|
|
|
nRet = DialogBoxParam(
|
|
GetHInstance(),
|
|
MAKEINTRESOURCE(IDD_DIALOG_CHANGE_PASSWORD),
|
|
hWndParent,
|
|
ChangePasswordDialogProc,
|
|
(LPARAM)&EapMsChapv2ChangePwdDialog);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We need to get this dialog from rasdlg because
|
|
// in XPSP1 no more resources can be added.
|
|
//
|
|
nRet = DialogBoxParam(
|
|
GetRasDlgDLLHInstance(),
|
|
MAKEINTRESOURCE(DID_CP_ChangePassword2),
|
|
hWndParent,
|
|
ChangePasswordDialogProc,
|
|
(LPARAM)&EapMsChapv2ChangePwdDialog);
|
|
|
|
|
|
}
|
|
if (-1 == nRet)
|
|
{
|
|
dwRetCode = GetLastError();
|
|
goto LDone;
|
|
}
|
|
else if (IDOK != nRet)
|
|
{
|
|
dwRetCode = ERROR_CANCELLED;
|
|
goto LDone;
|
|
}
|
|
//
|
|
// Setup the out parameters in the ppDataFromInteractiveUI
|
|
// so that we can send the new uid/pwd back
|
|
//
|
|
|
|
* ppDataFromInteractiveUI = LocalAlloc( LPTR, sizeof(EAPMSCHAPv2_INTERACTIVE_UI) );
|
|
if ( NULL == * ppDataFromInteractiveUI )
|
|
{
|
|
TRACE("Error allocating memory for pDataFromInteractiveUI");
|
|
dwRetCode = ERROR_OUTOFMEMORY;
|
|
goto LDone;
|
|
}
|
|
CopyMemory( *ppDataFromInteractiveUI,
|
|
EapMsChapv2ChangePwdDialog.pInteractiveUIData,
|
|
sizeof(EAPMSCHAPv2_INTERACTIVE_UI)
|
|
);
|
|
* pdwSizeOfDataFromInteractiveUI = sizeof(EAPMSCHAPv2_INTERACTIVE_UI);
|
|
}
|
|
LDone:
|
|
return dwRetCode;
|
|
}
|
|
|
|
|
|
DWORD
|
|
EapMSCHAPv2Initialize(
|
|
IN BOOL fInitialize
|
|
)
|
|
{
|
|
static DWORD dwRefCount = 0;
|
|
DWORD dwRetCode = NO_ERROR;
|
|
|
|
if ( fInitialize )
|
|
{
|
|
//Initialize
|
|
if (0 == dwRefCount)
|
|
{
|
|
dwRetCode = IASLogonInitialize();
|
|
}
|
|
dwRefCount ++;
|
|
}
|
|
else
|
|
{
|
|
dwRefCount --;
|
|
if (0 == dwRefCount)
|
|
{
|
|
IASLogonShutdown();
|
|
}
|
|
}
|
|
dwRetCode = ChapInit( fInitialize );
|
|
return dwRetCode;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// All the dialogs required for EAPMSCHAPv2 go here. Move into it's own file later.
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static const DWORD g_adwHelp[] =
|
|
{
|
|
0, 0
|
|
};
|
|
|
|
|
|
|
|
VOID
|
|
ContextHelp(
|
|
IN const DWORD* padwMap,
|
|
IN HWND hWndDlg,
|
|
IN UINT unMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam
|
|
)
|
|
{
|
|
return;
|
|
}
|
|
|
|
BOOL
|
|
LogonInitDialog(
|
|
IN HWND hWnd,
|
|
IN LPARAM lParam
|
|
)
|
|
{
|
|
PEAPMSCHAPv2_LOGON_DIALOG pMSCHAPv2LogonDialog;
|
|
PEAPMSCHAPv2_USER_PROPERTIES pUserProp;
|
|
|
|
SetWindowLongPtr(hWnd, DWLP_USER, lParam);
|
|
|
|
|
|
pMSCHAPv2LogonDialog = (PEAPMSCHAPv2_LOGON_DIALOG)lParam;
|
|
pUserProp = pMSCHAPv2LogonDialog->pUserProp;
|
|
|
|
pMSCHAPv2LogonDialog->hWndUserName =
|
|
GetDlgItem(hWnd, IDC_EDIT_USERNAME);
|
|
|
|
pMSCHAPv2LogonDialog->hWndPassword =
|
|
GetDlgItem(hWnd, IDC_EDIT_PASSWORD);
|
|
|
|
pMSCHAPv2LogonDialog->hWndDomain =
|
|
GetDlgItem(hWnd, IDC_EDIT_DOMAIN);
|
|
|
|
pMSCHAPv2LogonDialog->hWndSavePassword =
|
|
GetDlgItem(hWnd, IDC_CHECK_SAVE_UID_PWD);
|
|
|
|
|
|
|
|
//Setup upper limit on text boxes
|
|
SendMessage(pMSCHAPv2LogonDialog->hWndUserName,
|
|
EM_LIMITTEXT,
|
|
UNLEN,
|
|
0L
|
|
);
|
|
|
|
SendMessage(pMSCHAPv2LogonDialog->hWndPassword,
|
|
EM_LIMITTEXT,
|
|
PWLEN,
|
|
0L
|
|
);
|
|
|
|
SendMessage(pMSCHAPv2LogonDialog->hWndDomain,
|
|
EM_LIMITTEXT,
|
|
DNLEN,
|
|
0L
|
|
);
|
|
if ( pUserProp->fFlags & EAPMSCHAPv2_FLAG_CALLED_WITHIN_WINLOGON )
|
|
{
|
|
EnableWindow ( pMSCHAPv2LogonDialog->hWndSavePassword, FALSE );
|
|
}
|
|
else if ( pUserProp->fFlags & EAPMSCHAPv2_FLAG_8021x )
|
|
{
|
|
ShowWindow ( pMSCHAPv2LogonDialog->hWndSavePassword, SW_HIDE );
|
|
}
|
|
else
|
|
{
|
|
|
|
if ( pUserProp->fFlags & EAPMSCHAPv2_FLAG_SAVE_UID_PWD )
|
|
{
|
|
CheckDlgButton(hWnd, IDC_CHECK_SAVE_UID_PWD, BST_CHECKED);
|
|
}
|
|
}
|
|
|
|
if ( pUserProp->szUserName[0] )
|
|
{
|
|
SetWindowText( pMSCHAPv2LogonDialog->hWndUserName,
|
|
pUserProp->szUserName
|
|
);
|
|
}
|
|
|
|
if ( pUserProp->szPassword[0] )
|
|
{
|
|
SetWindowText( pMSCHAPv2LogonDialog->hWndPassword,
|
|
pUserProp->szPassword
|
|
);
|
|
}
|
|
|
|
if ( pUserProp->szDomain[0] )
|
|
{
|
|
SetWindowText( pMSCHAPv2LogonDialog->hWndDomain,
|
|
pUserProp->szDomain
|
|
);
|
|
}
|
|
|
|
if ( !pUserProp->szUserName[0] )
|
|
{
|
|
|
|
SetFocus(pMSCHAPv2LogonDialog->hWndUserName);
|
|
}
|
|
else
|
|
{
|
|
SetFocus(pMSCHAPv2LogonDialog->hWndPassword);
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
BOOL
|
|
LogonCommand(
|
|
IN PEAPMSCHAPv2_LOGON_DIALOG pMSCHAPv2LogonDialog,
|
|
IN WORD wNotifyCode,
|
|
IN WORD wId,
|
|
IN HWND hWndDlg,
|
|
IN HWND hWndCtrl
|
|
)
|
|
{
|
|
BOOL fRetVal = FALSE;
|
|
PEAPMSCHAPv2_USER_PROPERTIES pUserProp = pMSCHAPv2LogonDialog->pUserProp;
|
|
switch(wId)
|
|
{
|
|
case IDC_CHECK_SAVE_UID_PWD:
|
|
|
|
if ( pUserProp->fFlags & EAPMSCHAPv2_FLAG_SAVE_UID_PWD )
|
|
{
|
|
|
|
//
|
|
// We got the creds from rasman. So toggle the display
|
|
//
|
|
if ( BST_CHECKED ==
|
|
IsDlgButtonChecked ( hWndDlg, IDC_CHECK_SAVE_UID_PWD )
|
|
)
|
|
{
|
|
SetWindowText( pMSCHAPv2LogonDialog->hWndPassword,
|
|
pUserProp->szPassword
|
|
);
|
|
}
|
|
else
|
|
{
|
|
|
|
SetWindowText( pMSCHAPv2LogonDialog->hWndPassword,
|
|
""
|
|
);
|
|
}
|
|
}
|
|
break;
|
|
case IDOK:
|
|
//
|
|
//grab info from the fields and set it in
|
|
//the logon dialog structure
|
|
//
|
|
GetWindowText( pMSCHAPv2LogonDialog->hWndUserName,
|
|
pUserProp->szUserName,
|
|
UNLEN+1
|
|
);
|
|
|
|
GetWindowText( pMSCHAPv2LogonDialog->hWndPassword,
|
|
pUserProp->szPassword,
|
|
PWLEN+1
|
|
);
|
|
|
|
GetWindowText ( pMSCHAPv2LogonDialog->hWndDomain,
|
|
pUserProp->szDomain,
|
|
DNLEN+1
|
|
);
|
|
|
|
if ( !(pUserProp->fFlags & EAPMSCHAPv2_FLAG_CALLED_WITHIN_WINLOGON )
|
|
&& !(pUserProp->fFlags & EAPMSCHAPv2_FLAG_8021x) )
|
|
{
|
|
|
|
if ( BST_CHECKED ==
|
|
IsDlgButtonChecked ( hWndDlg, IDC_CHECK_SAVE_UID_PWD )
|
|
)
|
|
{
|
|
pUserProp->fFlags |= EAPMSCHAPv2_FLAG_SAVE_UID_PWD;
|
|
}
|
|
else
|
|
{
|
|
pUserProp->fFlags &= ~EAPMSCHAPv2_FLAG_SAVE_UID_PWD;
|
|
|
|
}
|
|
}
|
|
else if ( pUserProp->fFlags & EAPMSCHAPv2_FLAG_8021x )
|
|
{
|
|
pUserProp->fFlags |= EAPMSCHAPv2_FLAG_SAVE_UID_PWD;
|
|
}
|
|
|
|
case IDCANCEL:
|
|
|
|
EndDialog(hWndDlg, wId);
|
|
fRetVal = TRUE;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return fRetVal;
|
|
}
|
|
|
|
|
|
INT_PTR CALLBACK
|
|
LogonDialogProc(
|
|
IN HWND hWnd,
|
|
IN UINT unMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam
|
|
)
|
|
{
|
|
PEAPMSCHAPv2_LOGON_DIALOG pMSCHAPv2LogonDialog;
|
|
|
|
switch (unMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
|
|
return(LogonInitDialog(hWnd, lParam));
|
|
|
|
case WM_HELP:
|
|
case WM_CONTEXTMENU:
|
|
{
|
|
ContextHelp(g_adwHelp, hWnd, unMsg, wParam, lParam);
|
|
break;
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
|
|
pMSCHAPv2LogonDialog = (PEAPMSCHAPv2_LOGON_DIALOG)GetWindowLongPtr(hWnd, DWLP_USER);
|
|
|
|
return(LogonCommand(pMSCHAPv2LogonDialog,
|
|
HIWORD(wParam),
|
|
LOWORD(wParam),
|
|
hWnd,
|
|
(HWND)lParam)
|
|
);
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
RetryInitDialog(
|
|
IN HWND hWnd,
|
|
IN LPARAM lParam
|
|
)
|
|
{
|
|
PEAPMSCHAPv2_LOGON_DIALOG pMSCHAPv2LogonDialog;
|
|
PEAPMSCHAPv2_USER_PROPERTIES pUserProp;
|
|
|
|
SetWindowLongPtr(hWnd, DWLP_USER, lParam);
|
|
|
|
|
|
pMSCHAPv2LogonDialog = (PEAPMSCHAPv2_LOGON_DIALOG)lParam;
|
|
pUserProp = pMSCHAPv2LogonDialog->pUserProp;
|
|
|
|
pMSCHAPv2LogonDialog->hWndUserName =
|
|
GetDlgItem(hWnd, IDC_RETRY_USERNAME);
|
|
|
|
pMSCHAPv2LogonDialog->hWndPassword =
|
|
GetDlgItem(hWnd, IDC_RETRY_PASSWORD);
|
|
|
|
pMSCHAPv2LogonDialog->hWndDomain =
|
|
GetDlgItem(hWnd, IDC_RETRY_DOMAIN);
|
|
|
|
|
|
//Setup upper limit on text boxes
|
|
SendMessage(pMSCHAPv2LogonDialog->hWndUserName,
|
|
EM_LIMITTEXT,
|
|
UNLEN,
|
|
0L
|
|
);
|
|
|
|
SendMessage(pMSCHAPv2LogonDialog->hWndPassword,
|
|
EM_LIMITTEXT,
|
|
PWLEN,
|
|
0L
|
|
);
|
|
|
|
SendMessage(pMSCHAPv2LogonDialog->hWndDomain,
|
|
EM_LIMITTEXT,
|
|
DNLEN,
|
|
0L
|
|
);
|
|
|
|
if ( pUserProp->fFlags & EAPMSCHAPv2_FLAG_SAVE_UID_PWD )
|
|
{
|
|
CheckDlgButton(hWnd, IDC_CHECK_SAVE_UID_PWD, BST_CHECKED);
|
|
}
|
|
|
|
if ( pUserProp->szUserName[0] )
|
|
{
|
|
SetWindowText( pMSCHAPv2LogonDialog->hWndUserName,
|
|
pUserProp->szUserName
|
|
);
|
|
}
|
|
|
|
if ( pUserProp->szPassword[0] )
|
|
{
|
|
SetWindowText( pMSCHAPv2LogonDialog->hWndPassword,
|
|
pUserProp->szPassword
|
|
);
|
|
}
|
|
|
|
if ( pUserProp->szDomain[0] )
|
|
{
|
|
SetWindowText( pMSCHAPv2LogonDialog->hWndDomain,
|
|
pUserProp->szDomain
|
|
);
|
|
}
|
|
|
|
|
|
SetFocus(pMSCHAPv2LogonDialog->hWndUserName);
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
BOOL
|
|
RetryCommand(
|
|
IN PEAPMSCHAPv2_LOGON_DIALOG pMSCHAPv2LogonDialog,
|
|
IN WORD wNotifyCode,
|
|
IN WORD wId,
|
|
IN HWND hWndDlg,
|
|
IN HWND hWndCtrl
|
|
)
|
|
{
|
|
BOOL fRetVal = FALSE;
|
|
PEAPMSCHAPv2_USER_PROPERTIES pUserProp = pMSCHAPv2LogonDialog->pUserProp;
|
|
switch(wId)
|
|
{
|
|
case IDC_CHECK_SAVE_UID_PWD:
|
|
|
|
if ( BST_CHECKED ==
|
|
IsDlgButtonChecked ( hWndDlg, IDC_CHECK_SAVE_UID_PWD )
|
|
)
|
|
{
|
|
pUserProp->fFlags |= EAPMSCHAPv2_FLAG_SAVE_UID_PWD;
|
|
}
|
|
else
|
|
{
|
|
pUserProp->fFlags &= ~EAPMSCHAPv2_FLAG_SAVE_UID_PWD;
|
|
}
|
|
break;
|
|
case IDOK:
|
|
//
|
|
//grab new password from the dialog and set it in
|
|
//the logon dialog structure
|
|
//
|
|
|
|
GetWindowText( pMSCHAPv2LogonDialog->hWndPassword,
|
|
pUserProp->szPassword,
|
|
PWLEN+1
|
|
);
|
|
|
|
case IDCANCEL:
|
|
|
|
EndDialog(hWndDlg, wId);
|
|
fRetVal = TRUE;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return fRetVal;
|
|
}
|
|
|
|
|
|
INT_PTR CALLBACK
|
|
RetryDialogProc(
|
|
IN HWND hWnd,
|
|
IN UINT unMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam
|
|
)
|
|
{
|
|
PEAPMSCHAPv2_LOGON_DIALOG pMSCHAPv2LogonDialog;
|
|
|
|
switch (unMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
|
|
return(RetryInitDialog(hWnd, lParam));
|
|
|
|
case WM_HELP:
|
|
case WM_CONTEXTMENU:
|
|
{
|
|
ContextHelp(g_adwHelp, hWnd, unMsg, wParam, lParam);
|
|
break;
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
|
|
pMSCHAPv2LogonDialog = (PEAPMSCHAPv2_LOGON_DIALOG)GetWindowLongPtr(hWnd, DWLP_USER);
|
|
|
|
return(RetryCommand(pMSCHAPv2LogonDialog,
|
|
HIWORD(wParam),
|
|
LOWORD(wParam),
|
|
hWnd,
|
|
(HWND)lParam)
|
|
);
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
///
|
|
/// Client configuration dialog
|
|
///
|
|
|
|
BOOL
|
|
ClientConfigInitDialog(
|
|
IN HWND hWnd,
|
|
IN LPARAM lParam
|
|
)
|
|
{
|
|
PEAPMSCHAPv2_CLIENTCONFIG_DIALOG pClientConfigDialog;
|
|
PEAPMSCHAPv2_CONN_PROPERTIES pConnProp;
|
|
|
|
SetWindowLongPtr(hWnd, DWLP_USER, lParam);
|
|
|
|
|
|
pClientConfigDialog = (PEAPMSCHAPv2_CLIENTCONFIG_DIALOG)lParam;
|
|
pConnProp = pClientConfigDialog->pConnProp;
|
|
|
|
|
|
if ( pConnProp ->fFlags & EAPMSCHAPv2_FLAG_USE_WINLOGON_CREDS )
|
|
{
|
|
CheckDlgButton(hWnd, IDC_CHK_USE_WINLOGON, BST_CHECKED);
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
BOOL
|
|
ClientConfigCommand(
|
|
IN PEAPMSCHAPv2_CLIENTCONFIG_DIALOG pClientConfigDialog,
|
|
IN WORD wNotifyCode,
|
|
IN WORD wId,
|
|
IN HWND hWndDlg,
|
|
IN HWND hWndCtrl
|
|
)
|
|
{
|
|
BOOL fRetVal = FALSE;
|
|
PEAPMSCHAPv2_CONN_PROPERTIES pConnProp = pClientConfigDialog->pConnProp;
|
|
switch(wId)
|
|
{
|
|
case IDC_CHK_USE_WINLOGON:
|
|
|
|
if ( BST_CHECKED ==
|
|
IsDlgButtonChecked ( hWndDlg, IDC_CHK_USE_WINLOGON )
|
|
)
|
|
{
|
|
pConnProp->fFlags |= EAPMSCHAPv2_FLAG_USE_WINLOGON_CREDS;
|
|
}
|
|
else
|
|
{
|
|
pConnProp->fFlags &= ~EAPMSCHAPv2_FLAG_USE_WINLOGON_CREDS;
|
|
}
|
|
break;
|
|
case IDOK:
|
|
case IDCANCEL:
|
|
|
|
EndDialog(hWndDlg, wId);
|
|
fRetVal = TRUE;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return fRetVal;
|
|
}
|
|
|
|
|
|
INT_PTR CALLBACK
|
|
ClientConfigDialogProc(
|
|
IN HWND hWnd,
|
|
IN UINT unMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam
|
|
)
|
|
{
|
|
PEAPMSCHAPv2_CLIENTCONFIG_DIALOG pClientConfigDialog;
|
|
|
|
switch (unMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
|
|
return(ClientConfigInitDialog(hWnd, lParam));
|
|
|
|
case WM_HELP:
|
|
case WM_CONTEXTMENU:
|
|
{
|
|
ContextHelp(g_adwHelp, hWnd, unMsg, wParam, lParam);
|
|
break;
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
|
|
pClientConfigDialog = (PEAPMSCHAPv2_CLIENTCONFIG_DIALOG)GetWindowLongPtr(hWnd, DWLP_USER);
|
|
|
|
return(ClientConfigCommand(pClientConfigDialog,
|
|
HIWORD(wParam),
|
|
LOWORD(wParam),
|
|
hWnd,
|
|
(HWND)lParam)
|
|
);
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
//// Server Configuration
|
|
//
|
|
BOOL
|
|
ServerConfigInitDialog(
|
|
IN HWND hWnd,
|
|
IN LPARAM lParam
|
|
)
|
|
{
|
|
PEAPMSCHAPv2_SERVERCONFIG_DIALOG pServerConfigDialog;
|
|
PEAPMSCHAPv2_USER_PROPERTIES pUserProp;
|
|
CHAR szRetries[10] = {0};
|
|
|
|
SetWindowLongPtr(hWnd, DWLP_USER, lParam);
|
|
|
|
|
|
pServerConfigDialog = (PEAPMSCHAPv2_SERVERCONFIG_DIALOG)lParam;
|
|
pUserProp = pServerConfigDialog->pUserProp;
|
|
|
|
pServerConfigDialog->hWndRetries =
|
|
GetDlgItem(hWnd, IDC_EDIT_RETRIES);
|
|
|
|
SendMessage(pServerConfigDialog->hWndRetries ,
|
|
EM_LIMITTEXT,
|
|
2,
|
|
0L
|
|
);
|
|
|
|
if ( pUserProp->fFlags & EAPMSCHAPv2_FLAG_ALLOW_CHANGEPWD )
|
|
{
|
|
CheckDlgButton(hWnd, IDC_CHECK_ALLOW_CHANGEPWD, BST_CHECKED);
|
|
}
|
|
|
|
SetWindowText( pServerConfigDialog->hWndRetries,
|
|
_ltoa(pUserProp->dwMaxRetries, szRetries, 10)
|
|
);
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
ServerConfigCommand(
|
|
IN PEAPMSCHAPv2_SERVERCONFIG_DIALOG pServerConfigDialog,
|
|
IN WORD wNotifyCode,
|
|
IN WORD wId,
|
|
IN HWND hWndDlg,
|
|
IN HWND hWndCtrl
|
|
)
|
|
{
|
|
BOOL fRetVal = FALSE;
|
|
PEAPMSCHAPv2_USER_PROPERTIES pUserProp = pServerConfigDialog->pUserProp;
|
|
|
|
switch(wId)
|
|
{
|
|
case IDC_CHECK_ALLOW_CHANGEPWD:
|
|
|
|
if ( BST_CHECKED ==
|
|
IsDlgButtonChecked ( hWndDlg, IDC_CHECK_ALLOW_CHANGEPWD )
|
|
)
|
|
{
|
|
pUserProp->fFlags |= EAPMSCHAPv2_FLAG_ALLOW_CHANGEPWD;
|
|
}
|
|
else
|
|
{
|
|
pUserProp->fFlags &= ~EAPMSCHAPv2_FLAG_ALLOW_CHANGEPWD;
|
|
}
|
|
fRetVal = TRUE;
|
|
break;
|
|
case IDOK:
|
|
{
|
|
CHAR szRetries[10] = {0};
|
|
//
|
|
// Get the new value for retries
|
|
//
|
|
GetWindowText ( pServerConfigDialog->hWndRetries,
|
|
szRetries,
|
|
9
|
|
);
|
|
pUserProp->dwMaxRetries = atol(szRetries);
|
|
|
|
}
|
|
case IDCANCEL:
|
|
|
|
EndDialog(hWndDlg, wId);
|
|
fRetVal = TRUE;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return fRetVal;
|
|
}
|
|
|
|
|
|
INT_PTR CALLBACK
|
|
ServerConfigDialogProc(
|
|
IN HWND hWnd,
|
|
IN UINT unMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam
|
|
)
|
|
{
|
|
PEAPMSCHAPv2_SERVERCONFIG_DIALOG pServerConfigDialog;
|
|
|
|
switch (unMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
|
|
return(ServerConfigInitDialog(hWnd, lParam));
|
|
|
|
case WM_HELP:
|
|
case WM_CONTEXTMENU:
|
|
{
|
|
ContextHelp(g_adwHelp, hWnd, unMsg, wParam, lParam);
|
|
break;
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
|
|
pServerConfigDialog = (PEAPMSCHAPv2_SERVERCONFIG_DIALOG)GetWindowLongPtr(hWnd, DWLP_USER);
|
|
|
|
return(ServerConfigCommand(pServerConfigDialog,
|
|
HIWORD(wParam),
|
|
LOWORD(wParam),
|
|
hWnd,
|
|
(HWND)lParam)
|
|
);
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
|
|
|
|
//// Change Password Dialog
|
|
//
|
|
|
|
BOOL
|
|
ChangePasswordInitDialog(
|
|
IN HWND hWnd,
|
|
IN LPARAM lParam
|
|
)
|
|
{
|
|
PEAPMSCHAPv2_CHANGEPWD_DIALOG pChangePwdDialog;
|
|
|
|
|
|
SetWindowLongPtr(hWnd, DWLP_USER, lParam);
|
|
|
|
|
|
pChangePwdDialog = (PEAPMSCHAPv2_CHANGEPWD_DIALOG)lParam;
|
|
|
|
if ( pChangePwdDialog->pInteractiveUIData->fFlags & EAPMSCHAPv2_INTERACTIVE_UI_FLAG_CHANGE_PWD )
|
|
{
|
|
|
|
pChangePwdDialog->hWndNewPassword =
|
|
GetDlgItem(hWnd, IDC_NEW_PASSWORD);
|
|
|
|
pChangePwdDialog->hWndConfirmNewPassword =
|
|
GetDlgItem(hWnd, IDC_CONFIRM_NEW_PASSWORD);
|
|
|
|
SetWindowText( pChangePwdDialog->hWndNewPassword,
|
|
""
|
|
);
|
|
}
|
|
else
|
|
{
|
|
pChangePwdDialog->hWndNewPassword =
|
|
GetDlgItem(hWnd, CID_CP_EB_Password_RASDLG);
|
|
|
|
pChangePwdDialog->hWndConfirmNewPassword =
|
|
GetDlgItem(hWnd, CID_CP_EB_ConfirmPassword_RASDLG);
|
|
|
|
pChangePwdDialog->hWndOldPassword =
|
|
GetDlgItem(hWnd,CID_CP_EB_OldPassword_RASDLG);
|
|
|
|
SetWindowText ( pChangePwdDialog->hWndOldPassword,
|
|
""
|
|
);
|
|
SetFocus( pChangePwdDialog->hWndOldPassword );
|
|
}
|
|
|
|
|
|
|
|
SendMessage ( pChangePwdDialog->hWndNewPassword,
|
|
EM_LIMITTEXT,
|
|
PWLEN-1,
|
|
0L
|
|
);
|
|
|
|
SendMessage ( pChangePwdDialog->hWndConfirmNewPassword,
|
|
EM_LIMITTEXT,
|
|
PWLEN-1,
|
|
0L
|
|
);
|
|
|
|
SetWindowText( pChangePwdDialog->hWndNewPassword,
|
|
""
|
|
);
|
|
|
|
SetWindowText( pChangePwdDialog->hWndConfirmNewPassword,
|
|
""
|
|
);
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
ChangePasswordCommand(
|
|
IN PEAPMSCHAPv2_CHANGEPWD_DIALOG pChangePwdDialog,
|
|
IN WORD wNotifyCode,
|
|
IN WORD wId,
|
|
IN HWND hWndDlg,
|
|
IN HWND hWndCtrl
|
|
)
|
|
{
|
|
BOOL fRetVal = FALSE;
|
|
|
|
switch(wId)
|
|
{
|
|
case IDOK:
|
|
{
|
|
CHAR szOldPassword[PWLEN+1] = {0};
|
|
CHAR szNewPassword[PWLEN+1] = {0};
|
|
CHAR szConfirmNewPassword[PWLEN+1] = {0};
|
|
CHAR szMessage[512] = {0};
|
|
CHAR szHeader[64] = {0};
|
|
LoadString( GetHInstance(),
|
|
IDS_MESSAGE_HEADER,
|
|
szHeader,
|
|
sizeof(szHeader)-1
|
|
);
|
|
|
|
if ( pChangePwdDialog->pInteractiveUIData->fFlags &
|
|
EAPMSCHAPv2_INTERACTIVE_UI_FLAG_CHANGE_PWD_WINLOGON
|
|
)
|
|
{
|
|
GetWindowText ( pChangePwdDialog->hWndOldPassword,
|
|
szOldPassword,
|
|
PWLEN
|
|
);
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// Get the new value for retries
|
|
//
|
|
GetWindowText ( pChangePwdDialog->hWndNewPassword,
|
|
szNewPassword,
|
|
PWLEN
|
|
);
|
|
|
|
GetWindowText ( pChangePwdDialog->hWndConfirmNewPassword,
|
|
szConfirmNewPassword,
|
|
PWLEN
|
|
);
|
|
|
|
if ( szNewPassword[0] == 0 )
|
|
{
|
|
//
|
|
// Load resource from res file
|
|
//
|
|
|
|
LoadString( GetHInstance(),
|
|
IDS_PASSWORD_REQUIRED,
|
|
szMessage,
|
|
sizeof(szMessage)-1
|
|
);
|
|
|
|
MessageBox (hWndDlg,
|
|
szMessage,
|
|
szHeader,
|
|
MB_OK
|
|
);
|
|
break;
|
|
}
|
|
|
|
if ( pChangePwdDialog->pInteractiveUIData->fFlags &
|
|
EAPMSCHAPv2_INTERACTIVE_UI_FLAG_CHANGE_PWD_WINLOGON
|
|
)
|
|
{
|
|
if ( szOldPassword[0] == 0 )
|
|
{
|
|
LoadString( GetHInstance(),
|
|
IDS_PASSWORD_REQUIRED,
|
|
szMessage,
|
|
sizeof(szMessage)-1
|
|
);
|
|
|
|
MessageBox (hWndDlg,
|
|
szMessage,
|
|
szHeader,
|
|
MB_OK
|
|
);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( strncmp ( szNewPassword, szConfirmNewPassword, PWLEN ) )
|
|
{
|
|
LoadString( GetHInstance(),
|
|
IDS_PASSWORD_MISMATCH,
|
|
szMessage,
|
|
sizeof(szMessage)-1
|
|
);
|
|
|
|
MessageBox (hWndDlg,
|
|
szMessage,
|
|
szHeader,
|
|
MB_OK
|
|
);
|
|
break;
|
|
}
|
|
|
|
if ( pChangePwdDialog->pInteractiveUIData->fFlags &
|
|
EAPMSCHAPv2_INTERACTIVE_UI_FLAG_CHANGE_PWD_WINLOGON
|
|
)
|
|
{
|
|
//Save the old paswword.
|
|
CopyMemory ( pChangePwdDialog->pInteractiveUIData->UserProp.szPassword,
|
|
szOldPassword,
|
|
PWLEN
|
|
);
|
|
}
|
|
|
|
CopyMemory ( pChangePwdDialog->pInteractiveUIData->szNewPassword,
|
|
szNewPassword,
|
|
PWLEN
|
|
);
|
|
//fall thru
|
|
}
|
|
case IDCANCEL:
|
|
|
|
EndDialog(hWndDlg, wId);
|
|
fRetVal = TRUE;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return fRetVal;
|
|
}
|
|
|
|
DWORD
|
|
DwGetGlobalConfig(
|
|
IN DWORD dwEapTypeId,
|
|
OUT PBYTE* ppConfigDataOut,
|
|
OUT DWORD* pdwSizeOfConfigDataOut
|
|
)
|
|
{
|
|
DWORD dwErr = NO_ERROR;
|
|
PBYTE pbData = NULL;
|
|
|
|
dwErr = ServerConfigDataIO(
|
|
TRUE,
|
|
NULL,
|
|
ppConfigDataOut,
|
|
0);
|
|
|
|
if(NO_ERROR != dwErr)
|
|
{
|
|
goto done;
|
|
}
|
|
|
|
*pdwSizeOfConfigDataOut = sizeof(EAPMSCHAPv2_USER_PROPERTIES);
|
|
|
|
done:
|
|
return HRESULT_FROM_WIN32(dwErr);
|
|
}
|
|
|
|
INT_PTR CALLBACK
|
|
ChangePasswordDialogProc(
|
|
IN HWND hWnd,
|
|
IN UINT unMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam
|
|
)
|
|
{
|
|
PEAPMSCHAPv2_CHANGEPWD_DIALOG pChangePwdDialog;
|
|
|
|
switch (unMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
|
|
return(ChangePasswordInitDialog(hWnd, lParam));
|
|
|
|
case WM_HELP:
|
|
case WM_CONTEXTMENU:
|
|
{
|
|
ContextHelp(g_adwHelp, hWnd, unMsg, wParam, lParam);
|
|
break;
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
|
|
pChangePwdDialog = (PEAPMSCHAPv2_CHANGEPWD_DIALOG)GetWindowLongPtr(hWnd, DWLP_USER);
|
|
|
|
return(ChangePasswordCommand(pChangePwdDialog,
|
|
HIWORD(wParam),
|
|
LOWORD(wParam),
|
|
hWnd,
|
|
(HWND)lParam)
|
|
);
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
|