2025-11-28 00:35:46 +09:00

579 lines
19 KiB
C

// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
#ifndef _SAMPLE_CLIENT_EAPMETHOD_H_
#define _SAMPLE_CLIENT_EAPMETHOD_H_
#pragma once
#include <windows.h>
#include "eaptypes.h"
#include "eapmethodtypes.h"
#include "eapmethodpeerapis.h"
#include "lmcons.h" // <UNLEN, PWLEN>
/// UI dialog shown after receiving EAP-Challenge.
const WCHAR STRING_UI_ALLOW_AUTH[] = L"You are being authenticated by a Sample EAP provider.";
/// UI dialog shown after receiving EAP-Challenge.
const size_t STRING_LENGTH_UI_ALLOW_AUTH = sizeof(STRING_UI_ALLOW_AUTH);
/// UI context that we pass back for successful UI interactions.
const WCHAR STRING_UI_SUCCESS[] = L"OK";
/// Buffer length (in bytes) of UI context that we pass back for successful
/// UI interactions.
const size_t STRING_LENGTH_UI_SUCCESS = sizeof(STRING_UI_SUCCESS);
/// The title of the UI displayed for interactive authentication.
const WCHAR STRING_INTERACTIVE_UI_TITLE[] = L"EAP sample";
/// Buffer length (in bytes) of the title of the UI displayed for interactive
/// authentication.
const size_t STRING_LENGTH_INTERACTIVE_UI_TITLE = sizeof(STRING_INTERACTIVE_UI_TITLE);
/// Following are required for registering Eap Peer Method with EapHost.
const wchar_t peerFriendlyName[] = L"PeerFriendlyName";
const wchar_t peerDllPath[] = L"PeerDllPath";
const wchar_t properties[] = L"Properties";
const wchar_t peerInvokeUserNameDialog[] = L"PeerInvokeUsernameDialog";
const wchar_t peerInvokePasswordDialog[] = L"PeerInvokePasswordDialog";
const wchar_t peerFriendlyNameValue[] = L"SdkPeerEapMethod";
const DWORD propertiesValue = 0x280000; ///< eapPropMppeEncryption (0x80000) & eapPropSupportsConfig (0x200000)
const wchar_t peerMethodDllName[] = L"ClientSdkMethodDll.dll";
/// A named constant for the credential input field struct size.
static const DWORD CRED_FIELD_SIZE = sizeof(EAP_CONFIG_INPUT_FIELD_DATA);
/// The credential input fields needed for this method to authenticate users.
static EAP_CONFIG_INPUT_FIELD_DATA defaultCredentialInputFields[] =
{
{
CRED_FIELD_SIZE, ///< Size of this structure.
EapConfigInputUsername, ///< This element's field type.
EAP_CONFIG_INPUT_FIELD_PROPS_DEFAULT, ///< Desired EAP_CONFIG_FLAG values.
L"User name:", ///< Label/name for this field.
L"", ///< Data entered by the user for this field. (When passing this list of fields back to the caller, leave this value blank.)
1, ///< Minimum length (in bytes) for valid user data.
UNLEN + 1 ///< Maximum length (in bytes) for valid user data.
},
{
CRED_FIELD_SIZE, ///< Size of this structure.
EapConfigInputPassword, ///< This element's field type.
EAP_CONFIG_INPUT_FIELD_PROPS_DEFAULT, ///< Desired EAP_CONFIG_FLAG values.
L"Password:", ///< Label/name for this field.
L"", ///< Data entered by the user for this field. (When passing this list of fields back to the caller, leave this value blank.)
0, ///< Minimum length (in bytes) for valid user data.
PWLEN + 1 ///< Maximum length (in bytes) for valid user data.
},
};
/// A credential fields array, used when passing the credential fields from
/// this Eap Peer Method <--> EapHost <--> the Eap Supplicant <--> WinLogon.
static const EAP_CONFIG_INPUT_FIELD_ARRAY defaultCredentialInputArray =
{
1, ///< Version
2, ///< Number of fields in the array buffer
defaultCredentialInputFields ///< Pointer to the array of input fields needed.
};
/// Enum: States within the EAP state machines used by this EAP Peer Dll.
typedef enum _MYSTATE
{
MYSTATE_Initial,
MYSTATE_InteractiveUI,
MYSTATE_AfterUserOK,
MYSTATE_Done
} MYSTATE;
/// This structure is used to helps pass the user's username & password
/// between the interactive UI dialog & EAP Method.
typedef struct _EAP_NAME_DIALOG
{
WCHAR awszIdentity[ UNLEN + 1 ]; ///< A string buffer which will contain the authenticating user's username.
WCHAR awszPassword[ PWLEN + 1 ]; ///< A string buffer which will contain the authenticating user's password.
} EAP_NAME_DIALOG;
/// This structure is used to helps pass the Connection Data between
/// EapMethod and EapHost.
typedef struct _CONN_DATA_BLOB
{
DWORD eapTypeId;
WCHAR awszData[PATHLEN + 1];
}CONN_DATA_BLOB;
/// This structure is used to helps pass the User Data between
/// EapMethod and EapHost.
typedef struct _USER_DATA_BLOB
{
DWORD eapTypeId;
EAP_NAME_DIALOG eapUserNamePassword;
}USER_DATA_BLOB;
/**
* EAP working buffer.
*
* This structure contains all persistent data that the EAP protocol needs to
* operate. The data buffer is created inside EapPeerBeginSession(),
* persists through the entire authentication session, and is released inside
* EapPeerEndSession().
*/
typedef struct _EAPCB
{
LPVOID pWorkBuffer; ///< Pointer to self -- a pointer to the memory buffer containing this instance of the structure.
DWORD fFlags; ///< One or more flags that quantify the authentication process.
MYSTATE EapState; ///< Current state within EAP state machine.
DWORD dwResult; ///< The overall result of the authentication attempt.
BOOL ClientOK;
EapAttributes* pEapAttributes;
HANDLE hTokenImpersonateUser;
DWORD dwSizeofConnectionData;
PBYTE pConnectionData;
DWORD dwSizeofUserData;
PBYTE pUserData;
DWORD dwMaxSendPacketSize;
CHAR aszIdentity[ UNLEN + 1 ]; ///< A string buffer which will contain the authenticating user's username, once it is known.
CHAR aszPassword[ PWLEN + 1 ]; ///< A string buffer which will contain the authenticating user's password, once it is known.
BYTE bRecvPacketId; ///< The EAP Identifier from the last packet received.
PBYTE pDataFromInteractiveUI; ///< A buffer that will contain data from interactive UI displayed to the user.
DWORD dwSizeOfDataFromInteractiveUI; ///< The byte length of the buffer containing interactive UI data.
DWORD dwSizeOfUIContext; ///< The byte length of the buffer containing UI Context.
PBYTE pUIContext; ///< A buffer that will contain UI context data.
EapAttributes* pMPPEKeyAttributes; ///< Local pointer to the MPPE key EAP attributes generated by this EAP provider after a successful authentication transaction has been performed.
EapAttribute *pFakeAttribute;
}EAPCB;
//
// EAP Functions whose function pointer is returned back in EapPeerGetInfo().
//
DWORD WINAPI SdkEapPeerInitialize(OUT EAP_ERROR** pEapError);
DWORD WINAPI SdkEapPeerBeginSession(
IN DWORD dwFlags,
IN const EapAttributes* const pAttributeArray,
IN HANDLE hTokenImpersonateUser,
IN DWORD dwSizeofConnectionData,
IN BYTE* pConnectionData,
IN DWORD dwSizeofUserData,
IN BYTE* pUserData,
IN DWORD dwMaxSendPacketSize,
OUT EAP_SESSION_HANDLE* pSessionHandle,
OUT EAP_ERROR** ppEapError
);
DWORD WINAPI SdkEapPeerGetIdentity(
IN DWORD flags,
IN DWORD dwSizeofConnectionData,
IN const BYTE* pConnectionData,
IN DWORD dwSizeofUserData,
IN const BYTE* pUserData,
IN HANDLE hTokenImpersonateUser,
OUT BOOL* pfInvokeUI,
IN OUT DWORD* pdwSizeOfUserDataOut,
OUT BYTE** ppUserDataOut,
OUT __out LPWSTR* ppwszIdentity,
OUT EAP_ERROR** ppEapError
);
// A method exports either EapPeerGetIdentity (and EapPeerInvokeIdentityUI) or
// exports EapPeerSetCredentials (and sets the InvokeUserNameDlg regkey). The
// registry key controls which of the two apis will get called.
DWORD WINAPI SdkEapPeerSetCredentials(
IN EAP_SESSION_HANDLE sessionHandle,
IN __in LPWSTR pwszIdentity,
IN __in LPWSTR pwszPassword,
OUT EAP_ERROR** pEapError
);
DWORD WINAPI SdkEapPeerProcessRequestPacket(
IN EAP_SESSION_HANDLE sessionHandle,
IN DWORD cbReceivePacket,
IN EapPacket* pReceivePacket,
OUT EapPeerMethodOutput* pEapOutput,
OUT EAP_ERROR** pEapError
);
DWORD WINAPI SdkEapPeerGetResponsePacket(
IN EAP_SESSION_HANDLE sessionHandle,
IN OUT DWORD *pcbSendPacket,
OUT EapPacket* pSendPacket,
OUT EAP_ERROR** pEapError
);
// This will get called either when a method says that it has completed auth.
// or when the lower layer receives an alternative result.
DWORD WINAPI SdkEapPeerGetResult(
IN EAP_SESSION_HANDLE sessionHandle,
IN EapPeerMethodResultReason reason,
OUT EapPeerMethodResult* ppResult,
OUT EAP_ERROR** pEapError
);
DWORD WINAPI SdkEapPeerGetUIContext(
IN EAP_SESSION_HANDLE sessionHandle,
OUT DWORD* dwSizeOfUIContextData,
OUT BYTE** pUIContextData,
OUT EAP_ERROR** pEapError
);
DWORD WINAPI SdkEapPeerSetUIContext(
IN EAP_SESSION_HANDLE sessionHandle,
IN DWORD dwSizeOfUIContextData,
IN const BYTE* pUIContextData,
OUT EapPeerMethodOutput* pEapOutput,
OUT EAP_ERROR** pEapError
);
DWORD WINAPI SdkEapPeerGetResponseAttributes(
IN EAP_SESSION_HANDLE sessionHandle,
OUT EapAttributes* pAttribs,
OUT EAP_ERROR** pEapError
);
DWORD WINAPI SdkEapPeerSetResponseAttributes(
IN EAP_SESSION_HANDLE sessionHandle,
IN EapAttributes* pAttribs,
OUT EapPeerMethodOutput* pEapOutput,
OUT EAP_ERROR** pEapError
);
DWORD WINAPI SdkEapPeerEndSession(
IN EAP_SESSION_HANDLE sessionHandle,
OUT EAP_ERROR** pEapError
);
DWORD WINAPI SdkEapPeerShutdown(OUT EAP_ERROR** pEapError);
//
// Helper Functions
//
/**
* MakeResponseMessage() helper function: Construct a response message
*
* This function constructs the EAP provider's response to the received
* EAP-Challenge packet.
*
*
* @param pwb [in] Pointer to the work buffer.
*
* @param pSendBuf [out] Pointer to a EapPacket structure.
*
* @param cbSendBuf [out] Specifies the size, in bytes, of the buffer
* pointed to by pSendBuf.
*
*
* @return If the function succeeds, the return value is NO_ERROR.
*/
DWORD MakeResponseMessage(
IN EAPCB* pwb,
IN DWORD * pcbSendBuf,
OUT EapPacket * pSendBuf
);
/**
* GetIdentity() helper function: Get the username & password for the
* user to be authenticated.
*
* This function obtains credentials for the user being authenticated.
* It display UI requesting the username & password.
*
*
* @param hwndParent [in] Handle to the parent window for the
* user interface dialog.
*
* @param pUserDataIn [in] Pointer to the user-specific data.
*
*
* @param dwSizeOfUserDataIn [in] Specifies the size of the
* user-specific data currently stored.
*
* @param ppUserDataOut [out] Pointer to a pointer that, on
* successful return, points to the
* identity data for the user.
*
* @param pdwSizeOfUserDataOut [out] Pointer to a DWORD variable that
* receives the size of the data pointed
* to by the ppUserDataOut parameter.
*
*
* @return If the function succeeds, the return value is NO_ERROR.
*/
DWORD
GetIdentity(
IN HWND hwndParent,
IN BYTE* pUserDataIn,
IN DWORD dwSizeOfUserDataIn,
OUT BYTE** ppUserDataOut,
OUT DWORD* pdwSizeOfUserDataOut,
OUT __out LPWSTR* ppwszIdentityOut
);
DWORD GetConfigData(
IN HWND hwndParent,
IN BYTE* pConnectionDataIn,
IN DWORD dwSizeOfConnectionDataIn,
OUT BYTE** ppConnectionDataOut,
OUT DWORD* dwSizeOfConnectionDataOut
);
//---------------------------------------------------------------------------
//
// Dialog routines.
//
//---------------------------------------------------------------------------
/**
* GetUsernameAndPassword() helper function: Display user credentials UI.
*
* This function displays an interactive UI (the IDD_IDENTITY_DIALOG dialog box)
* requesting the user to enter their username and password.
*
*
* @param hwndParent [in] Handle to the parent window for the
* user interface dialog.
*
* @param pEapNameDialog [in] Pointer to an EAP_NAME_DIALOG structure
* that, on successful return, will be filled
* in with the user's username & password.
* The caller is responsible for allocating
* and freeing this buffer.
*
*
* @return If the function succeeds, the return value is NO_ERROR.
*/
DWORD GetUsernameAndPassword(
IN HWND hwndParent,
IN USER_DATA_BLOB* pEapUserData
);
/**
* This function handles Windows messages sent to the username/password UI
* dialog box. It is called by the Windows UI subsystem. *
*
* @param hWnd [in] Handle to the dialog box.
*
* @param unMsg [in] Specifies the message. Messages supported:
* \li WM_INITDIALOG -- Initialize the dialog box.
* \li WM_COMMAND -- The user has clicked on a
* menu, control, or has used an accelerator
* key.
*
* @param wParam [in] Specifies additional message-specific
* information.
*
* @param lParam [in] Specifies additional message-specific
* information.
*
*
* @return The dialog box procedure should return TRUE if it processed the
* message, and FALSE if it did not. If the dialog box procedure
* returns FALSE, the dialog manager performs the default dialog
* operation in response to the message.
*/
INT_PTR CALLBACK UsernameDialogProc(
IN HWND hWnd,
IN UINT unMsg,
IN WPARAM wParam,
IN LPARAM lParam
);
/**
* UsernameDialogProc() helper function: initialize the username dialog.
*
* This function handles the WM_INITDIALOG message, by initializing the
* username dialog.
*
*
* @param hWnd [in] Handle to the dialog box.
*
* @param lParam [in] Specifies additional message-specific
* information.
*
*
* @return FALSE, to prevent Windows from setting the default keyboard focus.
*/
BOOL InitUsernameDialog(
IN HWND hWnd,
IN LPARAM lParam
);
/**
*
* This function handles the WM_COMMAND message, by saving any data the user
* has entered into the text fields of the username dialog.
*
* @param pEapNameDialog [in] Pointer to an EAP_NAME_DIALOG structure
* that, on successful return, will be filled
* in with the user's username & password. This
* buffer must be allocated before this
* function is called.
*
* @param wId [in] The identifier of the menu item, control,
* or accelerator. Supported identifiers:
* \li IDOK - the dialog's OK button. The
* user's credentials will be saved.
* \li IDCANCEL - the dialog's Cancel button.
*
* @param hWndDlg [in] Handle to the dialog box.
*
*
* @return TRUE if we processed this message; FALSE if we did not process
* this message.
*/
BOOL UsernameCommand(
IN USER_DATA_BLOB* pEapUserData,
IN WORD wId,
IN HWND hWndDlg
);
DWORD
GetConnectionData(
IN HWND hwndParent,
IN CONN_DATA_BLOB* pEapConfigData
);
INT_PTR CALLBACK
ConnectionDialogProc(
IN HWND hWnd,
IN UINT unMsg,
IN WPARAM wParam,
IN LPARAM lParam
);
BOOL
InitConnectionDialog(
IN HWND hWnd,
IN LPARAM lParam
);
BOOL
ConnectionCommand(
IN CONN_DATA_BLOB* pEapConfigData,
IN WORD wId,
IN HWND hWndDlg
);
/**
* MakeMPPEKeyAttributes() helper function: Build MPPE Key attributes.
*
* @param pwb [in] Pointer to the work buffer.
*
* @return If the function succeeds, the return value is NO_ERROR.
*/
DWORD MakeMPPEKeyAttributes(
IN EAPCB * pwb
);
/**
* FillMppeKeyAttribute() helper function: Construct MPPE Key attributes.
*
* This function constructs MPPE encryption key attributes and saves them
* into the EAPCB work buffer.
*
* @return If the function succeeds, the return value is NO_ERROR.
*/
DWORD FillMppeKeyAttribute(IN EAPCB *pwb,
IN BYTE *&bBuffer,
IN DWORD pattern,
IN BYTE bKeyDirection,
IN OUT EapAttribute &pAttrib);
/**
* Construct a MPPE key vendor attribute.
*
* @param bKeyDirection [in] Either MS_MPPE_SEND_KEY or MS_MPPE_RECV_KEY.
*
* @param pMppeKeyData [in] The MPPE Key data.
*
* @param cbMppeKeyData [in] The byte length of the MPPE Key data.
*
* @param pAttrib [out] The EAP attribute that will contain the
* final MPPE Key vendor attribute.
*
*
* @return A Win32 error code, indicating success or failure.
*/
DWORD ConstructMppeKeyAttribute(
IN BYTE bKeyDirection,
IN PBYTE pMppeKeyData,
IN DWORD cbMppeKeyData,
IN OUT EapAttribute *pAttrib
);
DWORD GetXmlElementValue(
IN IXMLDOMDocument2 *pXmlDoc,
IN __in LPWSTR pElementName,
IN DWORD dwTypeOfDoc,
OUT BSTR &pElementValue
);
LPWSTR NewString(
IN const __in LPWSTR pInput
) throw();
DWORD CopyCredentialInputArray(
OUT EAP_CONFIG_INPUT_FIELD_ARRAY *pDest,
IN const EAP_CONFIG_INPUT_FIELD_ARRAY *pSrc
) throw();
DWORD ConstructUserBlobFromCredentialInputArray(
IN const EAP_METHOD_TYPE *pEapTypeIn,
IN const EAP_CONFIG_INPUT_FIELD_ARRAY *pEapConfigFieldsArray,
IN OUT DWORD *pdwUserBlobSize,
OUT PBYTE *ppbUserBlob
) throw();
LPWSTR GetCredentialInputValue(
IN const EAP_CONFIG_INPUT_FIELD_ARRAY *pSrc,
IN const DWORD valueType,
IN const __in LPWSTR pValueLabel = NULL
) throw();
void FreeCredentialInputArray(
IN OUT EAP_CONFIG_INPUT_FIELD_ARRAY *pArray
) throw();
#endif