authenticator_procedures.c
Go to the documentation of this file.
1 /**
2  * @file authenticator_procedures.c
3  * @brief Authenticator state machine procedures
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2022-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneEAP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL AUTHENTICATOR_TRACE_LEVEL
33 
34 //Dependencies
39 #include "eap/eap_debug.h"
40 #include "debug.h"
41 
42 //Check EAP library configuration
43 #if (AUTHENTICATOR_SUPPORT == ENABLED)
44 
45 
46 /**
47  * @brief Set authorization state for a given port
48  * @param[in] port Pointer to the port context
49  * @param[in] status Authorization state (authorized or unauthorized)
50  **/
51 
54 {
55  NetInterface *interface;
56 
57  //Point to the underlying network interface
58  interface = port->context->interface;
59 
60  //Update the state of the specified port
61  if(status == AUTHENTICATOR_PORT_STATUS_AUTH)
62  {
63  //Debug message
64  TRACE_INFO("Port %" PRIu8 ": Set port status to Authorized\r\n",
65  port->portIndex);
66 
67  //A port in the authorized state effectively means that the
68  //supplicant has been successfully authenticated
69  if(interface->switchDriver != NULL &&
70  interface->switchDriver->setPortState != NULL)
71  {
72  interface->switchDriver->setPortState(interface, port->portIndex,
74  }
75  }
76  else
77  {
78  //Debug message
79  TRACE_INFO("Port %" PRIu8 ": Set port status to Unauthorized\r\n",
80  port->portIndex);
81 
82  //If the port is in the unauthorized state, then the client is not
83  //granted access to the network
84  if(interface->switchDriver != NULL &&
85  interface->switchDriver->setPortState != NULL)
86  {
87  interface->switchDriver->setPortState(interface, port->portIndex,
89  }
90  }
91 
92  //Save authorization state
93  port->authPortStatus = status;
94 }
95 
96 
97 /**
98  * @brief Transmit an EAPOL frame containing an EAP failure (8.2.4.1.3 a)
99  * @param[in] port Pointer to the port context
100  **/
101 
103 {
104  size_t n;
105  EapolPdu *pdu;
106  EapPacket *packet;
107 
108  //Debug message
109  TRACE_DEBUG("txCannedFail() procedure...\r\n");
110 
111  //In the case that no EAP communication was taking place on the port, then
112  //any value of ID may be used in the Identifier field of the EAP frame. In
113  //the case that there was an EAP communication taking place on the port,
114  //then the value of the Identifier field in the EAP packet is set to a value
115  //that is different from the last delivered EAPOL frame of type EAP-Packet
116  //(refer to IEEE Std 802.1X-2004, section 8.2.4.1.3)
117  port->currentId = eapNextId(port->currentId);
118 
119  //Point to the buffer where to format the EAPOL packet
120  pdu = (EapolPdu *) port->eapTxBuffer;
121  //Point to the buffer where to format the EAP packet
122  packet = (EapPacket *) pdu->packetBody;
123 
124  //Total length of the EAP packet
125  n = sizeof(EapPacket);
126 
127  //Format EAP failure packet
128  packet->code = EAP_CODE_FAILURE;
129  packet->identifier = port->currentId;
130  packet->length = htons(n);
131 
132  //Debug message
133  TRACE_DEBUG("Port %" PRIu8 ": Sending EAP packet (%" PRIuSIZE " bytes)...\r\n",
134  port->portIndex, n);
135 
136  //Dump EAP header contents for debugging purpose
137  eapDumpHeader(packet);
138 
139  //Total length of the EAPOL packet
140  n += sizeof(EapolPdu);
141 
142  //Format EAPOL packet
143  pdu->protocolVersion = EAPOL_VERSION_2;
144  pdu->packetType = EAPOL_TYPE_EAP;
145  pdu->packetBodyLen = ntohs(n);
146 
147  //Debug message
148  TRACE_INFO("Port %" PRIu8 ": Sending EAPOL packet (%" PRIuSIZE " bytes)...\r\n",
149  port->portIndex, n);
150 
151  //Dump EAPOL header contents for debugging purpose
153 
154  //Send EAPOL PDU
155  authenticatorSendEapolPdu(port, port->eapTxBuffer, n);
156 }
157 
158 
159 /**
160  * @brief Transmit an EAPOL frame containing an EAP success (8.2.4.1.3 b)
161  * @param[in] port Pointer to the port context
162  **/
163 
165 {
166  size_t n;
167  EapolPdu *pdu;
168  EapPacket *packet;
169 
170  //Debug message
171  TRACE_DEBUG("txCannedSuccess() procedure...\r\n");
172 
173  //In the case that no EAP communication was taking place on the port, then
174  //any value of ID may be used in the Identifier field of the EAP frame. In
175  //the case that there was an EAP communication taking place on the port,
176  //then the value of the Identifier field in the EAP packet is set to a value
177  //that is different from the last delivered EAPOL frame of type EAP-Packet
178  //(refer to IEEE Std 802.1X-2004, section 8.2.4.1.3)
179  port->currentId = eapNextId(port->currentId);
180 
181  //Point to the buffer where to format the EAPOL packet
182  pdu = (EapolPdu *) port->eapTxBuffer;
183  //Point to the buffer where to format the EAP packet
184  packet = (EapPacket *) pdu->packetBody;
185 
186  //Total length of the EAP packet
187  n = sizeof(EapPacket);
188 
189  //Format EAP success packet
190  packet->code = EAP_CODE_SUCCESS;
191  packet->identifier = port->currentId;
192  packet->length = htons(n);
193 
194  //Debug message
195  TRACE_DEBUG("Port %" PRIu8 ": Sending EAP packet (%" PRIuSIZE " bytes)...\r\n",
196  port->portIndex, n);
197 
198  //Dump EAP header contents for debugging purpose
199  eapDumpHeader(packet);
200 
201  //Total length of the EAPOL packet
202  n += sizeof(EapolPdu);
203 
204  //Format EAPOL packet
205  pdu->protocolVersion = EAPOL_VERSION_2;
206  pdu->packetType = EAPOL_TYPE_EAP;
207  pdu->packetBodyLen = ntohs(n);
208 
209  //Debug message
210  TRACE_INFO("Port %" PRIu8 ": Sending EAPOL packet (%" PRIuSIZE " bytes)...\r\n",
211  port->portIndex, n);
212 
213  //Dump EAPOL header contents for debugging purpose
215 
216  //Send EAPOL PDU
217  authenticatorSendEapolPdu(port, port->eapTxBuffer, n);
218 }
219 
220 
221 /**
222  * @brief Transmit an EAPOL frame of type EAP-Packet (8.2.9.1.3 a)
223  * @param[in] port Pointer to the port context
224  **/
225 
227 {
228  size_t length;
229  EapolPdu *pdu;
230  EapRequest *request;
231 
232  //Debug message
233  TRACE_DEBUG("txReq() procedure...\r\n");
234 
235  //Point to the buffer where to format the EAPOL packet
236  pdu = (EapolPdu *) port->eapTxBuffer;
237  //Retrieve the length of the EAP request
238  length = port->eapReqDataLen;
239 
240  //Valid EAP packet?
241  if(length >= sizeof(EapPacket))
242  {
243  //EAP request?
244  if(port->eapReqData[0] == EAP_CODE_REQUEST &&
245  length >= sizeof(EapRequest))
246  {
247  //Point to the EAP request
248  request = (EapRequest *) port->eapReqData;
249 
250  //Update statistics
251  if(request->type == EAP_METHOD_TYPE_IDENTITY)
252  {
253  //Number of EAP Req/Id frames that have been transmitted
254  port->stats.eapolReqIdFramesTx++;
255  }
256  else
257  {
258  //Number of EAP Request frames (other than Rq/Id frames) that have
259  //been transmitted
260  port->stats.eapolReqFramesTx++;
261  }
262  }
263 
264  //Format EAPOL packet
265  pdu->protocolVersion = EAPOL_VERSION_2;
266  pdu->packetType = EAPOL_TYPE_EAP;
267  pdu->packetBodyLen = ntohs(length);
268 
269  //Total length of the EAPOL packet
270  length += sizeof(EapolPdu);
271 
272  //Debug message
273  TRACE_INFO("Port %" PRIu8 ": Sending EAPOL packet (%" PRIuSIZE " bytes)...\r\n",
274  port->portIndex, length);
275 
276  //Dump EAPOL header contents for debugging purpose
278 
279  //Send EAPOL PDU
280  authenticatorSendEapolPdu(port, port->eapTxBuffer, length);
281  }
282 }
283 
284 
285 /**
286  * @brief Deliver the received EAP frame to EAP for processing (8.2.9.1.3 b)
287  * @param[in] port Pointer to the port context
288  **/
289 
291 {
292  //Debug message
293  TRACE_DEBUG("sendRespToServer() procedure...\r\n");
294 }
295 
296 
297 /**
298  * @brief Release any system resources (8.2.9.1.3 c)
299  * @param[in] port Pointer to the port context
300  **/
301 
303 {
304 }
305 
306 
307 /**
308  * @brief Decrement timer value
309  * @param[in,out] x Actual timer value
310  **/
311 
313 {
314  //If the variable has a non-zero value, this procedure decrements the value
315  //of the variable by 1
316  if(*x > 0)
317  {
318  *x -= 1;
319  }
320 }
321 
322 #endif
802.1X authenticator
#define AuthenticatorPort
Definition: authenticator.h:40
error_t authenticatorSendEapolPdu(AuthenticatorPort *port, const uint8_t *pdu, size_t length)
Send EAPOL PDU.
Helper functions for 802.1X authenticator.
AuthenticatorPortStatus
Port status.
@ AUTHENTICATOR_PORT_STATUS_AUTH
void authenticatorSetAuthPortStatus(AuthenticatorPort *port, AuthenticatorPortStatus status)
Set authorization state for a given port.
void authenticatorAbortAuth(AuthenticatorPort *port)
Release any system resources (8.2.9.1.3 c)
void authenticatorSendRespToServer(AuthenticatorPort *port)
Deliver the received EAP frame to EAP for processing (8.2.9.1.3 b)
void authenticatorTxCannedSuccess(AuthenticatorPort *port)
Transmit an EAPOL frame containing an EAP success (8.2.4.1.3 b)
void authenticatorTxReq(AuthenticatorPort *port)
Transmit an EAPOL frame of type EAP-Packet (8.2.9.1.3 a)
void authenticatorTxCannedFail(AuthenticatorPort *port)
Transmit an EAPOL frame containing an EAP failure (8.2.4.1.3 a)
void authenticatorDecrementTimer(uint_t *x)
Decrement timer value.
Authenticator state machine procedures.
unsigned int uint_t
Definition: compiler_port.h:50
#define PRIuSIZE
#define htons(value)
Definition: cpu_endian.h:413
#define ntohs(value)
Definition: cpu_endian.h:421
Debugging facilities.
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define TRACE_INFO(...)
Definition: debug.h:95
uint8_t n
uint16_t port
Definition: dns_common.h:267
@ EAP_CODE_FAILURE
Failure.
Definition: eap.h:155
@ EAP_CODE_REQUEST
Request.
Definition: eap.h:152
@ EAP_CODE_SUCCESS
Success.
Definition: eap.h:154
EapRequest
Definition: eap.h:238
EapolPdu
Definition: eap.h:211
EapPacket
Definition: eap.h:224
@ EAPOL_VERSION_2
IEEE 802.1X-2004.
Definition: eap.h:123
@ EAPOL_TYPE_EAP
EAPOL-EAP.
Definition: eap.h:134
@ EAP_METHOD_TYPE_IDENTITY
Identity.
Definition: eap.h:166
uint_t eapNextId(uint_t id)
Determine the next identifier value to use.
EAP authenticator state machine procedures.
void eapolDumpHeader(const EapolPdu *header)
Dump EAPOL header for debugging purpose.
Definition: eap_debug.c:85
void eapDumpHeader(const EapPacket *header)
Dump EAP header for debugging purpose.
Definition: eap_debug.c:105
Data logging functions for debugging purpose (EAP)
uint8_t x
Definition: lldp_ext_med.h:211
uint8_t pdu[]
#define NetInterface
Definition: net.h:36
@ SWITCH_PORT_STATE_FORWARDING
Definition: nic.h:140
@ SWITCH_PORT_STATE_BLOCKING
Definition: nic.h:137
uint8_t length
Definition: tcp.h:368