Leaked source code of windows server 2003
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.
 
 
 
 
 
 

6560 lines
188 KiB

/*
Copyright (c) 1997, Microsoft Corporation, all rights reserved
Description:
History:
Nov 1997: Vijay Baliga created original version.
*/
#include <nt.h> // Required by windows.h
#include <ntrtl.h> // Required by windows.h
#include <nturtl.h> // Required by windows.h
#include <windows.h> // Win32 base API's
#include <windowsx.h>
#include <stdio.h> // For swprintf
#include <rasauth.h> // Required by raseapif.h
#include <rtutils.h> // For RTASSERT
#include <rasman.h> // For EAPLOGONINFO
#include <raserror.h> // For ERROR_NO_SMART_CARD_READER
#include <eaptypeid.h>
#include <commctrl.h>
#if WINVER > 0x0500
#include "wzcsapi.h"
#endif
#include <schannel.h>
#define SECURITY_WIN32
#include <security.h> // For GetUserNameExA, CredHandle
#include <sspi.h> // For CredHandle
#include <wincrypt.h>
#include <dsrole.h>
#include <eaptls.h>
#include <resource.h>
const DWORD g_adwHelp[] =
{
IDC_RADIO_USE_CARD, IDH_RADIO_USE_CARD,
IDC_RADIO_USE_REGISTRY, IDH_RADIO_USE_REGISTRY,
IDC_CHECK_VALIDATE_CERT, IDH_CHECK_VALIDATE_CERT,
IDC_CHECK_VALIDATE_NAME, IDH_CHECK_VALIDATE_NAME,
IDC_EDIT_SERVER_NAME, IDH_EDIT_SERVER_NAME,
IDC_STATIC_ROOT_CA_NAME, IDH_COMBO_ROOT_CA_NAME,
IDC_CHECK_DIFF_USER, IDH_CHECK_DIFF_USER,
IDC_STATIC_DIFF_USER, IDH_EDIT_DIFF_USER,
IDC_EDIT_DIFF_USER, IDH_EDIT_DIFF_USER,
IDC_STATIC_PIN, IDH_EDIT_PIN,
IDC_EDIT_PIN, IDH_EDIT_PIN,
IDC_CHECK_SAVE_PIN, IDH_CHECK_SAVE_PIN,
IDC_STATIC_SERVER_NAME, IDH_COMBO_SERVER_NAME,
IDC_COMBO_SERVER_NAME, IDH_COMBO_SERVER_NAME,
IDC_STATIC_USER_NAME, IDH_COMBO_USER_NAME,
IDC_COMBO_USER_NAME, IDH_COMBO_USER_NAME,
IDC_STATIC_FRIENDLY_NAME, IDH_EDIT_FRIENDLY_NAME,
IDC_EDIT_FRIENDLY_NAME, IDH_EDIT_FRIENDLY_NAME,
IDC_STATIC_ISSUER, IDH_EDIT_ISSUER,
IDC_EDIT_ISSUER, IDH_EDIT_ISSUER,
IDC_STATIC_EXPIRATION, IDH_EDIT_EXPIRATION,
IDC_EDIT_EXPIRATION, IDH_EDIT_EXPIRATION,
0, 0
};
/*
Returns:
VOID
Notes:
Calls WinHelp to popup context sensitive help. padwMap is an array of
control-ID help-ID pairs terminated with a 0,0 pair. unMsg is WM_HELP or
WM_CONTEXTMENU indicating the message received requesting help. wParam and
lParam are the parameters of the message received requesting help.
*/
VOID
ContextHelp(
IN const DWORD* padwMap,
IN HWND hWndDlg,
IN UINT unMsg,
IN WPARAM wParam,
IN LPARAM lParam
)
{
HWND hWnd;
UINT unType;
WCHAR* pwszHelpFile = NULL;
HELPINFO* pHelpInfo;
if (unMsg == WM_HELP)
{
pHelpInfo = (HELPINFO*) lParam;
if (pHelpInfo->iContextType != HELPINFO_WINDOW)
{
goto LDone;
}
hWnd = pHelpInfo->hItemHandle;
unType = HELP_WM_HELP;
}
else
{
// Standard Win95 method that produces a one-item "What's This?" menu
// that user must click to get help.
hWnd = (HWND) wParam;
unType = HELP_CONTEXTMENU;
};
pwszHelpFile = WszFromId(GetHInstance(), IDS_HELPFILE);
if (NULL == pwszHelpFile)
{
goto LDone;
}
WinHelp(hWnd, pwszHelpFile, unType, (ULONG_PTR)padwMap);
LDone:
LocalFree(pwszHelpFile);
}
VOID
DisplayResourceError (
IN HWND hwndParent,
IN DWORD dwResourceId
)
{
WCHAR* pwszTitle = NULL;
WCHAR* pwszMessage = NULL;
pwszTitle = WszFromId(GetHInstance(), IDS_CANT_CONFIGURE_SERVER_TITLE);
pwszMessage = WszFromId(GetHInstance(), dwResourceId);
MessageBox(hwndParent,
(pwszMessage != NULL)? pwszMessage : L"",
(pwszTitle != NULL) ? pwszTitle : L"",
MB_OK | MB_ICONERROR);
LocalFree(pwszTitle);
LocalFree(pwszMessage);
}
/*
Returns:
VOID
Notes:
Display the error message corresponding to dwErrNum. Used only on the server
side.
*/
VOID
DisplayError(
IN HWND hwndParent,
IN DWORD dwErrNum
)
{
WCHAR* pwszTitle = NULL;
WCHAR* pwszMessageFormat = NULL;
WCHAR* pwszMessage = NULL;
DWORD dwErr;
pwszTitle = WszFromId(GetHInstance(), IDS_CANT_CONFIGURE_SERVER_TITLE);
dwErr = MprAdminGetErrorString(dwErrNum, &pwszMessage);
if (NO_ERROR != dwErr)
{
pwszMessageFormat = WszFromId(GetHInstance(),
IDS_CANT_CONFIGURE_SERVER_TEXT);
if (NULL != pwszMessageFormat)
{
pwszMessage = LocalAlloc(LPTR, wcslen(pwszMessageFormat) + 20);
if (NULL != pwszMessage)
{
swprintf(pwszMessage, pwszMessageFormat, dwErrNum);
}
}
}
MessageBox(hwndParent,
(pwszMessage != NULL)? pwszMessage : L"",
(pwszTitle != NULL) ? pwszTitle : L"",
MB_OK | MB_ICONERROR);
LocalFree(pwszTitle);
LocalFree(pwszMessageFormat);
LocalFree(pwszMessage);
}
/* List view of check boxes state indices.
*/
#define SI_Unchecked 1
#define SI_Checked 2
#define SI_DisabledUnchecked 3
#define SI_DisabledChecked 4
#define LVXN_SETCHECK (LVN_LAST + 1)
//
//Work arounds for bugs in list ctrl...
//
BOOL
ListView_GetCheck(
IN HWND hwndLv,
IN INT iItem )
/* Returns true if the check box of item 'iItem' of listview of checkboxes
** 'hwndLv' is checked, false otherwise. This function works on disabled
** check boxes as well as enabled ones.
*/
{
UINT unState;
unState = ListView_GetItemState( hwndLv, iItem, LVIS_STATEIMAGEMASK );
return !!((unState == INDEXTOSTATEIMAGEMASK( SI_Checked )) ||
(unState == INDEXTOSTATEIMAGEMASK( SI_DisabledChecked )));
}
BOOL
ListView_IsCheckDisabled (
IN HWND hwndLv,
IN INT iItem)
/* Returns true if the check box of item 'iItem' of listview of checkboxes
** 'hwndLv' is disabled, false otherwise.
*/
{
UINT unState;
unState = ListView_GetItemState( hwndLv, iItem, LVIS_STATEIMAGEMASK );
if ((unState == INDEXTOSTATEIMAGEMASK( SI_DisabledChecked )) ||
(unState == INDEXTOSTATEIMAGEMASK( SI_DisabledUnchecked )))
return TRUE;
return FALSE;
}
VOID
ListView_SetCheck(
IN HWND hwndLv,
IN INT iItem,
IN BOOL fCheck )
/* Sets the check mark on item 'iItem' of listview of checkboxes 'hwndLv'
** to checked if 'fCheck' is true or unchecked if false.
*/
{
NM_LISTVIEW nmlv;
if (ListView_IsCheckDisabled(hwndLv, iItem))
return;
ListView_SetItemState( hwndLv, iItem,
INDEXTOSTATEIMAGEMASK( (fCheck) ? SI_Checked : SI_Unchecked ),
LVIS_STATEIMAGEMASK );
nmlv.hdr.code = LVXN_SETCHECK;
nmlv.hdr.hwndFrom = hwndLv;
nmlv.iItem = iItem;
FORWARD_WM_NOTIFY(
GetParent(hwndLv), GetDlgCtrlID(hwndLv), &nmlv, SendMessage
);
}
/*
Returns:
FALSE (prevent Windows from setting the default keyboard focus).
Notes:
Response to the WM_INITDIALOG message.
*/
BOOL
PinInitDialog(
IN HWND hWnd,
IN LPARAM lParam
)
{
EAPTLS_PIN_DIALOG* pEapTlsPinDialog;
EAPTLS_USER_PROPERTIES* pUserProp;
WCHAR* pwszTitleFormat = NULL;
WCHAR* pwszTitle = NULL;
WCHAR* pwszIdentity = NULL;
SetWindowLongPtr(hWnd, DWLP_USER, lParam);
pEapTlsPinDialog = (EAPTLS_PIN_DIALOG*)lParam;
pUserProp = pEapTlsPinDialog->pUserProp;
pEapTlsPinDialog->hWndStaticDiffUser =
GetDlgItem(hWnd, IDC_STATIC_DIFF_USER);
pEapTlsPinDialog->hWndEditDiffUser =
GetDlgItem(hWnd, IDC_EDIT_DIFF_USER);
pEapTlsPinDialog->hWndStaticPin =
GetDlgItem(hWnd, IDC_STATIC_PIN);
pEapTlsPinDialog->hWndEditPin =
GetDlgItem(hWnd, IDC_EDIT_PIN);
if (pUserProp->pwszDiffUser[0])
{
SetWindowText(pEapTlsPinDialog->hWndEditDiffUser,
pUserProp->pwszDiffUser);
}
if (pUserProp->pwszPin[0])
{
SetWindowText(pEapTlsPinDialog->hWndEditPin, pUserProp->pwszPin);
ZeroMemory(pUserProp->pwszPin,
wcslen(pUserProp->pwszPin) * sizeof(WCHAR));
}
if (!(pEapTlsPinDialog->fFlags & EAPTLS_PIN_DIALOG_FLAG_DIFF_USER))
{
EnableWindow(pEapTlsPinDialog->hWndStaticDiffUser, FALSE);
EnableWindow(pEapTlsPinDialog->hWndEditDiffUser, FALSE);
}
if (pUserProp->fFlags & EAPTLS_USER_FLAG_SAVE_PIN)
{
CheckDlgButton(hWnd, IDC_CHECK_SAVE_PIN, BST_CHECKED);
}
// Bug 428871 implies that SavePin must not be allowed.
ShowWindow(GetDlgItem(hWnd, IDC_CHECK_SAVE_PIN), SW_HIDE);
SetFocus(pEapTlsPinDialog->hWndEditPin);
{
// Set the title
pwszTitleFormat = WszFromId(GetHInstance(), IDS_CONNECT);
if (NULL != pwszTitleFormat)
{
pwszTitle = LocalAlloc(LPTR,
(wcslen(pwszTitleFormat) +
wcslen(pEapTlsPinDialog->pwszEntry)) *
sizeof(WCHAR));
if (NULL != pwszTitle)
{
swprintf(pwszTitle, pwszTitleFormat,
pEapTlsPinDialog->pwszEntry);
SetWindowText(hWnd, pwszTitle);
}
}
}
LocalFree(pwszTitleFormat);
LocalFree(pwszTitle);
return(FALSE);
}
void ValidatePIN ( IN EAPTLS_PIN_DIALOG* pEapTlsPinDialog )
{
pEapTlsPinDialog->dwRetCode =
MatchPublicPrivateKeys ( pEapTlsPinDialog->pCertContext,
TRUE,
pEapTlsPinDialog->pUserProp->pwszPin
);
#if 0
AssociatePinWithCertificate( pEapTlsPinDialog->pCertContext,
pEapTlsPinDialog->pUserProp,
FALSE,
TRUE
);
#endif
return;
}
/*
Returns:
TRUE: We prrocessed this message.
FALSE: We did not prrocess this message.
Notes:
Response to the WM_COMMAND message.
*/
BOOL
PinCommand(
IN EAPTLS_PIN_DIALOG* pEapTlsPinDialog,
IN WORD wNotifyCode,
IN WORD wId,
IN HWND hWndDlg,
IN HWND hWndCtrl
)
{
DWORD dwNumChars;
DWORD dwNameLength;
DWORD dwPinLength;
DWORD dwSize;
EAPTLS_USER_PROPERTIES* pUserProp;
switch(wId)
{
case IDOK:
dwNameLength = GetWindowTextLength(
pEapTlsPinDialog->hWndEditDiffUser);
dwPinLength = GetWindowTextLength(
pEapTlsPinDialog->hWndEditPin);
// There is already one character in awszString.
// Add the number of characters in DiffUser...
dwNumChars = dwNameLength;
// Add the number of characters in PIN...
dwNumChars += dwPinLength;
// Add one more for a terminating NULL. Use the extra character in
// awszString for the other terminating NULL.
dwNumChars += 1;
dwSize = sizeof(EAPTLS_USER_PROPERTIES) + dwNumChars*sizeof(WCHAR);
pUserProp = LocalAlloc(LPTR, dwSize);
if (NULL == pUserProp)
{
EapTlsTrace("LocalAlloc in Command failed and returned %d",
GetLastError());
}
else
{
CopyMemory(pUserProp, pEapTlsPinDialog->pUserProp,
sizeof(EAPTLS_USER_PROPERTIES));
pUserProp->dwSize = dwSize;
pUserProp->pwszDiffUser = pUserProp->awszString;
GetWindowText(pEapTlsPinDialog->hWndEditDiffUser,
pUserProp->pwszDiffUser,
dwNameLength + 1);
pUserProp->dwPinOffset = dwNameLength + 1;
pUserProp->pwszPin = pUserProp->awszString +
pUserProp->dwPinOffset;
GetWindowText(pEapTlsPinDialog->hWndEditPin,
pUserProp->pwszPin,
dwPinLength + 1);
LocalFree(pEapTlsPinDialog->pUserProp);
pEapTlsPinDialog->pUserProp = pUserProp;
}
if (BST_CHECKED == IsDlgButtonChecked(hWndDlg, IDC_CHECK_SAVE_PIN))
{
pEapTlsPinDialog->pUserProp->fFlags |= EAPTLS_USER_FLAG_SAVE_PIN;
}
else
{
pEapTlsPinDialog->pUserProp->fFlags &= ~EAPTLS_USER_FLAG_SAVE_PIN;
}
//
//Check if valid PIN has been entered and set the error code in pEapTlsPinDialog
//
ValidatePIN ( pEapTlsPinDialog);
// Fall through
case IDCANCEL:
EndDialog(hWndDlg, wId);
return(TRUE);
default:
return(FALSE);
}
}
/*
Returns:
Notes:
Callback function used with the DialogBoxParam function. It processes
messages sent to the dialog box. See the DialogProc documentation in MSDN.
*/
INT_PTR CALLBACK
PinDialogProc(
IN HWND hWnd,
IN UINT unMsg,
IN WPARAM wParam,
IN LPARAM lParam
)
{
EAPTLS_PIN_DIALOG* pEapTlsPinDialog;
switch (unMsg)
{
case WM_INITDIALOG:
return(PinInitDialog(hWnd, lParam));
case WM_HELP:
case WM_CONTEXTMENU:
{
ContextHelp(g_adwHelp, hWnd, unMsg, wParam, lParam);
break;
}
case WM_COMMAND:
pEapTlsPinDialog = (EAPTLS_PIN_DIALOG*)GetWindowLongPtr(hWnd, DWLP_USER);
return(PinCommand(pEapTlsPinDialog, HIWORD(wParam), LOWORD(wParam),
hWnd, (HWND)lParam));
}
return(FALSE);
}
/*
** Smart card and cert store accessing status dialog
*/
INT_PTR CALLBACK
StatusDialogProc(
IN HWND hWnd,
IN UINT unMsg,
IN WPARAM wParam,
IN LPARAM lParam
)
{
switch (unMsg)
{
case WM_INITDIALOG:
{
ShowWindow(GetDlgItem(hWnd, IDC_BITMAP_SCARD),
SW_SHOW
);
ShowWindow(GetDlgItem(hWnd, IDC_STATUS_SCARD),
SW_SHOW
);
return TRUE;
}
}
return FALSE;
}
/*
Returns:
VOID
Notes:
Enables or disables the controls in the "Validate server name" group.
*/
VOID
EnableValidateNameControls(
IN EAPTLS_CONN_DIALOG* pEapTlsConnDialog
)
{
BOOL fEnable;
RTASSERT(NULL != pEapTlsConnDialog);
fEnable = !(pEapTlsConnDialog->pConnPropv1->fFlags &
EAPTLS_CONN_FLAG_NO_VALIDATE_CERT);
EnableWindow(pEapTlsConnDialog->hWndCheckValidateName, fEnable);
EnableWindow(pEapTlsConnDialog->hWndStaticRootCaName, fEnable);
EnableWindow(pEapTlsConnDialog->hWndListRootCaName, fEnable);
fEnable = ( fEnable
&& !(pEapTlsConnDialog->pConnPropv1->fFlags &
EAPTLS_CONN_FLAG_NO_VALIDATE_NAME));
EnableWindow(pEapTlsConnDialog->hWndEditServerName, fEnable);
fEnable = pEapTlsConnDialog->pConnPropv1->fFlags
& EAPTLS_CONN_FLAG_REGISTRY;
EnableWindow( pEapTlsConnDialog->hWndCheckUseSimpleSel, fEnable );
}
/*
Returns:
VOID
Notes:
Displays the cert information
*/
VOID
DisplayCertInfo(
IN EAPTLS_USER_DIALOG* pEapTlsUserDialog
)
{
RTASSERT(NULL != pEapTlsUserDialog);
// Erase old values first
SetWindowText(pEapTlsUserDialog->hWndEditFriendlyName, L"");
SetWindowText(pEapTlsUserDialog->hWndEditIssuer, L"");
SetWindowText(pEapTlsUserDialog->hWndEditExpiration, L"");
SetWindowText(pEapTlsUserDialog->hWndEditDiffUser, L"");
if (NULL != pEapTlsUserDialog->pCert)
{
if (NULL != pEapTlsUserDialog->pCert->pwszFriendlyName)
{
SetWindowText(pEapTlsUserDialog->hWndEditFriendlyName,
pEapTlsUserDialog->pCert->pwszFriendlyName);
}
if (NULL != pEapTlsUserDialog->pCert->pwszIssuer)
{
SetWindowText(pEapTlsUserDialog->hWndEditIssuer,
pEapTlsUserDialog->pCert->pwszIssuer);
}
if (NULL != pEapTlsUserDialog->pCert->pwszExpiration)
{
SetWindowText(pEapTlsUserDialog->hWndEditExpiration,
pEapTlsUserDialog->pCert->pwszExpiration);
}
if ( (NULL != pEapTlsUserDialog->pCert->pwszDisplayName)
&& (NULL != pEapTlsUserDialog->hWndEditDiffUser)
&& (EAPTLS_USER_DIALOG_FLAG_DIFF_USER & pEapTlsUserDialog->fFlags))
{
SetWindowText(pEapTlsUserDialog->hWndEditDiffUser,
pEapTlsUserDialog->pCert->pwszDisplayName);
}
}
}
VOID InitComboBoxFromGroup (
IN HWND hWnd,
IN PEAPTLS_GROUPED_CERT_NODES pGroupList,
IN EAPTLS_CERT_NODE* pCert //Selected certificate
)
{
DWORD dwIndex;
DWORD dwItemIndex;
WCHAR* pwszDisplayName;
PEAPTLS_GROUPED_CERT_NODES pGListTemp = pGroupList;
SendMessage(hWnd, CB_RESETCONTENT, 0, 0);
dwIndex = 0;
dwItemIndex = 0;
while (NULL != pGListTemp)
{
pwszDisplayName = pGListTemp->pwszDisplayName;
if (NULL == pwszDisplayName)
{
pwszDisplayName = L" ";
}
SendMessage(hWnd, CB_ADDSTRING, 0, (LPARAM)pwszDisplayName);
if (pGListTemp->pMostRecentCert == pCert)
{
dwItemIndex = dwIndex;
}
pGListTemp = pGListTemp->pNext;
dwIndex++;
}
SendMessage(hWnd, CB_SETCURSEL, dwItemIndex, 0);
}
/*
Returns:
VOID
Notes:
Initializes a combo box
*/
VOID
InitComboBox(
IN HWND hWnd,
IN EAPTLS_CERT_NODE* pCertList,
IN EAPTLS_CERT_NODE* pCert
)
{
DWORD dwIndex;
DWORD dwItemIndex;
WCHAR* pwszDisplayName;
SendMessage(hWnd, CB_RESETCONTENT, 0, 0);
dwIndex = 0;
dwItemIndex = 0;
while (NULL != pCertList)
{
pwszDisplayName = pCertList->pwszDisplayName;
if (NULL == pwszDisplayName)
{
pwszDisplayName = L" ";
}
SendMessage(hWnd, CB_ADDSTRING, 0, (LPARAM)pwszDisplayName);
SendMessage(hWnd, CB_SETITEMDATA, (WORD)dwIndex, (LPARAM)pCertList);
if (pCertList == pCert)
{
dwItemIndex = dwIndex;
}
pCertList = pCertList->pNext;
dwIndex++;
}
SendMessage(hWnd, CB_SETCURSEL, dwItemIndex, 0);
}
/*
Returns:
VOID
Notes:
Initializes a List box with selected certs
*/
VOID InitListBox ( IN HWND hWnd,
IN EAPTLS_CERT_NODE * pCertList,
IN DWORD dwNumSelCerts,
IN EAPTLS_CERT_NODE ** ppSelectedCertList
)
{
int nIndex = 0;
int nNewIndex = 0;
DWORD dw = 0;
WCHAR* pwszDisplayName;
LVITEM lvItem;
ListView_DeleteAllItems(hWnd);
while (NULL != pCertList)
{
pwszDisplayName = pCertList->pwszDisplayName;
if (NULL == pwszDisplayName)
{
pCertList = pCertList->pNext;
continue;
}
ZeroMemory(&lvItem, sizeof(lvItem));
lvItem.mask = LVIF_TEXT|LVIF_PARAM;
lvItem.pszText = pwszDisplayName;
lvItem.iItem = nIndex;
lvItem.lParam = (LPARAM)pCertList;
nNewIndex = ListView_InsertItem ( hWnd, &lvItem );
for ( dw = 0; dw < dwNumSelCerts; dw ++ )
{
if ( pCertList == *(ppSelectedCertList+dw) )
{
ListView_SetCheckState(hWnd, nNewIndex,TRUE);
}
}
nIndex++;
pCertList = pCertList->pNext;
}
ListView_SetItemState( hWnd,
0,
LVIS_FOCUSED|LVIS_SELECTED,
LVIS_FOCUSED|LVIS_SELECTED
);
}
VOID CertListSelectedCount ( HWND hWndCtrl,
DWORD * pdwSelCertCount )
{
DWORD dwItemIndex = 0;
DWORD dwItemCount = 0;
dwItemCount = ListView_GetItemCount(hWndCtrl);
*pdwSelCertCount = 0;
for ( dwItemIndex = 0; dwItemIndex < dwItemCount; dwItemIndex ++ )
{
if ( ListView_GetCheckState(hWndCtrl, dwItemIndex) )
{
(*pdwSelCertCount) ++;
}
}
}
VOID
CertListSelected(
IN HWND hWndCtrl, //Handle to the list box
IN EAPTLS_CERT_NODE* pCertList, //List of certs in the listbox
IN OUT EAPTLS_CERT_NODE** ppSelCertList, //List of selected
IN OUT EAPTLS_HASH* pHash, //List of Hash
IN DWORD dwNumHash //Number of Items in the list
)
{
DWORD dwItemIndex = 0;
DWORD dwItemCount = ListView_GetItemCount(hWndCtrl);
DWORD dwCertIndex = 0;
LVITEM lvitem;
if (NULL == pCertList)
{
return;
}
//Skip the one with null display name...
pCertList = pCertList->pNext;
//
//Need to do two iterations on the list box.
//I am sure there is a better way of doing this but
//I just dont know...
//
for ( dwItemIndex = 0; dwItemIndex < dwItemCount; dwItemIndex ++ )
{
if ( ListView_GetCheckState(hWndCtrl, dwItemIndex) )
{
ZeroMemory( &lvitem, sizeof(lvitem) );
lvitem.mask = LVIF_PARAM;
lvitem.iItem = dwItemIndex;
ListView_GetItem(hWndCtrl, &lvitem);
*(ppSelCertList + dwCertIndex ) = (EAPTLS_CERT_NODE *)lvitem.lParam;
CopyMemory ( pHash + dwCertIndex,
&(((EAPTLS_CERT_NODE *)lvitem.lParam)->Hash),
sizeof(EAPTLS_HASH)
);
dwCertIndex ++;
}
}
}
/*
Returns:
VOID
Notes:
hWndCtrl is the HWND of a combo box. pCertList is the associated list of
certs. *ppCert will ultimately point to the cert that was selected. Its
hash will be stored in *pHash.
*/
VOID
CertSelected(
IN HWND hWndCtrl,
IN EAPTLS_CERT_NODE* pCertList,
IN EAPTLS_CERT_NODE** ppCert,
IN EAPTLS_HASH* pHash
)
{
LONG_PTR lIndex;
LRESULT lrItemIndex;
if (NULL == pCertList)
{
return;
}
if ( NULL == hWndCtrl )
{
lrItemIndex = 0;
}
else
{
lrItemIndex = SendMessage(hWndCtrl, CB_GETCURSEL, 0, 0);
}
for (lIndex = 0; lIndex != lrItemIndex; lIndex++)
{
pCertList = pCertList->pNext;
}
*ppCert = pCertList;
CopyMemory(pHash, &(pCertList->Hash), sizeof(EAPTLS_HASH));
}
VOID
GroupCertSelected(
IN HWND hWndCtrl,
IN PEAPTLS_GROUPED_CERT_NODES pGroupList,
IN EAPTLS_CERT_NODE** ppCert,
IN EAPTLS_HASH* pHash
)
{
LONG_PTR lIndex;
LRESULT lrItemIndex;
PEAPTLS_GROUPED_CERT_NODES pGList = pGroupList;
if (NULL == pGList)
{
return;
}
if ( NULL == hWndCtrl )
{
lrItemIndex = 0;
}
else
{
lrItemIndex = SendMessage(hWndCtrl, CB_GETCURSEL, 0, 0);
}
//
// This is really a very bogus way of doing things...
// We can setup a itemdata for this in the control itself...
//
for (lIndex = 0; lIndex != lrItemIndex; lIndex++)
{
pGList = pGList ->pNext;
}
*ppCert = pGList->pMostRecentCert;
CopyMemory(pHash, &(pGList ->pMostRecentCert->Hash), sizeof(EAPTLS_HASH));
}
/*
Returns:
FALSE (prevent Windows from setting the default keyboard focus).
Notes:
Response to the WM_INITDIALOG message.
*/
BOOL
UserInitDialog(
IN HWND hWnd,
IN LPARAM lParam
)
{
EAPTLS_USER_DIALOG* pEapTlsUserDialog;
WCHAR* pwszTitleFormat = NULL;
WCHAR* pwszTitle = NULL;
SetWindowLongPtr(hWnd, DWLP_USER, lParam);
pEapTlsUserDialog = (EAPTLS_USER_DIALOG*)lParam;
BringWindowToTop(hWnd);
pEapTlsUserDialog->hWndComboUserName =
GetDlgItem(hWnd, IDC_COMBO_USER_NAME);
if (NULL == pEapTlsUserDialog->hWndComboUserName)
{
// We must be showing the server's cert selection dialog
pEapTlsUserDialog->hWndComboUserName =
GetDlgItem(hWnd, IDC_COMBO_SERVER_NAME);
}
pEapTlsUserDialog->hWndBtnViewCert =
GetDlgItem(hWnd, IDC_BUTTON_VIEW_CERTIFICATE );
pEapTlsUserDialog->hWndEditFriendlyName =
GetDlgItem(hWnd, IDC_EDIT_FRIENDLY_NAME);
pEapTlsUserDialog->hWndEditIssuer =
GetDlgItem(hWnd, IDC_EDIT_ISSUER);
pEapTlsUserDialog->hWndEditExpiration =
GetDlgItem(hWnd, IDC_EDIT_EXPIRATION);
pEapTlsUserDialog->hWndStaticDiffUser =
GetDlgItem(hWnd, IDC_STATIC_DIFF_USER);
pEapTlsUserDialog->hWndEditDiffUser =
GetDlgItem(hWnd, IDC_EDIT_DIFF_USER);
if ( pEapTlsUserDialog->fFlags & EAPTLS_USER_DIALOG_FLAG_USE_SIMPLE_CERTSEL
)
{
InitComboBoxFromGroup(pEapTlsUserDialog->hWndComboUserName,
pEapTlsUserDialog->pGroupedList,
pEapTlsUserDialog->pCert);
}
else
{
InitComboBox(pEapTlsUserDialog->hWndComboUserName,
pEapTlsUserDialog->pCertList,
pEapTlsUserDialog->pCert);
}
if ( (NULL != pEapTlsUserDialog->hWndEditDiffUser)
&& (!(pEapTlsUserDialog->fFlags & EAPTLS_USER_DIALOG_FLAG_DIFF_USER)))
{
ShowWindow(pEapTlsUserDialog->hWndStaticDiffUser, SW_HIDE);
ShowWindow(pEapTlsUserDialog->hWndEditDiffUser, SW_HIDE);
}
DisplayCertInfo(pEapTlsUserDialog);
if (pEapTlsUserDialog->pUserProp->pwszDiffUser[0])
{
SetWindowText(pEapTlsUserDialog->hWndEditDiffUser,
pEapTlsUserDialog->pUserProp->pwszDiffUser);
}
SetFocus(pEapTlsUserDialog->hWndComboUserName);
if (pEapTlsUserDialog->fFlags & EAPTLS_USER_DIALOG_FLAG_DIFF_TITLE)
{
// Set the title
pwszTitleFormat = WszFromId(GetHInstance(), IDS_CONNECT);
if (NULL != pwszTitleFormat)
{
pwszTitle = LocalAlloc(LPTR,
(wcslen(pwszTitleFormat) +
wcslen(pEapTlsUserDialog->pwszEntry)) *
sizeof(WCHAR));
if (NULL != pwszTitle)
{
HWND hWndDuplicate = NULL;
DWORD dwThreadProcessId = 0;
DWORD dwRetCode = NO_ERROR;
swprintf(pwszTitle, pwszTitleFormat,
pEapTlsUserDialog->pwszEntry);
if ((hWndDuplicate = FindWindow (NULL, pwszTitle)) != NULL)
{
GetWindowThreadProcessId (hWndDuplicate, &dwThreadProcessId);
if ((GetCurrentProcessId ()) == dwThreadProcessId)
{
// Kill current dialog since old one may be in use
if (!PostMessage (hWnd, WM_DESTROY, 0, 0))
{
dwRetCode = GetLastError ();
EapTlsTrace("PostMessage failed with error %ld", dwRetCode);
}
goto LDone;
}
else
{
EapTlsTrace("Matching Window does not have same process id");
}
}
else
{
EapTlsTrace ("FindWindow could not find matching window");
}
SetWindowText(hWnd, pwszTitle);
}
}
}
LDone:
LocalFree(pwszTitleFormat);
LocalFree(pwszTitle);
return(FALSE);
}
/*
Returns:
TRUE: We prrocessed this message.
FALSE: We did not prrocess this message.
Notes:
Response to the WM_COMMAND message.
*/
BOOL
UserCommand(
IN EAPTLS_USER_DIALOG* pEapTlsUserDialog,
IN WORD wNotifyCode,
IN WORD wId,
IN HWND hWndDlg,
IN HWND hWndCtrl
)
{
DWORD dwNumChars;
DWORD dwTextLength;
DWORD dwSize;
EAPTLS_USER_PROPERTIES* pUserProp;
HCERTSTORE hCertStore;
PCCERT_CONTEXT pCertContext = NULL;
switch(wId)
{
case IDC_BUTTON_VIEW_CERTIFICATE:
{
WCHAR szError[256];
WCHAR szTitle[512] = {0};
CRYPT_HASH_BLOB chb;
GetWindowText(hWndDlg, szTitle, 511 );
//
// Show the certificate details here
//
if ( pEapTlsUserDialog->pCert )
{
//There is a selected cert - show details.
hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM,
0,
0,
CERT_STORE_READONLY_FLAG |
((pEapTlsUserDialog->fIdentity) ?
CERT_SYSTEM_STORE_CURRENT_USER:
CERT_SYSTEM_STORE_LOCAL_MACHINE
),
pEapTlsUserDialog->pwszStoreName
);
LoadString( GetHInstance(), IDS_NO_CERT_DETAILS,
szError, 255);
if ( !hCertStore )
{
MessageBox ( hWndDlg,
szError,
szTitle,
MB_OK|MB_ICONSTOP
);
return(TRUE);
}
chb.cbData = pEapTlsUserDialog->pCert->Hash.cbHash;
chb.pbData = pEapTlsUserDialog->pCert->Hash.pbHash;
pCertContext = CertFindCertificateInStore(
hCertStore,
0,
0,
CERT_FIND_HASH,
&chb,
0);
if ( NULL == pCertContext )
{
MessageBox ( hWndDlg,
szError,
szTitle,
MB_OK|MB_ICONSTOP
);
if ( hCertStore )
CertCloseStore( hCertStore, CERT_CLOSE_STORE_FORCE_FLAG );
return(TRUE);
}
//
// Show Cert detail
//
ShowCertDetails ( hWndDlg, hCertStore, pCertContext );
if ( pCertContext )
CertFreeCertificateContext(pCertContext);
if ( hCertStore )
CertCloseStore( hCertStore, CERT_CLOSE_STORE_FORCE_FLAG );
}
return(TRUE);
}
case IDC_COMBO_USER_NAME:
case IDC_COMBO_SERVER_NAME:
if (CBN_SELCHANGE != wNotifyCode)
{
return(FALSE); // We will not process this message
}
if ( pEapTlsUserDialog->fFlags & EAPTLS_USER_DIALOG_FLAG_USE_SIMPLE_CERTSEL
)
{
GroupCertSelected(hWndCtrl, pEapTlsUserDialog->pGroupedList,
&(pEapTlsUserDialog->pCert), &(pEapTlsUserDialog->pUserProp->Hash));
}
else
{
CertSelected(hWndCtrl, pEapTlsUserDialog->pCertList,
&(pEapTlsUserDialog->pCert), &(pEapTlsUserDialog->pUserProp->Hash));
}
DisplayCertInfo(pEapTlsUserDialog);
return(TRUE);
case IDOK:
if ( pEapTlsUserDialog->fFlags & EAPTLS_USER_DIALOG_FLAG_USE_SIMPLE_CERTSEL
)
{
GroupCertSelected(pEapTlsUserDialog->hWndComboUserName, pEapTlsUserDialog->pGroupedList,
&(pEapTlsUserDialog->pCert), &(pEapTlsUserDialog->pUserProp->Hash));
}
else
{
CertSelected(pEapTlsUserDialog->hWndComboUserName, pEapTlsUserDialog->pCertList,
&(pEapTlsUserDialog->pCert), &(pEapTlsUserDialog->pUserProp->Hash));
}
if (NULL != pEapTlsUserDialog->hWndEditDiffUser)
{
dwTextLength = GetWindowTextLength(
pEapTlsUserDialog->hWndEditDiffUser);
// There is already one character in awszString.
// Add the number of characters in DiffUser...
dwNumChars = dwTextLength;
// Add the number of characters in PIN...
dwNumChars += wcslen(pEapTlsUserDialog->pUserProp->pwszPin);
// Add one more for a terminating NULL. Use the extra character in
// awszString for the other terminating NULL.
dwNumChars += 1;
dwSize = sizeof(EAPTLS_USER_PROPERTIES) + dwNumChars*sizeof(WCHAR);
pUserProp = LocalAlloc(LPTR, dwSize);
if (NULL == pUserProp)
{
EapTlsTrace("LocalAlloc in Command failed and returned %d",
GetLastError());
}
else
{
CopyMemory(pUserProp, pEapTlsUserDialog->pUserProp,
sizeof(EAPTLS_USER_PROPERTIES));
pUserProp->dwSize = dwSize;
pUserProp->pwszDiffUser = pUserProp->awszString;
GetWindowText(pEapTlsUserDialog->hWndEditDiffUser,
pUserProp->pwszDiffUser,
dwTextLength + 1);
pUserProp->dwPinOffset = dwTextLength + 1;
pUserProp->pwszPin = pUserProp->awszString +
pUserProp->dwPinOffset;
wcscpy(pUserProp->pwszPin,
pEapTlsUserDialog->pUserProp->pwszPin);
ZeroMemory(pEapTlsUserDialog->pUserProp,
pEapTlsUserDialog->pUserProp->dwSize);
LocalFree(pEapTlsUserDialog->pUserProp);
pEapTlsUserDialog->pUserProp = pUserProp;
}
}
// Fall through
case IDCANCEL:
EndDialog(hWndDlg, wId);
return(TRUE);
default:
return(FALSE);
}
}
/*
Returns:
Notes:
Callback function used with the DialogBoxParam function. It processes
messages sent to the dialog box. See the DialogProc documentation in MSDN.
*/
INT_PTR CALLBACK
UserDialogProc(
IN HWND hWnd,
IN UINT unMsg,
IN WPARAM wParam,
IN LPARAM lParam
)
{
EAPTLS_USER_DIALOG* pEapTlsUserDialog;
switch (unMsg)
{
case WM_INITDIALOG:
return(UserInitDialog(hWnd, lParam));
case WM_HELP:
case WM_CONTEXTMENU:
{
ContextHelp(g_adwHelp, hWnd, unMsg, wParam, lParam);
break;
}
case WM_COMMAND:
pEapTlsUserDialog = (EAPTLS_USER_DIALOG*)GetWindowLongPtr(hWnd, DWLP_USER);
return(UserCommand(pEapTlsUserDialog, HIWORD(wParam), LOWORD(wParam),
hWnd, (HWND)lParam));
case WM_DESTROY:
EndDialog(hWnd, IDCANCEL);
break;
}
return(FALSE);
}
VOID CenterWindow(HWND hWnd, HWND hWndParent, BOOL bRightTop)
{
RECT rcWndParent,
rcWnd;
// Get the window rect for the parent window.
//
if (hWndParent == NULL)
GetWindowRect(GetDesktopWindow(), &rcWndParent);
else
GetWindowRect(hWndParent, &rcWndParent);
// Get the window rect for the window to be centered.
//
GetWindowRect(hWnd, &rcWnd);
// Now center the window.
//
if (bRightTop)
{
SetWindowPos(hWnd, HWND_TOPMOST,
rcWndParent.right - (rcWnd.right - rcWnd.left) - 5,
GetSystemMetrics(SM_CYCAPTION) * 2,
0, 0, SWP_NOSIZE | SWP_SHOWWINDOW);
}
else
{
SetWindowPos(hWnd, NULL,
rcWndParent.left + (rcWndParent.right - rcWndParent.left - (rcWnd.right - rcWnd.left)) / 2,
rcWndParent.top + (rcWndParent.bottom - rcWndParent.top - (rcWnd.bottom - rcWnd.top)) / 2,
0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);
}
}
void DeleteGroupedList(PEAPTLS_GROUPED_CERT_NODES pList)
{
PEAPTLS_GROUPED_CERT_NODES pTemp = NULL;
while ( pList )
{
pTemp = pList->pNext;
LocalFree(pList);
pList = pTemp;
}
}
DWORD
GroupCertificates ( EAPTLS_USER_DIALOG * pEapTlsUserDialog )
{
DWORD dwRetCode = NO_ERROR;
PEAPTLS_GROUPED_CERT_NODES pGroupList = NULL;
PEAPTLS_GROUPED_CERT_NODES pGroupListTemp = NULL;
EAPTLS_CERT_NODE* pCertList = pEapTlsUserDialog->pCertList;
EAPTLS_CERT_NODE* pSelCert = NULL;
BOOL fItemProcessed;
EapTlsTrace("GroupCertificates");
//
// This second pass to do grouping is not really required but
// is good in case we add
// something more to the groups later
//
while ( pCertList )
{
pGroupListTemp = pGroupList;
fItemProcessed = FALSE;
while ( pGroupListTemp )
{
if ( pCertList->pwszDisplayName &&
pGroupListTemp->pwszDisplayName &&
! wcscmp( pCertList->pwszDisplayName,
pGroupListTemp->pwszDisplayName
)
)
{
//
// Found the group. Now check to see
// if the new cert is more current than
// the one we have in the group. If so,
//
if ( ! pGroupListTemp->pMostRecentCert )
{
pGroupListTemp->pMostRecentCert = pCertList;
fItemProcessed = TRUE;
break;
}
else
{
if ( CompareFileTime ( &(pGroupListTemp->pMostRecentCert->IssueDate),
&(pCertList->IssueDate)
) < 0
)
{
pGroupListTemp->pMostRecentCert = pCertList;
}
//Or else drop the item.
fItemProcessed = TRUE;
break;
}
}
pGroupListTemp = pGroupListTemp->pNext;
}
if ( !fItemProcessed && pCertList->pwszDisplayName)
{
//
// need to create a new group
//
pGroupListTemp = (PEAPTLS_GROUPED_CERT_NODES)LocalAlloc(LPTR, sizeof(EAPTLS_GROUPED_CERT_NODES));
if ( NULL == pGroupListTemp )
{
dwRetCode = ERROR_OUTOFMEMORY;
goto LDone;
}
pGroupListTemp->pNext = pGroupList;
pGroupListTemp->pwszDisplayName = pCertList->pwszDisplayName;
pGroupListTemp->pMostRecentCert = pCertList;
pGroupList = pGroupListTemp;
}
pCertList = pCertList->pNext;
}
//
// now that we have grouped all the certs, check to see if
// the cert previously used is in the list. If so,
//
pGroupListTemp = pGroupList;
while ( pGroupListTemp )
{
if ( pEapTlsUserDialog->pCert == pGroupListTemp->pMostRecentCert )
{
pSelCert = pEapTlsUserDialog->pCert;
break;
}
pGroupListTemp = pGroupListTemp->pNext;
}
pEapTlsUserDialog->pGroupedList = pGroupList ;
pGroupList = NULL;
if ( NULL == pSelCert )
{
//
// Selected cert is not in the group.
//
pEapTlsUserDialog->pCert = pEapTlsUserDialog->pGroupedList->pMostRecentCert;
}
LDone:
DeleteGroupedList( pGroupList );
return dwRetCode;
}
/*
Returns:
Notes:
ppwszIdentity can be NULL.
Break up this ugly function.
*/
DWORD
GetCertInfo(
IN BOOL fServer,
IN BOOL fRouterConfig,
IN DWORD dwFlags,
IN const WCHAR* pwszPhonebook,
IN const WCHAR* pwszEntry,
IN HWND hwndParent,
IN WCHAR* pwszStoreName,
IN EAPTLS_CONN_PROPERTIES_V1* pConnProp,
IN OUT EAPTLS_USER_PROPERTIES** ppUserProp,
OUT WCHAR** ppwszIdentity
)
{
INT_PTR nRet;
HCERTSTORE hCertStore = NULL;
CRYPT_HASH_BLOB HashBlob;
PCCERT_CONTEXT pCertContext = NULL;
DWORD dwCertFlags;
BOOL fRouter;
BOOL fDiffUser = FALSE;
BOOL fGotIdentity = FALSE;
WCHAR* pwszIdentity = NULL;
WCHAR* pwszTemp;
DWORD dwNumChars;
BOOL fLogon;
EAPTLS_USER_DIALOG EapTlsUserDialog;
EAPTLS_PIN_DIALOG EapTlsPinDialog;
EAPTLS_USER_PROPERTIES* pUserProp = NULL;
EAPTLS_USER_PROPERTIES* pUserPropTemp;
RASCREDENTIALS RasCredentials;
DWORD dwErr = NO_ERROR;
DWORD dwNumCerts = 0;
HWND hWndStatus = NULL;
PCERT_ENHKEY_USAGE pUsageInternal = NULL;
RTASSERT(NULL != pwszStoreName);
RTASSERT(NULL != pConnProp);
RTASSERT(NULL != ppUserProp);
RTASSERT(NULL != *ppUserProp);
// ppwszIdentity can be NULL.
fRouter = dwFlags & RAS_EAP_FLAG_ROUTER;
fLogon = dwFlags & RAS_EAP_FLAG_LOGON;
EapTlsTrace("GetCertInfo");
pUserProp = *ppUserProp;
ZeroMemory(&EapTlsUserDialog, sizeof(EapTlsUserDialog));
ZeroMemory(&EapTlsPinDialog, sizeof(EapTlsPinDialog));
if (EAPTLS_CONN_FLAG_DIFF_USER & pConnProp->fFlags)
{
fDiffUser = TRUE;
EapTlsUserDialog.fFlags |= EAPTLS_USER_DIALOG_FLAG_DIFF_USER;
EapTlsPinDialog.fFlags |= EAPTLS_PIN_DIALOG_FLAG_DIFF_USER;
}
EapTlsUserDialog.pwszEntry = pwszEntry;
EapTlsPinDialog.pwszEntry = pwszEntry;
if ( fServer
|| fRouter
|| dwFlags & RAS_EAP_FLAG_MACHINE_AUTH //if this is a machine cert authentication
)
{
dwCertFlags = CERT_SYSTEM_STORE_LOCAL_MACHINE;
}
else
{
dwCertFlags = CERT_SYSTEM_STORE_CURRENT_USER;
EapTlsUserDialog.fFlags |= EAPTLS_USER_DIALOG_FLAG_DIFF_TITLE;
}
//Use simple cert selection logic
if ( pConnProp->fFlags & EAPTLS_CONN_FLAG_SIMPLE_CERT_SEL )
{
EapTlsUserDialog.fFlags |= EAPTLS_USER_DIALOG_FLAG_USE_SIMPLE_CERTSEL;
}
if (fLogon)
{
if (pConnProp->fFlags & EAPTLS_CONN_FLAG_REGISTRY)
{
dwErr = ERROR_NO_REG_CERT_AT_LOGON;
goto LDone;
}
else
{
EapTlsPinDialog.fFlags |= EAPTLS_PIN_DIALOG_FLAG_LOGON;
}
}
if ( fRouter )
{
EapTlsPinDialog.fFlags |= EAPTLS_PIN_DIALOG_FLAG_ROUTER;
}
if ( !fServer
&& !(pConnProp->fFlags & EAPTLS_CONN_FLAG_REGISTRY))
{
//this is smart card stuff
BOOL fCredentialsFound = FALSE;
BOOL fGotAllInfo = FALSE;
if ( dwFlags & RAS_EAP_FLAG_MACHINE_AUTH )
{
//
// Machine auth requested along with
// smart card auth so return an interactive
// mode error.
//
dwErr = ERROR_INTERACTIVE_MODE;
goto LDone;
}
hWndStatus = CreateDialogParam (GetHInstance(),
MAKEINTRESOURCE(IDD_STATUS),
hwndParent,
StatusDialogProc,
1
);
if ( NULL != hWndStatus )
{
CenterWindow(hWndStatus, NULL, FALSE);
ShowWindow(hWndStatus, SW_SHOW);
UpdateWindow(hWndStatus);
}
if (!FSmartCardReaderInstalled())
{
dwErr = ERROR_NO_SMART_CARD_READER;
goto LDone;
}
if (pUserProp->fFlags & EAPTLS_USER_FLAG_SAVE_PIN)
{
ZeroMemory(&RasCredentials, sizeof(RasCredentials));
RasCredentials.dwSize = sizeof(RasCredentials);
RasCredentials.dwMask = RASCM_Password;
dwErr = RasGetCredentials(pwszPhonebook, pwszEntry,
&RasCredentials);
if ( (dwErr == NO_ERROR)
&& (RasCredentials.dwMask & RASCM_Password))
{
fCredentialsFound = TRUE;
}
else
{
pUserProp->fFlags &= ~EAPTLS_USER_FLAG_SAVE_PIN;
}
dwErr = NO_ERROR;
}
if ( fCredentialsFound
&& ( !fDiffUser
|| (0 != pUserProp->pwszDiffUser[0])))
{
fGotAllInfo = TRUE;
}
if ( !fGotAllInfo
&& (dwFlags & RAS_EAP_FLAG_NON_INTERACTIVE))
{
dwErr = ERROR_INTERACTIVE_MODE;
goto LDone;
}
dwErr = GetCertFromCard(&pCertContext);
if (NO_ERROR != dwErr)
{
goto LDone;
}
//Check the time validity of the certificate
//got from the card
if ( !FCheckTimeValidity( pCertContext) )
{
dwErr = CERT_E_EXPIRED;
goto LDone;
}
dwErr = DwGetEKUUsage ( pCertContext,
&pUsageInternal);
if ( dwErr != ERROR_SUCCESS )
goto LDone;
if ( pUsageInternal->cUsageIdentifier )
{
//
// Check for client Auth EKU in the cert
// If there are no usage identifiers then it is an all
// purpose cert. So no need to check for usage.
//
if ( !FCheckUsage( pCertContext, pUsageInternal, FALSE ) )
{
dwErr = CERT_E_WRONG_USAGE;
goto LDone;
}
}
pUserProp->Hash.cbHash = MAX_HASH_SIZE;
if (!CertGetCertificateContextProperty(pCertContext,
CERT_HASH_PROP_ID, pUserProp->Hash.pbHash,
&(pUserProp->Hash.cbHash)))
{
dwErr = GetLastError();
EapTlsTrace("CertGetCertificateContextProperty failed and "
"returned 0x%x", dwErr);
goto LDone;
}
EapTlsPinDialog.pUserProp = pUserProp;
if ( !fDiffUser
|| (0 == pUserProp->pwszDiffUser[0]))
{
if (!FCertToStr(pCertContext, 0, fRouter, &pwszIdentity))
{
dwErr = E_FAIL;
goto LDone;
}
dwErr = AllocUserDataWithNewIdentity(pUserProp, pwszIdentity,
&pUserPropTemp);
LocalFree(pwszIdentity);
pwszIdentity = NULL;
if (NO_ERROR != dwErr)
{
goto LDone;
}
LocalFree(pUserProp);
EapTlsPinDialog.pUserProp = pUserProp = *ppUserProp = pUserPropTemp;
}
if (fCredentialsFound)
{
dwErr = AllocUserDataWithNewPin(
pUserProp,
(PBYTE)RasCredentials.szPassword,
lstrlen(RasCredentials.szPassword),
&pUserPropTemp);
if (NO_ERROR != dwErr)
{
goto LDone;
}
LocalFree(pUserProp);
EapTlsPinDialog.pUserProp = pUserProp = *ppUserProp = pUserPropTemp;
}
EapTlsPinDialog.pCertContext = pCertContext;
if ( !fGotAllInfo
|| (dwFlags & RAS_EAP_FLAG_PREVIEW))
{
if ( NULL != hWndStatus )
{
DestroyWindow(hWndStatus);
hWndStatus = NULL;
}
nRet = DialogBoxParam(
GetHInstance(),
MAKEINTRESOURCE(IDD_USERNAME_PIN_UI),
hwndParent,
PinDialogProc,
(LPARAM)&EapTlsPinDialog);
// EapTlsPinDialog.pUserProp may have been realloced
pUserProp = *ppUserProp = EapTlsPinDialog.pUserProp;
if (-1 == nRet)
{
dwErr = GetLastError();
goto LDone;
}
else if (IDOK != nRet)
{
dwErr = ERROR_CANCELLED;
goto LDone;
}
ZeroMemory(&RasCredentials, sizeof(RasCredentials));
RasCredentials.dwSize = sizeof(RasCredentials);
RasCredentials.dwMask = RASCM_Password;
if (EapTlsPinDialog.pUserProp->fFlags & EAPTLS_USER_FLAG_SAVE_PIN)
{
wcscpy(RasCredentials.szPassword,
EapTlsPinDialog.pUserProp->pwszPin);
RasSetCredentials(pwszPhonebook, pwszEntry, &RasCredentials,
FALSE /* fClearCredentials */);
}
else
{
RasSetCredentials(pwszPhonebook, pwszEntry, &RasCredentials,
TRUE /* fClearCredentials */);
}
}
EncodePin(EapTlsPinDialog.pUserProp);
pwszIdentity = LocalAlloc(LPTR,
(wcslen(pUserProp->pwszDiffUser) + 1) * sizeof(WCHAR));
if (NULL == pwszIdentity)
{
dwErr = GetLastError();
EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
goto LDone;
}
wcscpy(pwszIdentity, pUserProp->pwszDiffUser);
if (NULL != ppwszIdentity)
{
*ppwszIdentity = pwszIdentity;
pwszIdentity = NULL;
}
if (!fDiffUser)
{
pUserProp->pwszDiffUser[0] = 0;
}
if ( EapTlsPinDialog.dwRetCode != NO_ERROR )
dwErr = EapTlsPinDialog.dwRetCode ;
goto LDone;
}
dwCertFlags |= CERT_STORE_READONLY_FLAG;
hCertStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM_W,
X509_ASN_ENCODING,
0,
dwCertFlags,
pwszStoreName);
if (NULL == hCertStore)
{
dwErr = GetLastError();
EapTlsTrace("CertOpenStore failed and returned 0x%x", dwErr);
goto LDone;
}
if ( ( dwFlags & RAS_EAP_FLAG_MACHINE_AUTH) )
{
//if this is not machine authentication
//This is propably not the best way to do things.
//We should provide a way in which
//Get the default machine certificate and
//populate the out data structures...
dwErr = GetDefaultClientMachineCert(hCertStore, &pCertContext );
if ( NO_ERROR == dwErr )
{
EapTlsTrace("Got the default Machine Cert");
pUserProp->Hash.cbHash = MAX_HASH_SIZE;
if (!CertGetCertificateContextProperty(pCertContext,
CERT_HASH_PROP_ID, pUserProp->Hash.pbHash,
&(pUserProp->Hash.cbHash)))
{
dwErr = GetLastError();
EapTlsTrace("CertGetCertificateContextProperty failed and "
"returned 0x%x", dwErr);
}
pUserProp->pwszDiffUser[0] = 0;
if ( FMachineAuthCertToStr(pCertContext, &pwszIdentity))
{
//format the identity in the domain\machinename format.
FFormatMachineIdentity1 (pwszIdentity, ppwszIdentity );
pwszIdentity = NULL;
}
else
{
//if not possible get it from the subject field
if ( FCertToStr(pCertContext, 0, TRUE, &pwszIdentity))
{
//format the identity in the domain\machinename format.
FFormatMachineIdentity1 (pwszIdentity, ppwszIdentity );
pwszIdentity = NULL;
}
}
*ppUserProp = pUserProp;
}
goto LDone;
}
HashBlob.cbData = pUserProp->Hash.cbHash;
HashBlob.pbData = pUserProp->Hash.pbHash;
pCertContext = CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING,
0, CERT_FIND_HASH, &HashBlob, NULL);
if ( (NULL == pCertContext)
|| ( fDiffUser
&& (0 == pUserProp->pwszDiffUser[0])))
{
// We don't have complete information. Note that for registry certs,
// pwszDiffUser is not a different dialog.
if (fServer)
{
dwErr = GetDefaultMachineCert(hCertStore, &pCertContext);
if (NO_ERROR == dwErr)
{
pUserProp->Hash.cbHash = MAX_HASH_SIZE;
if (!CertGetCertificateContextProperty(pCertContext,
CERT_HASH_PROP_ID, pUserProp->Hash.pbHash,
&(pUserProp->Hash.cbHash)))
{
dwErr = GetLastError();
EapTlsTrace("CertGetCertificateContextProperty failed and "
"returned 0x%x", dwErr);
}
}
dwErr = NO_ERROR;
}
}
else
{
//
// This is a registry based cert scenario.
// So let's make sure that we've not picked up a smart card cert.
//
if ( !fServer
&& !fRouterConfig
&& !(dwFlags & RAS_EAP_FLAG_PREVIEW)
&& !(FCheckSCardCertAndCanOpenSilentContext ( pCertContext ))
)
{
fGotIdentity = FALSE;
if (!fDiffUser)
{
pUserProp->pwszDiffUser[0] = 0;
}
if ( fDiffUser
&& (pUserProp->pwszDiffUser[0]))
{
pwszIdentity = LocalAlloc(LPTR,
(wcslen(pUserProp->pwszDiffUser)+1) * sizeof(WCHAR));;
if (NULL == pwszIdentity)
{
dwErr = GetLastError();
EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
goto LDone;
}
wcscpy(pwszIdentity, pUserProp->pwszDiffUser);
EapTlsTrace("(saved) Sending EAP identity %ws", pwszIdentity);
fGotIdentity = TRUE;
}
else if (FCertToStr(pCertContext, 0, fRouter, &pwszIdentity))
{
EapTlsTrace("(saved) The name in the certificate is: %ws",
pwszIdentity);
fGotIdentity = TRUE;
}
if (fGotIdentity)
{
RTASSERT(NULL != ppwszIdentity);
*ppwszIdentity = pwszIdentity;
pwszIdentity = NULL;
goto LDone;
}
}
else if ( fServer )
{
//
// We have got a cert context. Now see if it has been renewed.
// If it has been renewed, set the new hash and
//
PCCERT_CONTEXT pNewCertContext = NULL;
if ( CheckForCertificateRenewal(SP_PROT_SERVERS,
pCertContext,
&pNewCertContext
)
)
{
if ( pNewCertContext )
{
//
// Change the hash.
//
pUserProp->Hash.cbHash = MAX_HASH_SIZE;
if (!CertGetCertificateContextProperty(pNewCertContext,
CERT_HASH_PROP_ID, pUserProp->Hash.pbHash,
&(pUserProp->Hash.cbHash)))
{
dwErr = GetLastError();
EapTlsTrace("CertGetCertificateContextProperty failed and "
"returned 0x%x", dwErr);
}
CertFreeCertificateContext(pNewCertContext);
}
}
}
}
EapTlsUserDialog.pUserProp = pUserProp;
CreateCertList( fServer,
fRouter,
FALSE /* fRoot */,
&(EapTlsUserDialog.pCertList),
&(EapTlsUserDialog.pCert),
1,
&(EapTlsUserDialog.pUserProp->Hash),
pwszStoreName);
if (NULL == EapTlsUserDialog.pCertList)
{
dwErr = ERROR_NO_EAPTLS_CERTIFICATE;
if (fServer || fRouter)
{
if (dwFlags & RAS_EAP_FLAG_NON_INTERACTIVE)
{
dwErr = ERROR_INTERACTIVE_MODE;
goto LDone;
}
DisplayError(hwndParent, dwErr);
}
goto LDone;
}
else
{
if ( NULL == EapTlsUserDialog.pCert )
{
EapTlsUserDialog.pCert = EapTlsUserDialog.pCertList;
}
EapTlsUserDialog.pwszStoreName = pwszStoreName;
if ( !fServer && !fRouter )
{
// if this is a client - not a server and not a router
// There are more than one certificates or the user has
// chosen to provide different identity
//
if ( EapTlsUserDialog.pCertList->pNext || EapTlsUserDialog.fFlags & EAPTLS_USER_DIALOG_FLAG_DIFF_USER )
{
if (dwFlags & RAS_EAP_FLAG_NON_INTERACTIVE)
{
dwErr = ERROR_INTERACTIVE_MODE;
goto LDone;
}
//
// Group Certs for the client UI
//
if ( !fServer )
{
if ( EapTlsUserDialog.fFlags & EAPTLS_USER_DIALOG_FLAG_USE_SIMPLE_CERTSEL )
{
//
// Grouping is done only if it is specified in
// the connection properties
//
dwErr = GroupCertificates (&EapTlsUserDialog);
if ( NO_ERROR != dwErr )
{
EapTlsTrace("Error grouping certificates. 0x%x", dwErr );
goto LDone;
}
}
//
// Now check to see if we have only one group
//
if ( EapTlsUserDialog.fFlags & EAPTLS_USER_DIALOG_FLAG_USE_SIMPLE_CERTSEL &&
!(EapTlsUserDialog.fFlags & EAPTLS_USER_DIALOG_FLAG_DIFF_USER ) &&
!(EapTlsUserDialog.pGroupedList->pNext)
)
{
//
// only one group. So select the cert and use it
//
CertSelected(NULL,
EapTlsUserDialog.pCertList,
&(EapTlsUserDialog.pGroupedList->pMostRecentCert),
&(EapTlsUserDialog.pUserProp->Hash)
);
}
else
{
EapTlsUserDialog.fIdentity = TRUE;
nRet = DialogBoxParam(
GetHInstance(),
MAKEINTRESOURCE(IDD_IDENTITY_UI),
hwndParent,
UserDialogProc,
(LPARAM)&EapTlsUserDialog);
if (-1 == nRet)
{
dwErr = GetLastError();
goto LDone;
}
else if (IDOK != nRet)
{
dwErr = ERROR_CANCELLED;
goto LDone;
}
}
}
else
{
nRet = DialogBoxParam(
GetHInstance(),
MAKEINTRESOURCE(IDD_SERVER_UI),
hwndParent,
UserDialogProc,
(LPARAM)&EapTlsUserDialog);
if (-1 == nRet)
{
dwErr = GetLastError();
goto LDone;
}
else if (IDOK != nRet)
{
dwErr = ERROR_CANCELLED;
goto LDone;
}
}
// EapTlsUserDialog.pUserProp may have been realloced
pUserProp = *ppUserProp = EapTlsUserDialog.pUserProp;
}
else
{
//
// There is only one relevant certificate so auto select it.
//
CertSelected(NULL, EapTlsUserDialog.pCertList,
&(EapTlsUserDialog.pCert), &(EapTlsUserDialog.pUserProp->Hash));
}
}
else
{
if (dwFlags & RAS_EAP_FLAG_NON_INTERACTIVE)
{
dwErr = ERROR_INTERACTIVE_MODE;
goto LDone;
}
if ( EapTlsUserDialog.fFlags & EAPTLS_USER_DIALOG_FLAG_USE_SIMPLE_CERTSEL )
{
//
// Grouping is done only if it is specified in
// the connection properties
//
dwErr = GroupCertificates (&EapTlsUserDialog);
if ( NO_ERROR != dwErr )
{
EapTlsTrace("Error grouping certificates. 0x%x", dwErr );
goto LDone;
}
}
nRet = DialogBoxParam(
GetHInstance(),
MAKEINTRESOURCE(fServer ? IDD_SERVER_UI : IDD_IDENTITY_UI),
hwndParent,
UserDialogProc,
(LPARAM)&EapTlsUserDialog);
// EapTlsUserDialog.pUserProp may have been realloced
pUserProp = *ppUserProp = EapTlsUserDialog.pUserProp;
if (-1 == nRet)
{
dwErr = GetLastError();
goto LDone;
}
else if (IDOK != nRet)
{
dwErr = ERROR_CANCELLED;
goto LDone;
}
}
}
if (NULL != EapTlsUserDialog.pCert)
{
if ( fDiffUser
&& (0 != EapTlsUserDialog.pUserProp->pwszDiffUser[0]))
{
pwszTemp = EapTlsUserDialog.pUserProp->pwszDiffUser;
}
else
{
pwszTemp = EapTlsUserDialog.pCert->pwszDisplayName;
}
pwszIdentity = LocalAlloc(LPTR, (wcslen(pwszTemp) + 1)*sizeof(WCHAR));
if (NULL == pwszIdentity)
{
dwErr = GetLastError();
EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
goto LDone;
}
wcscpy(pwszIdentity, pwszTemp);
if (NULL != ppwszIdentity)
{
*ppwszIdentity = pwszIdentity;
pwszIdentity = NULL;
}
}
LDone:
if ( pUsageInternal )
{
LocalFree(pUsageInternal);
}
if ( NULL != hWndStatus )
{
DestroyWindow(hWndStatus);
hWndStatus = NULL;
}
if (NULL != pCertContext)
{
CertFreeCertificateContext(pCertContext);
// Always returns TRUE;
}
if (NULL != hCertStore)
{
if (!CertCloseStore(hCertStore, 0))
{
EapTlsTrace("CertCloseStore failed and returned 0x%x",
GetLastError());
}
}
if ( pwszIdentity )
LocalFree(pwszIdentity);
FreeCertList(EapTlsUserDialog.pCertList);
ZeroMemory(&RasCredentials, sizeof(RasCredentials));
return(dwErr);
}
/*
Returns:
FALSE (prevent Windows from setting the default keyboard focus).
Notes:
Response to the WM_INITDIALOG message (Config UI).
*/
BOOL
ConnInitDialog(
IN HWND hWnd,
IN LPARAM lParam
)
{
EAPTLS_CONN_DIALOG* pEapTlsConnDialog;
LVCOLUMN lvColumn;
SetWindowLongPtr(hWnd, DWLP_USER, lParam);
pEapTlsConnDialog = (EAPTLS_CONN_DIALOG*)lParam;
pEapTlsConnDialog->hWndRadioUseCard =
GetDlgItem(hWnd, IDC_RADIO_USE_CARD);
pEapTlsConnDialog->hWndRadioUseRegistry =
GetDlgItem(hWnd, IDC_RADIO_USE_REGISTRY);
pEapTlsConnDialog->hWndCheckValidateCert =
GetDlgItem(hWnd, IDC_CHECK_VALIDATE_CERT);
pEapTlsConnDialog->hWndCheckValidateName =
GetDlgItem(hWnd, IDC_CHECK_VALIDATE_NAME);
pEapTlsConnDialog->hWndEditServerName =
GetDlgItem(hWnd, IDC_EDIT_SERVER_NAME);
pEapTlsConnDialog->hWndStaticRootCaName =
GetDlgItem(hWnd, IDC_STATIC_ROOT_CA_NAME);
//pEapTlsConnDialog->hWndComboRootCaName =
// GetDlgItem(hWnd, IDC_COMBO_ROOT_CA_NAME);
pEapTlsConnDialog->hWndListRootCaName =
GetDlgItem(hWnd, IDC_LIST_ROOT_CA_NAME);
pEapTlsConnDialog->hWndCheckDiffUser =
GetDlgItem(hWnd, IDC_CHECK_DIFF_USER);
pEapTlsConnDialog->hWndCheckUseSimpleSel =
GetDlgItem(hWnd, IDC_CHECK_USE_SIMPLE_CERT_SEL);
pEapTlsConnDialog->hWndViewCertDetails =
GetDlgItem(hWnd, IDC_BUTTON_VIEW_CERTIFICATE);
//Set the style to set list boxes.
ListView_SetExtendedListViewStyle
( pEapTlsConnDialog->hWndListRootCaName,
ListView_GetExtendedListViewStyle(pEapTlsConnDialog->hWndListRootCaName) | LVS_EX_CHECKBOXES
);
ZeroMemory ( &lvColumn, sizeof(lvColumn));
lvColumn.fmt = LVCFMT_LEFT;
ListView_InsertColumn( pEapTlsConnDialog->hWndListRootCaName,
0,
&lvColumn
);
ListView_SetColumnWidth(pEapTlsConnDialog->hWndListRootCaName,
0,
LVSCW_AUTOSIZE_USEHEADER
);
//
//Now we need to init the
//list box with all the certs and selected cert
InitListBox ( pEapTlsConnDialog->hWndListRootCaName,
pEapTlsConnDialog->pCertList,
pEapTlsConnDialog->pConnPropv1->dwNumHashes,
pEapTlsConnDialog->ppSelCertList
);
SetWindowText(pEapTlsConnDialog->hWndEditServerName,
(LPWSTR )(pEapTlsConnDialog->pConnPropv1->bData + sizeof( EAPTLS_HASH ) * pEapTlsConnDialog->pConnPropv1->dwNumHashes)
);
if (pEapTlsConnDialog->fFlags & EAPTLS_CONN_DIALOG_FLAG_ROUTER)
{
pEapTlsConnDialog->pConnPropv1->fFlags |= EAPTLS_CONN_FLAG_REGISTRY;
EnableWindow(pEapTlsConnDialog->hWndRadioUseCard, FALSE);
}
CheckRadioButton(hWnd, IDC_RADIO_USE_CARD, IDC_RADIO_USE_REGISTRY,
(pEapTlsConnDialog->pConnPropv1->fFlags & EAPTLS_CONN_FLAG_REGISTRY) ?
IDC_RADIO_USE_REGISTRY : IDC_RADIO_USE_CARD);
CheckDlgButton(hWnd, IDC_CHECK_VALIDATE_CERT,
(pEapTlsConnDialog->pConnPropv1->fFlags &
EAPTLS_CONN_FLAG_NO_VALIDATE_CERT) ?
BST_UNCHECKED : BST_CHECKED);
CheckDlgButton(hWnd, IDC_CHECK_VALIDATE_NAME,
(pEapTlsConnDialog->pConnPropv1->fFlags &
EAPTLS_CONN_FLAG_NO_VALIDATE_NAME) ?
BST_UNCHECKED : BST_CHECKED);
CheckDlgButton(hWnd, IDC_CHECK_DIFF_USER,
(pEapTlsConnDialog->pConnPropv1->fFlags &
EAPTLS_CONN_FLAG_DIFF_USER) ?
BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(hWnd, IDC_CHECK_USE_SIMPLE_CERT_SEL,
(pEapTlsConnDialog->pConnPropv1->fFlags &
EAPTLS_CONN_FLAG_SIMPLE_CERT_SEL) ?
BST_CHECKED : BST_UNCHECKED);
EnableValidateNameControls(pEapTlsConnDialog);
//
// Check to see if we are in readonly mode
// If so, disable the OK button and
// make the dialog go into readonly mode
//
return(FALSE);
}
DWORD GetSelCertContext(EAPTLS_CERT_NODE* pCertList,
int nIndex,
HCERTSTORE * phCertStore,
LPWSTR pwszStoreName,
PCCERT_CONTEXT * ppCertContext
)
{
PCCERT_CONTEXT pCertContext = NULL;
EAPTLS_CERT_NODE * pTemp = pCertList;
DWORD dwErr= NO_ERROR;
HCERTSTORE hStore = NULL;
CRYPT_HASH_BLOB chb;
if ( nIndex >= 0 )
{
pTemp = pTemp->pNext;
while ( nIndex && pTemp )
{
pTemp = pTemp->pNext;
nIndex --;
}
}
if ( pTemp )
{
*phCertStore = CertOpenStore (CERT_STORE_PROV_SYSTEM,
0,
0,
CERT_STORE_READONLY_FLAG |CERT_SYSTEM_STORE_CURRENT_USER,
pwszStoreName
);
if ( !*phCertStore )
{
dwErr = GetLastError();
goto LDone;
}
chb.cbData = pTemp->Hash.cbHash;
chb.pbData = pTemp->Hash.pbHash;
pCertContext = CertFindCertificateInStore(
*phCertStore,
0,
0,
CERT_FIND_HASH,
&chb,
0);
if ( NULL == pCertContext )
{
dwErr = GetLastError();
}
}
else
{
dwErr = ERROR_NOT_FOUND;
goto LDone;
}
*ppCertContext = pCertContext;
LDone:
if ( NO_ERROR != dwErr )
{
if ( pCertContext )
CertFreeCertificateContext(pCertContext);
if ( *phCertStore )
CertCloseStore( *phCertStore, CERT_CLOSE_STORE_FORCE_FLAG );
}
return dwErr;
}
/*
Returns:
TRUE: We prrocessed this message.
FALSE: We did not prrocess this message.
Notes:
Response to the WM_COMMAND message (Config UI).
*/
BOOL
ConnCommand(
IN EAPTLS_CONN_DIALOG* pEapTlsConnDialog,
IN WORD wNotifyCode,
IN WORD wId,
IN HWND hWndDlg,
IN HWND hWndCtrl
)
{
DWORD dwNumChars;
EAPTLS_CONN_PROPERTIES_V1 * pConnProp;
switch(wId)
{
case IDC_RADIO_USE_CARD:
pEapTlsConnDialog->pConnPropv1->fFlags &= ~EAPTLS_CONN_FLAG_REGISTRY;
pEapTlsConnDialog->pConnPropv1->fFlags &= ~EAPTLS_CONN_FLAG_SIMPLE_CERT_SEL;
EnableValidateNameControls(pEapTlsConnDialog);
return(TRUE);
case IDC_RADIO_USE_REGISTRY:
pEapTlsConnDialog->pConnPropv1->fFlags |= EAPTLS_CONN_FLAG_REGISTRY;
pEapTlsConnDialog->pConnPropv1->fFlags |= EAPTLS_CONN_FLAG_SIMPLE_CERT_SEL;
CheckDlgButton(hWndDlg, IDC_CHECK_USE_SIMPLE_CERT_SEL, BST_CHECKED);
EnableValidateNameControls(pEapTlsConnDialog);
return(TRUE);
case IDC_CHECK_USE_SIMPLE_CERT_SEL:
if (BST_CHECKED == IsDlgButtonChecked(hWndDlg, IDC_CHECK_USE_SIMPLE_CERT_SEL))
{
pEapTlsConnDialog->pConnPropv1->fFlags |= EAPTLS_CONN_FLAG_SIMPLE_CERT_SEL;
}
else
{
pEapTlsConnDialog->pConnPropv1->fFlags &= ~EAPTLS_CONN_FLAG_SIMPLE_CERT_SEL;
}
return TRUE;
case IDC_CHECK_VALIDATE_CERT:
if (BST_CHECKED == IsDlgButtonChecked(hWndDlg, IDC_CHECK_VALIDATE_CERT))
{
pEapTlsConnDialog->pConnPropv1->fFlags &=
~EAPTLS_CONN_FLAG_NO_VALIDATE_CERT;
pEapTlsConnDialog->pConnPropv1->fFlags &=
~EAPTLS_CONN_FLAG_NO_VALIDATE_NAME;
CheckDlgButton(hWndDlg, IDC_CHECK_VALIDATE_NAME, BST_CHECKED);
}
else
{
pEapTlsConnDialog->pConnPropv1->fFlags |=
EAPTLS_CONN_FLAG_NO_VALIDATE_CERT;
pEapTlsConnDialog->pConnPropv1->fFlags |=
EAPTLS_CONN_FLAG_NO_VALIDATE_NAME;
CheckDlgButton(hWndDlg, IDC_CHECK_VALIDATE_NAME, BST_UNCHECKED);
}
EnableValidateNameControls(pEapTlsConnDialog);
return(TRUE);
case IDC_CHECK_VALIDATE_NAME:
if (BST_CHECKED == IsDlgButtonChecked(hWndDlg, IDC_CHECK_VALIDATE_NAME))
{
pEapTlsConnDialog->pConnPropv1->fFlags &=
~EAPTLS_CONN_FLAG_NO_VALIDATE_NAME;
}
else
{
pEapTlsConnDialog->pConnPropv1->fFlags |=
EAPTLS_CONN_FLAG_NO_VALIDATE_NAME;
}
EnableValidateNameControls(pEapTlsConnDialog);
return(TRUE);
case IDC_CHECK_DIFF_USER:
if (BST_CHECKED == IsDlgButtonChecked(hWndDlg, IDC_CHECK_DIFF_USER))
{
pEapTlsConnDialog->pConnPropv1->fFlags |=
EAPTLS_CONN_FLAG_DIFF_USER;
}
else
{
pEapTlsConnDialog->pConnPropv1->fFlags &=
~EAPTLS_CONN_FLAG_DIFF_USER;
}
return(TRUE);
case IDC_BUTTON_VIEW_CERTIFICATE:
{
//Show cert details here
INT nIndex = -1;
HCERTSTORE hCertStore = NULL;
PCCERT_CONTEXT pCertContext = NULL;
LVITEM lvItem;
nIndex = ListView_GetNextItem(pEapTlsConnDialog->hWndListRootCaName,
-1,
LVNI_SELECTED
);
if ( nIndex >= 0 )
{
ZeroMemory( &lvItem, sizeof(lvItem) );
lvItem.iItem = nIndex;
lvItem.mask = LVIF_PARAM;
ListView_GetItem ( pEapTlsConnDialog->hWndListRootCaName,
&lvItem
);
if ( NO_ERROR == GetSelCertContext( (EAPTLS_CERT_NODE*)(lvItem.lParam),
-1,
&hCertStore,
L"ROOT",
&pCertContext
)
)
{
ShowCertDetails( hWndDlg, hCertStore, pCertContext );
CertFreeCertificateContext(pCertContext);
CertCloseStore( hCertStore, CERT_CLOSE_STORE_FORCE_FLAG );
}
}
}
return TRUE;
case IDOK:
{
EAPTLS_HASH * pHash = NULL;
DWORD dwNumHash = 0;
DWORD dwSelCount = 0;
EAPTLS_CERT_NODE ** ppSelCertList = NULL;
WCHAR wszTitle[200] = {0};
WCHAR wszMessage[200] = {0};
CertListSelectedCount ( pEapTlsConnDialog->hWndListRootCaName, &dwSelCount );
if ( pEapTlsConnDialog->fFlags & EAPTLS_CONN_DIALOG_FLAG_ROUTER)
{
//
// If we are a router,
// check to see if Validate Server certificate is selected
// and no cert is selected.
// Also, check to see if server name is checked and no server's
// are entered.
//
if ( !( pEapTlsConnDialog->pConnPropv1->fFlags & EAPTLS_CONN_FLAG_NO_VALIDATE_CERT) &&
0 == dwSelCount )
{
LoadString ( GetHInstance(),
IDS_CANT_CONFIGURE_SERVER_TITLE,
wszTitle, sizeof(wszTitle)/sizeof(WCHAR)
);
LoadString ( GetHInstance(),
IDS_NO_ROOT_CERT,
wszMessage, sizeof(wszMessage)/sizeof(WCHAR)
);
MessageBox ( GetFocus(), wszMessage, wszTitle, MB_OK|MB_ICONWARNING );
return TRUE;
}
if ( !( pEapTlsConnDialog->pConnPropv1->fFlags & EAPTLS_CONN_FLAG_NO_VALIDATE_NAME) &&
!GetWindowTextLength(pEapTlsConnDialog->hWndEditServerName) )
{
//
// Nothing entered in server name field
//
LoadString ( GetHInstance(),
IDS_CANT_CONFIGURE_SERVER_TITLE,
wszTitle, sizeof(wszTitle)/sizeof(WCHAR)
);
LoadString ( GetHInstance(),
IDS_NO_SERVER_NAME,
wszMessage, sizeof(wszMessage)/sizeof(WCHAR)
);
MessageBox ( GetFocus(), wszMessage, wszTitle, MB_OK|MB_ICONWARNING );
return TRUE;
}
}
if ( dwSelCount > 0 )
{
ppSelCertList = (EAPTLS_CERT_NODE **)LocalAlloc(LPTR, sizeof(EAPTLS_CERT_NODE *) * dwSelCount );
if ( NULL == ppSelCertList )
{
EapTlsTrace("LocalAlloc in Command failed and returned %d",
GetLastError());
return TRUE;
}
pHash = (EAPTLS_HASH *)LocalAlloc(LPTR, sizeof(EAPTLS_HASH ) * dwSelCount );
if ( NULL == pHash )
{
EapTlsTrace("LocalAlloc in Command failed and returned %d",
GetLastError());
return TRUE;
}
CertListSelected( pEapTlsConnDialog->hWndListRootCaName,
pEapTlsConnDialog->pCertList,
ppSelCertList,
pHash,
dwSelCount
);
}
dwNumChars = GetWindowTextLength(pEapTlsConnDialog->hWndEditServerName);
pConnProp = LocalAlloc( LPTR,
sizeof(EAPTLS_CONN_PROPERTIES_V1) +
sizeof(EAPTLS_HASH) * dwSelCount +
dwNumChars * sizeof(WCHAR) + sizeof(WCHAR) //one for null.
);
if (NULL == pConnProp)
{
EapTlsTrace("LocalAlloc in Command failed and returned %d",
GetLastError());
}
else
{
CopyMemory( pConnProp,
pEapTlsConnDialog->pConnPropv1,
sizeof(EAPTLS_CONN_PROPERTIES_V1)
);
pConnProp->dwSize = sizeof(EAPTLS_CONN_PROPERTIES_V1) +
sizeof(EAPTLS_HASH) * dwSelCount +
dwNumChars * sizeof(WCHAR);
CopyMemory ( pConnProp->bData,
pHash,
sizeof(EAPTLS_HASH) * dwSelCount
);
pConnProp->dwNumHashes = dwSelCount;
GetWindowText(pEapTlsConnDialog->hWndEditServerName,
(LPWSTR)(pConnProp->bData + sizeof(EAPTLS_HASH) * dwSelCount) ,
dwNumChars + 1);
LocalFree(pEapTlsConnDialog->pConnPropv1);
if ( pEapTlsConnDialog->ppSelCertList )
LocalFree(pEapTlsConnDialog->ppSelCertList);
pEapTlsConnDialog->ppSelCertList = ppSelCertList;
pEapTlsConnDialog->pConnPropv1 = pConnProp;
}
}
// Fall through
case IDCANCEL:
EndDialog(hWndDlg, wId);
return(TRUE);
default:
return(FALSE);
}
}
BOOL ConnNotify( EAPTLS_CONN_DIALOG *pEaptlsConnDialog,
WPARAM wParam,
LPARAM lParam,
HWND hWnd
)
{
HCERTSTORE hCertStore = NULL;
PCCERT_CONTEXT pCertContext = NULL;
LPNMITEMACTIVATE lpnmItem;
LVITEM lvItem;
if ( wParam == IDC_LIST_ROOT_CA_NAME )
{
lpnmItem = (LPNMITEMACTIVATE) lParam;
if ( lpnmItem->hdr.code == NM_DBLCLK )
{
ZeroMemory(&lvItem, sizeof(lvItem) );
lvItem.mask = LVIF_PARAM;
lvItem.iItem = lpnmItem->iItem;
ListView_GetItem(lpnmItem->hdr.hwndFrom, &lvItem);
if ( NO_ERROR == GetSelCertContext( //pEaptlsConnDialog->pCertList,
(EAPTLS_CERT_NODE*)(lvItem.lParam) ,
-1,
&hCertStore,
L"ROOT",
&pCertContext
)
)
{
ShowCertDetails( hWnd, hCertStore, pCertContext );
CertFreeCertificateContext(pCertContext);
CertCloseStore( hCertStore, CERT_CLOSE_STORE_FORCE_FLAG );
return TRUE;
}
return TRUE;
}
}
return FALSE;
}
/*
Returns:
Notes:
Callback function used with the Config UI DialogBoxParam function. It
processes messages sent to the dialog box. See the DialogProc documentation
in MSDN.
*/
INT_PTR CALLBACK
ConnDialogProc(
IN HWND hWnd,
IN UINT unMsg,
IN WPARAM wParam,
IN LPARAM lParam
)
{
EAPTLS_CONN_DIALOG* pEapTlsConnDialog;
switch (unMsg)
{
case WM_INITDIALOG:
return(ConnInitDialog(hWnd, lParam));
case WM_HELP:
case WM_CONTEXTMENU:
{
ContextHelp(g_adwHelp, hWnd, unMsg, wParam, lParam);
break;
}
case WM_NOTIFY:
{
pEapTlsConnDialog = (EAPTLS_CONN_DIALOG*)GetWindowLongPtr(hWnd, DWLP_USER);
return ConnNotify( pEapTlsConnDialog,
wParam,
lParam,
hWnd
);
}
case WM_COMMAND:
pEapTlsConnDialog = (EAPTLS_CONN_DIALOG*)GetWindowLongPtr(hWnd, DWLP_USER);
return(ConnCommand(pEapTlsConnDialog, HIWORD(wParam), LOWORD(wParam),
hWnd, (HWND)lParam));
}
return(FALSE);
}
DWORD
RasEapTlsInvokeConfigUI(
IN DWORD dwEapTypeId,
IN HWND hwndParent,
IN DWORD dwFlags,
IN BYTE* pConnectionDataIn,
IN DWORD dwSizeOfConnectionDataIn,
OUT BYTE** ppConnectionDataOut,
OUT DWORD* pdwSizeOfConnectionDataOut
)
{
DWORD dwErr = NO_ERROR;
BOOL fRouter = FALSE;
INT_PTR nRet;
EAPTLS_CONN_DIALOG EapTlsConnDialog;
RTASSERT(NULL != ppConnectionDataOut);
RTASSERT(NULL != pdwSizeOfConnectionDataOut);
EapTlsInitialize2(TRUE, TRUE /* fUI */);
*ppConnectionDataOut = NULL;
*pdwSizeOfConnectionDataOut = 0;
ZeroMemory(&EapTlsConnDialog, sizeof(EAPTLS_CONN_DIALOG));
if (dwFlags & RAS_EAP_FLAG_ROUTER)
{
fRouter = TRUE;
EapTlsConnDialog.fFlags = EAPTLS_CONN_DIALOG_FLAG_ROUTER;
}
#if 0
if ( dwFlags & RAS_EAP_FLAG_READ_ONLY_UI )
{
EapTlsConnDialog.fFlags |= EAPTLS_CONN_DIALOG_FLAG_READONLY;
}
#endif
dwErr = ReadConnectionData( ( dwFlags & RAS_EAP_FLAG_8021X_AUTH ),
pConnectionDataIn,
dwSizeOfConnectionDataIn,
&(EapTlsConnDialog.pConnProp)
);
if (NO_ERROR != dwErr)
{
goto LDone;
}
dwErr = ConnPropGetV1Struct ( EapTlsConnDialog.pConnProp, &(EapTlsConnDialog.pConnPropv1) );
if ( NO_ERROR != dwErr )
{
goto LDone;
}
//
//if there are certificates that need to be selected, allocate
//memory upfront for them
//
if ( EapTlsConnDialog.pConnPropv1->dwNumHashes )
{
EapTlsConnDialog.ppSelCertList = (EAPTLS_CERT_NODE **)LocalAlloc(LPTR, sizeof(EAPTLS_CERT_NODE *) * EapTlsConnDialog.pConnPropv1->dwNumHashes );
if ( NULL == EapTlsConnDialog.ppSelCertList )
{
dwErr = GetLastError();
EapTlsTrace("LocalAlloc failed and returned %d",
dwErr);
goto LDone;
}
}
CreateCertList( FALSE /* fServer */,
fRouter,
TRUE /* fRoot */,
&(EapTlsConnDialog.pCertList), //lined list of all certs in the store.
EapTlsConnDialog.ppSelCertList, //list of selected certificates - null if nothing's in the list
EapTlsConnDialog.pConnPropv1->dwNumHashes,
(EAPTLS_HASH*)(EapTlsConnDialog.pConnPropv1->bData),
L"ROOT"
);
nRet = DialogBoxParam(
GetHInstance(),
MAKEINTRESOURCE(IDD_CONFIG_UI),
hwndParent,
ConnDialogProc,
(LPARAM)&EapTlsConnDialog);
if (-1 == nRet)
{
dwErr = GetLastError();
goto LDone;
}
else if (IDOK != nRet)
{
dwErr = ERROR_CANCELLED;
goto LDone;
}
//
//Convert the connpropv1 back to connpropv0 + extra cludge
//here
//
RTASSERT(NULL != EapTlsConnDialog.pConnPropv1);
dwErr = ConnPropGetV0Struct ( EapTlsConnDialog.pConnPropv1, (EAPTLS_CONN_PROPERTIES ** )ppConnectionDataOut );
if ( NO_ERROR != dwErr )
{
goto LDone;
}
*pdwSizeOfConnectionDataOut = ((EAPTLS_CONN_PROPERTIES * )*ppConnectionDataOut)->dwSize;
LDone:
EapTlsInitialize2(FALSE, TRUE /* fUI */);
FreeCertList(EapTlsConnDialog.pCertList);
if ( EapTlsConnDialog.ppSelCertList )
{
LocalFree( EapTlsConnDialog.ppSelCertList );
EapTlsConnDialog.ppSelCertList = NULL;
}
LocalFree( EapTlsConnDialog.pConnProp );
LocalFree( EapTlsConnDialog.pConnPropv1 );
return dwErr;
}
DWORD
RasEapPeapInvokeConfigUI(
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;
PEAP_CONN_DIALOG PeapConnDialog;
BOOL fRouter = FALSE;
INT_PTR nRet;
//
// Do the following here:
//
// Get a list of Root Certs:
// Get the list of all the eaptypes registered for PEAP:
// and set in in the GUI
//
EapTlsInitialize2(TRUE, TRUE /* fUI */);
*ppConnectionDataOut = NULL;
*pdwSizeOfConnectionDataOut = 0;
ZeroMemory(&PeapConnDialog, sizeof(PEAP_CONN_DIALOG));
if (dwFlags & RAS_EAP_FLAG_ROUTER)
{
fRouter = TRUE;
PeapConnDialog.fFlags = PEAP_CONN_DIALOG_FLAG_ROUTER;
}
if ( dwFlags & RAS_EAP_FLAG_8021X_AUTH )
{
PeapConnDialog.fFlags |= PEAP_CONN_DIALOG_FLAG_8021x;
}
dwRetCode = PeapReadConnectionData(( dwFlags & RAS_EAP_FLAG_8021X_AUTH ),
pConnectionDataIn, dwSizeOfConnectionDataIn,
&(PeapConnDialog.pConnProp));
if (NO_ERROR != dwRetCode)
{
goto LDone;
}
//
//if there are certificates that need to be selected, allocate
//memory upfront for them
//
if ( PeapConnDialog.pConnProp->EapTlsConnProp.dwNumHashes )
{
PeapConnDialog.ppSelCertList = (EAPTLS_CERT_NODE **)LocalAlloc(LPTR,
sizeof(EAPTLS_CERT_NODE *) * PeapConnDialog.pConnProp->EapTlsConnProp.dwNumHashes );
if ( NULL == PeapConnDialog.ppSelCertList )
{
dwRetCode = GetLastError();
EapTlsTrace("LocalAlloc failed and returned %d",
dwRetCode);
goto LDone;
}
}
CreateCertList( FALSE /* fServer */,
fRouter,
TRUE /* fRoot */,
&(PeapConnDialog.pCertList), //lined list of all certs in the store.
PeapConnDialog.ppSelCertList, //list of selected certificates - null if nothing's in the list
PeapConnDialog.pConnProp->EapTlsConnProp.dwNumHashes,
(EAPTLS_HASH*)(PeapConnDialog.pConnProp->EapTlsConnProp.bData),
L"ROOT"
);
//
// Create a list of all Eap Types here
//
dwRetCode = PeapEapInfoGetList ( NULL, FALSE, &(PeapConnDialog.pEapInfo) );
if ( NO_ERROR != dwRetCode )
{
EapTlsTrace("Error Creating list of PEAP EapTypes");
goto LDone;
}
// Setup the conn props for each of the eaptypes from our PeapConnprop
// in
dwRetCode = PeapEapInfoSetConnData ( PeapConnDialog.pEapInfo,
PeapConnDialog.pConnProp );
nRet = DialogBoxParam(
GetHInstance(),
MAKEINTRESOURCE(IDD_PEAP_CONFIG_UI),
hwndParent,
PeapConnDialogProc,
(LPARAM)&PeapConnDialog);
if (-1 == nRet)
{
dwRetCode = GetLastError();
goto LDone;
}
else if (IDOK != nRet)
{
dwRetCode = ERROR_CANCELLED;
goto LDone;
}
//
//Convert the connpropv1 back to connpropv0 + extra cludge
//here
//
RTASSERT(NULL != PeapConnDialog.pConnProp);
*ppConnectionDataOut = (PBYTE)PeapConnDialog.pConnProp;
*pdwSizeOfConnectionDataOut = PeapConnDialog.pConnProp->dwSize;
PeapConnDialog.pConnProp = NULL;
LDone:
EapTlsInitialize2(FALSE, TRUE /* fUI */);
FreeCertList(PeapConnDialog.pCertList);
if ( PeapConnDialog.ppSelCertList )
{
LocalFree( PeapConnDialog.ppSelCertList );
PeapConnDialog.ppSelCertList = NULL;
}
PeapEapInfoFreeList ( PeapConnDialog.pEapInfo );
LocalFree( PeapConnDialog.pConnProp );
return dwRetCode;
}
/*
Returns:
Notes:
Called to get the EAP-TLS properties for a connection.
*/
DWORD
RasEapInvokeConfigUI(
IN DWORD dwEapTypeId,
IN HWND hwndParent,
IN DWORD dwFlags,
IN BYTE* pConnectionDataIn,
IN DWORD dwSizeOfConnectionDataIn,
OUT BYTE** ppConnectionDataOut,
OUT DWORD* pdwSizeOfConnectionDataOut
)
{
DWORD dwErr = ERROR_INVALID_PARAMETER;
//
// This is invoked in case of client configuration
//
if ( PPP_EAP_TLS == dwEapTypeId )
{
dwErr = RasEapTlsInvokeConfigUI(
dwEapTypeId,
hwndParent,
dwFlags,
pConnectionDataIn,
dwSizeOfConnectionDataIn,
ppConnectionDataOut,
pdwSizeOfConnectionDataOut
);
}
#ifdef IMPL_PEAP
else
{
//Invoke the client config UI
dwErr = RasEapPeapInvokeConfigUI(
dwEapTypeId,
hwndParent,
dwFlags,
pConnectionDataIn,
dwSizeOfConnectionDataIn,
ppConnectionDataOut,
pdwSizeOfConnectionDataOut
);
}
#endif
return(dwErr);
}
/*
Returns:
Notes:
pConnectionDataIn, pUserDataIn, and ppwszIdentity may be NULL.
*/
DWORD
EapTlsInvokeIdentityUI(
IN BOOL fServer,
IN BOOL fRouterConfig,
IN DWORD dwFlags,
IN WCHAR* pwszStoreName,
IN const WCHAR* pwszPhonebook,
IN const WCHAR* pwszEntry,
IN HWND hwndParent,
IN BYTE* pConnectionDataIn,
IN DWORD dwSizeOfConnectionDataIn,
IN BYTE* pUserDataIn,
IN DWORD dwSizeOfUserDataIn,
OUT BYTE** ppUserDataOut,
OUT DWORD* pdwSizeOfUserDataOut,
OUT WCHAR** ppwszIdentity
)
{
DWORD dwErr = NO_ERROR;
EAPTLS_USER_PROPERTIES* pUserProp = NULL;
EAPTLS_CONN_PROPERTIES* pConnProp = NULL;
EAPTLS_CONN_PROPERTIES_V1 * pConnPropv1 = NULL;
WCHAR* pwszIdentity = NULL;
PBYTE pbEncPIN = NULL;
DWORD cbEncPIN = 0;
RTASSERT(NULL != pwszStoreName);
RTASSERT(NULL != ppUserDataOut);
RTASSERT(NULL != pdwSizeOfUserDataOut);
// pConnectionDataIn, pUserDataIn, and ppwszIdentity may be NULL.
EapTlsInitialize2(TRUE, TRUE /* fUI */);
EapTlsTrace("EapTlsInvokeIdentityUI");
*ppUserDataOut = NULL;
*pdwSizeOfUserDataOut = 0;
if (NULL != ppwszIdentity)
{
*ppwszIdentity = NULL;
}
dwErr = ReadConnectionData( ( dwFlags & RAS_EAP_FLAG_8021X_AUTH ),
pConnectionDataIn,
dwSizeOfConnectionDataIn,
&pConnProp);
if (NO_ERROR != dwErr)
{
goto LDone;
}
dwErr = ConnPropGetV1Struct ( pConnProp, &pConnPropv1 );
if ( NO_ERROR != dwErr )
{
goto LDone;
}
dwErr = ReadUserData(pUserDataIn, dwSizeOfUserDataIn, &pUserProp);
if (NO_ERROR != dwErr)
{
goto LDone;
}
if ( !(dwFlags & RAS_EAP_FLAG_LOGON)
|| (NULL == pUserDataIn))
{
dwErr = GetCertInfo(fServer, fRouterConfig, dwFlags, pwszPhonebook,
pwszEntry, hwndParent, pwszStoreName, pConnPropv1, &pUserProp,
ppwszIdentity);
if (NO_ERROR != dwErr)
{
#if WINVER > 0x0500
if ( dwErr == SCARD_E_CANCELLED || dwErr == SCARD_W_CANCELLED_BY_USER )
{
dwErr = ERROR_READING_SCARD;
}
#endif
goto LDone;
}
if ( (!fServer) &&
( dwFlags & RAS_EAP_FLAG_8021X_AUTH ) &&
!(pConnProp->fFlags & EAPTLS_CONN_FLAG_REGISTRY)
)
{
//
// Encrypt PIN and send it back
//
dwErr = EncryptData ( (PBYTE)pUserProp->pwszPin,
lstrlen(pUserProp->pwszPin) * sizeof(WCHAR),
&pbEncPIN,
&cbEncPIN
);
if ( NO_ERROR != dwErr )
{
goto LDone;
}
dwErr = AllocUserDataWithNewPin(pUserProp, pbEncPIN, cbEncPIN, &pUserProp);
}
*ppUserDataOut = (BYTE*)(pUserProp);
*pdwSizeOfUserDataOut = pUserProp->dwSize;
pUserProp = NULL;
goto LDone;
}
else
{
if (EAPTLS_CONN_FLAG_REGISTRY & pConnProp->fFlags)
{
dwErr = ERROR_NO_REG_CERT_AT_LOGON;
goto LDone;
}
if (EAPTLS_CONN_FLAG_DIFF_USER & pConnProp->fFlags)
{
dwErr = ERROR_NO_DIFF_USER_AT_LOGON;
goto LDone;
}
dwErr = GetIdentityFromLogonInfo(pUserDataIn, dwSizeOfUserDataIn,
&pwszIdentity);
if (NO_ERROR != dwErr)
{
goto LDone;
}
if (NULL != ppwszIdentity)
{
*ppwszIdentity = pwszIdentity;
pwszIdentity = NULL;
}
}
LDone:
EapTlsInitialize2(FALSE, TRUE /* fUI */);
LocalFree(pwszIdentity);
LocalFree(pUserProp);
LocalFree(pConnProp);
LocalFree(pConnPropv1);
LocalFree(pbEncPIN);
return(dwErr);
}
BOOL IsStandaloneServer(LPCWSTR pMachineName)
{
BOOL fRetCode = FALSE;
DSROLE_PRIMARY_DOMAIN_INFO_BASIC* pdsRole = NULL;
DWORD netRet =
DsRoleGetPrimaryDomainInformation
(pMachineName,
DsRolePrimaryDomainInfoBasic,
(LPBYTE*)&pdsRole);
if(netRet != 0)
{
goto L_ERR;
}
ASSERT(pdsRole);
// if the machine is not a standalone server
if(pdsRole->MachineRole == DsRole_RoleStandaloneServer)
{
fRetCode=TRUE;
}
L_ERR:
if(pdsRole)
DsRoleFreeMemory(pdsRole);
return fRetCode;
}
DWORD
PeapInvokeServerConfigUI(
IN HWND hWnd,
IN WCHAR* pwszMachineName,
IN BOOL fConfigDataInRegistry,
IN const BYTE* pConfigDataIn,
IN DWORD dwSizeofConfigDataIn,
OUT PBYTE* ppConfigDataOut,
OUT DWORD* pdwSizeofConfigDataOut
)
{
WCHAR awszStoreName[MAX_COMPUTERNAME_LENGTH + 10 + 1];
DWORD dwStrLen;
BYTE* pUserDataOut = NULL;
DWORD dwSizeOfUserDataOut;
BOOL fLocal = FALSE;
PEAP_SERVER_CONFIG_DIALOG ServerConfigDialog;
PPEAP_ENTRY_USER_PROPERTIES pEntryProp = NULL;
INT_PTR nRet = -1;
DWORD dwErr = NO_ERROR;
CRYPT_HASH_BLOB HashBlob;
PCCERT_CONTEXT pCertContext = NULL;
HCERTSTORE hCertStore = NULL;
EapTlsInitialize2(TRUE, TRUE /* fUI */);
ASSERT(pwszMachineName != NULL);
if (!fConfigDataInRegistry)
{
ASSERT((ppConfigDataOut != NULL) && (pdwSizeofConfigDataOut != NULL));
*ppConfigDataOut = NULL;
*pdwSizeofConfigDataOut = 0;
}
else
{
ASSERT(
(pConfigDataIn == NULL) &&
(dwSizeofConfigDataIn == 0) &&
(ppConfigDataOut == NULL) &&
(pdwSizeofConfigDataOut == NULL)
);
}
ZeroMemory ( &ServerConfigDialog, sizeof(ServerConfigDialog));
if (0 == *pwszMachineName)
{
fLocal = TRUE;
}
ServerConfigDialog.pwszMachineName = pwszMachineName;
wcscpy(awszStoreName, L"\\\\");
wcsncat(awszStoreName, pwszMachineName, MAX_COMPUTERNAME_LENGTH);
if(fConfigDataInRegistry)
{
dwErr = PeapServerConfigDataIO(
TRUE /* fRead */,
fLocal ? NULL : awszStoreName,
(BYTE**)&( ServerConfigDialog.pUserProp), 0);
if (NO_ERROR != dwErr)
{
goto LDone;
}
}
else
{
ServerConfigDialog.pUserProp = (PEAP_USER_PROP *)pConfigDataIn;
if(NULL == ServerConfigDialog.pUserProp)
{
dwErr = PeapReadUserData(TRUE, NULL, 0, &ServerConfigDialog.pUserProp);
if(NO_ERROR != dwErr)
{
goto LDone;
}
}
}
//
// Create cert list to display and then show the server config UI.
//
dwStrLen = wcslen(awszStoreName);
wcsncat(awszStoreName, L"\\MY", wcslen(L"\\MY") );
hCertStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
0,
0,
CERT_STORE_READONLY_FLAG |
CERT_SYSTEM_STORE_LOCAL_MACHINE,
awszStoreName);
if ( hCertStore )
{
//
// Check to see if the hash in the user prop still
// exists in the store and if so, check to see
// if it has been renewed.
//
HashBlob.cbData = ServerConfigDialog.pUserProp->CertHash.cbHash;
HashBlob.pbData = ServerConfigDialog.pUserProp->CertHash.pbHash;
pCertContext = CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING,
0, CERT_FIND_HASH, &HashBlob, NULL);
if (NULL != pCertContext)
{
//
// Check to see if we've been renewed.
//
PCCERT_CONTEXT pNewCertContext = NULL;
if ( CheckForCertificateRenewal(SP_PROT_SERVERS,
pCertContext,
&pNewCertContext
)
)
{
if ( pNewCertContext )
{
//
// Change the hash.
//
ServerConfigDialog.pUserProp->CertHash.cbHash = MAX_HASH_SIZE;
if (!CertGetCertificateContextProperty(pNewCertContext,
CERT_HASH_PROP_ID, ServerConfigDialog.pUserProp->CertHash.pbHash,
&(ServerConfigDialog.pUserProp->CertHash.cbHash)))
{
EapTlsTrace("CertGetCertificateContextProperty failed and "
"returned 0x%x", GetLastError());
}
CertFreeCertificateContext(pNewCertContext);
pNewCertContext = NULL;
}
CertFreeCertificateContext(pCertContext);
pCertContext = NULL;
}
}
CertCloseStore ( hCertStore, CERT_CLOSE_STORE_FORCE_FLAG );
}
CreateCertList( TRUE,
FALSE, /*fRouter */
FALSE /* fRoot */,
&(ServerConfigDialog.pCertList),
&(ServerConfigDialog.pSelCertList),
1,
&(ServerConfigDialog.pUserProp->CertHash),
fLocal ? L"MY": awszStoreName);
if (NULL == ServerConfigDialog.pCertList)
{
//
// Setup the in param to out param. Since we're
// not sending back any error this will cause
// IAS to store back empty configuration.
//
if ( pConfigDataIn && dwSizeofConfigDataIn )
{
//
//We were send in some config data
//
*ppConfigDataOut = (PBYTE)LocalAlloc(LPTR, ServerConfigDialog.pUserProp->dwSize) ;
if ( *ppConfigDataOut )
{
CopyMemory ( *ppConfigDataOut,
ServerConfigDialog.pUserProp,
ServerConfigDialog.pUserProp->dwSize
);
*pdwSizeofConfigDataOut = ServerConfigDialog.pUserProp->dwSize;
}
}
DisplayError(hWnd, ERROR_NO_EAPTLS_CERTIFICATE);
goto LDone;
}
wcsncat(awszStoreName, L"\\MY", wcslen(L"\\MY"));
awszStoreName[dwStrLen] = 0; // Get rid of the \MY
//
// Create list of All EAP Types allowed and check to see
// if standalone is supported.
//
dwErr = PeapEapInfoGetList ( pwszMachineName, TRUE, &(ServerConfigDialog.pEapInfo) );
if ( NO_ERROR != dwErr )
{
goto LDone;
}
//
// From the user info get the selected PEAP Type if any
//
dwErr = PeapGetFirstEntryUserProp ( ServerConfigDialog.pUserProp,
&pEntryProp
);
if ( NO_ERROR == dwErr )
{
// Set the selected EAP type
//
PeapEapInfoFindListNode ( pEntryProp->dwEapTypeId,
ServerConfigDialog.pEapInfo,
&(ServerConfigDialog.pSelEapInfo)
);
}
ServerConfigDialog.fStandAloneMachine =
IsStandaloneServer(pwszMachineName);
//
// Invoke the config UI.
//
nRet = DialogBoxParam(
GetHInstance(),
MAKEINTRESOURCE(IDD_PEAP_SERVER_UI),
hWnd,
PeapServerDialogProc,
(LPARAM)&ServerConfigDialog);
if (-1 == nRet)
{
dwErr = GetLastError();
goto LDone;
}
else if (IDOK != nRet)
{
dwErr = ERROR_CANCELLED;
goto LDone;
}
if ( (fConfigDataInRegistry)
&& (NULL != ServerConfigDialog.pNewUserProp))
{
//
// Save the config data in registry.
//
dwErr = PeapServerConfigDataIO(
FALSE /* fRead */,
fLocal ? NULL : awszStoreName,
(PBYTE *) &(ServerConfigDialog.pNewUserProp),
(ServerConfigDialog.pNewUserProp)->dwSize);
// Ignore errors
RasEapFreeMemory(pUserDataOut);
LocalFree(ServerConfigDialog.pNewUserProp );
}
else if(!fConfigDataInRegistry)
{
//
// pass the data back to the eap engine
//
*ppConfigDataOut = (PBYTE)ServerConfigDialog.pNewUserProp;
*pdwSizeofConfigDataOut = ServerConfigDialog.pNewUserProp->dwSize;
}
LDone:
if(pConfigDataIn != (PBYTE) ServerConfigDialog.pUserProp)
{
LocalFree(ServerConfigDialog.pUserProp );
}
PeapEapInfoFreeList ( ServerConfigDialog.pEapInfo );
EapTlsInitialize2(FALSE, TRUE /* fUI */);
return dwErr;
}
/*
Returns:
NO_ERROR: iff Success
Notes:
Congigure EAP-TLS for the RAS server.
*/
DWORD
InvokeServerConfigUI(
IN HWND hWnd,
IN WCHAR* pwszMachineName,
IN BOOL fConfigDataInRegistry,
IN const BYTE* pConfigDataIn,
IN DWORD dwSizeofConfigDataIn,
OUT PBYTE* ppConfigDataOut,
OUT DWORD* pdwSizeofConfigDataOut
)
{
#define MAX_STORE_NAME_LENGTH MAX_COMPUTERNAME_LENGTH + 10
WCHAR awszStoreName[MAX_STORE_NAME_LENGTH + 1];
DWORD dwStrLen;
EAPTLS_USER_PROPERTIES* pUserProp = NULL;
BYTE* pUserDataOut = NULL;
DWORD dwSizeOfUserDataOut;
BOOL fLocal = FALSE;
DWORD dwErr = NO_ERROR;
if (0 == *pwszMachineName)
{
fLocal = TRUE;
}
wcscpy(awszStoreName, L"\\\\");
wcsncat(awszStoreName, pwszMachineName, MAX_COMPUTERNAME_LENGTH);
if(fConfigDataInRegistry)
{
dwErr = ServerConfigDataIO(TRUE /* fRead */,
fLocal ? NULL : awszStoreName,
(BYTE**)&pUserProp, 0);
if (NO_ERROR != dwErr)
{
goto LDone;
}
}
else
{
//
// Config data was passed in to the eap dll.
//
dwErr = ReadUserData((PBYTE)pConfigDataIn, dwSizeofConfigDataIn, &pUserProp);
if (NO_ERROR != dwErr)
{
goto LDone;
}
#if 0
if(NULL == pUserProp)
{
//
// If no data was passed in, allocate default data.
//
pUserProp = (EAPTLS_USER_PROPERTIES *)LocalAlloc(LPTR,
sizeof(EAPTLS_USER_PROPERTIES));
if(NULL == pUserProp)
{
dwErr = E_OUTOFMEMORY;
goto LDone;
}
pUserProp->dwVersion = 0;
pUserProp->dwSize = sizeof(EAPTLS_USER_PROPERTIES);
}
#endif
}
dwStrLen = wcslen(awszStoreName);
wcsncat(awszStoreName, L"\\MY", wcslen(L"\\MY"));
dwErr = EapTlsInvokeIdentityUI(
TRUE /* fServer */,
FALSE /* fRouterConfig */,
0 /* dwFlags */,
fLocal ? L"MY" : awszStoreName,
L"" /* pwszPhonebook */,
L"" /* pwszEntry */,
hWnd,
NULL /* pConnectionDataIn */,
0 /* dwSizeOfConnectionDataIn */,
(BYTE*)pUserProp,
pUserProp->dwSize,
&pUserDataOut,
&dwSizeOfUserDataOut,
NULL /* pszIdentity */);
if (NO_ERROR != dwErr)
{
goto LDone;
}
awszStoreName[dwStrLen] = 0; // Get rid of the \MY
if(fConfigDataInRegistry)
{
dwErr = ServerConfigDataIO(FALSE /* fRead */,
fLocal ? NULL : awszStoreName,
&pUserDataOut,
dwSizeOfUserDataOut);
}
else
{
*ppConfigDataOut = pUserDataOut;
*pdwSizeofConfigDataOut = dwSizeOfUserDataOut;
}
LDone:
if ( dwErr == ERROR_NO_EAPTLS_CERTIFICATE )
dwErr = NO_ERROR;
if(fConfigDataInRegistry)
{
// Ignore errors
RasEapFreeMemory(pUserDataOut);
}
if((PBYTE) pUserProp != pConfigDataIn)
{
LocalFree(pUserProp);
}
return(dwErr);
}
DWORD
PeapGetIdentity(
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;
PPEAP_CONN_PROP pConnProp = NULL;
PPEAP_USER_PROP pUserProp = NULL;
PPEAP_USER_PROP pUserPropNew = NULL;
PPEAP_EAP_INFO pEapInfo = NULL;
PPEAP_EAP_INFO pFirstEapInfo = NULL;
PEAP_ENTRY_CONN_PROPERTIES UNALIGNED * pFirstEntryConnProp = NULL;
PEAP_ENTRY_USER_PROPERTIES UNALIGNED * pFirstEntryUserProp = NULL;
PEAP_DEFAULT_CRED_DIALOG DefaultCredDialog;
INT_PTR nRet;
LPWSTR lpwszLocalMachineName = NULL;
//
// Since PEAP itself does not have any client identity of its own,
// check the first configured eap type and call it's get identity
// entry point. If we dont have any eaptype configured, it is an
// error condition.
//
dwRetCode = PeapReadConnectionData( ( dwFlags & RAS_EAP_FLAG_8021X_AUTH ),
pConnectionDataIn,
dwSizeOfConnectionDataIn,
&pConnProp
);
if ( NO_ERROR != dwRetCode )
{
goto LDone;
}
dwRetCode = PeapReadUserData ( FALSE,
pUserDataIn,
dwSizeOfUserDataIn,
&pUserProp
);
if ( NO_ERROR != dwRetCode )
{
goto LDone;
}
//
// This is probably not a very good thing. Modify PeapReadConnectionData to
// put in the default of first eap type that it finds...
// For now we have the only one - mschap v2 so may not be an issue...
//
if ( !pConnProp->dwNumPeapTypes )
{
dwRetCode = ERROR_PROTOCOL_NOT_CONFIGURED;
goto LDone;
}
//
// Check to see if the conn prop and user prop are mismatched. If so, we need to get the
// User props all over again
//
// Now invoke the first EAP method configured ( in this release, the only EAP )
// method and get the config info from it...
//
dwRetCode = PeapEapInfoGetList ( NULL, FALSE, &pEapInfo);
if ( NO_ERROR != dwRetCode )
{
goto LDone;
}
//
// If we have come this far, we have at least one configured eaptype in
// PEAP. So, get the entry properties for it.
//
dwRetCode = PeapGetFirstEntryConnProp ( pConnProp,
&pFirstEntryConnProp
);
if ( NO_ERROR != dwRetCode )
{
goto LDone;
}
dwRetCode = PeapGetFirstEntryUserProp ( pUserProp,
&pFirstEntryUserProp
);
if ( NO_ERROR != dwRetCode )
{
goto LDone;
}
dwRetCode = PeapEapInfoFindListNode ( pFirstEntryConnProp->dwEapTypeId,
pEapInfo,
&pFirstEapInfo
);
if ( NO_ERROR != dwRetCode )
{
goto LDone;
}
if ( pFirstEntryConnProp->dwEapTypeId != pFirstEntryUserProp->dwEapTypeId )
{
//
// We have mismatched user prop and conn prop. So Reset the USer Prop Structure
//
LocalFree ( pUserProp );
dwRetCode = PeapReDoUserData (pFirstEntryConnProp->dwEapTypeId,
&pUserProp
);
if ( NO_ERROR != dwRetCode )
{
goto LDone;
}
dwRetCode = PeapGetFirstEntryUserProp ( pUserProp,
&pFirstEntryUserProp
);
if ( NO_ERROR != dwRetCode )
{
goto LDone;
}
}
if ( pFirstEntryConnProp->dwSize > sizeof(PEAP_ENTRY_CONN_PROPERTIES))
{
pFirstEapInfo->pbClientConfigOrig = pFirstEntryConnProp->bData;
pFirstEapInfo->dwClientConfigOrigSize = pFirstEntryConnProp->dwSize - sizeof(PEAP_ENTRY_CONN_PROPERTIES) + 1;
}
else
{
pFirstEapInfo->pbClientConfigOrig = NULL;
pFirstEapInfo->dwClientConfigOrigSize = 0;
}
//if typeid is 0, no user props are setup yet.
if ( pFirstEntryUserProp->dwSize > sizeof(PEAP_ENTRY_USER_PROPERTIES))
{
pFirstEapInfo->pbUserConfigOrig = pFirstEntryUserProp->bData;
pFirstEapInfo->dwUserConfigOrigSize = pFirstEntryUserProp->dwSize - sizeof(PEAP_ENTRY_USER_PROPERTIES) + 1;
}
else
{
pFirstEapInfo->pbUserConfigOrig = NULL;
pFirstEapInfo->dwUserConfigOrigSize = 0;
}
//
// Invoke Identity UI for the first entry
// and - NOTE we will have to chain this later.
// and save it in the conn prop of each
if ( pFirstEapInfo->lpwszIdentityUIPath )
{
dwRetCode = PeapEapInfoInvokeIdentityUI ( hwndParent,
pFirstEapInfo,
pwszPhonebook,
pwszEntry,
pUserDataIn,
dwSizeOfUserDataIn,
ppwszIdentityOut,
dwFlags
);
if ( NO_ERROR == dwRetCode )
{
//
// Check to see if we have new user data
//
if ( pFirstEapInfo->pbUserConfigNew && pFirstEapInfo->dwNewUserConfigSize )
{
//
// redo the user prop blob
//
pUserPropNew = (PPEAP_USER_PROP)
LocalAlloc ( LPTR, sizeof(PEAP_USER_PROP) + pFirstEapInfo->dwNewUserConfigSize );
if ( NULL == pUserPropNew )
{
dwRetCode = ERROR_OUTOFMEMORY;
goto LDone;
}
CopyMemory ( pUserPropNew, pUserProp, sizeof(PEAP_USER_PROP) );
pUserPropNew->dwVersion = 2;
pUserPropNew->UserProperties.dwVersion = 1;
pUserPropNew->UserProperties.dwSize = sizeof(PEAP_ENTRY_USER_PROPERTIES) +
pFirstEapInfo->dwNewUserConfigSize -1;
pUserPropNew->dwSize = pUserPropNew->UserProperties.dwSize +
sizeof(PEAP_USER_PROP) - sizeof(PEAP_ENTRY_USER_PROPERTIES);
pUserPropNew->UserProperties.dwEapTypeId = pFirstEapInfo->dwTypeId;
pUserPropNew->UserProperties.fUsingPeapDefault = 0;
CopyMemory (pUserPropNew->UserProperties.bData,
pFirstEapInfo->pbUserConfigNew,
pFirstEapInfo->dwNewUserConfigSize
);
*ppUserDataOut = (PBYTE)pUserPropNew;
*pdwSizeOfUserDataOut = pUserPropNew->dwSize;
pUserPropNew = NULL;
}
else
{
*ppUserDataOut = (PBYTE)pUserProp;
*pdwSizeOfUserDataOut = pUserProp->dwSize;
pUserProp = NULL;
}
}
}
else
{
//MAchine Auth
if ( dwFlags & RAS_EAP_FLAG_MACHINE_AUTH)
{
//Send the identity back as domain\machine$
dwRetCode = GetLocalMachineName(&lpwszLocalMachineName );
if ( NO_ERROR != dwRetCode )
{
EapTlsTrace("Failed to get computer name");
goto LDone;
}
if ( ! FFormatMachineIdentity1 ( lpwszLocalMachineName,
ppwszIdentityOut )
)
{
EapTlsTrace("Failed to format machine identity");
}
goto LDone;
}
if ( dwFlags & RAS_EAP_FLAG_NON_INTERACTIVE )
{
EapTlsTrace("Passed non interactive mode when interactive mode expected.");
dwRetCode = ERROR_INTERACTIVE_MODE;
goto LDone;
}
//
// provide our default identity - You cannot save this identity or anything like that.
// This is for the lame EAP methods that dont supply their own identity
//
ZeroMemory ( &DefaultCredDialog, sizeof(DefaultCredDialog) );
nRet = DialogBoxParam(
GetHInstance(),
MAKEINTRESOURCE(IDD_DIALOG_DEFAULT_CREDENTIALS),
hwndParent,
DefaultCredDialogProc,
(LPARAM)&DefaultCredDialog);
// EapTlsPinDialog.pUserProp may have been realloced
if (-1 == nRet)
{
dwRetCode = GetLastError();
goto LDone;
}
else if (IDOK != nRet)
{
dwRetCode = ERROR_CANCELLED;
goto LDone;
}
//CReate the new user prop blob
pUserPropNew = (PPEAP_USER_PROP)
LocalAlloc ( LPTR,
sizeof(PEAP_USER_PROP) + sizeof( PEAP_DEFAULT_CREDENTIALS ) );
if ( NULL == pUserPropNew )
{
dwRetCode = ERROR_OUTOFMEMORY;
goto LDone;
}
CopyMemory ( pUserPropNew, pUserProp, sizeof(PEAP_USER_PROP) );
pUserPropNew->UserProperties.dwVersion = 1;
pUserPropNew->UserProperties.dwSize = sizeof(PEAP_ENTRY_USER_PROPERTIES) +
sizeof(PEAP_DEFAULT_CREDENTIALS) - 1;
pUserPropNew->UserProperties.fUsingPeapDefault = 1;
pUserPropNew->dwSize = pUserPropNew->UserProperties.dwSize +
sizeof(PEAP_USER_PROP) - sizeof(PEAP_ENTRY_USER_PROPERTIES);
pUserPropNew->UserProperties.dwEapTypeId = pFirstEapInfo->dwTypeId;
CopyMemory (pUserPropNew->UserProperties.bData,
&(DefaultCredDialog.PeapDefaultCredentials),
sizeof(DefaultCredDialog.PeapDefaultCredentials)
);
pUserPropNew->dwVersion = 2;
*ppUserDataOut = (PBYTE)pUserPropNew;
*pdwSizeOfUserDataOut = pUserPropNew->dwSize;
//
// Now create the identity with uid and domain if any
//
dwRetCode = GetIdentityFromUserName (
DefaultCredDialog.PeapDefaultCredentials.wszUserName,
DefaultCredDialog.PeapDefaultCredentials.wszDomain,
ppwszIdentityOut
);
if ( NO_ERROR != dwRetCode )
{
goto LDone;
}
pUserPropNew = NULL;
}
LDone:
LocalFree( lpwszLocalMachineName );
LocalFree(pConnProp);
LocalFree(pUserProp);
LocalFree(pUserPropNew);
PeapEapInfoFreeList( pEapInfo );
return dwRetCode;
}
/*
Returns:
NO_ERROR: iff Success
Notes:
*/
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 dwErr = ERROR_INVALID_PARAMETER;
if ( PPP_EAP_TLS == dwEapTypeId )
{
dwErr = EapTlsInvokeIdentityUI(
FALSE /* fServer */,
FALSE /* fRouterConfig */,
dwFlags,
L"MY",
pwszPhonebook,
pwszEntry,
hwndParent,
pConnectionDataIn,
dwSizeOfConnectionDataIn,
pUserDataIn,
dwSizeOfUserDataIn,
ppUserDataOut,
pdwSizeOfUserDataOut,
ppwszIdentityOut);
}
#ifdef IMPL_PEAP
else if ( PPP_EAP_PEAP == dwEapTypeId )
{
dwErr = PeapGetIdentity(dwEapTypeId,
hwndParent,
dwFlags,
pwszPhonebook,
pwszEntry,
pConnectionDataIn,
dwSizeOfConnectionDataIn,
pUserDataIn,
dwSizeOfUserDataIn,
ppUserDataOut,
pdwSizeOfUserDataOut,
ppwszIdentityOut
);
}
#endif
return(dwErr);
}
/*
Returns:
Notes:
Called to free memory.
*/
DWORD
RasEapFreeMemory(
IN BYTE* pMemory
)
{
LocalFree(pMemory);
return(NO_ERROR);
}
#if 0
#if WINVER > 0x0500
/*
Returns:
Notes:
API to create a connection Properties V1 Blob
*/
/*
Returns:
Notes:
API to create a connection Properties V1 Blob
*/
DWORD
RasEapCreateConnProp
(
IN PEAPTLS_CONNPROP_ATTRIBUTE pAttr,
IN PVOID * ppConnPropIn,
IN DWORD * pdwConnPropSizeIn,
OUT PVOID * ppConnPropOut,
OUT DWORD * pdwConnPropSizeOut
)
{
DWORD dwRetCode = NO_ERROR;
DWORD dwAllocBytes = 0;
DWORD dwNumHashesOrig = 0;
DWORD dwServerNamesLengthOrig = 0;
PEAPTLS_CONNPROP_ATTRIBUTE pAttrInternal = pAttr;
EAPTLS_CONN_PROPERTIES_V1 * pConnPropv1 = NULL;
EAPTLS_CONN_PROPERTIES_V1 * pConnPropv1Orig = NULL;
PEAPTLS_CONNPROP_ATTRIBUTE pAttrServerNames = NULL;
PEAPTLS_CONNPROP_ATTRIBUTE pAttrHashes = NULL;
EAPTLS_HASH sHash;
DWORD i;
if ( !pAttr || !ppConnPropOut )
{
dwRetCode = ERROR_INVALID_PARAMETER;
goto done;
}
*ppConnPropOut = NULL;
//
// Get the sizeof this allocation.
//
dwAllocBytes = sizeof(EAPTLS_CONN_PROPERTIES_V1);
while ( pAttrInternal->ecaType != ecatMinimum )
{
switch ( pAttrInternal->ecaType )
{
case ecatMinimum:
case ecatFlagRegistryCert:
case ecatFlagScard:
case ecatFlagValidateServer:
case ecatFlagValidateName:
case ecatFlagDiffUser:
break;
case ecatServerNames:
dwAllocBytes += pAttrInternal->dwLength;
break;
case ecatRootHashes:
dwAllocBytes += ( ( (pAttrInternal->dwLength)/MAX_HASH_SIZE) * sizeof(EAPTLS_HASH) );
break;
default:
dwRetCode = ERROR_INVALID_PARAMETER;
goto done;
}
pAttrInternal ++;
}
pAttrInternal = pAttr;
if (*ppConnPropIn == NULL)
{
pConnPropv1 = (EAPTLS_CONN_PROPERTIES_V1 *) LocalAlloc(LPTR, dwAllocBytes );
if ( NULL == pConnPropv1 )
{
dwRetCode = GetLastError();
goto done;
}
}
else
{
// Input struct with always be Version 0, convert internally to
// Version 1
dwRetCode = ConnPropGetV1Struct ( ((EAPTLS_CONN_PROPERTIES *)(*ppConnPropIn)), &pConnPropv1Orig );
if ( NO_ERROR != dwRetCode )
{
goto done;
}
if (pConnPropv1Orig->dwNumHashes)
{
dwAllocBytes += pConnPropv1Orig->dwNumHashes*sizeof(EAPTLS_HASH);
}
dwAllocBytes += wcslen ( (WCHAR *)( pConnPropv1Orig->bData + (pConnPropv1Orig->dwNumHashes * sizeof(EAPTLS_HASH)) )) * sizeof(WCHAR) + sizeof(WCHAR);
pConnPropv1 = (EAPTLS_CONN_PROPERTIES_V1 *) LocalAlloc(LPTR, dwAllocBytes );
if ( NULL == pConnPropv1 )
{
dwRetCode = GetLastError();
goto done;
}
}
pConnPropv1->dwVersion = 1;
pConnPropv1->dwSize = dwAllocBytes;
//
//Set the flags first
//
while ( pAttrInternal->ecaType != ecatMinimum )
{
switch ( pAttrInternal->ecaType )
{
case ecatFlagRegistryCert:
pConnPropv1->fFlags |= EAPTLS_CONN_FLAG_REGISTRY;
break;
case ecatFlagScard:
pConnPropv1->fFlags &= ~EAPTLS_CONN_FLAG_REGISTRY;
break;
case ecatFlagValidateServer:
if ( *((BOOL *)(pAttrInternal->Value)) )
pConnPropv1->fFlags &= ~EAPTLS_CONN_FLAG_NO_VALIDATE_CERT;
else
pConnPropv1->fFlags |= EAPTLS_CONN_FLAG_NO_VALIDATE_CERT;
break;
case ecatFlagValidateName:
if ( *((BOOL *)(pAttrInternal->Value)) )
pConnPropv1->fFlags &= ~EAPTLS_CONN_FLAG_NO_VALIDATE_NAME;
else
pConnPropv1->fFlags |= EAPTLS_CONN_FLAG_NO_VALIDATE_NAME;
break;
case ecatFlagDiffUser:
if ( *((BOOL *)(pAttrInternal->Value)) )
pConnPropv1->fFlags &= ~EAPTLS_CONN_FLAG_DIFF_USER;
else
pConnPropv1->fFlags |= EAPTLS_CONN_FLAG_DIFF_USER;
break;
case ecatServerNames:
pAttrServerNames = pAttrInternal;
break;
case ecatRootHashes:
pAttrHashes = pAttrInternal;
break;
}
pAttrInternal++;
}
dwNumHashesOrig = pConnPropv1Orig?pConnPropv1Orig->dwNumHashes:0;
if ( dwNumHashesOrig )
{
CopyMemory( pConnPropv1->bData, pConnPropv1Orig->bData, sizeof(EAPTLS_HASH)*dwNumHashesOrig );
pConnPropv1->dwNumHashes = dwNumHashesOrig;
}
if ( pAttrHashes )
{
DWORD dwNumHashes = 0;
dwNumHashes = (pAttrHashes->dwLength)/MAX_HASH_SIZE;
for ( i = 0; i < dwNumHashes; i ++ )
{
ZeroMemory( &sHash, sizeof(sHash) );
sHash.cbHash = MAX_HASH_SIZE;
CopyMemory( sHash.pbHash, ((PBYTE)pAttrHashes->Value) + MAX_HASH_SIZE * i, MAX_HASH_SIZE );
CopyMemory( pConnPropv1->bData + sizeof(EAPTLS_HASH) * (pConnPropv1->dwNumHashes + i) , &sHash, sizeof(sHash) );
}
pConnPropv1->dwNumHashes += dwNumHashes;
}
dwServerNamesLengthOrig = pConnPropv1Orig?(wcslen((WCHAR*)(pConnPropv1Orig->bData+sizeof(EAPTLS_HASH) * (pConnPropv1Orig->dwNumHashes)))*sizeof(WCHAR) + sizeof (WCHAR) ):0;
if ( dwServerNamesLengthOrig )
{
CopyMemory ( pConnPropv1->bData + sizeof(EAPTLS_HASH) * pConnPropv1->dwNumHashes,
pConnPropv1Orig->bData+sizeof(EAPTLS_HASH) * pConnPropv1Orig->dwNumHashes,
dwServerNamesLengthOrig
);
}
if ( pAttrServerNames )
{
//Setup the server name
CopyMemory ( pConnPropv1->bData + sizeof(EAPTLS_HASH) * pConnPropv1->dwNumHashes + dwServerNamesLengthOrig,
pAttrServerNames->Value,
pAttrServerNames->dwLength
);
}
dwRetCode = ConnPropGetV0Struct ( pConnPropv1, (EAPTLS_CONN_PROPERTIES ** )ppConnPropOut );
if ( NO_ERROR != dwRetCode )
{
goto done;
}
*pdwConnPropSizeOut = ((EAPTLS_CONN_PROPERTIES * )*ppConnPropOut)->dwSize;
done:
LocalFree ( pConnPropv1 );
return dwRetCode;
}
#endif
#endif
////////////////////////// all PEAP related stuff ///////////////////////////////////////
TCHAR*
ComboBox_GetPsz(
IN HWND hwnd,
IN INT nIndex )
/* Returns heap block containing the text contents of the 'nIndex'th item
** of combo box 'hwnd' or NULL. It is caller's responsibility to Free the
** returned string.
*/
{
INT cch;
TCHAR* psz;
cch = ComboBox_GetLBTextLen( hwnd, nIndex );
if (cch < 0)
return NULL;
psz = LocalAlloc (LPTR, (cch + 1) * sizeof(TCHAR) );
if (psz)
{
*psz = TEXT('\0');
ComboBox_GetLBText( hwnd, nIndex, psz );
}
return psz;
}
VOID
ComboBox_AutoSizeDroppedWidth(
IN HWND hwndLb )
/* Set the width of the drop-down list 'hwndLb' to the width of the
** longest item (or the width of the list box if that's wider).
*/
{
HDC hdc;
HFONT hfont;
TCHAR* psz;
SIZE size;
DWORD cch;
DWORD dxNew;
DWORD i;
hfont = (HFONT )SendMessage( hwndLb, WM_GETFONT, 0, 0 );
if (!hfont)
return;
hdc = GetDC( hwndLb );
if (!hdc)
return;
SelectObject( hdc, hfont );
dxNew = 0;
for (i = 0; psz = ComboBox_GetPsz( hwndLb, i ); ++i)
{
cch = lstrlen( psz );
if (GetTextExtentPoint32( hdc, psz, cch, &size ))
{
if (dxNew < (DWORD )size.cx)
dxNew = (DWORD )size.cx;
}
LocalFree( psz );
}
ReleaseDC( hwndLb, hdc );
/* Allow for the spacing on left and right added by the control.
*/
dxNew += 6;
/* Figure out if the vertical scrollbar will be displayed and, if so,
** allow for it's width.
*/
{
RECT rectD;
RECT rectU;
DWORD dyItem;
DWORD cItemsInDrop;
DWORD cItemsInList;
GetWindowRect( hwndLb, &rectU );
SendMessage( hwndLb, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM )&rectD );
dyItem = (DWORD)SendMessage( hwndLb, CB_GETITEMHEIGHT, 0, 0 );
cItemsInDrop = (rectD.bottom - rectU.bottom) / dyItem;
cItemsInList = ComboBox_GetCount( hwndLb );
if (cItemsInDrop < cItemsInList)
dxNew += GetSystemMetrics( SM_CXVSCROLL );
}
SendMessage( hwndLb, CB_SETDROPPEDWIDTH, dxNew, 0 );
}
VOID
PeapEnableValidateNameControls(
IN PPEAP_CONN_DIALOG pPeapConnDialog
)
{
BOOL fEnable;
RTASSERT(NULL != pPeapConnDialog);
fEnable = !(pPeapConnDialog->pConnProp->EapTlsConnProp.fFlags &
EAPTLS_CONN_FLAG_NO_VALIDATE_CERT);
EnableWindow(pPeapConnDialog->hWndCheckValidateName, fEnable);
EnableWindow(pPeapConnDialog->hWndStaticRootCaName, fEnable);
EnableWindow(pPeapConnDialog->hWndListRootCaName, fEnable);
fEnable = ( fEnable
&& !(pPeapConnDialog->pConnProp->EapTlsConnProp.fFlags &
EAPTLS_CONN_FLAG_NO_VALIDATE_NAME));
EnableWindow(pPeapConnDialog->hWndEditServerName, fEnable);
}
BOOL
PeapConnInitDialog(
IN HWND hWnd,
IN LPARAM lParam
)
{
PPEAP_CONN_DIALOG pPeapConnDialog;
LVCOLUMN lvColumn;
LPWSTR lpwszServerName = NULL;
DWORD dwCount = 0;
PPEAP_EAP_INFO pEapInfo;
DWORD dwSelItem = 0;
PEAP_ENTRY_CONN_PROPERTIES UNALIGNED * pEntryProp;
INT_PTR nIndex = 0;
BOOL fCripplePeap = FALSE;
SetWindowLongPtr(hWnd, DWLP_USER, lParam);
pPeapConnDialog = (PPEAP_CONN_DIALOG)lParam;
pPeapConnDialog->hWndCheckValidateCert =
GetDlgItem(hWnd, IDC_CHECK_VALIDATE_CERT);
pPeapConnDialog->hWndCheckValidateName =
GetDlgItem(hWnd, IDC_CHECK_VALIDATE_NAME);
pPeapConnDialog->hWndEditServerName =
GetDlgItem(hWnd, IDC_EDIT_SERVER_NAME);
pPeapConnDialog->hWndStaticRootCaName =
GetDlgItem(hWnd, IDC_STATIC_ROOT_CA_NAME);
pPeapConnDialog->hWndListRootCaName =
GetDlgItem(hWnd, IDC_LIST_ROOT_CA_NAME);
pPeapConnDialog->hWndComboPeapType =
GetDlgItem(hWnd, IDC_COMBO_PEAP_TYPE);
pPeapConnDialog->hWndButtonConfigure =
GetDlgItem(hWnd, IDC_BUTTON_CONFIGURE);
pPeapConnDialog->hWndCheckEnableFastReconnect =
GetDlgItem(hWnd, IDC_CHECK_ENABLE_FAST_RECONNECT);
//Set the style to set list boxes.
ListView_SetExtendedListViewStyle
( pPeapConnDialog->hWndListRootCaName,
ListView_GetExtendedListViewStyle(pPeapConnDialog->hWndListRootCaName) | LVS_EX_CHECKBOXES
);
ZeroMemory ( &lvColumn, sizeof(lvColumn));
lvColumn.fmt = LVCFMT_LEFT;
ListView_InsertColumn( pPeapConnDialog->hWndListRootCaName,
0,
&lvColumn
);
ListView_SetColumnWidth(pPeapConnDialog->hWndListRootCaName,
0,
LVSCW_AUTOSIZE_USEHEADER
);
//
//Now we need to init the
//list box with all the certs and selected cert
InitListBox ( pPeapConnDialog->hWndListRootCaName,
pPeapConnDialog->pCertList,
pPeapConnDialog->pConnProp->EapTlsConnProp.dwNumHashes,
pPeapConnDialog->ppSelCertList
);
lpwszServerName =
(LPWSTR )(pPeapConnDialog->pConnProp->EapTlsConnProp.bData +
sizeof( EAPTLS_HASH ) * pPeapConnDialog->pConnProp->EapTlsConnProp.dwNumHashes);
SetWindowText(pPeapConnDialog->hWndEditServerName,
lpwszServerName
);
if (pPeapConnDialog->fFlags & EAPTLS_CONN_DIALOG_FLAG_ROUTER)
{
pPeapConnDialog->pConnProp->EapTlsConnProp.fFlags |= EAPTLS_CONN_FLAG_REGISTRY;
}
CheckDlgButton(hWnd, IDC_CHECK_VALIDATE_CERT,
(pPeapConnDialog->pConnProp->EapTlsConnProp.fFlags &
EAPTLS_CONN_FLAG_NO_VALIDATE_CERT) ?
BST_UNCHECKED : BST_CHECKED);
CheckDlgButton(hWnd, IDC_CHECK_VALIDATE_NAME,
(pPeapConnDialog->pConnProp->EapTlsConnProp.fFlags &
EAPTLS_CONN_FLAG_NO_VALIDATE_NAME) ?
BST_UNCHECKED : BST_CHECKED);
PeapEnableValidateNameControls(pPeapConnDialog);
//
//Add all the PEAP eap type friendly names
//
pEapInfo = pPeapConnDialog->pEapInfo;
dwCount = 0;
while ( pEapInfo )
{
if ( fCripplePeap )
{
if ( pEapInfo->dwTypeId != PPP_EAP_MSCHAPv2 )
{
pEapInfo = pEapInfo->pNext;
continue;
}
}
nIndex = SendMessage(pPeapConnDialog->hWndComboPeapType,
CB_ADDSTRING,
0,
(LPARAM)pEapInfo->lpwszFriendlyName);
SendMessage ( pPeapConnDialog->hWndComboPeapType,
CB_SETITEMDATA,
(WPARAM)nIndex,
(LPARAM)pEapInfo
);
ComboBox_AutoSizeDroppedWidth( pPeapConnDialog->hWndComboPeapType );
dwCount++;
if ( pPeapConnDialog->pConnProp->dwNumPeapTypes )
{
/*
if ( pPeapConnDialog->pConnProp->EapTlsConnProp.dwSize == sizeof(EAPTLS_CONN_PROPERTIES_V1) )
{
//This is a newly initialized structure.
pEntryProp = (PEAP_ENTRY_CONN_PROPERTIES UNALIGNED *)
(((BYTE UNALIGNED *)(pPeapConnDialog->pConnProp)) + sizeof(PEAP_CONN_PROP));
}
else
*/
{
pEntryProp = ( PEAP_ENTRY_CONN_PROPERTIES UNALIGNED *)
( (BYTE UNALIGNED *)pPeapConnDialog->pConnProp->EapTlsConnProp.bData
+ pPeapConnDialog->pConnProp->EapTlsConnProp.dwNumHashes * sizeof(EAPTLS_HASH) +
wcslen(lpwszServerName) * sizeof(WCHAR) + sizeof(WCHAR));
}
if ( pEntryProp->dwEapTypeId == pEapInfo->dwTypeId )
{
pPeapConnDialog->pSelEapInfo = pEapInfo;
pPeapConnDialog->pSelEapInfo->pbClientConfigOrig =
pEntryProp->bData;
pPeapConnDialog->pSelEapInfo->dwClientConfigOrigSize =
pEntryProp->dwSize - sizeof(PEAP_ENTRY_CONN_PROPERTIES) + 1;
}
}
pEapInfo = pEapInfo->pNext;
}
dwSelItem = 0;
for ( nIndex = 0; nIndex < (INT_PTR)dwCount; nIndex ++ )
{
pEapInfo = (PPEAP_EAP_INFO)SendMessage( pPeapConnDialog->hWndComboPeapType,
CB_GETITEMDATA,
(WPARAM)nIndex,
(LPARAM)0L
);
if ( pEapInfo == pPeapConnDialog->pSelEapInfo )
{
dwSelItem = (DWORD)nIndex;
break;
}
}
SendMessage(pPeapConnDialog->hWndComboPeapType, CB_SETCURSEL, dwSelItem, 0);
//
// Hide/Show Fast reconnect based on if this is a
// Wireless client or VPN client.
//
if ( pPeapConnDialog->fFlags & PEAP_CONN_DIALOG_FLAG_8021x )
{
ShowWindow ( pPeapConnDialog->hWndCheckEnableFastReconnect,
SW_SHOW
);
//Check the box based on what the
CheckDlgButton(hWnd, IDC_CHECK_ENABLE_FAST_RECONNECT,
( pPeapConnDialog->pConnProp->dwFlags &
PEAP_CONN_FLAG_FAST_ROAMING) ?
BST_CHECKED : BST_UNCHECKED
);
}
else
{
ShowWindow ( pPeapConnDialog->hWndCheckEnableFastReconnect,
SW_HIDE
);
}
if ( pPeapConnDialog->pSelEapInfo->lpwszConfigUIPath )
{
EnableWindow(pPeapConnDialog->hWndButtonConfigure, TRUE );
}
else
{
//
// There is no configuration option here.
//
EnableWindow(pPeapConnDialog->hWndButtonConfigure, FALSE );
}
//
// if this is to function in readonly mode,
// disable the controls - set them in read only mode.
return(FALSE);
}
/*
Returns:
TRUE: We prrocessed this message.
FALSE: We did not prrocess this message.
Notes:
Response to the WM_COMMAND message (Config UI).
*/
BOOL
PeapConnCommand(
IN PPEAP_CONN_DIALOG pPeapConnDialog,
IN WORD wNotifyCode,
IN WORD wId,
IN HWND hWndDlg,
IN HWND hWndCtrl
)
{
DWORD dwNumChars;
PPEAP_CONN_PROP pPeapConnProp;
switch(wId)
{
case IDC_CHECK_VALIDATE_CERT:
if (BST_CHECKED == IsDlgButtonChecked(hWndDlg, IDC_CHECK_VALIDATE_CERT))
{
pPeapConnDialog->pConnProp->EapTlsConnProp.fFlags &=
~EAPTLS_CONN_FLAG_NO_VALIDATE_CERT;
pPeapConnDialog->pConnProp->EapTlsConnProp.fFlags &=
~EAPTLS_CONN_FLAG_NO_VALIDATE_NAME;
CheckDlgButton(hWndDlg, IDC_CHECK_VALIDATE_NAME, BST_CHECKED);
}
else
{
pPeapConnDialog->pConnProp->EapTlsConnProp.fFlags |=
EAPTLS_CONN_FLAG_NO_VALIDATE_CERT;
pPeapConnDialog->pConnProp->EapTlsConnProp.fFlags |=
EAPTLS_CONN_FLAG_NO_VALIDATE_NAME;
CheckDlgButton(hWndDlg, IDC_CHECK_VALIDATE_NAME, BST_UNCHECKED);
}
PeapEnableValidateNameControls(pPeapConnDialog);
return(TRUE);
case IDC_CHECK_VALIDATE_NAME:
if (BST_CHECKED == IsDlgButtonChecked(hWndDlg, IDC_CHECK_VALIDATE_NAME))
{
pPeapConnDialog->pConnProp->EapTlsConnProp.fFlags &=
~EAPTLS_CONN_FLAG_NO_VALIDATE_NAME;
}
else
{
pPeapConnDialog->pConnProp->EapTlsConnProp.fFlags |=
EAPTLS_CONN_FLAG_NO_VALIDATE_NAME;
}
PeapEnableValidateNameControls(pPeapConnDialog);
return(TRUE);
case IDC_COMBO_PEAP_TYPE:
if (CBN_SELCHANGE != wNotifyCode)
{
return(FALSE); // We will not process this message
}
//Fall Thru'
case IDC_BUTTON_CONFIGURE:
{
INT nIndex = -1;
nIndex = (INT)SendMessage ( pPeapConnDialog->hWndComboPeapType,
CB_GETCURSEL,
0,0
);
if ( nIndex != -1 )
{
//
// Change the currently selected EAP Type.
//
pPeapConnDialog->pSelEapInfo = (PPEAP_EAP_INFO)
SendMessage ( pPeapConnDialog->hWndComboPeapType,
CB_GETITEMDATA,
(WPARAM)nIndex,
(LPARAM)0
);
if ( pPeapConnDialog->pSelEapInfo->lpwszConfigUIPath )
{
EnableWindow(pPeapConnDialog->hWndButtonConfigure, TRUE );
if ( wId == IDC_BUTTON_CONFIGURE )
{
//
// Invoke the configure method for selected eap type and if no error is
// returned, then set the new configuration
//
DWORD dwFlags = 0;
if ( pPeapConnDialog->fFlags & EAPTLS_CONN_DIALOG_FLAG_ROUTER )
{
dwFlags |= RAS_EAP_FLAG_ROUTER;
}
if ( pPeapConnDialog->fFlags & PEAP_CONN_DIALOG_FLAG_8021x )
{
dwFlags |= RAS_EAP_FLAG_8021X_AUTH;
}
PeapEapInfoInvokeClientConfigUI ( hWndDlg,
pPeapConnDialog->pSelEapInfo,
dwFlags
);
}
}
else
{
//
// There is no configuration option here.
//
EnableWindow(pPeapConnDialog->hWndButtonConfigure, FALSE );
}
}
else
{
EnableWindow(pPeapConnDialog->hWndButtonConfigure, FALSE );
pPeapConnDialog->pSelEapInfo = NULL;
}
return TRUE;
}
case IDOK:
{
// Setup new PPEAP_CONN_PROP here.
//
EAPTLS_HASH * pHash = NULL;
DWORD dwNumHash = 0;
DWORD dwSelCount = 0;
DWORD dwPeapConnBlobSize = 0;
PEAP_ENTRY_CONN_PROPERTIES UNALIGNED * pEntryProp;
EAPTLS_CERT_NODE ** ppSelCertList = NULL;
WCHAR wszTitle[200] = {0};
WCHAR wszMessage[200] = {0};
if ( NULL == pPeapConnDialog->pSelEapInfo )
{
// No item selected so cannot complete configuration
// $TODO:show message
LoadString ( GetHInstance(),
IDS_CANT_CONFIGURE_SERVER_TITLE,
wszTitle, sizeof(wszTitle)/sizeof(WCHAR)
);
LoadString ( GetHInstance(),
IDS_PEAP_NO_EAP_TYPE,
wszMessage, sizeof(wszMessage)/sizeof(WCHAR)
);
MessageBox ( GetFocus(), wszMessage, wszTitle, MB_OK|MB_ICONWARNING );
return TRUE;
}
CertListSelectedCount ( pPeapConnDialog->hWndListRootCaName, &dwSelCount );
if ( dwSelCount > 0 )
{
ppSelCertList = (EAPTLS_CERT_NODE **)LocalAlloc(LPTR, sizeof(EAPTLS_CERT_NODE *) * dwSelCount );
if ( NULL == ppSelCertList )
{
EapTlsTrace("LocalAlloc in Command failed and returned %d",
GetLastError());
return TRUE;
}
pHash = (EAPTLS_HASH *)LocalAlloc(LPTR, sizeof(EAPTLS_HASH ) * dwSelCount );
if ( NULL == pHash )
{
EapTlsTrace("LocalAlloc in Command failed and returned %d",
GetLastError());
return TRUE;
}
CertListSelected( pPeapConnDialog->hWndListRootCaName,
pPeapConnDialog->pCertList,
ppSelCertList,
pHash,
dwSelCount
);
}
dwNumChars = GetWindowTextLength(pPeapConnDialog->hWndEditServerName);
//Allocate memory for pPeapConnProp
//Size of Peap conn prop includes
// sizeof peap conn prop +
// sizeof eaptls hashes of selected certs +
// sizeof server name +
// sizeof PEAP_ENTRY_CONN_PROPERTIES +
// sizeof conn prop returned by the selected type.
//
dwPeapConnBlobSize = sizeof(PEAP_CONN_PROP) + sizeof(EAPTLS_HASH) * dwSelCount +
dwNumChars * sizeof(WCHAR) + sizeof(WCHAR) +
sizeof(PEAP_ENTRY_CONN_PROPERTIES );
if ( pPeapConnDialog->pSelEapInfo->pbNewClientConfig )
{
dwPeapConnBlobSize += pPeapConnDialog->pSelEapInfo->dwNewClientConfigSize;
}
else
{
dwPeapConnBlobSize += pPeapConnDialog->pSelEapInfo->dwClientConfigOrigSize;
}
pPeapConnProp = (PPEAP_CONN_PROP)LocalAlloc( LPTR, dwPeapConnBlobSize );
if (NULL == pPeapConnProp)
{
EapTlsTrace("LocalAlloc in Command failed and returned %d",
GetLastError());
}
else
{
pPeapConnProp->dwVersion = 1;
pPeapConnProp->dwSize = dwPeapConnBlobSize;
pPeapConnProp->dwNumPeapTypes = 1;
//
// See if fast roaming is enabled or not.
//
if ( pPeapConnDialog->fFlags & PEAP_CONN_DIALOG_FLAG_8021x )
{
if ( IsDlgButtonChecked ( hWndDlg,
IDC_CHECK_ENABLE_FAST_RECONNECT
) == BST_CHECKED
)
{
pPeapConnProp->dwFlags |= PEAP_CONN_FLAG_FAST_ROAMING;
}
else
{
pPeapConnProp->dwFlags &= ~PEAP_CONN_FLAG_FAST_ROAMING;
}
}
CopyMemory( &pPeapConnProp->EapTlsConnProp,
&(pPeapConnDialog->pConnProp->EapTlsConnProp),
sizeof(EAPTLS_CONN_PROPERTIES_V1)
);
//
//Size of EapTlsConnProp is sizeof (EAPTLS_CONN_PROP_V1) -1 ( for bdata)
//+ sizeof(EAPTLS_HASH) * dwSelCount + sizeof( string) + one for null.
//
pPeapConnProp->EapTlsConnProp.dwSize = (sizeof(EAPTLS_CONN_PROPERTIES_V1) - 1) +
sizeof(EAPTLS_HASH) * dwSelCount +
dwNumChars * sizeof(WCHAR) + sizeof(WCHAR);
if ( pHash )
{
CopyMemory ( pPeapConnProp->EapTlsConnProp.bData,
pHash,
sizeof(EAPTLS_HASH) * dwSelCount
);
}
pPeapConnProp->EapTlsConnProp.dwVersion = 1;
pPeapConnProp->EapTlsConnProp.dwNumHashes = dwSelCount;
GetWindowText(pPeapConnDialog->hWndEditServerName,
(LPWSTR)(pPeapConnProp->EapTlsConnProp.bData + sizeof(EAPTLS_HASH) * dwSelCount) ,
dwNumChars + 1);
//
// Now copy over the PEAP_ENTRY_CONN_PROPERTIES structure
//
pEntryProp = (PEAP_ENTRY_CONN_PROPERTIES UNALIGNED *)
((BYTE UNALIGNED *)pPeapConnProp->EapTlsConnProp.bData + sizeof(EAPTLS_HASH) * dwSelCount
+ dwNumChars * sizeof(WCHAR)+ sizeof(WCHAR));
pEntryProp->dwVersion = 1;
pEntryProp->dwEapTypeId = pPeapConnDialog->pSelEapInfo->dwTypeId;
pEntryProp->dwSize = sizeof(PEAP_ENTRY_CONN_PROPERTIES)-1;
if ( pPeapConnDialog->pSelEapInfo->pbNewClientConfig )
{
pEntryProp->dwSize += pPeapConnDialog->pSelEapInfo->dwNewClientConfigSize ;
if ( pPeapConnDialog->pSelEapInfo->dwNewClientConfigSize )
{
CopyMemory( pEntryProp->bData,
pPeapConnDialog->pSelEapInfo->pbNewClientConfig,
pPeapConnDialog->pSelEapInfo->dwNewClientConfigSize
);
}
}
else
{
pEntryProp->dwSize += pPeapConnDialog->pSelEapInfo->dwClientConfigOrigSize;
if ( pPeapConnDialog->pSelEapInfo->dwClientConfigOrigSize )
{
CopyMemory( pEntryProp->bData,
pPeapConnDialog->pSelEapInfo->pbClientConfigOrig,
pPeapConnDialog->pSelEapInfo->dwClientConfigOrigSize
);
}
}
LocalFree(pPeapConnDialog->pConnProp);
if ( pPeapConnDialog->ppSelCertList )
LocalFree(pPeapConnDialog->ppSelCertList);
pPeapConnDialog->ppSelCertList = ppSelCertList;
pPeapConnDialog->pConnProp= pPeapConnProp;
}
}
// Fall through
case IDCANCEL:
EndDialog(hWndDlg, wId);
return(TRUE);
default:
return(FALSE);
}
}
BOOL PeapConnNotify( PEAP_CONN_DIALOG *pPeapConnDialog,
WPARAM wParam,
LPARAM lParam,
HWND hWnd
)
{
HCERTSTORE hCertStore = NULL;
PCCERT_CONTEXT pCertContext = NULL;
LPNMITEMACTIVATE lpnmItem;
LVITEM lvItem;
if ( wParam == IDC_LIST_ROOT_CA_NAME )
{
lpnmItem = (LPNMITEMACTIVATE) lParam;
if ( lpnmItem->hdr.code == NM_DBLCLK )
{
ZeroMemory(&lvItem, sizeof(lvItem) );
lvItem.mask = LVIF_PARAM;
lvItem.iItem = lpnmItem->iItem;
ListView_GetItem(lpnmItem->hdr.hwndFrom, &lvItem);
if ( NO_ERROR == GetSelCertContext( //pEaptlsConnDialog->pCertList,
(EAPTLS_CERT_NODE*)(lvItem.lParam) ,
-1,
&hCertStore,
L"ROOT",
&pCertContext
)
)
{
ShowCertDetails( hWnd, hCertStore, pCertContext );
CertFreeCertificateContext(pCertContext);
CertCloseStore( hCertStore, CERT_CLOSE_STORE_FORCE_FLAG );
return TRUE;
}
return TRUE;
}
}
return FALSE;
}
/*
Returns:
Notes:
Callback function used with the Config UI DialogBoxParam function. It
processes messages sent to the dialog box. See the DialogProc documentation
in MSDN.
*/
INT_PTR CALLBACK
PeapConnDialogProc(
IN HWND hWnd,
IN UINT unMsg,
IN WPARAM wParam,
IN LPARAM lParam
)
{
PPEAP_CONN_DIALOG pPeapConnDialog;
switch (unMsg)
{
case WM_INITDIALOG:
return(PeapConnInitDialog(hWnd, lParam));
case WM_HELP:
case WM_CONTEXTMENU:
{
ContextHelp(g_adwHelp, hWnd, unMsg, wParam, lParam);
break;
}
case WM_NOTIFY:
{
pPeapConnDialog = (PPEAP_CONN_DIALOG)GetWindowLongPtr(hWnd, DWLP_USER);
return PeapConnNotify( pPeapConnDialog,
wParam,
lParam,
hWnd
);
}
case WM_COMMAND:
pPeapConnDialog = (PPEAP_CONN_DIALOG)GetWindowLongPtr(hWnd, DWLP_USER);
return(PeapConnCommand(pPeapConnDialog, HIWORD(wParam), LOWORD(wParam),
hWnd, (HWND)lParam));
}
return(FALSE);
}
BOOL
PeapServerAddEapDialogInit(
IN HWND hWnd,
IN LPARAM lParam
)
{
PPEAP_SERVER_CONFIG_DIALOG pPeapServerDialog;
PPEAP_EAP_INFO pEapInfo;
PPEAP_USER_PROP pUserProp = NULL;
PEAP_ENTRY_USER_PROPERTIES UNALIGNED * pEntryUserProp = NULL;
DWORD dwCount = 0;
HWND hWndList, hWndOK;
SetWindowLongPtr( hWnd, DWLP_USER, lParam);
hWndList = GetDlgItem(hWnd, IDC_LIST_EAP_TYPES);
hWndOK = GetDlgItem ( hWnd, IDOK );
pPeapServerDialog = (PPEAP_SERVER_CONFIG_DIALOG)lParam;
//
// Add all the available EAP Types to this list
// and disable the OK button
//
if ( pPeapServerDialog->pNewUserProp )
{
pUserProp = pPeapServerDialog->pNewUserProp;
}
else
{
pUserProp = pPeapServerDialog->pUserProp;
}
pEapInfo = pPeapServerDialog->pEapInfo;
while ( pEapInfo )
{
BOOL bEntryUsed = FALSE;
//
// Check to see if this EAP Type has already
// been configured. If so, dont add it
//
PeapGetFirstEntryUserProp ( pUserProp,
&pEntryUserProp
);
for ( dwCount =0; dwCount < pUserProp->dwNumberOfEntries; dwCount++)
{
if ( pEntryUserProp->dwEapTypeId == pEapInfo->dwTypeId )
{
bEntryUsed = TRUE;
break;
}
PeapGetNextEntryUserProp ( pEntryUserProp,
&pEntryUserProp
);
}
if ( !bEntryUsed )
{
INT_PTR nIndex = 0;
nIndex = SendMessage( hWndList,
LB_ADDSTRING,
0,
(LPARAM)pEapInfo->lpwszFriendlyName);
SendMessage ( hWndList,
LB_SETITEMDATA,
(WPARAM)nIndex,
(LPARAM)pEapInfo
);
}
pEapInfo = pEapInfo->pNext;
}
//Preselect the first item in the list
SendMessage ( hWndList,
LB_SETCURSEL,
0,
0L
);
//EnableWindow(hWndOK, FALSE);
return(FALSE);
}
BOOL
PeapServerAddEapDialogCommand(
IN PPEAP_SERVER_CONFIG_DIALOG pPeapServerDialog,
IN WORD wNotifyCode,
IN WORD wId,
IN HWND hWndDlg,
IN HWND hWndCtrl
)
{
PPEAP_USER_PROP pNewUserProp = NULL;
//
//
//
switch(wId)
{
case IDC_LIST_EAP_TYPES:
if (LBN_SELCHANGE == wNotifyCode)
{
EnableWindow(GetDlgItem(hWndDlg,IDOK), TRUE);
return TRUE;
}
else if ( LBN_DBLCLK == wNotifyCode )
{
wId = IDOK;
//fall thru
}
else
{
// We will not process any other message
return(FALSE);
}
case IDOK:
//
// Modify the User Properties and set
// it with the new user properties
//
//Add the new EAP Type in the user prop and return
//
{
DWORD dwSelItemIndex;
PPEAP_EAP_INFO pEapInfo = NULL;
dwSelItemIndex = (DWORD)SendMessage ( GetDlgItem(hWndDlg, IDC_LIST_EAP_TYPES),
LB_GETCURSEL,
0,
0L
);
pEapInfo = (PPEAP_EAP_INFO)SendMessage ( GetDlgItem(hWndDlg, IDC_LIST_EAP_TYPES),
LB_GETITEMDATA,
dwSelItemIndex,
0L
);
PeapAddEntryUserProp ( (pPeapServerDialog->pNewUserProp?
pPeapServerDialog->pNewUserProp:
pPeapServerDialog->pUserProp),
pEapInfo,
&pNewUserProp
);
if ( pNewUserProp )
{
if ( pPeapServerDialog->pNewUserProp )
{
LocalFree (pPeapServerDialog->pNewUserProp);
pPeapServerDialog->pNewUserProp = NULL;
}
pPeapServerDialog->pNewUserProp = pNewUserProp;
pNewUserProp = NULL;
}
}
wId = IDOK;
// fall thru
case IDCANCEL:
EndDialog(hWndDlg, wId);
return TRUE;
default:
return FALSE;
}
return(FALSE);
}
//
// All the dialogs for Adding EAP method.
//
INT_PTR CALLBACK
PeapServerAddEapDialogProc(
IN HWND hWnd,
IN UINT unMsg,
IN WPARAM wParam,
IN LPARAM lParam
)
{
PPEAP_SERVER_CONFIG_DIALOG pPeapServerDialog;
switch (unMsg)
{
case WM_INITDIALOG:
return(PeapServerAddEapDialogInit(hWnd, lParam));
case WM_HELP:
case WM_CONTEXTMENU:
{
ContextHelp(g_adwHelp, hWnd, unMsg, wParam, lParam);
break;
}
case WM_COMMAND:
pPeapServerDialog = (PPEAP_SERVER_CONFIG_DIALOG)GetWindowLongPtr(hWnd, DWLP_USER);
return(PeapServerAddEapDialogCommand(pPeapServerDialog, HIWORD(wParam), LOWORD(wParam),
hWnd, (HWND)lParam));
}
return(FALSE);
}
VOID
PeapDisplayCertInfo (
IN PPEAP_SERVER_CONFIG_DIALOG pServerConfigDialog
)
{
RTASSERT(NULL != pServerConfigDialog);
// Erase old values first
SetWindowText(pServerConfigDialog->hWndEditFriendlyName, L"");
SetWindowText(pServerConfigDialog->hWndEditIssuer, L"");
SetWindowText(pServerConfigDialog->hWndEditExpiration, L"");
if (NULL != pServerConfigDialog->pSelCertList)
{
if (NULL != pServerConfigDialog->pSelCertList->pwszFriendlyName)
{
SetWindowText(pServerConfigDialog->hWndEditFriendlyName,
pServerConfigDialog->pSelCertList->pwszFriendlyName);
}
if (NULL != pServerConfigDialog->pSelCertList->pwszIssuer)
{
SetWindowText(pServerConfigDialog->hWndEditIssuer,
pServerConfigDialog->pSelCertList->pwszIssuer);
}
if (NULL != pServerConfigDialog->pSelCertList->pwszExpiration)
{
SetWindowText(pServerConfigDialog->hWndEditExpiration,
pServerConfigDialog->pSelCertList->pwszExpiration);
}
}
}
//
// This function will set the states of MoveUp/MoveDown/Add/Remove/Modify
// Buttons.
//
VOID
PeapServerSetButtonStates ( PPEAP_SERVER_CONFIG_DIALOG pPeapServerDialog )
{
DWORD dwItemCount = 0; //Total number of items
DWORD dwSelItem = 0; //Selected Item
DWORD dwConfigItemCount = 0;
PPEAP_EAP_INFO pEapInfo = NULL;
//
// If All EAP Methods are configured, then disable Add Button
// Else Enable Add Button
// If Any EAP Method is selected then enable Edit and Remove Buttons
// Else Disable Edit and Remove Buttons
// If there is only one EAP method in the list, disable MoveUP and MoveDown
// Else Enable them
//
//Add Button
dwItemCount = PeapEapInfoGetItemCount ( pPeapServerDialog->pEapInfo );
//
// If there is a new user prop, check against that, else the old one.
//
if ( pPeapServerDialog->pNewUserProp )
{
dwConfigItemCount = pPeapServerDialog->pNewUserProp->dwNumberOfEntries;
}
else
{
dwConfigItemCount = pPeapServerDialog->pUserProp->dwNumberOfEntries;
}
if ( dwConfigItemCount != dwItemCount )
{
EnableWindow( pPeapServerDialog->hWndBtnAdd, TRUE );
}
else
{
EnableWindow( pPeapServerDialog->hWndBtnAdd, FALSE );
}
dwSelItem = (DWORD)SendMessage ( pPeapServerDialog->hWndListPeapType,
LB_GETCURSEL,
0,0L);
dwItemCount = (DWORD)SendMessage( pPeapServerDialog->hWndListPeapType,
LB_GETCOUNT,
0,
0L
);
//
// Edit and Remove buttons
//
if ( dwSelItem != LB_ERR )
{
//
// There is an item selected
//
EnableWindow(pPeapServerDialog->hWndBtnRemove, TRUE);
//Default behavior for this Edit button
EnableWindow(pPeapServerDialog->hWndBtnEdit, FALSE);
//
// If there is no config available for EAP method,
// disable the Edit button.
//
pEapInfo =
(PPEAP_EAP_INFO)SendMessage(pPeapServerDialog->hWndListPeapType,
LB_GETITEMDATA,
dwSelItem,
0L
);
if ( pEapInfo && pEapInfo->lpwszConfigClsId )
{
EnableWindow(pPeapServerDialog->hWndBtnEdit, TRUE);
}
}
else
{
EnableWindow(pPeapServerDialog->hWndBtnEdit, FALSE);
EnableWindow(pPeapServerDialog->hWndBtnRemove, FALSE);
}
//
// MoveUp and MoveDown Buttons
//
if ( dwItemCount == 1 )
{
EnableWindow(pPeapServerDialog->hWndBtnMoveUp, FALSE);
EnableWindow(pPeapServerDialog->hWndBtnMoveDown, FALSE);
EnableWindow(pPeapServerDialog->hWndBtnRemove, FALSE);
}
else
{
EnableWindow(pPeapServerDialog->hWndBtnMoveUp, TRUE);
EnableWindow(pPeapServerDialog->hWndBtnMoveDown, TRUE);
}
//
// If the selected item is the first item, we gray out
// MoveUp. Or else we gray out MoveDown.
//
if ( dwSelItem != LB_ERR )
{
if ( dwSelItem == 0 )
{
//
// First item is selected. So disable move up
//
EnableWindow(pPeapServerDialog->hWndBtnMoveUp, FALSE);
}
if ( dwSelItem == dwItemCount-1 )
{
//
// Last Item is selected so diable move down
//
EnableWindow(pPeapServerDialog->hWndBtnMoveDown, FALSE);
}
}
else
{
//
//No items selected
//
EnableWindow(pPeapServerDialog->hWndBtnMoveUp, FALSE);
EnableWindow(pPeapServerDialog->hWndBtnMoveDown, FALSE);
}
}
VOID
PeapServerAddConfiguredEapTypes (
PPEAP_SERVER_CONFIG_DIALOG pPeapServerDialog
)
{
PPEAP_USER_PROP pUserProp;
PEAP_ENTRY_USER_PROPERTIES UNALIGNED * pEntryUserProp = NULL;
PPEAP_EAP_INFO pEapInfo = NULL;
DWORD dwCount = 0;
if ( pPeapServerDialog->pNewUserProp )
{
pUserProp = pPeapServerDialog->pNewUserProp;
}
else
{
pUserProp = pPeapServerDialog->pUserProp;
}
SendMessage( pPeapServerDialog->hWndListPeapType,
LB_RESETCONTENT,
0,
0L);
PeapGetFirstEntryUserProp ( pUserProp,
&pEntryUserProp
);
for ( dwCount =0; dwCount < pUserProp->dwNumberOfEntries; dwCount++)
{
PeapEapInfoFindListNode ( pEntryUserProp->dwEapTypeId,
pPeapServerDialog->pEapInfo,
&pEapInfo
);
if ( pEapInfo )
{
INT_PTR nIndex = 0;
nIndex = SendMessage( pPeapServerDialog->hWndListPeapType,
LB_ADDSTRING,
0,
(LPARAM)pEapInfo->lpwszFriendlyName);
SendMessage ( pPeapServerDialog->hWndListPeapType,
LB_SETITEMDATA,
(WPARAM)nIndex,
(LPARAM)pEapInfo
);
}
PeapGetNextEntryUserProp ( pEntryUserProp,
&pEntryUserProp
);
}
}
BOOL
PeapServerInitDialog(
IN HWND hWnd,
IN LPARAM lParam
)
{
PPEAP_SERVER_CONFIG_DIALOG pPeapServerDialog;
SetWindowLongPtr( hWnd, DWLP_USER, lParam);
pPeapServerDialog = (PPEAP_SERVER_CONFIG_DIALOG)lParam;
pPeapServerDialog ->hWndComboServerName =
GetDlgItem(hWnd, IDC_COMBO_SERVER_NAME);
pPeapServerDialog ->hWndEditFriendlyName=
GetDlgItem(hWnd, IDC_EDIT_FRIENDLY_NAME);
pPeapServerDialog ->hWndEditIssuer=
GetDlgItem(hWnd, IDC_EDIT_ISSUER);
pPeapServerDialog ->hWndEditExpiration=
GetDlgItem(hWnd, IDC_EDIT_EXPIRATION);
pPeapServerDialog ->hWndListPeapType =
GetDlgItem(hWnd, IDC_LIST_PEAP_TYPE);
pPeapServerDialog ->hWndBtnAdd =
GetDlgItem(hWnd, IDC_BTN_ADD);
pPeapServerDialog ->hWndBtnEdit =
GetDlgItem(hWnd, IDC_BTN_EDIT);
pPeapServerDialog ->hWndBtnRemove =
GetDlgItem(hWnd, IDC_BTN_REMOVE);
pPeapServerDialog ->hWndBtnMoveUp =
GetDlgItem(hWnd, IDC_BTN_MOVEUP);
pPeapServerDialog ->hWndBtnMoveDown =
GetDlgItem(hWnd, IDC_BTN_MOVEDOWN);
pPeapServerDialog->hEndEnableFastReconnect =
GetDlgItem(hWnd, IDC_CHECK_ENABLE_FAST_RECONNECT );
if ( NULL == pPeapServerDialog ->pSelCertList )
{
pPeapServerDialog ->pSelCertList =
pPeapServerDialog ->pCertList;
}
InitComboBox(pPeapServerDialog ->hWndComboServerName,
pPeapServerDialog ->pCertList,
pPeapServerDialog ->pSelCertList
);
CheckDlgButton(hWnd, IDC_CHECK_ENABLE_FAST_RECONNECT,
( pPeapServerDialog->pUserProp->dwFlags &
PEAP_USER_FLAG_FAST_ROAMING) ?
BST_CHECKED : BST_UNCHECKED);
PeapDisplayCertInfo(pPeapServerDialog);
//
// First check to see if we are a stand alone server and
// need to reajust our properties.
//
PeapVerifyUserData ( pPeapServerDialog->pEapInfo,
pPeapServerDialog->pUserProp,
&(pPeapServerDialog->pNewUserProp)
);
//
// Add the friendly names of configured EAP Types
// in our list. There should be at least EAP-MSCHAPv2
// configured by default.
//
PeapServerAddConfiguredEapTypes ( pPeapServerDialog );
//
// Preselect the first item in list.
//
SendMessage ( pPeapServerDialog->hWndListPeapType,
LB_SETCURSEL,
0,
0L
);
PeapServerSetButtonStates ( pPeapServerDialog );
return(FALSE);
}
/*
Routine Description:
This routine fills in the config information for PEAP. It invokes
UI depending on fDefault flag. The ConfigInfo for the UI is initialized
by the pNewUserProp structure or pUserProp structure if pNewUserProp is
NULL. If no specific config information is available for the selected
eap, the eap is initialized with no data. If the routine returns
succesfully, pNewUserProp has the new configuration required for all
the selected eaps and for PEAP.
Arguments:
pPeapServerDialog
Structure used to pass config information to and out of the routine.
hWndDlg
handle to window to display the config dialog if required.
fSilent
Invokes no UI if this flag is TRUE.
Return Value:
*/
BOOL
ProcessPeapEapConfigCommand(
PPEAP_SERVER_CONFIG_DIALOG pPeapServerDialog,
HWND hWndDlg,
BOOL fSilent
)
{
BYTE* pbConfigDataIn = NULL;
DWORD dwSizeOfConfigDataIn = 0;
DWORD i = 0;
BYTE* pbData = NULL;
DWORD cbData = 0;
PEAP_USER_PROP *pUserProp = (NULL != pPeapServerDialog->pNewUserProp)
? pPeapServerDialog->pNewUserProp
: pPeapServerDialog->pUserProp;
PEAP_USER_PROP* pOutUserProp =
pPeapServerDialog->pNewUserProp;
PEAP_ENTRY_USER_PROPERTIES* pEntry = NULL;
PEAP_ENTRY_USER_PROPERTIES* pEntryOut;
DWORD dwSize;
//
// Find the config data for this eap in the user properties
// that was passed in.
//
pEntry = PeapGetEapConfigInfo(pUserProp,
pPeapServerDialog->pSelEapInfo->dwTypeId,
&pbConfigDataIn,
&dwSizeOfConfigDataIn);
if(!fSilent)
{
//
// Invoke the configure method for selected eap type
// and if no error is returned, set the new configuration
//
PeapEapInfoInvokeServerConfigUI (
hWndDlg,
pPeapServerDialog->pwszMachineName,
pPeapServerDialog->pSelEapInfo,
pbConfigDataIn,
dwSizeOfConfigDataIn,
&pbData,
&cbData
);
}
//
// If nothing changed in the config just return
//
if( !fSilent
&& ((NULL == pbData)
|| (0 == cbData)))
{
goto done;
}
if(fSilent && (NULL != pEntry))
{
cbData = pEntry->dwSize -
FIELD_OFFSET(PEAP_ENTRY_USER_PROPERTIES, bData);
pbData = LocalAlloc(LPTR, cbData);
if(NULL == pbData)
{
goto done;
}
CopyMemory(pbData, pEntry->bData, cbData);
}
//
// Check to see if this is the first eap that was being configured
// and allocate the out user prop if it was.
//
dwSize = pUserProp->dwSize;
if(NULL != pEntry)
{
ASSERT(dwSize > pEntry->dwSize);
}
//
// Add size for the eap data that will be added
//
dwSize += ((cbData != 0 ) ? RASMAN_ALIGN8(cbData) : 0) +
FIELD_OFFSET(PEAP_ENTRY_USER_PROPERTIES, bData);
//
// Subtract the information being replaced.
//
dwSize -= ((NULL != pEntry) ? pEntry->dwSize : 0);
pOutUserProp = (PEAP_USER_PROP *) LocalAlloc(LPTR, dwSize);
if(NULL == pOutUserProp)
{
goto done;
}
//
// Copy over the eap information in its right place. If the
// selected eap is not found, copy it in the first place
// in the list of user properties.
//
pEntryOut = &pOutUserProp->UserProperties;
CopyMemory(pOutUserProp, pUserProp, sizeof(PEAP_USER_PROP));
pOutUserProp->dwSize = dwSize;
//
// Place the selected eap in the first place.
//
pEntryOut->dwVersion = 1;
pEntryOut->dwEapTypeId = pPeapServerDialog->pSelEapInfo->dwTypeId;
pEntryOut->dwSize =
FIELD_OFFSET(PEAP_ENTRY_USER_PROPERTIES, bData) +
((0 != cbData) ? RASMAN_ALIGN8(cbData) : 0);
CopyMemory(pEntryOut->bData, pbData, cbData);
pEntryOut = (PEAP_ENTRY_USER_PROPERTIES *)
((BYTE *)pEntryOut + pEntryOut->dwSize);
if(NULL == pEntry)
{
pOutUserProp->dwNumberOfEntries = pUserProp->dwNumberOfEntries + 1;
}
pEntry = &pUserProp->UserProperties;
for(i = 0; i < pUserProp->dwNumberOfEntries; i++)
{
//
// Copy over from pUserProp for all eaps except the selected one.
// We copy over the data from pbData for the selected eap. Make
// sure that the copied data is 8 byte aligned.
//
if(pEntry->dwEapTypeId == pPeapServerDialog->pSelEapInfo->dwTypeId)
{
pEntry = (PEAP_ENTRY_USER_PROPERTIES *)
((BYTE *)pEntry + pEntry->dwSize);
continue;
}
else
{
CopyMemory(pEntryOut, pEntry, pEntry->dwSize);
pEntryOut = (PEAP_ENTRY_USER_PROPERTIES *)
((BYTE *)pEntryOut + pEntryOut->dwSize);
pEntry = (PEAP_ENTRY_USER_PROPERTIES *)
((BYTE *)pEntry + pEntry->dwSize);
}
}
LocalFree(pPeapServerDialog->pNewUserProp);
pPeapServerDialog->pNewUserProp = pOutUserProp;
done:
LocalFree(pbData);
return TRUE;
}
/*
Returns:
TRUE: We prrocessed this message.
FALSE: We did not prrocess this message.
Notes:
Response to the WM_COMMAND message (Config UI).
*/
BOOL
PeapServerCommand(
IN PPEAP_SERVER_CONFIG_DIALOG pPeapServerDialog,
IN WORD wNotifyCode,
IN WORD wId,
IN HWND hWndDlg,
IN HWND hWndCtrl
)
{
switch(wId)
{
case IDC_COMBO_SERVER_NAME:
if (CBN_SELCHANGE != wNotifyCode)
{
return(FALSE); // We will not process this message
}
pPeapServerDialog->pSelCertList = (EAPTLS_CERT_NODE *)
SendMessage ( hWndCtrl,
CB_GETITEMDATA,
SendMessage(hWndCtrl,
CB_GETCURSEL,
0,0L
),
0L
);
PeapDisplayCertInfo(pPeapServerDialog);
return(TRUE);
case IDC_BTN_ADD:
//
// If we have come this far then it means that
// the button is enabled. So show the dialog box
// With all the list of EAP Types.
//
{
INT_PTR nRet;
nRet = DialogBoxParam(
GetHInstance(),
MAKEINTRESOURCE(IDD_ADD_EAP),
hWndDlg,
PeapServerAddEapDialogProc,
(LPARAM)pPeapServerDialog);
if ( nRet == IDOK )
{
//
// We have got a new User Prop
//
PeapServerAddConfiguredEapTypes ( pPeapServerDialog );
//
// Preselect the first item in list.
//
SendMessage ( pPeapServerDialog->hWndListPeapType,
LB_SETCURSEL,
0,
0L
);
PeapServerSetButtonStates ( pPeapServerDialog );
}
}
break;
case IDC_LIST_PEAP_TYPE:
if ( LBN_SELCHANGE == wNotifyCode )
{
PeapServerSetButtonStates ( pPeapServerDialog );
break;
}
else if ( LBN_DBLCLK == wNotifyCode )
{
//fall thru
}
else
{
break;
}
case IDC_BTN_EDIT:
//
// Invoke the configuration of the selected item
//
{
DWORD dwSelItemIndex = 0;
PPEAP_EAP_INFO pEapInfo = NULL;
dwSelItemIndex = (DWORD)
SendMessage ( pPeapServerDialog->hWndListPeapType,
LB_GETCURSEL,
0,
0L);
if ( dwSelItemIndex != LB_ERR )
{
pEapInfo = (PPEAP_EAP_INFO)
SendMessage ( pPeapServerDialog->hWndListPeapType,
LB_GETITEMDATA,
dwSelItemIndex,
0L
);
pPeapServerDialog->pSelEapInfo = pEapInfo;
ProcessPeapEapConfigCommand(pPeapServerDialog,
hWndDlg,
FALSE
);
#if 0
PeapEapInfoInvokeServerConfigUI ( hWndDlg,
pPeapServerDialog->pwszMachineName,
pEapInfo
);
#endif
}
}
break;
case IDC_BTN_REMOVE:
//
// Remove item from the list and new user prop and
// repopulate the list and set button states
//
{
PPEAP_USER_PROP pUserProp = NULL;
PPEAP_USER_PROP pNewUserProp = NULL;
PPEAP_EAP_INFO pEapInfo = NULL;
DWORD dwSelItemIndex = 0;
dwSelItemIndex = (DWORD)
SendMessage ( pPeapServerDialog->hWndListPeapType,
LB_GETCURSEL,
0,
0L);
if ( dwSelItemIndex != LB_ERR )
{
pEapInfo = (PPEAP_EAP_INFO)
SendMessage ( pPeapServerDialog->hWndListPeapType,
LB_GETITEMDATA,
dwSelItemIndex,
0L
);
if ( pPeapServerDialog->pNewUserProp )
{
pUserProp = pPeapServerDialog->pNewUserProp;
}
else
{
pUserProp = pPeapServerDialog->pUserProp;
}
PeapRemoveEntryUserProp( pUserProp,
pEapInfo,
&pNewUserProp
);
if ( pNewUserProp )
{
LocalFree ( pPeapServerDialog->pNewUserProp );
pPeapServerDialog->pNewUserProp = pNewUserProp;
PeapServerAddConfiguredEapTypes ( pPeapServerDialog );
//
// Preselect the first item in list.
//
SendMessage ( pPeapServerDialog->hWndListPeapType,
LB_SETCURSEL,
0,
0L
);
PeapServerSetButtonStates ( pPeapServerDialog );
}
}
}
break;
case IDC_BTN_MOVEUP:
case IDC_BTN_MOVEDOWN:
//
// The fact that we've come this far means
// that move up and down are enabled.
//
{
PPEAP_USER_PROP pUserProp = NULL;
PPEAP_USER_PROP pNewUserProp = NULL;
DWORD dwSelItemIndex = 0;
dwSelItemIndex = (DWORD)
SendMessage ( pPeapServerDialog->hWndListPeapType,
LB_GETCURSEL,
0,
0L);
if ( dwSelItemIndex != LB_ERR )
{
if ( pPeapServerDialog->pNewUserProp )
{
pUserProp = pPeapServerDialog->pNewUserProp;
}
else
{
pUserProp = pPeapServerDialog->pUserProp;
}
if ( PeapMoveEntryUserProp ( pUserProp,
dwSelItemIndex,
( (wId==IDC_BTN_MOVEUP)?
TRUE:FALSE
)
) == NO_ERROR
)
{
PeapServerAddConfiguredEapTypes ( pPeapServerDialog );
//
// Setup the new sel index
//
if ( wId == IDC_BTN_MOVEUP )
dwSelItemIndex --;
else
dwSelItemIndex ++;
SendMessage ( pPeapServerDialog->hWndListPeapType,
LB_SETCURSEL,
dwSelItemIndex,
0L
);
PeapServerSetButtonStates ( pPeapServerDialog );
}
}
}
break;
/*
case IDC_COMBO_PEAP_TYPE:
if (CBN_SELCHANGE != wNotifyCode)
{
return(FALSE); // We will not process this message
}
//Fall Through...
case IDC_BUTTON_CONFIGURE:
{
INT nIndex = -1;
nIndex = (INT)SendMessage ( pPeapServerDialog->hWndComboPeapType,
CB_GETCURSEL,
0,0
);
if ( nIndex != -1 )
{
//
// Change the currently selected EAP Type.
//
pPeapServerDialog->pSelEapInfo = (PPEAP_EAP_INFO)
SendMessage ( pPeapServerDialog->hWndComboPeapType,
CB_GETITEMDATA,
(WPARAM)nIndex,
(LPARAM)0
);
if ( pPeapServerDialog->pSelEapInfo->lpwszConfigClsId )
{
EnableWindow(pPeapServerDialog->hWndBtnConfigure, TRUE );
if ( wId == IDC_BUTTON_CONFIGURE )
{
//
// Invoke the configure method for selected eap type and if no error is
// returned, then set the new configuration
//
PeapEapInfoInvokeServerConfigUI ( hWndDlg,
pPeapServerDialog->pwszMachineName,
pPeapServerDialog->pSelEapInfo
);
}
}
else
{
//
// There is no configuration option here.
//
EnableWindow(pPeapServerDialog->hWndBtnConfigure, FALSE );
}
}
else
{
EnableWindow(pPeapServerDialog->hWndBtnConfigure, FALSE );
pPeapServerDialog->pSelEapInfo = NULL;
}
return TRUE;
}
*/
case IDOK:
{
// Setup new PPEAP_USER_PROP here.
//
if ( NULL == pPeapServerDialog->pSelCertList )
{
DisplayResourceError ( hWndDlg, IDS_PEAP_NO_SERVER_CERT );
return TRUE;
}
if ( pPeapServerDialog->pNewUserProp )
{
//
// Copy the cert hash over and we are done
//
CopyMemory( &pPeapServerDialog->pNewUserProp->CertHash,
&(pPeapServerDialog->pSelCertList->Hash),
sizeof(pPeapServerDialog->pNewUserProp->CertHash)
);
}
else
{
pPeapServerDialog->pNewUserProp = (PPEAP_USER_PROP)
LocalAlloc(LPTR, pPeapServerDialog->pUserProp->dwSize);
if ( NULL == pPeapServerDialog->pNewUserProp )
{
EapTlsTrace("LocalAlloc in Command failed and returned %d",
GetLastError());
return FALSE;
}
else
{
CopyMemory ( pPeapServerDialog->pNewUserProp,
pPeapServerDialog->pUserProp,
pPeapServerDialog->pUserProp->dwSize
);
CopyMemory( &(pPeapServerDialog->pNewUserProp->CertHash),
&(pPeapServerDialog->pSelCertList->Hash),
sizeof(pPeapServerDialog->pNewUserProp->CertHash)
);
}
}
if (BST_CHECKED == IsDlgButtonChecked(hWndDlg, IDC_CHECK_ENABLE_FAST_RECONNECT))
{
pPeapServerDialog->pNewUserProp->dwFlags |= PEAP_USER_FLAG_FAST_ROAMING;
}
else
{
pPeapServerDialog->pNewUserProp->dwFlags &= ~PEAP_USER_FLAG_FAST_ROAMING;
}
}
// Fall through
case IDCANCEL:
EndDialog(hWndDlg, wId);
return(TRUE);
default:
return(FALSE);
}
return FALSE;
}
INT_PTR CALLBACK
PeapServerDialogProc(
IN HWND hWnd,
IN UINT unMsg,
IN WPARAM wParam,
IN LPARAM lParam
)
{
PPEAP_SERVER_CONFIG_DIALOG pPeapServerDialog;
switch (unMsg)
{
case WM_INITDIALOG:
return(PeapServerInitDialog(hWnd, lParam));
case WM_HELP:
case WM_CONTEXTMENU:
{
ContextHelp(g_adwHelp, hWnd, unMsg, wParam, lParam);
break;
}
case WM_COMMAND:
pPeapServerDialog = (PPEAP_SERVER_CONFIG_DIALOG)GetWindowLongPtr(hWnd, DWLP_USER);
return(PeapServerCommand(pPeapServerDialog, HIWORD(wParam), LOWORD(wParam),
hWnd, (HWND)lParam));
}
return(FALSE);
}
/////
//// Default credentials UI
////
BOOL
DefaultCredInitDialog(
IN HWND hWnd,
IN LPARAM lParam
)
{
PPEAP_DEFAULT_CRED_DIALOG pDefaultCredDialog;
SetWindowLongPtr( hWnd, DWLP_USER, lParam);
pDefaultCredDialog = (PPEAP_DEFAULT_CRED_DIALOG)lParam;
pDefaultCredDialog->hWndUserName=
GetDlgItem(hWnd, IDC_EDIT_USERNAME);
pDefaultCredDialog->hWndPassword=
GetDlgItem(hWnd, IDC_EDIT_PASSWORD);
pDefaultCredDialog->hWndDomain=
GetDlgItem(hWnd, IDC_EDIT_DOMAIN);
SendMessage(pDefaultCredDialog->hWndUserName,
EM_LIMITTEXT,
UNLEN,
0L
);
SendMessage(pDefaultCredDialog->hWndPassword,
EM_LIMITTEXT,
PWLEN,
0L
);
SendMessage(pDefaultCredDialog->hWndDomain,
EM_LIMITTEXT,
DNLEN,
0L
);
if ( pDefaultCredDialog->PeapDefaultCredentials.wszUserName[0] )
{
SetWindowText( pDefaultCredDialog->hWndUserName,
pDefaultCredDialog->PeapDefaultCredentials.wszUserName
);
}
if ( pDefaultCredDialog->PeapDefaultCredentials.wszPassword[0] )
{
SetWindowText( pDefaultCredDialog->hWndPassword,
pDefaultCredDialog->PeapDefaultCredentials.wszPassword
);
}
if ( pDefaultCredDialog->PeapDefaultCredentials.wszDomain[0] )
{
SetWindowText( pDefaultCredDialog->hWndDomain,
pDefaultCredDialog->PeapDefaultCredentials.wszDomain
);
}
return(FALSE);
}
/*
Returns:
TRUE: We prrocessed this message.
FALSE: We did not prrocess this message.
Notes:
Response to the WM_COMMAND message (Config UI).
*/
BOOL
DefaultCredCommand(
IN PPEAP_DEFAULT_CRED_DIALOG pDefaultCredDialog,
IN WORD wNotifyCode,
IN WORD wId,
IN HWND hWndDlg,
IN HWND hWndCtrl
)
{
switch(wId)
{
case IDOK:
//
//grab info from the fields and set it in
//the logon dialog structure
//
GetWindowText( pDefaultCredDialog->hWndUserName,
pDefaultCredDialog->PeapDefaultCredentials.wszUserName,
UNLEN+1
);
GetWindowText( pDefaultCredDialog->hWndPassword,
pDefaultCredDialog->PeapDefaultCredentials.wszPassword,
PWLEN+1
);
GetWindowText ( pDefaultCredDialog->hWndDomain,
pDefaultCredDialog->PeapDefaultCredentials.wszDomain,
DNLEN+1
);
// Fall through
case IDCANCEL:
EndDialog(hWndDlg, wId);
return(TRUE);
default:
return(FALSE);
}
}
INT_PTR CALLBACK
DefaultCredDialogProc(
IN HWND hWnd,
IN UINT unMsg,
IN WPARAM wParam,
IN LPARAM lParam
)
{
PPEAP_DEFAULT_CRED_DIALOG pDefaultCredDialog;
switch (unMsg)
{
case WM_INITDIALOG:
return(DefaultCredInitDialog(hWnd, lParam));
case WM_HELP:
case WM_CONTEXTMENU:
{
ContextHelp(g_adwHelp, hWnd, unMsg, wParam, lParam);
break;
}
case WM_COMMAND:
pDefaultCredDialog = (PPEAP_DEFAULT_CRED_DIALOG)GetWindowLongPtr(hWnd, DWLP_USER);
return(DefaultCredCommand(pDefaultCredDialog, HIWORD(wParam), LOWORD(wParam),
hWnd, (HWND)lParam));
}
return(FALSE);
}