eap_auth_procedures.c
Go to the documentation of this file.
1 /**
2  * @file eap_auth_procedures.c
3  * @brief EAP 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.4
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL SUPPLICANT_TRACE_LEVEL
33 
34 //Dependencies
37 #include "eap/eap_debug.h"
38 #include "debug.h"
39 
40 //Check EAP library configuration
41 #if (AUTHENTICATOR_SUPPORT == ENABLED)
42 
43 
44 /**
45  * @brief Calculate retransmission timeout
46  * @param[in] port Pointer to the port context
47  * @return Timeout value
48  **/
49 
51 {
52  //Debug message
53  TRACE_DEBUG("calculateTimeout() procedure...\r\n");
54 
55  //Calculate the retransmission timeout, taking into account the
56  //retransmission count, round-trip time measurements, and method-specific
57  //timeout hint
58  return port->methodTimeout;
59 }
60 
61 
62 /**
63  * @brief Determine the code, identifier value, and type of the current response
64  * @param[in] port Pointer to the port context
65  **/
66 
68 {
69  const EapPacket *packet;
70  const EapResponse *response;
71 
72  //Debug message
73  TRACE_DEBUG("parseEapResp() procedure...\r\n");
74 
75  //In the case of a parsing error, rxResp will be set to FALSE. The values of
76  //respId and respMethod may be undefined as a result (refer to RFC 4137,
77  //section 5.4)
78  port->rxResp = 0;
79 
80  //Point to the EAP packet
81  packet = (EapPacket *) port->eapRespData;
82 
83  //Save the identifier from the current EAP response
84  port->respId = packet->identifier;
85 
86  //Check code field
87  if(packet->code == EAP_CODE_RESPONSE)
88  {
89  //Valid EAP response?
90  if(port->eapRespDataLen >= sizeof(EapResponse))
91  {
92  //The current received packet is an EAP response
93  port->rxResp = TRUE;
94 
95  //Point to the EAP response
96  response = (EapResponse *) port->eapRespData;
97  //Determine the type of the current response
98  port->respMethod = (EapMethodType) response->type;
99 
100  //Update statistics
101  if(response->type == EAP_METHOD_TYPE_IDENTITY)
102  {
103  //Number of EAP Resp/Id frames that have been received
104  port->stats.eapolRespIdFramesRx++;
105  }
106  else
107  {
108  //Number of valid EAP Response frames (other than Resp/Id frames)
109  //that have been received
110  port->stats.eapolRespFramesRx++;
111  }
112  }
113  }
114  else
115  {
116  //Unknown code
117  }
118 }
119 
120 
121 /**
122  * @brief Create an EAP success packet
123  * @param[in] port Pointer to the port context
124  **/
125 
127 {
128  size_t n;
129  EapPacket *packet;
130 
131  //Debug message
132  TRACE_DEBUG("buildSuccess() procedure...\r\n");
133 
134  //Point to the buffer where to format the EAP packet
135  packet = (EapPacket *) port->eapReqData;
136 
137  //Total length of the EAP packet
138  n = sizeof(EapPacket);
139 
140  //Format EAP success packet
141  packet->code = EAP_CODE_SUCCESS;
142  packet->identifier = port->currentId;
143  packet->length = htons(n);
144 
145  //Debug message
146  TRACE_DEBUG("Port %" PRIu8 ": Sending EAP packet (%" PRIuSIZE " bytes)...\r\n",
147  port->portIndex, n);
148 
149  //Dump EAP header contents for debugging purpose
150  eapDumpHeader(packet);
151 
152  //Save the length of the EAP packet
153  port->eapReqDataLen = n;
154 }
155 
156 
157 /**
158  * @brief Create an EAP failure packet
159  * @param[in] port Pointer to the port context
160  **/
161 
163 {
164  size_t n;
165  EapPacket *packet;
166 
167  //Debug message
168  TRACE_DEBUG("buildFailure() procedure...\r\n");
169 
170  //Point to the buffer where to format the EAP packet
171  packet = (EapPacket *) port->eapReqData;
172 
173  //Total length of the EAP packet
174  n = sizeof(EapPacket);
175 
176  //Format EAP failure packet
177  packet->code = EAP_CODE_FAILURE;
178  packet->identifier = port->currentId;
179  packet->length = htons(n);
180 
181  //Debug message
182  TRACE_DEBUG("Port %" PRIu8 ": Sending EAP packet (%" PRIuSIZE " bytes)...\r\n",
183  port->portIndex, n);
184 
185  //Dump EAP header contents for debugging purpose
186  eapDumpHeader(packet);
187 
188  //Save the length of the EAP packet
189  port->eapReqDataLen = n;
190 }
191 
192 
193 /**
194  * @brief Determine the next identifier value to use
195  * @param[in] id Current identifier value
196  * @return Next identifier value to use
197  **/
198 
200 {
201  //Debug message
202  TRACE_DEBUG("nextId() procedure...\r\n");
203 
204  //Increment identifier value
205  if(id == EAP_CURRENT_ID_NONE)
206  {
207  id = 0;
208  }
209  else
210  {
211  id = (id + 1) % 256;
212  }
213 
214  //Return the next identifier value to use
215  return id;
216 }
217 
218 
219 /**
220  * @brief Update all variables related to internal policy state
221  * @param[in] port Pointer to the port context
222  **/
223 
225 {
226  //Debug message
227  TRACE_DEBUG("Policy.update() procedure...\r\n");
228 }
229 
230 
231 /**
232  * @brief Determine the method that should be used at this point in the conversation
233  * @param[in] port Pointer to the port context
234  * @return Next method to use
235  **/
236 
238 {
239  //Debug message
240  TRACE_DEBUG("Policy.getNextMethod() procedure...\r\n");
241 
242  //The NAS initiates the conversation by sending an EAP-Request/Identity
244 }
245 
246 
247 /**
248  * @brief Determine if the policy will allow SUCCESS, FAIL, or is yet to determine
249  * @param[in] port Pointer to the port context
250  * @return Decision enumeration
251  **/
252 
254 {
255  EapDecision decision;
256 
257  //Debug message
258  TRACE_DEBUG("Policy.getDecision() procedure...\r\n");
259 
260  //Determine policy decision
261  if(port->currentMethod == EAP_METHOD_TYPE_NONE)
262  {
263  //The NAS should send an initial EAP-Request message to the authenticating
264  //peer (refer to RFC 3579, section 2.1)
265  decision = EAP_DECISION_CONTINUE;
266  }
267  else
268  {
269  //The NAS acts as a pass-through for subsequent messages
270  decision = EAP_DECISION_PASSTHROUGH;
271  }
272 
273  //Return policy decision
274  return decision;
275 }
276 
277 
278 /**
279  * @brief Test for the validity of a message
280  * @param[in] port Pointer to the port context
281  * @return TRUE if the message is invalid and must be ignored, else FALSE
282  **/
283 
285 {
286  bool_t ignore;
287 
288  //Debug message
289  TRACE_DEBUG("m.check() procedure...\r\n");
290 
291  //Identity method?
292  if(port->currentMethod == EAP_METHOD_TYPE_IDENTITY)
293  {
294  ignore = FALSE;
295  }
296  else
297  {
298  ignore = TRUE;
299  }
300 
301  //Return TRUE if the message is invalid and must be ignored
302  return ignore;
303 }
304 
305 
306 /**
307  * @brief Parse and process a response
308  * @param[in] port Pointer to the port context
309  **/
310 
312 {
313  //Debug message
314  TRACE_DEBUG("m.process() procedure...\r\n");
315 }
316 
317 
318 /**
319  * @brief Method procedure to initialize state just before use
320  * @param[in] port Pointer to the port context
321  **/
322 
324 {
325  //Debug message
326  TRACE_DEBUG("m.init() procedure...\r\n");
327 }
328 
329 
330 /**
331  * @brief The method is ending in the middle of or before completion
332  * @param[in] port Pointer to the port context
333  **/
334 
336 {
337  //Debug message
338  TRACE_DEBUG("m.reset() procedure...\r\n");
339 }
340 
341 
342 /**
343  * @brief Check for method completion
344  * @param[in] port Pointer to the port context
345  * @return Boolean
346  **/
347 
349 {
350  //Debug message
351  TRACE_DEBUG("m.isDone() procedure...\r\n");
352 
353  //This method returns a boolean
354  return TRUE;
355 }
356 
357 
358 /**
359  * @brief Determine an appropriate timeout hint for the method
360  * @param[in] port Pointer to the port context
361  * @return Timeout value
362  **/
363 
365 {
366  //Debug message
367  TRACE_DEBUG("m.getTimeout() procedure...\r\n");
368 
369  //Return default timeout
371 }
372 
373 
374 /**
375  * @brief Obtain key material for use by EAP or lower layers
376  * @param[in] port Pointer to the port context
377  * @return EAP key
378  **/
379 
381 {
382  //Debug message
383  TRACE_DEBUG("m.getKey() procedure...\r\n");
384 
385  //Not implemented
386  return NULL;
387 }
388 
389 
390 /**
391  * @brief Produce the next request
392  * @param[in] port Pointer to the port context
393  **/
394 
396 {
397  size_t n;
398  EapRequest *request;
399 
400  //Debug message
401  TRACE_DEBUG("m.buildReq() procedure...\r\n");
402 
403  //Identity method?
404  if(port->currentMethod == EAP_METHOD_TYPE_IDENTITY)
405  {
406  //Point to the buffer where to format the EAP packet
407  request = (EapRequest *) port->eapReqData;
408 
409  //Format EAP packet
410  request->code = EAP_CODE_REQUEST;
411  request->identifier = port->currentId;
412  request->type = EAP_METHOD_TYPE_IDENTITY;
413 
414  //Retrieve the length of the user name
415  n = osStrlen("User name:");
416  //Copy user name
417  osMemcpy(request->data, "User name:", n);
418 
419  //Total length of the EAP packet
420  n += sizeof(EapRequest);
421  //Convert the length field to network byte order
422  request->length = htons(n);
423 
424  //Debug message
425  TRACE_DEBUG("Port %" PRIu8 ": Sending EAP packet (%" PRIuSIZE " bytes)...\r\n",
426  port->portIndex, n);
427 
428  //Dump EAP header contents for debugging purpose
429  eapDumpHeader((EapPacket *) request);
430 
431  //Save the length of the EAP request
432  port->eapReqDataLen = n;
433  }
434  else
435  {
436  //Unknown EAP method
437  port->eapReqDataLen = 0;
438  }
439 }
440 
441 
442 /**
443  * @brief Determine the identifier value for the current EAP request
444  * @param[in] eapReqData Pointer to the EAP request
445  * @param[in] eapReqDataLen Length of the EAP request, in bytes
446  * @return Identifier value
447  **/
448 
449 uint_t eapGetId(const uint8_t *eapReqData, size_t eapReqDataLen)
450 {
451  uint_t id;
452  const EapPacket *packet;
453 
454  //Debug message
455  TRACE_DEBUG("getId() procedure...\r\n");
456 
457  //Check the length of the EAP packet
458  if(eapReqDataLen >= sizeof(EapPacket))
459  {
460  //Point to the EAP packet
461  packet = (EapPacket *) eapReqData;
462  //The Identifier field is one octet
463  id = packet->identifier;
464  }
465  else
466  {
467  //Malformed EAP packet
468  id = EAP_CURRENT_ID_NONE;
469  }
470 
471  //Return identifier value
472  return id;
473 }
474 
475 #endif
#define htons(value)
Definition: cpu_endian.h:413
int bool_t
Definition: compiler_port.h:53
void eapDumpHeader(const EapPacket *header)
Dump EAP header for debugging purpose.
Definition: eap_debug.c:105
EapMethodType
EAP method types.
Definition: eap.h:164
@ EAP_CODE_RESPONSE
Response.
Definition: eap.h:153
@ EAP_DECISION_CONTINUE
@ EAP_METHOD_TYPE_NONE
None.
Definition: eap.h:165
#define TRUE
Definition: os_port.h:50
@ EAP_CODE_FAILURE
Failure.
Definition: eap.h:155
@ EAP_DECISION_PASSTHROUGH
#define osStrlen(s)
Definition: os_port.h:165
void eapProcessResp(AuthenticatorPort *port)
Parse and process a response.
bool_t eapIsDone(AuthenticatorPort *port)
Check for method completion.
#define AUTHENTICATOR_DEFAULT_METHOD_TIMEOUT
uint_t eapNextId(uint_t id)
Determine the next identifier value to use.
Authenticator state machine procedures.
void eapReset(AuthenticatorPort *port)
The method is ending in the middle of or before completion.
#define FALSE
Definition: os_port.h:46
void eapParseResp(AuthenticatorPort *port)
Determine the code, identifier value, and type of the current response.
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
802.1X authenticator
@ EAP_METHOD_TYPE_IDENTITY
Identity.
Definition: eap.h:166
uint_t eapGetId(const uint8_t *eapReqData, size_t eapReqDataLen)
Determine the identifier value for the current EAP request.
void eapBuildFailure(AuthenticatorPort *port)
Create an EAP failure packet.
@ EAP_CODE_SUCCESS
Success.
Definition: eap.h:154
bool_t eapCheckResp(AuthenticatorPort *port)
Test for the validity of a message.
@ EAP_CODE_REQUEST
Request.
Definition: eap.h:152
EapResponse
Definition: eap.h:252
EapDecision
Decisions.
void eapBuildSuccess(AuthenticatorPort *port)
Create an EAP success packet.
uint16_t port
Definition: dns_common.h:267
EapRequest
Definition: eap.h:238
void eapPolicyUpdate(AuthenticatorPort *port)
Update all variables related to internal policy state.
#define TRACE_DEBUG(...)
Definition: debug.h:107
void eapInit(AuthenticatorPort *port)
Method procedure to initialize state just before use.
Data logging functions for debugging purpose (EAP)
void eapBuildReq(AuthenticatorPort *port)
Produce the next request.
uint8_t n
EapPacket
Definition: eap.h:224
EapMethodType eapPolicyGetNextMethod(AuthenticatorPort *port)
Determine the method that should be used at this point in the conversation.
#define EAP_CURRENT_ID_NONE
uint_t eapGetTimeout(AuthenticatorPort *port)
Determine an appropriate timeout hint for the method.
#define PRIuSIZE
unsigned int uint_t
Definition: compiler_port.h:50
#define AuthenticatorPort
Definition: authenticator.h:40
Debugging facilities.
EapDecision eapPolicyGetDecision(AuthenticatorPort *port)
Determine if the policy will allow SUCCESS, FAIL, or is yet to determine.
uint8_t * eapAuthGetKey(AuthenticatorPort *port)
Obtain key material for use by EAP or lower layers.
uint_t eapCalculateTimeout(AuthenticatorPort *port)
Calculate retransmission timeout.