// 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 #include "eaptypes.h" #include "eapmethodtypes.h" #include "EapMethodAuthenticatorApis.h" #include "lmcons.h" // /// 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"ServerSdkMethodDll.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 SdkEapMethodAuthenticatorInitialize( IN EAP_METHOD_TYPE* pEapType, OUT EAP_ERROR** ppEapError ); DWORD 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 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 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 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 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 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 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 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 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_bcount(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