windows-nt/Source/XPSP1/NT/net/rras/ras/ui/rasdlg/security.c

1246 lines
32 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
// Copyright (c) 1997, Microsoft Corporation, all rights reserved
//
// security.c
// Remote Access Common Dialog APIs
// Security dialogs
//
// 11/06/97 Steve Cobb
//
#include "rasdlgp.h"
#include <rasauth.h>
#include <rrascfg.h>
const IID IID_IEAPProviderConfig = {0x66A2DB19,
0xD706,
0x11D0,
{0xA3,0x7B,0x00,0xC0,0x4F,0xC9,0xDA,0x04}};
//----------------------------------------------------------------------------
// Help maps
//----------------------------------------------------------------------------
static DWORD g_adwCaHelp[] =
{
CID_CA_ST_Encryption, HID_CA_LB_Encryption,
CID_CA_LB_Encryption, HID_CA_LB_Encryption,
CID_CA_GB_LogonSecurity, HID_CA_GB_LogonSecurity,
CID_CA_RB_Eap, HID_CA_RB_Eap,
CID_CA_LB_EapPackages, HID_CA_LB_EapPackages,
CID_CA_PB_Properties, HID_CA_PB_Properties,
CID_CA_RB_AllowedProtocols, HID_CA_RB_AllowedProtocols,
CID_CA_CB_Pap, HID_CA_CB_Pap,
CID_CA_CB_Spap, HID_CA_CB_Spap,
CID_CA_CB_Chap, HID_CA_CB_Chap,
CID_CA_CB_MsChap, HID_CA_CB_MsChap,
CID_CA_CB_W95MsChap, HID_CA_CB_W95MsChap,
CID_CA_CB_MsChap2, HID_CA_CB_MsChap2,
CID_CA_CB_UseWindowsPw, HID_CA_CB_UseWindowsPw,
0, 0
};
//----------------------------------------------------------------------------
// Local datatypes
//----------------------------------------------------------------------------
// Custom authentication dialog argument block.
//
typedef struct
_CAARGS
{
PBENTRY* pEntry;
BOOL fStrongEncryption;
// Set if we have been called via RouterEntryDlg.
//
BOOL fRouter;
// Set if pszRouter is an NT4 steelhead machine. Valid only
// if fRouter is true.
//
BOOL fNt4Router;
// The name of the server in "\\server" form or NULL if none (or if
// 'fRouter' is not set).
//
TCHAR* pszRouter;
}
CAARGS;
// Custom authentication dialog context block.
//
typedef struct
_CAINFO
{
// Caller's arguments to the dialog.
//
CAARGS* pArgs;
// Handle of this dialog and some of it's controls.
//
HWND hwndDlg;
HWND hwndLbEncryption;
HWND hwndRbEap;
HWND hwndLbEapPackages;
HWND hwndPbProperties;
HWND hwndRbAllowedProtocols;
HWND hwndCbPap;
HWND hwndCbSpap;
HWND hwndCbChap;
HWND hwndCbMsChap;
HWND hwndCbW95MsChap;
HWND hwndCbMsChap2;
HWND hwndCbUseWindowsPw;
// List of EAPCFGs read from the registry, with the originally selected
// node for use in consistency tests later.
//
DTLLIST* pListEapcfgs;
DTLNODE* pOriginalEapcfgNode;
// "Restore" states for controls that may be disabled with
// EnableCbWithRestore or EnableLbWithRestore routines.
//
DWORD iLbEapPackages;
BOOL fPap;
BOOL fSpap;
BOOL fChap;
BOOL fMsChap;
BOOL fW95MsChap;
BOOL fMsChap2;
BOOL fUseWindowsPw;
}
CAINFO;
//-----------------------------------------------------------------------------
// Local prototypes (alphabetically)
//-----------------------------------------------------------------------------
VOID
CaCbToggle(
IN CAINFO* pInfo,
IN HWND hwndCb );
BOOL
CaCommand(
IN CAINFO* pInfo,
IN WORD wNotification,
IN WORD wId,
IN HWND hwndCtrl );
INT_PTR CALLBACK
CaDlgProc(
IN HWND hwnd,
IN UINT unMsg,
IN WPARAM wparam,
IN LPARAM lparam );
BOOL
CaInit(
IN HWND hwndDlg,
IN CAARGS* pArgs );
VOID
CaLbEapPackagesSelChange(
IN CAINFO* pInfo );
VOID
CaPropertiesLocal(
IN CAINFO* pInfo );
VOID
CaPropertiesRemote(
IN CAINFO* pInfo );
VOID
CaRbToggle(
IN CAINFO* pInfo,
IN BOOL fEapSelected );
BOOL
CaSave(
IN CAINFO* pInfo );
VOID
CaTerm(
IN HWND hwndDlg );
//----------------------------------------------------------------------------
// Advanced Security dialog routines
// Listed alphabetically following entrypoint and dialog proc
//----------------------------------------------------------------------------
BOOL
AdvancedSecurityDlg(
IN HWND hwndOwner,
IN OUT EINFO* pArgs )
// Popup a dialog to select advanced security options for phonebook entry
// represented by 'pArgs'. 'HwndOwner' is the owning window.
//
// Returns true if user pressed OK and succeeded or false on Cancel or
// error. If successful, the new configuration is written to the
// appropriate 'pArgs->pEntry' fields. The routine assumes that these same
// 'pEntry' fields contain the desired defaults on entry.
//
{
INT_PTR nStatus;
CAARGS args;
TRACE( "AdvSecurityDlg" );
args.pEntry = pArgs->pEntry;
args.fStrongEncryption = pArgs->fStrongEncryption;
args.fRouter = pArgs->fRouter;
args.fNt4Router = pArgs->fNt4Router;
args.pszRouter = pArgs->pszRouter;
nStatus =
DialogBoxParam(
g_hinstDll,
MAKEINTRESOURCE( DID_CA_CustomAuth ),
hwndOwner,
CaDlgProc,
(LPARAM )&args );
if (nStatus == -1)
{
ErrorDlg( hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL );
nStatus = FALSE;
}
return (nStatus) ? TRUE : FALSE;
}
INT_PTR CALLBACK
CaDlgProc(
IN HWND hwnd,
IN UINT unMsg,
IN WPARAM wparam,
IN LPARAM lparam )
// DialogProc callback for the Custom Authentication dialog. Parameters
// and return value are as described for standard windows 'DialogProc's.
//
{
#if 0
TRACE4( "CaDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)",
(DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam );
#endif
switch (unMsg)
{
case WM_INITDIALOG:
{
return CaInit( hwnd, (CAARGS* )lparam );
}
case WM_HELP:
case WM_CONTEXTMENU:
{
ContextHelp( g_adwCaHelp, hwnd, unMsg, wparam, lparam );
break;
}
case WM_COMMAND:
{
CAINFO* pInfo = (CAINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
ASSERT( pInfo );
return CaCommand(
pInfo, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam );
}
case WM_DESTROY:
{
CaTerm( hwnd );
break;
}
}
return FALSE;
}
BOOL
CaCommand(
IN CAINFO* pInfo,
IN WORD wNotification,
IN WORD wId,
IN HWND hwndCtrl )
// Called on WM_COMMAND. 'PInfo' is the dialog context. 'WNotification'
// is the notification code of the command. 'wId' is the control/menu
// identifier of the command. 'HwndCtrl' is the control window handle of
// the command.
//
// Returns true if processed message, false otherwise.
//
{
TRACE3( "CaCommand(n=%d,i=%d,c=$%x)",
(DWORD )wNotification, (DWORD )wId, (ULONG_PTR )hwndCtrl );
switch (wId)
{
case CID_CA_RB_Eap:
case CID_CA_RB_AllowedProtocols:
{
switch (wNotification)
{
case BN_CLICKED:
{
CaRbToggle( pInfo, (wId == CID_CA_RB_Eap) );
return TRUE;
}
}
break;
}
case CID_CA_LB_EapPackages:
{
CaLbEapPackagesSelChange( pInfo );
return TRUE;
}
case CID_CA_PB_Properties:
{
if ( ( pInfo->pArgs->fRouter )
&& ( !pInfo->pArgs->fNt4Router )
&& ( pInfo->pArgs->pszRouter )
&& ( pInfo->pArgs->pszRouter[0] ) )
{
CaPropertiesRemote( pInfo );
}
else
{
CaPropertiesLocal( pInfo );
}
return TRUE;
}
case CID_CA_CB_Pap:
case CID_CA_CB_Spap:
case CID_CA_CB_Chap:
case CID_CA_CB_MsChap:
case CID_CA_CB_W95MsChap:
case CID_CA_CB_MsChap2:
{
CaCbToggle( pInfo, hwndCtrl );
return TRUE;
}
case IDOK:
{
if (CaSave( pInfo ))
{
EndDialog( pInfo->hwndDlg, TRUE );
}
return TRUE;
}
case IDCANCEL:
{
TRACE( "Cancel pressed" );
EndDialog( pInfo->hwndDlg, FALSE );
return TRUE;
}
}
return FALSE;
}
VOID
CaCbToggle(
IN CAINFO* pInfo,
IN HWND hwndCb )
// Called when one of the 6 authentication protocol check boxes is toggled
// and/or the toggle processing should be performed. 'HwndCb' is the
// window handle of the toggled checkbox or NULL if none. 'PInfo' is the
// dialog context.
//
{
BOOL fMsChap;
BOOL fW95MsChap;
BOOL fMsChap2;
fMsChap = Button_GetCheck( pInfo->hwndCbMsChap );
EnableCbWithRestore(
pInfo->hwndCbW95MsChap,
fMsChap,
FALSE,
&pInfo->fW95MsChap );
if (IsWindowEnabled( pInfo->hwndCbW95MsChap ))
{
fW95MsChap = Button_GetCheck( pInfo->hwndCbW95MsChap );
}
else
{
fW95MsChap = FALSE;
}
fMsChap2 = Button_GetCheck( pInfo->hwndCbMsChap2 );
EnableCbWithRestore(
pInfo->hwndCbUseWindowsPw,
fMsChap || fW95MsChap || fMsChap2,
FALSE,
&pInfo->fUseWindowsPw );
}
BOOL
CaInit(
IN HWND hwndDlg,
IN CAARGS* pArgs )
// Called on WM_INITDIALOG. 'HwndDlg' is the handle of the phonebook
// dialog window. 'PArgs' is caller's arguments as passed to the stub
// API.
//
// Return false if focus was set, true otherwise, i.e. as defined for
// WM_INITDIALOG.
//
{
DWORD dwErr;
DWORD dwAr;
CAINFO* pInfo;
PBENTRY* pEntry;
TRACE( "CaInit" );
// Allocate the dialog context block. Initialize minimally for proper
// cleanup, then attach to the dialog window.
//
{
pInfo = Malloc( sizeof(*pInfo) );
if (!pInfo)
{
ErrorDlg( hwndDlg, SID_OP_LoadDlg, ERROR_NOT_ENOUGH_MEMORY, NULL );
EndDialog( hwndDlg, FALSE );
return TRUE;
}
ZeroMemory( pInfo, sizeof(*pInfo) );
pInfo->pArgs = pArgs;
pInfo->hwndDlg = hwndDlg;
SetWindowLongPtr( hwndDlg, DWLP_USER, (ULONG_PTR )pInfo );
TRACE( "Context set" );
}
pEntry = pArgs->pEntry;
pInfo->hwndLbEncryption = GetDlgItem( hwndDlg, CID_CA_LB_Encryption );
ASSERT( pInfo->hwndLbEncryption );
pInfo->hwndRbEap = GetDlgItem( hwndDlg, CID_CA_RB_Eap );
ASSERT( pInfo->hwndRbEap );
pInfo->hwndLbEapPackages = GetDlgItem( hwndDlg, CID_CA_LB_EapPackages );
ASSERT( pInfo->hwndLbEapPackages );
pInfo->hwndPbProperties = GetDlgItem( hwndDlg, CID_CA_PB_Properties );
ASSERT( pInfo->hwndPbProperties );
pInfo->hwndRbAllowedProtocols =
GetDlgItem( hwndDlg, CID_CA_RB_AllowedProtocols );
ASSERT( pInfo->hwndRbAllowedProtocols );
pInfo->hwndCbPap = GetDlgItem( hwndDlg, CID_CA_CB_Pap );
ASSERT( pInfo->hwndCbPap );
pInfo->hwndCbSpap = GetDlgItem( hwndDlg, CID_CA_CB_Spap );
ASSERT( pInfo->hwndCbSpap );
pInfo->hwndCbChap = GetDlgItem( hwndDlg, CID_CA_CB_Chap );
ASSERT( pInfo->hwndCbChap );
pInfo->hwndCbMsChap = GetDlgItem( hwndDlg, CID_CA_CB_MsChap );
ASSERT( pInfo->hwndCbMsChap );
pInfo->hwndCbW95MsChap = GetDlgItem( hwndDlg, CID_CA_CB_W95MsChap );
ASSERT( pInfo->hwndCbW95MsChap );
pInfo->hwndCbMsChap2 = GetDlgItem( hwndDlg, CID_CA_CB_MsChap2 );
ASSERT( pInfo->hwndCbMsChap2 );
pInfo->hwndCbUseWindowsPw = GetDlgItem( hwndDlg, CID_CA_CB_UseWindowsPw );
ASSERT( pInfo->hwndCbUseWindowsPw );
// Initialize the encryption list.
//
{
LBTABLEITEM* pItem;
INT i;
static LBTABLEITEM aItems[] =
{
SID_DE_None, DE_None,
SID_DE_IfPossible, DE_IfPossible,
SID_DE_Require, DE_Require,
SID_DE_RequireMax, DE_RequireMax,
0, 0
};
static LBTABLEITEM aItemsExport[] =
{
SID_DE_None, DE_None,
SID_DE_IfPossible, DE_IfPossible,
SID_DE_Require, DE_Require,
0, 0
};
// Warn user if entry is configured for strong encryption and none is
// available on the machine. (See bug 289692)
//
if (pEntry->dwDataEncryption == DE_RequireMax
&& !pArgs->fStrongEncryption)
{
MsgDlg( pInfo->hwndDlg, SID_NoStrongEncryption, NULL );
pEntry->dwDataEncryption = DE_Require;
}
for (pItem = (pArgs->fStrongEncryption) ? aItems : aItemsExport, i = 0;
pItem->sidItem;
++pItem, ++i)
{
ComboBox_AddItemFromId(
g_hinstDll, pInfo->hwndLbEncryption,
pItem->sidItem, (VOID* )UlongToPtr(pItem->dwData));
if (pEntry->dwDataEncryption == pItem->dwData)
{
ComboBox_SetCurSel( pInfo->hwndLbEncryption, i );
}
}
}
// Initialize EAP package list.
//
{
DTLNODE* pNode;
TCHAR* pszEncEnabled;
// Read the EAPCFG information from the registry and find the node
// selected in the entry, or the default, if none.
//
if ( ( pInfo->pArgs->fRouter )
&& ( !pInfo->pArgs->fNt4Router )
&& ( pInfo->pArgs->pszRouter )
&& ( pInfo->pArgs->pszRouter[0] ) )
{
pInfo->pListEapcfgs = ReadEapcfgList( pInfo->pArgs->pszRouter );
}
else
{
pInfo->pListEapcfgs = ReadEapcfgList( NULL );
}
if (pInfo->pListEapcfgs)
{
DTLNODE* pNodeEap;
DWORD cbData = 0;
PBYTE pbData = NULL;
DWORD dwkey = pEntry->dwCustomAuthKey;
for (pNodeEap = DtlGetFirstNode(pInfo->pListEapcfgs);
pNodeEap;
pNodeEap = DtlGetNextNode(pNodeEap))
{
EAPCFG* pEapcfg = (EAPCFG* )DtlGetData(pNodeEap);
ASSERT( pEapcfg );
pEntry->dwCustomAuthKey = pEapcfg->dwKey;
if(NO_ERROR == DwGetCustomAuthData(
pEntry,
&cbData,
&pbData)
&& (cbData > 0)
&& (pbData))
{
VOID *pData = Malloc(cbData);
if(pData)
{
CopyMemory(pData,
pbData,
cbData);
Free0(pEapcfg->pData);
pEapcfg->pData = pData;
pEapcfg->cbData = cbData;
}
}
}
pEntry->dwCustomAuthKey = dwkey;
if (pEntry->dwCustomAuthKey == (DWORD )-1)
{
pNode = DtlGetFirstNode( pInfo->pListEapcfgs );
}
else
{
pNode = EapcfgNodeFromKey(
pInfo->pListEapcfgs, pEntry->dwCustomAuthKey );
}
pInfo->pOriginalEapcfgNode = pNode;
}
// Fill the EAP packages listbox and select the previously identified
// selection. The Properties button is disabled by default, but may
// be enabled when the EAP list selection is set.
//
EnableWindow( pInfo->hwndPbProperties, FALSE );
pszEncEnabled = PszFromId( g_hinstDll, SID_EncEnabled );
if (pszEncEnabled)
{
for (pNode = DtlGetFirstNode( pInfo->pListEapcfgs );
pNode;
pNode = DtlGetNextNode( pNode ))
{
DWORD cb;
EAPCFG* pEapcfg;
INT i;
TCHAR* pszBuf;
pEapcfg = (EAPCFG* )DtlGetData( pNode );
ASSERT( pEapcfg );
ASSERT( pEapcfg->pszFriendlyName );
// Whistler bug 224074 use only lstrcpyn's to prevent
// maliciousness
//
cb = lstrlen( pEapcfg->pszFriendlyName ) +
lstrlen( pszEncEnabled ) + 1;
pszBuf = Malloc( cb * sizeof(TCHAR) );
if (!pszBuf)
{
continue;
}
// Whistler bug 224074 use only lstrcpyn's to prevent
// maliciousness
//
lstrcpyn( pszBuf, pEapcfg->pszFriendlyName, cb );
if (pEapcfg->fProvidesMppeKeys)
{
lstrcat( pszBuf, pszEncEnabled );
}
i = ComboBox_AddItem(
pInfo->hwndLbEapPackages, pszBuf, pNode );
if (pNode == pInfo->pOriginalEapcfgNode)
{
ComboBox_SetCurSelNotify( pInfo->hwndLbEapPackages, i );
}
Free( pszBuf );
}
Free0( pszEncEnabled );
ComboBox_AutoSizeDroppedWidth( pInfo->hwndLbEapPackages );
}
}
// Set initial check box settings. The values may be changed when the
// radio button handling does it's enabling/disabling.
//
dwAr = pEntry->dwAuthRestrictions;
Button_SetCheck( pInfo->hwndCbPap, !!(dwAr & AR_F_AuthPAP) );
Button_SetCheck( pInfo->hwndCbSpap, !!(dwAr & AR_F_AuthSPAP) );
Button_SetCheck( pInfo->hwndCbChap, !!(dwAr & AR_F_AuthMD5CHAP) );
Button_SetCheck( pInfo->hwndCbMsChap, !!(dwAr & AR_F_AuthMSCHAP) );
Button_SetCheck( pInfo->hwndCbW95MsChap, !!(dwAr & AR_F_AuthW95MSCHAP) );
Button_SetCheck( pInfo->hwndCbMsChap2, !!(dwAr & AR_F_AuthMSCHAP2) );
if (!pInfo->pArgs->fRouter)
{
pInfo->fUseWindowsPw = pEntry->fAutoLogon;
Button_SetCheck( pInfo->hwndCbUseWindowsPw, pInfo->fUseWindowsPw );
}
else
{
pInfo->fUseWindowsPw = FALSE;
Button_SetCheck( pInfo->hwndCbUseWindowsPw, FALSE );
EnableWindow( pInfo->hwndCbUseWindowsPw, FALSE );
ShowWindow( pInfo->hwndCbUseWindowsPw, FALSE );
}
// Set the appropriate radio button which triggers appropriate
// enabling/disabling.
//
{
HWND hwndRb;
if (dwAr & AR_F_AuthEAP)
{
hwndRb = pInfo->hwndRbEap;
}
else
{
hwndRb = pInfo->hwndRbAllowedProtocols;
}
SendMessage( hwndRb, BM_CLICK, 0, 0 );
}
// Center dialog on the owner window.
//
CenterWindow( hwndDlg, GetParent( hwndDlg ) );
// Add context help button to title bar.
//
AddContextHelpButton( hwndDlg );
SetFocus( pInfo->hwndLbEncryption );
return TRUE;
}
VOID
CaLbEapPackagesSelChange(
IN CAINFO* pInfo )
// Called when the EAP list selection changes. 'PInfo' is the dialog
// context.
//
{
EAPCFG* pEapcfg;
INT iSel;
// Get the EAPCFG information for the selected EAP package.
//
pEapcfg = NULL;
iSel = ComboBox_GetCurSel( pInfo->hwndLbEapPackages );
if (iSel >= 0)
{
DTLNODE* pNode;
pNode =
(DTLNODE* )ComboBox_GetItemDataPtr(
pInfo->hwndLbEapPackages, iSel );
if (pNode)
{
pEapcfg = (EAPCFG* )DtlGetData( pNode );
}
}
// Enable the Properties button if the selected package has a
// configuration entrypoint.
//
EnableWindow(
pInfo->hwndPbProperties, (pEapcfg && !!(pEapcfg->pszConfigDll)) );
}
VOID
CaPropertiesLocal(
IN CAINFO* pInfo )
// Called when the EAP properties button is pressed. Call the
// configuration DLL to popup the properties of the package. 'PInfo' is
// the dialog context.
//
{
DWORD dwErr;
DTLNODE* pNode;
EAPCFG* pEapcfg;
RASEAPINVOKECONFIGUI pInvokeConfigUi;
RASEAPFREE pFreeConfigUIData;
HINSTANCE h;
BYTE* pConnectionData;
DWORD cbConnectionData;
// Look up the selected package configuration and load the associated
// configuration DLL.
//
pNode = (DTLNODE* )ComboBox_GetItemDataPtr(
pInfo->hwndLbEapPackages,
ComboBox_GetCurSel( pInfo->hwndLbEapPackages ) );
ASSERT( pNode );
if(NULL == pNode)
{
return;
}
pEapcfg = (EAPCFG* )DtlGetData( pNode );
ASSERT( pEapcfg );
h = NULL;
if (!(h = LoadLibrary( pEapcfg->pszConfigDll ))
|| !(pInvokeConfigUi =
(RASEAPINVOKECONFIGUI )GetProcAddress(
h, "RasEapInvokeConfigUI" ))
|| !(pFreeConfigUIData =
(RASEAPFREE) GetProcAddress(
h, "RasEapFreeMemory" )))
{
MsgDlg( pInfo->hwndDlg, SID_CannotLoadConfigDll, NULL );
if (h)
{
FreeLibrary( h );
}
return;
}
// Call the configuration DLL to popup it's custom configuration UI.
//
pConnectionData = NULL;
cbConnectionData = 0;
dwErr = pInvokeConfigUi(
pEapcfg->dwKey, pInfo->hwndDlg,
pInfo->pArgs->fRouter ? RAS_EAP_FLAG_ROUTER : 0,
pEapcfg->pData,
pEapcfg->cbData,
&pConnectionData, &cbConnectionData
);
if (dwErr != 0)
{
if (dwErr != ERROR_CANCELLED)
MsgDlg( pInfo->hwndDlg, SID_ConfigDllApiFailed, NULL );
FreeLibrary( h );
return;
}
// Store the configuration information returned in the package descriptor.
//
Free( pEapcfg->pData );
pEapcfg->pData = NULL;
pEapcfg->cbData = 0;
if (pConnectionData)
{
if (cbConnectionData > 0)
{
// Copy it into the eap node
pEapcfg->pData = Malloc( cbConnectionData );
if (pEapcfg->pData)
{
CopyMemory( pEapcfg->pData, pConnectionData, cbConnectionData );
pEapcfg->cbData = cbConnectionData;
}
}
}
pFreeConfigUIData( pConnectionData );
// Note any "force user to configure" requirement on the package has been
// satisfied.
//
pEapcfg->fConfigDllCalled = TRUE;
FreeLibrary( h );
}
VOID
CaPropertiesRemote(
IN CAINFO* pInfo )
// Called when the EAP properties button is pressed. Call the
// configuration DLL to popup the properties of the package. 'PInfo' is
// the dialog context.
//
{
DWORD dwErr;
HRESULT hr;
DTLNODE* pNode;
EAPCFG* pEapcfg;
BOOL fComInitialized = FALSE;
BYTE* pConnectionData = NULL;
DWORD cbConnectionData = 0;
IEAPProviderConfig* pEapProv = NULL;
ULONG_PTR uConnectionParam;
BOOL fInitialized = FALSE;
pNode = (DTLNODE* )ComboBox_GetItemDataPtr(
pInfo->hwndLbEapPackages,
ComboBox_GetCurSel( pInfo->hwndLbEapPackages ) );
ASSERT( pNode );
if(NULL == pNode)
{
goto LDone;
}
pEapcfg = (EAPCFG* )DtlGetData( pNode );
ASSERT( pEapcfg );
hr = CoInitializeEx( NULL, COINIT_APARTMENTTHREADED );
if ( RPC_E_CHANGED_MODE == hr )
{
hr = CoInitializeEx( NULL, COINIT_MULTITHREADED );
}
if ( ( S_OK != hr )
&& ( S_FALSE != hr ) )
{
goto LDone;
}
fComInitialized = TRUE;
hr = CoCreateInstance(
&(pEapcfg->guidConfigCLSID),
NULL,
CLSCTX_SERVER,
&IID_IEAPProviderConfig,
(PVOID*)&pEapProv
);
if ( FAILED( hr ) )
{
pEapProv = NULL;
goto LDone;
}
// Call the configuration DLL to popup it's custom configuration UI.
//
hr = IEAPProviderConfig_Initialize(
pEapProv,
pInfo->pArgs->pszRouter,
pEapcfg->dwKey,
&uConnectionParam );
if ( FAILED( hr ) )
{
goto LDone;
}
fInitialized = TRUE;
hr = IEAPProviderConfig_RouterInvokeConfigUI(
pEapProv,
pEapcfg->dwKey,
uConnectionParam,
pInfo->hwndDlg,
RAS_EAP_FLAG_ROUTER,
pEapcfg->pData,
pEapcfg->cbData,
&pConnectionData,
&cbConnectionData );
if ( FAILED( hr ) )
{
// if (dwErr != ERROR_CANCELLED)
// MsgDlg( pInfo->hwndDlg, SID_ConfigDllApiFailed, NULL );
goto LDone;
}
// Store the configuration information returned in the package descriptor.
//
Free( pEapcfg->pData );
pEapcfg->pData = NULL;
pEapcfg->cbData = 0;
if (pConnectionData)
{
if (cbConnectionData > 0)
{
// Copy it into the eap node
pEapcfg->pData = Malloc( cbConnectionData );
if (pEapcfg->pData)
{
CopyMemory( pEapcfg->pData, pConnectionData, cbConnectionData );
pEapcfg->cbData = cbConnectionData;
}
}
}
// Note any "force user to configure" requirement on the package has been
// satisfied.
//
pEapcfg->fConfigDllCalled = TRUE;
LDone:
if ( NULL != pConnectionData )
{
CoTaskMemFree( pConnectionData );
}
if ( fInitialized )
{
IEAPProviderConfig_Uninitialize(
pEapProv,
pEapcfg->dwKey,
uConnectionParam );
}
if ( NULL != pEapProv )
{
IEAPProviderConfig_Release(pEapProv);
}
if ( fComInitialized )
{
CoUninitialize();
}
}
VOID
CaRbToggle(
IN CAINFO* pInfo,
IN BOOL fEapSelected )
// Called when the radio button setting is toggled. 'FEapSelected' is set
// if the EAP option was selected, clear if the "Allowed protocols" option
// was selected. 'PInfo' is the dialog context.
//
{
EnableLbWithRestore(
pInfo->hwndLbEapPackages, fEapSelected, &pInfo->iLbEapPackages );
EnableCbWithRestore(
pInfo->hwndCbPap, !fEapSelected, FALSE, &pInfo->fPap );
EnableCbWithRestore(
pInfo->hwndCbSpap, !fEapSelected, FALSE, &pInfo->fSpap );
EnableCbWithRestore(
pInfo->hwndCbChap, !fEapSelected, FALSE, &pInfo->fChap );
EnableCbWithRestore(
pInfo->hwndCbMsChap, !fEapSelected, FALSE, &pInfo->fMsChap );
EnableCbWithRestore(
pInfo->hwndCbW95MsChap, !fEapSelected, FALSE, &pInfo->fW95MsChap );
EnableCbWithRestore(
pInfo->hwndCbMsChap2, !fEapSelected, FALSE, &pInfo->fMsChap2 );
if (fEapSelected)
{
EnableCbWithRestore(
pInfo->hwndCbUseWindowsPw, FALSE, FALSE, &pInfo->fUseWindowsPw );
}
else
{
CaCbToggle( pInfo, NULL );
}
}
BOOL
CaSave(
IN CAINFO* pInfo )
// Saves control contents to caller's PBENTRY argument. 'PInfo' is the
// dialog context.
//
// Returns TRUE if successful or false if invalid combination of
// selections was detected and reported.
//
{
DWORD dwDe;
PBENTRY* pEntry;
DTLNODE* pNodeEap;
DWORD dwEapKey;
pEntry = pInfo->pArgs->pEntry;
dwDe =
(DWORD )ComboBox_GetItemData(
pInfo->hwndLbEncryption,
ComboBox_GetCurSel( pInfo->hwndLbEncryption ) );
if (Button_GetCheck( pInfo->hwndRbEap ))
{
DTLNODE* pNode;
EAPCFG* pEapcfg;
pNode = (DTLNODE* )ComboBox_GetItemDataPtr(
pInfo->hwndLbEapPackages,
ComboBox_GetCurSel( pInfo->hwndLbEapPackages ) );
ASSERT( pNode );
if(NULL == pNode)
{
return FALSE;
}
pEapcfg = (EAPCFG* )DtlGetData( pNode );
ASSERT( pEapcfg );
// Tell user about required EAP configuration, if applicable.
//
if (pNode != pInfo->pOriginalEapcfgNode
&& pEapcfg->fForceConfig
&& !pEapcfg->fConfigDllCalled)
{
MsgDlg(
pInfo->hwndDlg, SID_CustomAuthConfigRequired, NULL );
ASSERT( IsWindowEnabled( pInfo->hwndPbProperties ) );
SetFocus( pInfo->hwndPbProperties );
return FALSE;
}
// Tell user EAP doesn't support encryption, if it doesn't and he
// chose encryption. This check doesn't apply to L2TP which does not
// use MPPE.
//
if (!(pEntry->dwType == RASET_Vpn
&& pEntry->dwVpnStrategy == VS_L2tpOnly)
&& (dwDe != DE_None && !pEapcfg->fProvidesMppeKeys))
{
MsgDlg( pInfo->hwndDlg, SID_NeedEapKeys, NULL );
return FALSE;
}
// Save settings.
//
pEntry->dwDataEncryption = dwDe;
pEntry->dwAuthRestrictions = AR_F_AuthCustom | AR_F_AuthEAP;
pEntry->fAutoLogon = FALSE;
dwEapKey = pEapcfg->dwKey;
}
else
{
DWORD dwAr;
if (dwDe != DE_None
&& dwDe != DE_IfPossible
&& !(pEntry->dwType == RASET_Vpn
&& pEntry->dwVpnStrategy == VS_L2tpOnly)
&& !(Button_GetCheck( pInfo->hwndCbMsChap )
|| Button_GetCheck( pInfo->hwndCbW95MsChap )
|| Button_GetCheck( pInfo->hwndCbMsChap2 )))
{
MsgDlg( pInfo->hwndDlg, SID_MsChapRequired, NULL );
return FALSE;
}
dwAr = AR_F_AuthCustom;
if (Button_GetCheck( pInfo->hwndCbPap ))
{
dwAr |= AR_F_AuthPAP;
}
if (Button_GetCheck( pInfo->hwndCbSpap ))
{
dwAr |= AR_F_AuthSPAP;
}
if (Button_GetCheck( pInfo->hwndCbChap ))
{
dwAr |= AR_F_AuthMD5CHAP;
}
if (Button_GetCheck( pInfo->hwndCbMsChap ))
{
dwAr |= AR_F_AuthMSCHAP;
}
if (IsWindowEnabled( pInfo->hwndCbW95MsChap )
&& Button_GetCheck( pInfo->hwndCbW95MsChap ))
{
dwAr |= AR_F_AuthW95MSCHAP;
}
if (Button_GetCheck( pInfo->hwndCbMsChap2 ))
{
dwAr |= AR_F_AuthMSCHAP2;
}
if (dwDe != DE_None
&& !(pEntry->dwType == RASET_Vpn
&& pEntry->dwVpnStrategy == VS_L2tpOnly)
&& (dwAr & (AR_F_AuthPAP | AR_F_AuthSPAP | AR_F_AuthMD5CHAP)))
{
MSGARGS msgargs;
ZeroMemory( &msgargs, sizeof(msgargs) );
msgargs.dwFlags = MB_YESNO | MB_DEFBUTTON2 | MB_ICONINFORMATION;
if (MsgDlg(
pInfo->hwndDlg, SID_OptionalAuthQuery, &msgargs) == IDNO)
{
Button_SetCheck( pInfo->hwndCbPap, FALSE );
Button_SetCheck( pInfo->hwndCbSpap, FALSE );
Button_SetCheck( pInfo->hwndCbChap, FALSE );
return FALSE;
}
}
if (dwAr == AR_F_AuthCustom)
{
MsgDlg( pInfo->hwndDlg, SID_NoAuthChecked, NULL );
return FALSE;
}
// Save settings.
//
pEntry->dwAuthRestrictions = dwAr;
pEntry->dwDataEncryption = dwDe;
if (IsWindowEnabled( pInfo->hwndCbUseWindowsPw ))
{
pEntry->fAutoLogon = Button_GetCheck( pInfo->hwndCbUseWindowsPw );
}
else
{
pEntry->fAutoLogon = FALSE;
}
dwEapKey = pEntry->dwCustomAuthKey;
}
for (pNodeEap = DtlGetFirstNode(pInfo->pListEapcfgs);
pNodeEap;
pNodeEap = DtlGetNextNode(pNodeEap))
{
EAPCFG* pcfg = (EAPCFG* )DtlGetData(pNodeEap);
ASSERT( pcfg );
pEntry->dwCustomAuthKey = pcfg->dwKey;
(VOID) DwSetCustomAuthData(
pEntry,
pcfg->cbData,
pcfg->pData);
Free0(pcfg->pData);
pcfg->pData = NULL;
}
pEntry->dwCustomAuthKey = dwEapKey;
return TRUE;
}
VOID
CaTerm(
IN HWND hwndDlg )
// Dialog termination. Releases the context block. 'HwndDlg' is the
// handle of a dialog.
//
{
CAINFO* pInfo;
TRACE( "CaTerm" );
pInfo = (CAINFO* )GetWindowLongPtr( hwndDlg, DWLP_USER );
if (pInfo)
{
if (pInfo->pListEapcfgs)
{
DtlDestroyList( pInfo->pListEapcfgs, DestroyEapcfgNode );
}
Free( pInfo );
TRACE( "Context freed" );
}
}