/*++ Copyright (c) 1999, Microsoft Corporation Module Name: elport.h Abstract: This module contains declarations for port management for EAPOL, r/w to ports Revision History: sachins, Apr 23 2000, Created --*/ #ifndef _EAPOL_PORT_H_ #define _EAPOL_PORT_H_ // // EAPOL PCB State Flags // #define EAPOL_PORT_FLAG_DELETED 0x8000 #define EAPOL_PORT_DELETED(i) \ ((i)->dwFlags & EAPOL_PORT_FLAG_DELETED) #define EAPOL_PORT_FLAG_ACTIVE 0x4000 #define EAPOL_PORT_ACTIVE(i) \ ((i)->dwFlags & EAPOL_PORT_FLAG_ACTIVE) #define EAPOL_PORT_FLAG_DISABLED 0x2000 #define EAPOL_PORT_DISABLED(i) \ ((i)->dwFlags & EAPOL_PORT_FLAG_DISABLED) // // EAPOL Timer Flags // #define EAPOL_AUTH_TIMER 0x8000 #define EAPOL_AUTH_TIMER_SET(i) \ ((i)->dwTimerFlags & EAPOL_AUTH_TIMER) #define EAPOL_HELD_TIMER 0x4000 #define EAPOL_HELD_TIMER_SET(i) \ ((i)->dwTimerFlags & EAPOL_HELD_TIMER) #define EAPOL_START_TIMER 0x2000 #define EAPOL_START_TIMER_SET(i) \ ((i)->dwTimerFlags & EAPOL_START_TIMER) #define EAPOL_TRANSMIT_KEY_TIMER 0x1000 #define EAPOL_TRANSMIT_KEY_TIMER_SET(i) \ ((i)->dwTimerFlags & EAPOL_TRANSMIT_KEY_TIMER) #define EAPOL_NO_TIMER 0x0000 #define EAPOL_NO_TIMER_SET(i) \ ((i)->dwTimerFlags & EAPOL_NO_TIMER) #define SET_EAPOL_AUTH_TIMER(i) \ ((i)->dwTimerFlags = EAPOL_AUTH_TIMER) #define SET_EAPOL_HELD_TIMER(i) \ ((i)->dwTimerFlags = EAPOL_HELD_TIMER) #define SET_EAPOL_START_TIMER(i) \ ((i)->dwTimerFlags = EAPOL_START_TIMER) #define SET_TRANSMIT_KEY_TIMER(i) \ ((i)->dwTimerFlags = EAPOL_TRANSMIT_KEY_TIMER) #define SET_EAPOL_NO_TIMER(i) \ ((i)->dwTimerFlags = EAPOL_NO_TIMER) #define CHECK_EAPOL_TIMER(i) \ ((i)->dwTimerFlags & (EAPOL_AUTH_TIMER|EAPOL_HELD_TIMER|EAPOL_START_TIMER|EAPOL_TRANSMIT_KEY_TIMER)) // // Structure: ETH_HEADER // typedef struct _ETH_HEADER { BYTE bDstAddr[SIZE_MAC_ADDR]; BYTE bSrcAddr[SIZE_MAC_ADDR]; } ETH_HEADER, *PETH_HEADER; // // Structure: EAPOL_BUFFER // // This structure holds a buffer used for I/O to the ndis uio driver // EAPOL_BUFFER structure is used in the OVERLAPPED read-write operations. // On the OVERLAPPED read/write completion, pvContext is used to // identity the port on which the I/O occured // typedef struct _EAPOL_BUFFER { // // This is the pointer to the EAPOL_PCB structure of the interface on which // I/O was performed // PVOID pvContext; // Send/Recv data buffer CHAR pBuffer[MAX_PACKET_SIZE]; // // Passed as the system context area for any I/O using the buffer // OVERLAPPED Overlapped; // // Pointer to Completion Routine // VOID (CALLBACK *CompletionRoutine) (DWORD, DWORD, struct _EAPOL_BUFFER *); // Fields which are filled on IoCompletion DWORD dwErrorCode; DWORD dwBytesTransferred; } EAPOL_BUFFER, *PEAPOL_BUFFER; // // Structure: EAPOL_PCB // // EAPOL Port Control Block // This structure holds the operational information for an interface/port // from the EAPOL protocol standpoint. // It also maintains state information for EAP protocol. // // Each PCB is inserted in a hash bucket list, one for each interface // // Synchronization on PCBs is done using a read-write PCB list lock, // and a per-PCB read-write lock, and a per-port ref count. // The locks are single-write, multiple-read. Currently, locks are used // in write mode only // // If PCB's are to be added or deleted, the PCB list lock should // be acquired. // // If any PCB needs to be modified, the per-PCB list lock should be acquired // in write mode. // // Acquiring a reference to a port guarantees the PCBs existence; // acquiring the PCB lock guarantees consistency of the PCB fields // // typedef struct _EAPOL_PCB { // Pointer to next PCB in the hash bucket struct _EAPOL_PCB *pNext; // Handle to NDIS UIO device HANDLE hPort; // Port number on the system Will be an integer value cast DWORD dwPortIndex; // Debug Flags DWORD dwDebugFlags; // Friendly name of the interface on which this port is opened WCHAR *pwszFriendlyName; // GUID string uniquely identifying the interface WCHAR *pwszDeviceGUID; // Additional identiifier for a connected port e.g. MSFTWLAN WCHAR *pwszSSID; // Additional identiifier for a connected port e.g. MSFTWLAN NDIS_802_11_SSID *pSSID; // Version of EAPOL supported on this port DWORD dwEapolVersion; // Pointer to EAP Work Buffer for this PCB PVOID pEapWorkBuffer; // Per PCB read-write lock READ_WRITE_LOCK rwLock; // Number of references made to this port DWORD dwRefCount; // Indicates whether port is ACTIVE or DISABLED DWORD dwFlags; // Indicates the EAPOL settings DWORD dwEapFlags; // EAPOL state EAPOL_STATE State; // EAPOL statistics for this port EAPOL_STATS EapolStats; // EAPOL configuration parameters for this port EAPOL_CONFIG EapolConfig; // Version of EAPOL supported BYTE bProtocolVersion; // Handle to EAPOL timer currently running on this machine HANDLE hTimer; // Ethertype for this LAN BYTE bEtherType[SIZE_ETHERNET_TYPE]; // Mac Addr of peer (switch port access point) BYTE bSrcMacAddr[SIZE_MAC_ADDR]; // Mac Addr of last successfully authenticated peer (access point) BYTE bPreviousDestMacAddr[SIZE_MAC_ADDR]; // Mac Addr of peer (switch port or access point) BYTE bDestMacAddr[SIZE_MAC_ADDR]; // Media State NDIS_MEDIA_STATE MediaState; // Physical Medium Type NDIS_PHYSICAL_MEDIUM PhysicalMediumType; DWORD dwTimerFlags; // Number of EAPOL_Start messages that have been sent without // receiving response ULONG ulStartCount; // Identifier in the most recently received EAP Request frame DWORD dwPreviousId; // Copy of last sent out EAPOL packet // Used for retransmission BYTE *pbPreviousEAPOLPkt; DWORD dwSizeOfPreviousEAPOLPkt; // Has Identity for the user obtained using RasEapGetIdentity ? BOOL fGotUserIdentity; // Is the port on a authenticated network i.e. is the remote end // EAPOL aware BOOL fIsRemoteEndEAPOLAware; // Flag set based on the supplicant mode BOOL fEAPOLTransmissionFlag; // // EAP related variables // BOOL fEapInitialized; BOOL fLogon; BOOL fUserLoggedIn; // Authentication identity using RasGetUserIdentity or other means CHAR *pszIdentity; // User Password for EAP MD5 CHAP DATA_BLOB PasswordBlob; // Token for interactively logged-on user obtained using // GetCurrentUserToken HANDLE hUserToken; // EAP configuration blob stored for each GUID EAPOL_CUSTOM_AUTH_DATA *pCustomAuthConnData; // User blob stored for GUID EAPOL_CUSTOM_AUTH_DATA *pCustomAuthUserData; // Data obtained using RasEapInvokeInteractiveUI EAPOL_EAP_UI_DATA EapUIData; // Interactive data received from InvokeInteractiveUI BOOL fEapUIDataReceived; // EAP type for the connection DWORD dwEapTypeToBeUsed; // Index for current EAP type in index table DWORD dwEapIndex; // Current EAP identifier working with BYTE bCurrentEAPId; // Unique identifier for UI invocation DWORD dwUIInvocationId; // Interactive dialog allowed? BOOL fNonInteractive; // EAP state for the port EAPSTATE EapState; // EAP UI state for the port EAPUISTATE EapUIState; // Work space for EAP implementation DLL // PCB just holds the pointer, the memory allocation is done by the EAP DLL // during RasEapBegin and should be passed to RasEapEnd for cleanup LPVOID lpEapDllWorkBuffer; // Notification message WCHAR *pwszEapReplyMessage; // Master secrets used in decrypting EAPOL-Key messages DATA_BLOB MasterSecretSend; DATA_BLOB MasterSecretRecv; // Copies of the MPPE Keys obtained from EAP authentication DATA_BLOB MPPESendKey; DATA_BLOB MPPERecvKey; // Last replay counter. Used to guard against security attacks ULONGLONG ullLastReplayCounter; // EAPOL to run on this port or not DWORD dwEapolEnabled; // Has EAPOL_Logoff packet been sent out on this port? DWORD dwLogoffSent; // Authentication type last performed - Used with MACHINE_AUTH EAPOL_AUTHENTICATION_TYPE PreviousAuthenticationType; // Number of current authentication failures for the port - MACHINE_AUTH DWORD dwAuthFailCount; // Is authentication being done on a new AP/Switch/Network? BOOLEAN fAuthenticationOnNewNetwork; // Tick count, the last time the port was restart DWORD dwLastRestartTickCount; // Zero Config transaction Id DWORD dwZeroConfigId; // Total Max Authentication tries (Machine + User + Guest) DWORD dwTotalMaxAuthFailCount; // Did EAP on Client-side actually succeed BOOLEAN fLocalEAPAuthSuccess; // Client-side auth result code DWORD dwLocalEAPAuthResult; // Supplicant-mode DWORD dwSupplicantMode; // EAPOL Authentication Mode 0 = XP RTM, 1 = XP SP1, 2 = Machine auth only DWORD dwEAPOLAuthMode; // Flag to indicate where the Session Keys which module the session keys // were last used from BOOLEAN fLastUsedEAPOLKeys; // Flag to indicate whether EAPOL-Key packet for transmit key // was received after getting into AUTHENTICATED state for wireless // interface BOOLEAN fTransmitKeyReceived; } EAPOL_PCB, *PEAPOL_PCB; // // Synchronization // #define EAPOL_REFERENCE_PORT(PCB) \ (EAPOL_PORT_DELETED(PCB) ? FALSE : (InterlockedIncrement(&(PCB)->dwRefCount), TRUE)) #define EAPOL_DEREFERENCE_PORT(PCB) \ (InterlockedDecrement(&(PCB)->dwRefCount) ? TRUE : (ElCleanupPort(PCB), FALSE)) // // FUNCTION DECLARATIONS // DWORD ElHashPortToBucket ( IN WCHAR *pwszDeviceGUID ); VOID ElRemovePCBFromTable ( IN EAPOL_PCB *pPCB ); PEAPOL_PCB ElGetPCBPointerFromPortGUID ( IN WCHAR *pwszDeviceGUID ); DWORD ElCreatePort ( IN HANDLE hDevice, IN WCHAR *pwszGUID, IN WCHAR *pwszFriendlyName, IN DWORD dwZeroConfigId, IN PRAW_DATA prdRawData ); DWORD ElDeletePort ( IN WCHAR *pwszDeviceName, OUT HANDLE *hDevice ); VOID ElCleanupPort ( IN EAPOL_PCB *pPCB ); DWORD ElReStartPort ( IN PEAPOL_PCB pPCB, IN DWORD dwZeroConfigId, IN PRAW_DATA prdUserData ); DWORD ElReadFromPort ( IN PEAPOL_PCB pPCB, IN PCHAR pBuffer, IN DWORD dwBufferLength ); DWORD ElWriteToPort ( IN PEAPOL_PCB pPCB, IN PCHAR pBuffer, IN DWORD dwBufferLength ); DWORD ElInitializeEAPOL ( ); DWORD ElEAPOLDeInit ( ); VOID ElReadPortStatistics ( IN WCHAR *pwszDeviceName, OUT PEAPOL_STATS pEapolStats ); VOID ElReadPortConfiguration ( IN WCHAR *pwszDeviceName, OUT PEAPOL_CONFIG pEapolConfig ); ULONG ElSetPortConfiguration ( IN WCHAR *pwszDeviceName, IN PEAPOL_CONFIG pEapolConfig ); VOID CALLBACK ElReadCompletionRoutine ( IN DWORD dwError, IN DWORD dwBytesReceived, IN PEAPOL_BUFFER pEapolBuffer ); VOID CALLBACK ElWriteCompletionRoutine ( IN DWORD dwError, IN DWORD dwBytesSent, IN PEAPOL_BUFFER pEapolBuffer ); VOID CALLBACK ElIoCompletionRoutine ( IN DWORD dwError, IN DWORD dwBytesTransferred, IN LPOVERLAPPED lpOverlapped ); DWORD ElReadPerPortRegistryParams( IN WCHAR *pwszDeviceGUID, IN EAPOL_PCB *pNewPCB ); #endif // _EAPOL_PORT_H_