554 lines
18 KiB
C
554 lines
18 KiB
C
/*++
|
|
|
|
Copyright (c) 2000, Microsoft Corporation
|
|
|
|
Module Name:
|
|
elutil.c
|
|
|
|
Abstract:
|
|
|
|
Tools and ends
|
|
|
|
|
|
Revision History:
|
|
|
|
sachins, Apr 23 2001, Created
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
//
|
|
// EAPOLUI function mapping
|
|
//
|
|
|
|
EAPOLUIFUNCMAP EapolUIFuncMap[NUM_EAPOL_DLG_MSGS]=
|
|
{
|
|
{EAPOLUI_GET_USERIDENTITY, ElGetUserIdentityDlgWorker, ElGetUserIdentityDlgWorker, TRUE, SID_GetUserIdentity},
|
|
{EAPOLUI_GET_USERNAMEPASSWORD, ElGetUserNamePasswordDlgWorker, NULL, TRUE, SID_GetUserNamePassword},
|
|
{EAPOLUI_INVOKEINTERACTIVEUI, ElInvokeInteractiveUIDlgWorker, NULL, TRUE, SID_InvokeInteractiveUI},
|
|
{EAPOLUI_EAP_NOTIFICATION, NULL, NULL, TRUE, 0},
|
|
{EAPOLUI_REAUTHENTICATE, NULL, NULL, FALSE, 0},
|
|
{EAPOLUI_CREATEBALLOON, NULL, NULL, TRUE, SID_AuthenticationFailed},
|
|
{EAPOLUI_CLEANUP, NULL, NULL, FALSE, 0},
|
|
{EAPOLUI_DUMMY, NULL, NULL, FALSE, 0}
|
|
};
|
|
|
|
|
|
//
|
|
// ElCanShowBalloon
|
|
//
|
|
// Description:
|
|
// Function called by netshell, to query if balloon is to be displayed
|
|
//
|
|
// Arguments:
|
|
// pGUIDConn - Interface GUID string
|
|
// pszConnectionName - Connection Name
|
|
// pszBalloonText - Pointer to text to be display
|
|
// pszCookie - EAPOL specific information
|
|
//
|
|
// Return values:
|
|
// S_OK - Display balloon
|
|
// S_FALSE - Do not display balloon
|
|
//
|
|
|
|
HRESULT
|
|
ElCanShowBalloon (
|
|
IN const GUID * pGUIDConn,
|
|
IN const WCHAR * pszConnectionName,
|
|
IN OUT BSTR * pszBalloonText,
|
|
IN OUT BSTR * pszCookie
|
|
)
|
|
{
|
|
EAPOL_EAP_UI_CONTEXT *pEapolUIContext = NULL;
|
|
DWORD dwIndex = 0;
|
|
DWORD dwSessionId = 0;
|
|
WCHAR cwszBuffer[MAX_BALLOON_MSG_LEN];
|
|
WCHAR wsSSID[MAX_SSID_LEN+1];
|
|
DWORD dwSizeOfSSID = 0;
|
|
BYTE *bSSID = NULL;
|
|
WCHAR *pszFinalBalloonText = NULL;
|
|
DWORD dwFinalStringId = 0;
|
|
DWORD dwRetCode = NO_ERROR;
|
|
DWORD dwRetCode1 = NO_ERROR;
|
|
HRESULT hr = S_OK;
|
|
|
|
do
|
|
{
|
|
pEapolUIContext = (EAPOL_EAP_UI_CONTEXT *)(*pszCookie);
|
|
|
|
if (!ProcessIdToSessionId (GetCurrentProcessId (), &dwSessionId))
|
|
{
|
|
dwRetCode = GetLastError ();
|
|
break;
|
|
}
|
|
|
|
if (pEapolUIContext->dwSessionId != dwSessionId)
|
|
{
|
|
// Not intended for this session
|
|
dwRetCode = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
dwSizeOfSSID = pEapolUIContext->dwSizeOfSSID;
|
|
bSSID = pEapolUIContext->bSSID;
|
|
|
|
for (dwIndex=0; dwIndex < NUM_EAPOL_DLG_MSGS; dwIndex++)
|
|
{
|
|
if (pEapolUIContext->dwEAPOLUIMsgType ==
|
|
EapolUIFuncMap[dwIndex].dwEAPOLUIMsgType)
|
|
{
|
|
if (EapolUIFuncMap[dwIndex].fShowBalloon)
|
|
{
|
|
TRACE1 (RPC, "ElCanShowBalloon: Response function found, msg (%ld)",
|
|
EapolUIContext->dwEAPOLUIMsgType);
|
|
|
|
dwFinalStringId = EapolUIFuncMap[dwIndex].dwStringID;
|
|
|
|
// Verify is balloon indeed needs to be popped up OR
|
|
// can purpose be achieved without user involvement
|
|
|
|
if (EapolUIFuncMap[dwIndex].EapolUIVerify != NULL)
|
|
{
|
|
// Indicate that it is verification cycle, by passing
|
|
// NULL connection name, to indicate no display !
|
|
dwRetCode1 = EapolUIFuncMap[dwIndex].EapolUIVerify (
|
|
NULL,
|
|
pEapolUIContext
|
|
);
|
|
if (dwRetCode1 == ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION)
|
|
{
|
|
// Continue with show balloon
|
|
dwRetCode = NO_ERROR;
|
|
}
|
|
else
|
|
{
|
|
if (dwRetCode1 != NO_ERROR)
|
|
{
|
|
switch (dwRetCode1)
|
|
{
|
|
case ERROR_NO_EAPTLS_CERTIFICATE:
|
|
// No certificate found
|
|
// Pop balloon accordingly
|
|
dwFinalStringId = SID_NoCertificateFound;
|
|
// Since we wont take action on this
|
|
// balloon being clicked, flag it as
|
|
// EAPOLUI_DUMMY
|
|
pEapolUIContext->dwEAPOLUIMsgType = EAPOLUI_DUMMY;
|
|
dwRetCode = NO_ERROR;
|
|
break;
|
|
|
|
case ERROR_NO_SMART_CARD_READER:
|
|
// No smartcard reader found
|
|
dwFinalStringId = SID_NoSmartCardReaderFound;
|
|
// Since we wont take action on this
|
|
// balloon being clicked, flag it as
|
|
// EAPOLUI_DUMMY
|
|
pEapolUIContext->dwEAPOLUIMsgType = EAPOLUI_DUMMY;
|
|
dwRetCode = NO_ERROR;
|
|
break;
|
|
|
|
default:
|
|
// Continue with show balloon for any
|
|
// error in verification function
|
|
dwRetCode = NO_ERROR;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// No need to process more.
|
|
// Response has been sent successfully
|
|
// without user intervention
|
|
dwRetCode = ERROR_CAN_NOT_COMPLETE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (dwFinalStringId != 0)
|
|
{
|
|
// Load string based on Id
|
|
if (dwFinalStringId <= SID_NoCertificateFound)
|
|
{
|
|
if (LoadString (GetModuleHandle(cszModuleName), dwFinalStringId, cwszBuffer, MAX_BALLOON_MSG_LEN) == 0)
|
|
{
|
|
dwRetCode = GetLastError ();
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (LoadString (WZCGetSPResModule(), dwFinalStringId, cwszBuffer, MAX_BALLOON_MSG_LEN) == 0)
|
|
{
|
|
dwRetCode = GetLastError ();
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Append the network-name / SSID
|
|
if (dwSizeOfSSID != 0)
|
|
{
|
|
if (0 == MultiByteToWideChar (
|
|
CP_ACP,
|
|
0,
|
|
bSSID,
|
|
dwSizeOfSSID,
|
|
wsSSID,
|
|
MAX_SSID_LEN+1))
|
|
{
|
|
dwRetCode = GetLastError();
|
|
break;
|
|
}
|
|
|
|
if ((pszFinalBalloonText = MALLOC ((wcslen(cwszBuffer)+1+ dwSizeOfSSID)*sizeof(WCHAR))) == NULL)
|
|
{
|
|
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
wcscpy (pszFinalBalloonText, cwszBuffer);
|
|
memcpy ((BYTE *)(pszFinalBalloonText + wcslen(cwszBuffer)), (BYTE *)wsSSID, dwSizeOfSSID*sizeof(WCHAR));
|
|
pszFinalBalloonText[wcslen(cwszBuffer)+dwSizeOfSSID] = L'\0';
|
|
}
|
|
else
|
|
{
|
|
// Append a "." (period)
|
|
if ((pszFinalBalloonText = MALLOC ((wcslen(cwszBuffer) + 3)*sizeof(WCHAR))) == NULL)
|
|
{
|
|
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
wcscpy (pszFinalBalloonText, cwszBuffer);
|
|
pszFinalBalloonText[wcslen(cwszBuffer)+1] = L'.';
|
|
pszFinalBalloonText[wcslen(cwszBuffer)+2] = L'\0';
|
|
}
|
|
|
|
if (*pszBalloonText)
|
|
{
|
|
if (!SysReAllocString (pszBalloonText, pszFinalBalloonText))
|
|
{
|
|
dwRetCode = ERROR_CAN_NOT_COMPLETE;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*pszBalloonText = SysAllocString (pszFinalBalloonText);
|
|
if (*pszBalloonText == NULL)
|
|
{
|
|
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Display the string that was passed
|
|
}
|
|
|
|
// If notification message, check to see if explorer
|
|
// needs to be started off
|
|
if (pEapolUIContext->dwEAPOLUIMsgType == EAPOLUI_EAP_NOTIFICATION)
|
|
{
|
|
// Parse text message
|
|
// Attach to cookie
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TRACE1 (RPC, "ElCanShowBalloon: No balloon display, msg (%ld)",
|
|
EapolUIContext.dwEAPOLUIMsgType);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
while (FALSE);
|
|
|
|
if (pszFinalBalloonText != NULL)
|
|
{
|
|
FREE (pszFinalBalloonText);
|
|
}
|
|
|
|
if (dwRetCode != NO_ERROR)
|
|
{
|
|
hr = S_FALSE;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
//
|
|
// ElOnBalloonClick
|
|
//
|
|
// Description:
|
|
//
|
|
// Function called by netshell, in response to a balloon click
|
|
//
|
|
// Arguments:
|
|
// pGUIDConn - Interface GUID string
|
|
// szCookie - EAPOL specific information
|
|
//
|
|
// Return values:
|
|
// S_OK - No error
|
|
// S_FALSE - Error
|
|
//
|
|
|
|
HRESULT
|
|
ElOnBalloonClick (
|
|
IN const GUID * pGUIDConn,
|
|
IN const WCHAR * pszConnectionName,
|
|
IN const BSTR szCookie
|
|
)
|
|
{
|
|
EAPOL_EAP_UI_CONTEXT *pEapolUIContext = NULL;
|
|
DWORD dwIndex = 0;
|
|
DWORD dwSessionId = 0;
|
|
DWORD dwRetCode = NO_ERROR;
|
|
WCHAR *pwszConnectionName = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
do
|
|
{
|
|
pEapolUIContext = (EAPOL_EAP_UI_CONTEXT *)szCookie;
|
|
pwszConnectionName = (WCHAR *)pszConnectionName;
|
|
|
|
for (dwIndex=0; dwIndex < NUM_EAPOL_DLG_MSGS; dwIndex++)
|
|
{
|
|
if (pEapolUIContext->dwEAPOLUIMsgType ==
|
|
EapolUIFuncMap[dwIndex].dwEAPOLUIMsgType)
|
|
{
|
|
if (EapolUIFuncMap[dwIndex].EapolUIFunc)
|
|
{
|
|
TRACE1 (RPC, "ElOnBalloonClick: Response function found, msg (%ld)",
|
|
EapolUIContext->dwEAPOLUIMsgType);
|
|
// Cleanup any previous dialogs for this interface
|
|
if ((dwRetCode =
|
|
ElDialogCleanup (
|
|
(WCHAR *)pszConnectionName,
|
|
szCookie
|
|
)) != NO_ERROR)
|
|
{
|
|
TRACE0 (RPC, "ElOnBalloonClick: Error in dialog cleanup");
|
|
break;
|
|
}
|
|
|
|
if ((dwRetCode =
|
|
EapolUIFuncMap[dwIndex].EapolUIFunc (
|
|
pwszConnectionName,
|
|
pEapolUIContext
|
|
)) != NO_ERROR)
|
|
{
|
|
TRACE1 (RPC, "ElOnBalloonClick: Response function failed with error %ld",
|
|
dwRetCode);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TRACE1 (RPC, "ElOnBalloonClick: No response function, msg (%ld)",
|
|
EapolUIContext.dwEAPOLUIMsgType);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
while (FALSE);
|
|
|
|
hr = HRESULT_FROM_NT (dwRetCode);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//
|
|
// ElSecureEncodePw
|
|
//
|
|
// Description:
|
|
//
|
|
// Encrypt password locally using user-ACL
|
|
//
|
|
|
|
DWORD
|
|
ElSecureEncodePw (
|
|
IN PWCHAR *ppwszPassword,
|
|
OUT DATA_BLOB *pDataBlob
|
|
)
|
|
{
|
|
DWORD dwRetCode = NO_ERROR;
|
|
DATA_BLOB blobIn, blobOut;
|
|
|
|
do
|
|
{
|
|
blobIn.cbData = (wcslen (*ppwszPassword) + 1)*sizeof(WCHAR);
|
|
blobIn.pbData = (BYTE *)*ppwszPassword;
|
|
|
|
if (!CryptProtectData (
|
|
&blobIn,
|
|
L"",
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
&blobOut))
|
|
{
|
|
dwRetCode = GetLastError ();
|
|
break;
|
|
}
|
|
|
|
// copy over blob to password
|
|
|
|
if (pDataBlob->pbData != NULL)
|
|
{
|
|
FREE (pDataBlob->pbData);
|
|
pDataBlob->pbData = NULL;
|
|
pDataBlob->cbData = 0;
|
|
}
|
|
|
|
pDataBlob->pbData = MALLOC (blobOut.cbData);
|
|
if (pDataBlob->pbData == NULL)
|
|
{
|
|
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
memcpy (pDataBlob->pbData, blobOut.pbData, blobOut.cbData);
|
|
pDataBlob->cbData = blobOut.cbData;
|
|
}
|
|
while (FALSE);
|
|
|
|
if (blobOut.pbData != NULL)
|
|
{
|
|
LocalFree (blobOut.pbData);
|
|
}
|
|
|
|
if (dwRetCode != NO_ERROR)
|
|
{
|
|
if (pDataBlob->pbData != NULL)
|
|
{
|
|
FREE (pDataBlob->pbData);
|
|
pDataBlob->pbData = NULL;
|
|
pDataBlob->cbData = 0;
|
|
}
|
|
}
|
|
|
|
return dwRetCode;
|
|
}
|
|
|
|
|
|
//
|
|
// ElQueryConnectionStatusText
|
|
//
|
|
// Description:
|
|
//
|
|
// Function called by netshell, to query appropriate text for 802.1X states
|
|
//
|
|
// Arguments:
|
|
// pGUIDConn - Interface GUID string
|
|
// ncs - NETCON_STATUS for the interface
|
|
// pszStatusText - Detailed 802.1X status to be displayed
|
|
//
|
|
// Return values:
|
|
// S_OK - No error
|
|
// S_FALSE - Error
|
|
//
|
|
|
|
HRESULT
|
|
ElQueryConnectionStatusText (
|
|
IN const GUID * pGUIDConn,
|
|
IN const NETCON_STATUS ncs,
|
|
IN OUT BSTR * pszStatusText
|
|
)
|
|
{
|
|
WCHAR wszGuid[GUID_STRING_LEN_WITH_TERM];
|
|
WCHAR cwszBuffer[MAX_BALLOON_MSG_LEN];
|
|
EAPOL_INTF_STATE EapolIntfState = {0};
|
|
DWORD dwStringId = 0;
|
|
DWORD dwRetCode = NO_ERROR;
|
|
HRESULT hr = S_OK;
|
|
|
|
do
|
|
{
|
|
ZeroMemory ((PVOID)&EapolIntfState, sizeof(EAPOL_INTF_STATE));
|
|
StringFromGUID2 (pGUIDConn, wszGuid, GUID_STRING_LEN_WITH_TERM);
|
|
|
|
// Query current EAPOL state
|
|
if ((dwRetCode = WZCEapolQueryState (
|
|
NULL,
|
|
wszGuid,
|
|
&EapolIntfState
|
|
)) != NO_ERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// Assign appropriate display string
|
|
switch (EapolIntfState.dwEapUIState)
|
|
{
|
|
case 0:
|
|
if (EapolIntfState.dwState == EAPOLSTATE_ACQUIRED)
|
|
{
|
|
dwStringId = SID_ContactingServer;
|
|
}
|
|
break;
|
|
case EAPUISTATE_WAITING_FOR_IDENTITY:
|
|
dwStringId = SID_AcquiringIdentity;
|
|
break;
|
|
case EAPUISTATE_WAITING_FOR_UI_RESPONSE:
|
|
dwStringId = SID_UserResponse;
|
|
break;
|
|
}
|
|
|
|
if (dwStringId != 0)
|
|
{
|
|
// Load string based on Id
|
|
if (dwStringId <= SID_NoCertificateFound)
|
|
{
|
|
if (LoadString (GetModuleHandle(cszModuleName), dwStringId, cwszBuffer, MAX_BALLOON_MSG_LEN) == 0)
|
|
{
|
|
dwRetCode = GetLastError ();
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (LoadString (WZCGetSPResModule(), dwStringId, cwszBuffer, MAX_BALLOON_MSG_LEN) == 0)
|
|
{
|
|
dwRetCode = GetLastError ();
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (*pszStatusText)
|
|
{
|
|
if (!SysReAllocString (pszStatusText, cwszBuffer))
|
|
{
|
|
dwRetCode = ERROR_CAN_NOT_COMPLETE;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*pszStatusText = SysAllocString (cwszBuffer);
|
|
if (*pszStatusText == NULL)
|
|
{
|
|
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Indicate to netshell that it need not process this response
|
|
hr = S_FALSE;
|
|
}
|
|
}
|
|
while (FALSE);
|
|
|
|
if (dwRetCode != NO_ERROR)
|
|
hr = HRESULT_FROM_NT (dwRetCode);
|
|
|
|
WZCEapolFreeState (&EapolIntfState);
|
|
return hr;
|
|
}
|
|
|