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

528 lines
20 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_AUTHENTICATOR_EAPMETHOD_H_
#define _SAMPLE_AUTHENTICATOR_EAPMETHOD_H_
#pragma once
#include <windows.h>
#include "eaptypes.h"
#include "eapmethodtypes.h"
#include "EapMethodAuthenticatorApis.h"
#include "lmcons.h" // <UNLEN, PWLEN>
/// This Sample DLL sends a simple challenge request from server -> client.
const char STRING_CHALLENGE_MESSAGE[] = "send password";
/// Byte length of simple challenge request.
const size_t STRING_LENGTH_CHALLENGE_MESSAGE = sizeof(STRING_CHALLENGE_MESSAGE);
/// The # of attributes we need to add during authentication.
/// (Attributes: username, password)
const DWORD ATTRIBUTE_COUNT_AUTHENTICATION = 2;
/// Following are required for registering Eap Authenticator Method with EapHost.
const wchar_t authFriendlyName[] = L"AuthenticatorFriendlyName";
const wchar_t authDllPath[] = L"AuthenticatorDllPath";
const wchar_t properties[] = L"Properties";
const wchar_t authFriendlyNameValue[] = L"SdkAuthenticatorEapMethod";
const DWORD propertiesValue = 0x280000; ///< eapPropMppeEncryption (0x80000) & eapPropSupportsConfig (0x200000)
const wchar_t authMethodDllName[] = L"EapHostServerMethodSample.dll";
const DWORD AUTH_SUCCESS = 0;
const DWORD AUTH_FAILURE = 1;
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;
typedef struct _USER_DATA_BLOB
{
DWORD eapTypeId;
EAP_NAME_DIALOG eapUserNamePassword;
}USER_DATA_BLOB;
/// Enum: States within the EAP state machines used by this EAP Authenticator Dll.
typedef enum _MYSTATE
{
MYSTATE_Initial,
MYSTATE_ReqSent,
} MYSTATE;
/**
* EAP working buffer.
*
* This structure contains all persistent data that the EAP method needs to
* operate. The data buffer is created inside EapMethodAuthenticatorBeginSession(),
* persists through the entire authentication session, and is released inside
* EapMethodAuthenticatorEndSession().
*/
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.
EapAttributes* pEapAttributes;
DWORD dwSizeofConnectionData; ///< Size of Connection Data
PBYTE pConnectionData; ///< Pointer to Connection Data
DWORD dwMaxSendPacketSize; ///< Max Size of EAP packet to send back.
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.
EapAttributes* pUserAttributes; ///< Local pointer to EAP attributes that contains UserName and Password and may be sent to the authenticator for authentication..
EapAttributes* pMPPEKeyAttributes; ///< Local pointer to the MPPE key EAP attributes generated by this EAP provider after a successful authentication transaction has been performed.
}EAPCB;
//
// EAP Functions whose function pointer is returned back in EapMethodAuthenticatorGetInfo().
//
DWORD APIENTRY SdkEapMethodAuthenticatorInitialize(
IN EAP_METHOD_TYPE* pEapType,
OUT EAP_ERROR** ppEapError
);
DWORD APIENTRY SdkEapMethodAuthenticatorBeginSession(
// Flags to qualify the authentication process.
IN DWORD dwFlags,
// Identity of the user being authenticated
IN LPCWSTR pwszIdentity,
// Pointer to an array of attributes. This array contains attributes that
// describe the entity being authenticated.
IN const EapAttributes* const pAttributeArray,
// Specifies the size in bytes of the data pointed to by pConnectionData.
// If pConnectionData is NULL, this member is zero.
IN DWORD dwSizeofConnectionData,
// Pointer to connection data received from the authentication protocol's
// configuration user interface.
IN const BYTE* const pConnectionData,
// This is the maximum size of an eap packet that the authenticator can send.
IN DWORD dwMaxSendPacketSize,
// The session handle that identifies the current authentication session.
OUT EAP_SESSION_HANDLE* pSessionHandle,
// On an unsuccessful call, this will contain any error information about
// the failure. This will be null on a successful call.
OUT EAP_ERROR** pEapError
);
DWORD APIENTRY SdkEapMethodAuthenticatorUpdateInnerMethodParams(
// context handle as returned from a successful call to
// EapAuthenticatorBeginSession
IN EAP_SESSION_HANDLE sessionHandle,
IN DWORD dwFlags,
IN CONST WCHAR* pwszIdentity,
// Pointer to an array of attributes. This array contains attributes that
// describe the entity being authenticated.
IN const EapAttributes* const pAttributeArray,
// On an unsuccessful call, this will contain any error information about
// the failure. This will be null on a successful call.
OUT EAP_ERROR** pEapError
);
// The authenticator calls this any time it receives a packet that the eaphost
// needs to process. This should be called only after a successful call to
// EapAuthenticatorBeginSession.
DWORD APIENTRY SdkEapMethodAuthenticatorReceivePacket(
// context handle as returned from a successful call to
// EapAuthenticatorBeginSession
IN EAP_SESSION_HANDLE sessionHandle,
// Specifies the size, in bytes, of the buffer pointed to by
// pReceivePacket
IN DWORD cbReceivePacket,
// Pointer to a buffer that contains the incoming EAP data received by
// the supplicant.
IN const EapPacket* const pReceivePacket,
// This enumeration tells the supplicant to take an appropriate action.
// The supplicant will typically look at this action and either call
// another method on eaphost or do something else on its own.
OUT EAP_METHOD_AUTHENTICATOR_RESPONSE_ACTION* pEapOutput,
// On an unsuccessful call, this will contain any error information about
// the failure. This will be null on a successful call.
OUT EAP_ERROR** pEapError
);
DWORD APIENTRY SdkEapMethodAuthenticatorSendPacket(
// context handle as returned from a successful call to
// EapHostAuthenticatorBeginSession
IN EAP_SESSION_HANDLE sessionHandle,
// Id to use when constructing the SendPacket
IN BYTE bPacketId,
// Specifies the limit on the size, in bytes, on the packet generated
// by eaphost. On a successful return, this will contain the size of the
// data added by the eap module.
OUT DWORD* pcbSendPacket,
// Pointer to a buffer that is allocated by the client and populated
// by the eap module. The value of the incoming buffer is ignored and
// the method populates it from the beginning of the buffer.
OUT EapPacket* pSendPacket,
// Timeout option for sending the packet
OUT EAP_AUTHENTICATOR_SEND_TIMEOUT* pTimeout,
// On an unsuccessful call, this will contain any error information about
// the failure. This will be null on a successful call.
OUT EAP_ERROR** pEapError
);
// Returns an array of attributes that the caller needs to act on.
// The supplicant will call this when a call to
// EapHostAuthenticatorProcessRequestPacket returns EapHostAuthenticatorResponseRespond.
DWORD APIENTRY SdkEapMethodAuthenticatorGetAttributes(
// context handle as returned from a successful call to
// EapHostAuthenticatorBeginSession
IN EAP_SESSION_HANDLE sessionHandle,
// Array of attributes that the caller needs to act on.
OUT EapAttributes* pAttribs,
OUT EAP_ERROR** pEapError
);
// Sets an array of attributes that the caller wants the eap method to act
// on.
DWORD APIENTRY SdkEapMethodAuthenticatorSetAttributes(
// context handle as returned from a successful call to
// EapHostAuthenticatorBeginSession
IN EAP_SESSION_HANDLE sessionHandle,
IN const EapAttributes* const pAttribs,
// This enumeration tells the supplicant to take an appropriate action.
// The supplicant will typically look at this action and either call
// another method on eaphost or do something else on its own.
OUT EAP_METHOD_AUTHENTICATOR_RESPONSE_ACTION* pEapOutput,
// On an unsuccessful call, this will contain any error information about
// the failure. This will be null on a successful call.
OUT EAP_ERROR** ppEapError
);
// The authenticator will call this on completion of an authentication. This
// can happen in any of the following scenarios:
// 1. A call to EapHostAuthenticatorReceivePacket returned
// EAP_HOST_AUTHENTICATOR_RESPONSE_SUCCESS or EAP_HOST_AUTHENTICATOR_RESPONSE_FAILURE
// Even if the action returned above was a success, the authenticator can choose to call
// this method with a failure.
// 2. The server can choose to terminate an authentication with a failure in the middle of
// an authentication.
DWORD APIENTRY SdkEapMethodAuthenticatorGetResult(
// context handle as returned from a successful call to
// EapHostPeerBeginSession
IN EAP_SESSION_HANDLE sessionHandle,
// A structure that indicates the result and any state that the
// supplicant needs to save for future authentications.
OUT EAP_METHOD_AUTHENTICATOR_RESULT* ppResult,
// On an unsuccessful call, this will contain any error information about
// the failure. This will be null on a successful call.
OUT EAP_ERROR** pEapError
);
// Ends the authentication session. This cleans up any state that the eap
// method or eaphost might be keeping.
DWORD APIENTRY SdkEapMethodAuthenticatorEndSession(
// context handle as returned from a successful call to
// EapHostPeerBeginSession. This will be set to NULL on a successful call.
IN EAP_SESSION_HANDLE sessionHandle,
// On an unsuccessful call, this will contain any error information about
// the failure. This will be null on a successful call.
OUT EAP_ERROR** ppEapError
);
DWORD APIENTRY SdkEapAuthenticatorShutdown(
IN EAP_METHOD_TYPE* pEapType,
OUT EAP_ERROR** ppEapError
);
//
// Helper Functions
//
/**
* MakeRequestMessage() helper function: Construct a request message
*
* This function builds the EAP-Challenge message(s) sent to the client.
*
*
* @param pwb [in] Pointer to the work buffer.
*
* @param bPacketId [in] PacketId to be used in the EapChallenge Method.
*
* @param pSendPacket [out] Pointer to a EapPacket structure. The
* authentication protocol can use this structure
* to specify a packet to send.
*
* @param pcbSendPacket [out] Specifies the size, in bytes, of the buffer
* pointed to by pSendPacket.
*
*
* @return If the function succeeds, the return value is NO_ERROR.
*/
DWORD
MakeRequestMessage(
IN EAPCB* pwb,
IN BYTE bPacketId,
OUT EapPacket *pSendPacket,
OUT DWORD * pcbSendPacket
);
/**
* GetPasswordFromResponse() helper function: Parse a response packet to extract
* the password.
*
* This function handles reading the EAP client's response packet. It
* obtains the user's password, to use when authenticating the user.
*
*
* @param pReceiveBuf [in] Pointer to a EapPacket structure that
* contains a received packet.
*
* @param pszPassword [out] Pointer to a buffer, into which the password
* will be copied. The caller is responsible for
* allocating & freeing this buffer.
*
* @param size [in,out] size of the password
*
* @return If the function succeeds, the return value is NO_ERROR.
*/
DWORD
GetPasswordFromResponse(
IN const BYTE* const pReceivePacket,
OUT _Out_writes_bytes_(size) CHAR* pszPassword,
size_t &size
);
/**
* MakeAuthenticationAttributes() helper function: Build authentication
* attributes to be sent to the authentication provider.
*
* This function wraps the received username & password into EAP
* authentication attributes. The authentication provider will process these
* attributes, determine whether the authentication succeeded or failed.
*
*
* @param szUserName [in] The username received from the EAP client.
*
* @param szPassword [in] The password received from the EAP client.
*
* @param pwb [in] Pointer to the work buffer.
*
*
* @return If the function succeeds, the return value is NO_ERROR.
*/
DWORD
MakeAuthenticationAttributes(
IN _In_ CHAR * szUserName,
IN _In_ CHAR * szPassword,
IN EAPCB * pwb
);
/**
* 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 A Win32 error code, indicating success or failure.
*/
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
VerifyAuthenticationAttributes(
IN EAPCB *pwb);
/**
* 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 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
GetIdentityAsConfigData(
IN HWND hwndParent,
OUT BYTE** ppUserDataOut,
OUT DWORD* pdwSizeOfUserDataOut
);
/**
* GetUsernameAndPassword() helper function: Display user credentials UI.
*
* This function displays an interactive UI (the IDD_CONFIG_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
);
#endif