/* Copyright (c) 1997, Microsoft Corporation, all rights reserved Description: History: Nov 1997: Vijay Baliga created original version. */ #include // Required by windows.h #include // Required by windows.h #include // Required by windows.h #include // Win32 base API's #include #include // For swprintf #include // Required by raseapif.h #include // For RTASSERT #include // For EAPLOGONINFO #include // For ERROR_NO_SMART_CARD_READER #include #include #if WINVER > 0x0500 #include "wzcsapi.h" #endif #include #define SECURITY_WIN32 #include // For GetUserNameExA, CredHandle #include // For CredHandle #include #include #include #include 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); }