authenticator.c
Go to the documentation of this file.
1 /**
2  * @file authenticator.c
3  * @brief 802.1X authenticator
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2022-2026 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.6.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL AUTHENTICATOR_TRACE_LEVEL
33 
34 //Dependencies
39 #include "radius/radius.h"
40 #include "debug.h"
41 
42 //Check EAP library configuration
43 #if (AUTHENTICATOR_SUPPORT == ENABLED)
44 
45 
46 /**
47  * @brief Initialize settings with default values
48  * @param[out] settings Structure that contains 802.1X authenticator settings
49  **/
50 
52 {
53  //Default task parameters
54  settings->task = OS_TASK_DEFAULT_PARAMS;
57 
58  //Peer interface
59  settings->interface = NULL;
60 
61  //Number of ports
62  settings->numPorts = 0;
63  //Ports
64  settings->ports = NULL;
65 
66  //RADIUS server interface
67  settings->serverInterface = NULL;
68  //Switch port used to reach the RADIUS server
69  settings->serverPortIndex = 0;
70 
71  //RADIUS server's IP address
73  //RADIUS server's port
74  settings->serverPort = RADIUS_PORT;
75 
76  //Pseudo-random number generator
77  settings->prngAlgo = NULL;
78  settings->prngContext = NULL;
79 
80  //Authenticator PAE state change callback function
81  settings->paeStateChangeCallback = NULL;
82  //Backend authentication state change callback function
83  settings->backendStateChangeCallback = NULL;
84  //Reauthentication timer state change callback function
85  settings->reauthTimerStateChangeCallback = NULL;
86  //EAP full authenticator state change callback function
87  settings->eapFullAuthStateChangeCallback = NULL;
88  //Tick callback function
89  settings->tickCallback = NULL;
90 }
91 
92 
93 /**
94  * @brief Initialize 802.1X authenticator context
95  * @param[in] context Pointer to the 802.1X authenticator context
96  * @param[in] settings 802.1X authenticator specific settings
97  * @return Error code
98  **/
99 
101  const AuthenticatorSettings *settings)
102 {
103  error_t error;
104  uint_t i;
106 
107  //Debug message
108  TRACE_INFO("Initializing 802.1X authenticator...\r\n");
109 
110  //Ensure the parameters are valid
111  if(context == NULL || settings == NULL)
113 
114  if(settings->interface == NULL)
116 
117  if(settings->numPorts == 0 || settings->ports == NULL)
119 
120  if(settings->prngAlgo == NULL || settings->prngContext == NULL)
122 
123  //Clear authenticator context
124  osMemset(context, 0, sizeof(AuthenticatorContext));
125 
126  //Initialize task parameters
127  context->taskParams = settings->task;
128  context->taskId = OS_INVALID_TASK_ID;
129 
130  //Attach TCP/IP stack context
131  context->netContext = settings->interface->netContext;
132 
133  //Save user settings
134  context->interface = settings->interface;
135  context->numPorts = settings->numPorts;
136  context->ports = settings->ports;
137  context->serverPortIndex = settings->serverPortIndex;
138  context->serverIpAddr = settings->serverIpAddr;
139  context->serverPort = settings->serverPort;
140  context->prngAlgo = settings->prngAlgo;
141  context->prngContext = settings->prngContext;
142  context->paeStateChangeCallback = settings->paeStateChangeCallback;
143  context->backendStateChangeCallback = settings->backendStateChangeCallback;
144  context->reauthTimerStateChangeCallback = settings->reauthTimerStateChangeCallback;
145  context->eapFullAuthStateChangeCallback = settings->eapFullAuthStateChangeCallback;
146  context->tickCallback = settings->tickCallback;
147 
148  //Select the interface used to reach the RADIUS server
149  if(settings->serverInterface != NULL)
150  {
151  context->serverInterface = settings->serverInterface;
152  }
153  else
154  {
155  context->serverInterface = settings->interface;
156  }
157 
158  //Loop through the ports
159  for(i = 0; i < context->numPorts; i++)
160  {
161  //Point to the current port
162  port = &context->ports[i];
163 
164  //Clear port context
165  osMemset(port, 0, sizeof(AuthenticatorPort));
166 
167  //Attach authenticator context to each port
168  port->context = context;
169  //Set port index
170  port->portIndex = i + 1;
171 
172  //Default value of parameters
179  port->reAuthEnabled = FALSE;
180  port->keyTxEnabled = FALSE;
181 
182  //Each port must assigned a unique MAC address
184 
185  //The port is down
186  port->sessionStats.sessionTerminateCause =
188  }
189 
190  //Initialize authenticator state machine
191  authenticatorInitFsm(context);
192 
193  //Start of exception handling block
194  do
195  {
196  //Create a mutex to prevent simultaneous access to 802.1X authenticator
197  //context
198  if(!osCreateMutex(&context->mutex))
199  {
200  //Failed to create mutex
201  error = ERROR_OUT_OF_RESOURCES;
202  break;
203  }
204 
205  //Create an event object to poll the state of sockets
206  if(!osCreateEvent(&context->event))
207  {
208  //Failed to create event
209  error = ERROR_OUT_OF_RESOURCES;
210  break;
211  }
212 
213  //Successful initialization
214  error = NO_ERROR;
215 
216  //End of exception handling block
217  } while(0);
218 
219  //Any error to report?
220  if(error)
221  {
222  //Clean up side effects
223  authenticatorDeinit(context);
224  }
225 
226  //Return status code
227  return error;
228 }
229 
230 
231 /**
232  * @brief Specify the IP address of the RADIUS server
233  * @param[in] context Pointer to the 802.1X authenticator context
234  * @param[in] serverIpAddr IP address of the RADIUS server
235  * @param[in] serverPort Port number
236  * @return Error code
237  **/
238 
240  const IpAddr *serverIpAddr, uint16_t serverPort)
241 {
242  //Check parameters
243  if(context == NULL || serverIpAddr == NULL)
245 
246  //Acquire exclusive access to the 802.1X authenticator context
247  osAcquireMutex(&context->mutex);
248 
249  //Save the IP address and the port number of the RADIUS server
250  context->serverIpAddr = *serverIpAddr;
251  context->serverPort = serverPort;
252 
253  //Release exclusive access to the 802.1X authenticator context
254  osReleaseMutex(&context->mutex);
255 
256  //Successful processing
257  return NO_ERROR;
258 }
259 
260 
261 /**
262  * @brief Set RADIUS server's key
263  * @param[in] context Pointer to the 802.1X authenticator context
264  * @param[in] key Pointer to the key
265  * @param[in] keyLen Length of the key, in bytes
266  * @return Error code
267  **/
268 
270  const uint8_t *key, size_t keyLen)
271 {
272  //Make sure the 802.1X authenticator context is valid
273  if(context == NULL)
275 
276  //Check parameters
277  if(key == NULL && keyLen != 0)
279 
280  //Check the length of the key
282  return ERROR_INVALID_LENGTH;
283 
284  //Acquire exclusive access to the 802.1X authenticator context
285  osAcquireMutex(&context->mutex);
286 
287  //Copy key
288  osMemcpy(context->serverKey, key, keyLen);
289  //Save the length of the key
290  context->serverKeyLen = keyLen;
291 
292  //Release exclusive access to the 802.1X authenticator context
293  osReleaseMutex(&context->mutex);
294 
295  //Successful processing
296  return NO_ERROR;
297 }
298 
299 
300 /**
301  * @brief Reinitialize the specified port
302  * @param[in] context Pointer to the 802.1X authenticator context
303  * @param[in] portIndex Port index
304  * @return Error code
305  **/
306 
308  uint_t portIndex)
309 {
310  error_t error;
311 
312  //Make sure the 802.1X authenticator context is valid
313  if(context != NULL)
314  {
315  //Acquire exclusive access to the 802.1X authenticator context
316  osAcquireMutex(&context->mutex);
317 
318  //Perform management operation
319  error = authenticatorMgmtSetInitialize(context, portIndex, TRUE,
320  TRUE);
321 
322  //Release exclusive access to the 802.1X authenticator context
323  osReleaseMutex(&context->mutex);
324  }
325  else
326  {
327  //Report an error
328  error = ERROR_INVALID_PARAMETER;
329  }
330 
331  //Return status code
332  return error;
333 }
334 
335 
336 /**
337  * @brief Force the authenticator to reauthenticate the supplicant
338  * @param[in] context Pointer to the 802.1X authenticator context
339  * @param[in] portIndex Port index
340  * @return Error code
341  **/
342 
344  uint_t portIndex)
345 {
346  error_t error;
347 
348  //Make sure the 802.1X authenticator context is valid
349  if(context != NULL)
350  {
351  //Acquire exclusive access to the 802.1X authenticator context
352  osAcquireMutex(&context->mutex);
353 
354  //Perform management operation
355  error = authenticatorMgmtSetReauthenticate(context, portIndex, TRUE,
356  TRUE);
357 
358  //Release exclusive access to the 802.1X authenticator context
359  osReleaseMutex(&context->mutex);
360  }
361  else
362  {
363  //Report an error
364  error = ERROR_INVALID_PARAMETER;
365  }
366 
367  //Return status code
368  return error;
369 }
370 
371 
372 /**
373  * @brief Set the value of the AuthControlledPortControl parameter
374  * @param[in] context Pointer to the 802.1X authenticator context
375  * @param[in] portIndex Port index
376  * @param[in] portControl Value of the AuthControlledPortControl parameter
377  * @return Error code
378  **/
379 
381  uint_t portIndex, AuthenticatorPortMode portControl)
382 {
383  error_t error;
384 
385  //Make sure the 802.1X authenticator context is valid
386  if(context != NULL)
387  {
388  //Acquire exclusive access to the 802.1X authenticator context
389  osAcquireMutex(&context->mutex);
390 
391  //Perform management operation
392  error = authenticatorMgmtSetPortControl(context, portIndex, portControl,
393  TRUE);
394 
395  //Release exclusive access to the 802.1X authenticator context
396  osReleaseMutex(&context->mutex);
397  }
398  else
399  {
400  //Report an error
401  error = ERROR_INVALID_PARAMETER;
402  }
403 
404  //Return status code
405  return error;
406 }
407 
408 
409 /**
410  * @brief Set the value of the quietPeriod parameter
411  * @param[in] context Pointer to the 802.1X authenticator context
412  * @param[in] portIndex Port index
413  * @param[in] quietPeriod Value of the quietPeriod parameter
414  * @return Error code
415  **/
416 
418  uint_t portIndex, uint_t quietPeriod)
419 {
420  error_t error;
421 
422  //Make sure the 802.1X authenticator context is valid
423  if(context != NULL)
424  {
425  //Acquire exclusive access to the 802.1X authenticator context
426  osAcquireMutex(&context->mutex);
427 
428  //Perform management operation
429  error = authenticatorMgmtSetQuietPeriod(context, portIndex, quietPeriod,
430  TRUE);
431 
432  //Release exclusive access to the 802.1X authenticator context
433  osReleaseMutex(&context->mutex);
434  }
435  else
436  {
437  //Report an error
438  error = ERROR_INVALID_PARAMETER;
439  }
440 
441  //Return status code
442  return error;
443 }
444 
445 
446 /**
447  * @brief Set the value of the serverTimeout parameter
448  * @param[in] context Pointer to the 802.1X authenticator context
449  * @param[in] portIndex Port index
450  * @param[in] serverTimeout Value of the serverTimeout parameter
451  * @return Error code
452  **/
453 
455  uint_t portIndex, uint_t serverTimeout)
456 {
457  error_t error;
458 
459  //Make sure the 802.1X authenticator context is valid
460  if(context != NULL)
461  {
462  //Acquire exclusive access to the 802.1X authenticator context
463  osAcquireMutex(&context->mutex);
464 
465  //Perform management operation
466  error = authenticatorMgmtSetServerTimeout(context, portIndex,
467  serverTimeout, TRUE);
468 
469  //Release exclusive access to the 802.1X authenticator context
470  osReleaseMutex(&context->mutex);
471  }
472  else
473  {
474  //Report an error
475  error = ERROR_INVALID_PARAMETER;
476  }
477 
478  //Return status code
479  return error;
480 }
481 
482 
483 /**
484  * @brief Set the value of the reAuthEnabled parameter
485  * @param[in] context Pointer to the 802.1X authenticator context
486  * @param[in] portIndex Port index
487  * @param[in] reAuthEnabled Value of the reAuthEnabled parameter
488  * @return Error code
489  **/
490 
492  uint_t portIndex, bool_t reAuthEnabled)
493 {
494  error_t error;
495 
496  //Make sure the 802.1X authenticator context is valid
497  if(context != NULL)
498  {
499  //Acquire exclusive access to the 802.1X authenticator context
500  osAcquireMutex(&context->mutex);
501 
502  //Perform management operation
503  error = authenticatorMgmtSetReAuthEnabled(context, portIndex,
504  reAuthEnabled, TRUE);
505 
506  //Release exclusive access to the 802.1X authenticator context
507  osReleaseMutex(&context->mutex);
508  }
509  else
510  {
511  //Report an error
512  error = ERROR_INVALID_PARAMETER;
513  }
514 
515  //Return status code
516  return error;
517 }
518 
519 
520 /**
521  * @brief Set the value of the reAuthPeriod parameter
522  * @param[in] context Pointer to the 802.1X authenticator context
523  * @param[in] portIndex Port index
524  * @param[in] reAuthPeriod Value of the reAuthPeriod parameter
525  * @return Error code
526  **/
527 
529  uint_t portIndex, uint_t reAuthPeriod)
530 {
531  error_t error;
532 
533  //Make sure the 802.1X authenticator context is valid
534  if(context != NULL)
535  {
536  //Acquire exclusive access to the 802.1X authenticator context
537  osAcquireMutex(&context->mutex);
538 
539  //Perform management operation
540  error = authenticatorMgmtSetReAuthPeriod(context, portIndex,
541  reAuthPeriod, TRUE);
542 
543  //Release exclusive access to the 802.1X authenticator context
544  osReleaseMutex(&context->mutex);
545  }
546  else
547  {
548  //Report an error
549  error = ERROR_INVALID_PARAMETER;
550  }
551 
552  //Return status code
553  return error;
554 }
555 
556 
557 /**
558  * @brief Get the current value of the AuthControlledPortControl parameter
559  * @param[in] context Pointer to the 802.1X authenticator context
560  * @param[in] portIndex Port index
561  * @param[out] portControl value of the AuthControlledPortControl parameter
562  * @return Error code
563  **/
564 
566  uint_t portIndex, AuthenticatorPortMode *portControl)
567 {
568  //Check parameters
569  if(context == NULL || portControl == NULL)
571 
572  //Invalid port index?
573  if(portIndex < 1 || portIndex > context->numPorts)
574  return ERROR_INVALID_PORT;
575 
576  //Acquire exclusive access to the 802.1X authenticator context
577  osAcquireMutex(&context->mutex);
578  //Get the current value of the parameter
579  *portControl = context->ports[portIndex - 1].portControl;
580  //Release exclusive access to the 802.1X authenticator context
581  osReleaseMutex(&context->mutex);
582 
583  //Successful processing
584  return NO_ERROR;
585 }
586 
587 
588 /**
589  * @brief Get the current value of the quietPeriod parameter
590  * @param[in] context Pointer to the 802.1X authenticator context
591  * @param[in] portIndex Port index
592  * @param[out] quietPeriod value of the quietPeriod parameter
593  * @return Error code
594  **/
595 
597  uint_t portIndex, uint_t *quietPeriod)
598 {
599  //Check parameters
600  if(context == NULL || quietPeriod == NULL)
602 
603  //Invalid port index?
604  if(portIndex < 1 || portIndex > context->numPorts)
605  return ERROR_INVALID_PORT;
606 
607  //Acquire exclusive access to the 802.1X authenticator context
608  osAcquireMutex(&context->mutex);
609  //Get the current value of the parameter
610  *quietPeriod = context->ports[portIndex - 1].quietPeriod;
611  //Release exclusive access to the 802.1X authenticator context
612  osReleaseMutex(&context->mutex);
613 
614  //Successful processing
615  return NO_ERROR;
616 }
617 
618 
619 /**
620  * @brief Get the current value of the serverTimeout parameter
621  * @param[in] context Pointer to the 802.1X authenticator context
622  * @param[in] portIndex Port index
623  * @param[out] serverTimeout value of the serverTimeout parameter
624  * @return Error code
625  **/
626 
628  uint_t portIndex, uint_t *serverTimeout)
629 {
630  //Check parameters
631  if(context == NULL || serverTimeout == NULL)
633 
634  //Invalid port index?
635  if(portIndex < 1 || portIndex > context->numPorts)
636  return ERROR_INVALID_PORT;
637 
638  //Acquire exclusive access to the 802.1X authenticator context
639  osAcquireMutex(&context->mutex);
640  //Get the current value of the parameter
641  *serverTimeout = context->ports[portIndex - 1].serverTimeout;
642  //Release exclusive access to the 802.1X authenticator context
643  osReleaseMutex(&context->mutex);
644 
645  //Successful processing
646  return NO_ERROR;
647 }
648 
649 
650 /**
651  * @brief Get the current value of the reAuthEnabled parameter
652  * @param[in] context Pointer to the 802.1X authenticator context
653  * @param[in] portIndex Port index
654  * @param[out] reAuthEnabled value of the reAuthEnabled parameter
655  * @return Error code
656  **/
657 
659  uint_t portIndex, bool_t *reAuthEnabled)
660 {
661  //Check parameters
662  if(context == NULL || reAuthEnabled == NULL)
664 
665  //Invalid port index?
666  if(portIndex < 1 || portIndex > context->numPorts)
667  return ERROR_INVALID_PORT;
668 
669  //Acquire exclusive access to the 802.1X authenticator context
670  osAcquireMutex(&context->mutex);
671  //Get the current value of the parameter
672  *reAuthEnabled = context->ports[portIndex - 1].reAuthEnabled;
673  //Release exclusive access to the 802.1X authenticator context
674  osReleaseMutex(&context->mutex);
675 
676  //Successful processing
677  return NO_ERROR;
678 }
679 
680 
681 /**
682  * @brief Get the current value of the reAuthPeriod parameter
683  * @param[in] context Pointer to the 802.1X authenticator context
684  * @param[in] portIndex Port index
685  * @param[out] reAuthPeriod value of the reAuthPeriod parameter
686  * @return Error code
687  **/
688 
690  uint_t portIndex, uint_t *reAuthPeriod)
691 {
692  //Check parameters
693  if(context == NULL || reAuthPeriod == NULL)
695 
696  //Invalid port index?
697  if(portIndex < 1 || portIndex > context->numPorts)
698  return ERROR_INVALID_PORT;
699 
700  //Acquire exclusive access to the 802.1X authenticator context
701  osAcquireMutex(&context->mutex);
702  //Get the current value of the parameter
703  *reAuthPeriod = context->ports[portIndex - 1].reAuthPeriod;
704  //Release exclusive access to the 802.1X authenticator context
705  osReleaseMutex(&context->mutex);
706 
707  //Successful processing
708  return NO_ERROR;
709 }
710 
711 
712 /**
713  * @brief Get the current value of the AuthControlledPortStatus variable
714  * @param[in] context Pointer to the 802.1X authenticator context
715  * @param[in] portIndex Port index
716  * @param[out] portStatus Current value of the AuthControlledPortStatus variable
717  * @return Error code
718  **/
719 
721  uint_t portIndex, AuthenticatorPortStatus *portStatus)
722 {
723  //Check parameters
724  if(context == NULL || portStatus == NULL)
726 
727  //Invalid port index?
728  if(portIndex < 1 || portIndex > context->numPorts)
729  return ERROR_INVALID_PORT;
730 
731  //Acquire exclusive access to the 802.1X authenticator context
732  osAcquireMutex(&context->mutex);
733  //Get the current value of the variable
734  *portStatus = context->ports[portIndex - 1].authPortStatus;
735  //Release exclusive access to the 802.1X authenticator context
736  osReleaseMutex(&context->mutex);
737 
738  //Successful processing
739  return NO_ERROR;
740 }
741 
742 
743 /**
744  * @brief Get the current state of the authenticator PAE state state machine
745  * @param[in] context Pointer to the 802.1X authenticator context
746  * @param[in] portIndex Port index
747  * @param[out] paeState Current state of the authenticator PAE state machine
748  * @return Error code
749  **/
750 
752  uint_t portIndex, AuthenticatorPaeState *paeState)
753 {
754  //Check parameters
755  if(context == NULL || paeState == NULL)
757 
758  //Invalid port index?
759  if(portIndex < 1 || portIndex > context->numPorts)
760  return ERROR_INVALID_PORT;
761 
762  //Acquire exclusive access to the 802.1X authenticator context
763  osAcquireMutex(&context->mutex);
764  //Get the current state
765  *paeState = context->ports[portIndex - 1].authPaeState;
766  //Release exclusive access to the 802.1X authenticator context
767  osReleaseMutex(&context->mutex);
768 
769  //Successful processing
770  return NO_ERROR;
771 }
772 
773 
774 /**
775  * @brief Get the current state of the backend authentication state machine
776  * @param[in] context Pointer to the 802.1X authenticator context
777  * @param[in] portIndex Port index
778  * @param[out] backendState Current state of the backend authentication state
779  * machine
780  * @return Error code
781  **/
782 
784  uint_t portIndex, AuthenticatorBackendState *backendState)
785 {
786  //Check parameters
787  if(context == NULL || backendState == NULL)
789 
790  //Invalid port index?
791  if(portIndex < 1 || portIndex > context->numPorts)
792  return ERROR_INVALID_PORT;
793 
794  //Acquire exclusive access to the 802.1X authenticator context
795  osAcquireMutex(&context->mutex);
796  //Get the current state
797  *backendState = context->ports[portIndex - 1].authBackendState;
798  //Release exclusive access to the 802.1X authenticator context
799  osReleaseMutex(&context->mutex);
800 
801  //Successful processing
802  return NO_ERROR;
803 }
804 
805 
806 /**
807  * @brief Get the current state of the reauthentication timer state machine
808  * @param[in] context Pointer to the 802.1X authenticator context
809  * @param[in] portIndex Port index
810  * @param[out] reauthTimerState Current state of the reauthentication timer state
811  * machine
812  * @return Error code
813  **/
814 
816  uint_t portIndex, AuthenticatorReauthTimerState *reauthTimerState)
817 {
818  //Check parameters
819  if(context == NULL || reauthTimerState == NULL)
821 
822  //Invalid port index?
823  if(portIndex < 1 || portIndex > context->numPorts)
824  return ERROR_INVALID_PORT;
825 
826  //Acquire exclusive access to the 802.1X authenticator context
827  osAcquireMutex(&context->mutex);
828  //Get the current state
829  *reauthTimerState = context->ports[portIndex - 1].reauthTimerState;
830  //Release exclusive access to the 802.1X authenticator context
831  osReleaseMutex(&context->mutex);
832 
833  //Successful processing
834  return NO_ERROR;
835 }
836 
837 
838 /**
839  * @brief Get the current state of the EAP full authenticator state machine
840  * @param[in] context Pointer to the 802.1X authenticator context
841  * @param[in] portIndex Port index
842  * @param[out] eapFullAuthState Current state of the EAP full authenticator state
843  * machine
844  * @return Error code
845  **/
846 
848  uint_t portIndex, EapFullAuthState *eapFullAuthState)
849 {
850  //Check parameters
851  if(context == NULL || eapFullAuthState == NULL)
853 
854  //Invalid port index?
855  if(portIndex < 1 || portIndex > context->numPorts)
856  return ERROR_INVALID_PORT;
857 
858  //Acquire exclusive access to the 802.1X authenticator context
859  osAcquireMutex(&context->mutex);
860  //Get the current state
861  *eapFullAuthState = context->ports[portIndex - 1].eapFullAuthState;
862  //Release exclusive access to the 802.1X authenticator context
863  osReleaseMutex(&context->mutex);
864 
865  //Successful processing
866  return NO_ERROR;
867 }
868 
869 
870 /**
871  * @brief Start 802.1X authenticator
872  * @param[in] context Pointer to the 802.1X authenticator context
873  * @return Error code
874  **/
875 
877 {
878  error_t error;
879 
880  //Make sure the 802.1X authenticator context is valid
881  if(context == NULL)
883 
884  //Debug message
885  TRACE_INFO("Starting 802.1X authenticator...\r\n");
886 
887  //Make sure the authenticator is not already running
888  if(context->running)
889  return ERROR_ALREADY_RUNNING;
890 
891  //Start of exception handling block
892  do
893  {
894  //Open a UDP socket
895  context->serverSocket = socketOpenEx(context->netContext,
897  //Failed to open socket?
898  if(context->serverSocket == NULL)
899  {
900  //Report an error
901  error = ERROR_OPEN_FAILED;
902  break;
903  }
904 
905  //Force the socket to operate in non-blocking mode
906  error = socketSetTimeout(context->serverSocket, 0);
907  //Any error to report?
908  if(error)
909  break;
910 
911  //Associate the socket with the relevant interface
912  error = socketBindToInterface(context->serverSocket,
913  context->serverInterface);
914  //Any error to report?
915  if(error)
916  break;
917 
918  //Open a raw socket
919  context->peerSocket = socketOpenEx(context->netContext,
921  //Failed to open socket?
922  if(context->peerSocket == NULL)
923  {
924  //Report an error
925  error = ERROR_OPEN_FAILED;
926  break;
927  }
928 
929  //Force the socket to operate in non-blocking mode
930  error = socketSetTimeout(context->peerSocket, 0);
931  //Any error to report?
932  if(error)
933  break;
934 
935  //Associate the socket with the relevant interface
936  error = socketBindToInterface(context->peerSocket, context->interface);
937  //Any error to report?
938  if(error)
939  break;
940 
941  //The PAE group address is one of the reserved set of group MAC addresses
942  //that are not forwarded by MAC Bridges (refer to IEEE Std 802.1X-2010,
943  //section 7.8)
944  error = authenticatorAcceptPaeGroupAddr(context);
945  //Any error to report?
946  if(error)
947  break;
948 
949  //Start the authenticator
950  context->stop = FALSE;
951  context->running = TRUE;
952 
953  //Save current time
954  context->timestamp = osGetSystemTime();
955 
956  //Reinitialize authenticator state machine
957  authenticatorInitFsm(context);
958 
959  //Create a task
960  context->taskId = osCreateTask("Authenticator", (OsTaskCode) authenticatorTask,
961  context, &context->taskParams);
962 
963  //Failed to create task?
964  if(context->taskId == OS_INVALID_TASK_ID)
965  {
966  //Report an error
967  error = ERROR_OUT_OF_RESOURCES;
968  break;
969  }
970 
971  //End of exception handling block
972  } while(0);
973 
974  //Any error to report?
975  if(error)
976  {
977  //Clean up side effects
978  context->running = FALSE;
979 
980  //Remove the PAE group address from the static MAC table
982 
983  //Close the raw socket
984  if(context->peerSocket != NULL)
985  {
986  socketClose(context->peerSocket);
987  context->peerSocket = NULL;
988  }
989 
990  //Close the UDP socket
991  if(context->serverSocket != NULL)
992  {
993  socketClose(context->serverSocket);
994  context->serverSocket = NULL;
995  }
996  }
997 
998  //Return status code
999  return error;
1000 }
1001 
1002 
1003 /**
1004  * @brief Stop 802.1X authenticator
1005  * @param[in] context Pointer to the 802.1X authenticator context
1006  * @return Error code
1007  **/
1008 
1010 {
1011  //Make sure the 802.1X authenticator context is valid
1012  if(context == NULL)
1013  return ERROR_INVALID_PARAMETER;
1014 
1015  //Debug message
1016  TRACE_INFO("Stopping 802.1X authenticator...\r\n");
1017 
1018  //Check whether the authenticator is running
1019  if(context->running)
1020  {
1021 #if (NET_RTOS_SUPPORT == ENABLED)
1022  //Stop the authenticator
1023  context->stop = TRUE;
1024  //Send a signal to the task to abort any blocking operation
1025  osSetEvent(&context->event);
1026 
1027  //Wait for the task to terminate
1028  while(context->running)
1029  {
1030  osDelayTask(1);
1031  }
1032 #endif
1033 
1034  //Remove the PAE group address from the static MAC table
1036 
1037  //Close the raw socket
1038  socketClose(context->peerSocket);
1039  context->peerSocket = NULL;
1040 
1041  //Close the UDP socket
1042  socketClose(context->serverSocket);
1043  context->serverSocket = NULL;
1044  }
1045 
1046  //Successful processing
1047  return NO_ERROR;
1048 }
1049 
1050 
1051 /**
1052  * @brief 802.1X authenticator task
1053  * @param[in] context Pointer to the 802.1X authenticator context
1054  **/
1055 
1057 {
1058  systime_t time;
1059  systime_t timeout;
1060  SocketEventDesc eventDesc[2];
1061 
1062 #if (NET_RTOS_SUPPORT == ENABLED)
1063  //Task prologue
1064  osEnterTask();
1065 
1066  //Process events
1067  while(1)
1068  {
1069 #endif
1070  //Get current time
1071  time = osGetSystemTime();
1072 
1073  //Maximum time to wait for an incoming datagram
1074  if((time - context->timestamp) < AUTHENTICATOR_TICK_INTERVAL)
1075  {
1076  timeout = context->timestamp + AUTHENTICATOR_TICK_INTERVAL - time;
1077  }
1078  else
1079  {
1080  timeout = 0;
1081  }
1082 
1083  //Specify the events the application is interested in
1084  eventDesc[0].socket = context->peerSocket;
1085  eventDesc[0].eventMask = SOCKET_EVENT_RX_READY;
1086  eventDesc[0].eventFlags = 0;
1087  eventDesc[1].socket = context->serverSocket;
1088  eventDesc[1].eventMask = SOCKET_EVENT_RX_READY;
1089  eventDesc[1].eventFlags = 0;
1090 
1091  //Wait for an event
1092  socketPoll(eventDesc, 2, &context->event, timeout);
1093 
1094  //Stop request?
1095  if(context->stop)
1096  {
1097  //Stop authenticator operation
1098  context->running = FALSE;
1099  //Task epilogue
1100  osExitTask();
1101  //Kill ourselves
1103  }
1104 
1105  //Any EAPOL packet received?
1106  if(eventDesc[0].eventFlags != 0)
1107  {
1108  //Acquire exclusive access to the 802.1X authenticator context
1109  osAcquireMutex(&context->mutex);
1110  //Process incoming EAPOL packet
1112  //Release exclusive access to the 802.1X authenticator context
1113  osReleaseMutex(&context->mutex);
1114  }
1115 
1116  //Any RADIUS packet received?
1117  if(eventDesc[1].eventFlags != 0)
1118  {
1119  //Acquire exclusive access to the 802.1X authenticator context
1120  osAcquireMutex(&context->mutex);
1121  //Process incoming RADIUS packet
1123  //Release exclusive access to the 802.1X authenticator context
1124  osReleaseMutex(&context->mutex);
1125  }
1126 
1127  //Get current time
1128  time = osGetSystemTime();
1129 
1130  //Timers have a resolution of one second
1131  if((time - context->timestamp) >= AUTHENTICATOR_TICK_INTERVAL)
1132  {
1133  //Acquire exclusive access to the 802.1X authenticator context
1134  osAcquireMutex(&context->mutex);
1135  //Handle periodic operations
1136  authenticatorTick(context);
1137  //Release exclusive access to the 802.1X authenticator context
1138  osReleaseMutex(&context->mutex);
1139 
1140  //Save current time
1141  context->timestamp = time;
1142  }
1143 
1144 #if (NET_RTOS_SUPPORT == ENABLED)
1145  }
1146 #endif
1147 }
1148 
1149 
1150 /**
1151  * @brief Release 802.1X authenticator context
1152  * @param[in] context Pointer to the 802.1X authenticator context
1153  **/
1154 
1156 {
1157  //Make sure the 802.1X authenticator context is valid
1158  if(context != NULL)
1159  {
1160  //Free previously allocated resources
1161  osDeleteMutex(&context->mutex);
1162  osDeleteEvent(&context->event);
1163 
1164  //Clear authenticator context
1165  osMemset(context, 0, sizeof(AuthenticatorContext));
1166  }
1167 }
1168 
1169 #endif
error_t authenticatorSetServerAddr(AuthenticatorContext *context, const IpAddr *serverIpAddr, uint16_t serverPort)
Specify the IP address of the RADIUS server.
OsTaskId osCreateTask(const char_t *name, OsTaskCode taskCode, void *arg, const OsTaskParameters *params)
Create a task.
@ SOCKET_IP_PROTO_UDP
Definition: socket.h:108
error_t authenticatorGetPortControl(AuthenticatorContext *context, uint_t portIndex, AuthenticatorPortMode *portControl)
Get the current value of the AuthControlledPortControl parameter.
int bool_t
Definition: compiler_port.h:63
@ AUTHENTICATOR_TERMINATE_CAUSE_PORT_FAILURE
error_t authenticatorMgmtSetQuietPeriod(AuthenticatorContext *context, uint_t portIndex, uint_t quietPeriod, bool_t commit)
Set the value of the quietPeriod parameter.
bool_t osCreateMutex(OsMutex *mutex)
Create a mutex object.
#define RADIUS_PORT
Definition: radius.h:45
AuthenticatorPortStatus
Port status.
OsTaskParameters task
Task parameters.
#define osExitTask()
void authenticatorGeneratePortAddr(AuthenticatorPort *port)
Port's MAC address generation.
IP network address.
Definition: ip.h:90
error_t authenticatorStart(AuthenticatorContext *context)
Start 802.1X authenticator.
error_t authenticatorGetPaeState(AuthenticatorContext *context, uint_t portIndex, AuthenticatorPaeState *paeState)
Get the current state of the authenticator PAE state state machine.
void authenticatorProcessRadiusPacket(AuthenticatorContext *context)
Process incoming RADIUS packet.
@ AUTHENTICATOR_PORT_MODE_FORCE_AUTH
const IpAddr IP_ADDR_UNSPECIFIED
Definition: ip.c:54
#define TRUE
Definition: os_port.h:50
error_t authenticatorSetPortControl(AuthenticatorContext *context, uint_t portIndex, AuthenticatorPortMode portControl)
Set the value of the AuthControlledPortControl parameter.
#define OS_INVALID_TASK_ID
void authenticatorInitFsm(AuthenticatorContext *context)
Authenticator state machine initialization.
uint_t numPorts
Number of ports.
void socketClose(Socket *socket)
Close an existing socket.
Definition: socket.c:2094
error_t authenticatorSetReAuthEnabled(AuthenticatorContext *context, uint_t portIndex, bool_t reAuthEnabled)
Set the value of the reAuthEnabled parameter.
@ ERROR_OUT_OF_RESOURCES
Definition: error.h:64
NetInterface * serverInterface
RADIUS server interface.
error_t authenticatorMgmtSetServerTimeout(AuthenticatorContext *context, uint_t portIndex, uint_t serverTimeout, bool_t commit)
Set the value of the serverTimeout parameter.
#define AUTHENTICATOR_DEFAULT_REAUTH_MAX
@ SOCKET_TYPE_DGRAM
Definition: socket.h:93
NetInterface * interface
Underlying network interface.
AuthenticatorPaeState
Authenticator PAE states.
error_t authenticatorInitPort(AuthenticatorContext *context, uint_t portIndex)
Reinitialize the specified port.
error_t authenticatorGetServerTimeout(AuthenticatorContext *context, uint_t portIndex, uint_t *serverTimeout)
Get the current value of the serverTimeout parameter.
@ ERROR_INVALID_PORT
Definition: error.h:104
error_t authenticatorDropPaeGroupAddr(AuthenticatorContext *context)
Remove the PAE group address from the static MAC table.
AuthenticatorTickCallback tickCallback
Tick callback function.
802.1X authenticator settings
#define AUTHENTICATOR_MAX_SERVER_KEY_LEN
Definition: authenticator.h:92
#define OS_SELF_TASK_ID
error_t authenticatorMgmtSetInitialize(AuthenticatorContext *context, uint_t portIndex, bool_t initialize, bool_t commit)
Force the value of the initialize variable.
#define AUTHENTICATOR_PRIORITY
Definition: authenticator.h:66
Structure describing socket events.
Definition: socket.h:433
AuthenticatorBackendStateChangeCallback backendStateChangeCallback
Backend authentication state change callback function.
error_t authenticatorGetBackendState(AuthenticatorContext *context, uint_t portIndex, AuthenticatorBackendState *backendState)
Get the current state of the backend authentication state machine.
EapFullAuthState
EAP full authenticator states.
@ ERROR_OPEN_FAILED
Definition: error.h:75
Helper functions for 802.1X authenticator.
uint_t serverPortIndex
Switch port used to reach the RADIUS server.
error_t authenticatorMgmtSetPortControl(AuthenticatorContext *context, uint_t portIndex, AuthenticatorPortMode portControl, bool_t commit)
Set the value of the AuthControlledPortControl parameter.
#define AUTHENTICATOR_DEFAULT_MAX_RETRANS
void osDeleteTask(OsTaskId taskId)
Delete a task.
AuthenticatorPort * ports
Ports.
#define AUTHENTICATOR_DEFAULT_SERVER_TIMEOUT
error_t authenticatorStop(AuthenticatorContext *context)
Stop 802.1X authenticator.
#define FALSE
Definition: os_port.h:46
error_t authenticatorGetQuietPeriod(AuthenticatorContext *context, uint_t portIndex, uint_t *quietPeriod)
Get the current value of the quietPeriod parameter.
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define osMemcpy(dest, src, length)
Definition: os_port.h:144
802.1X authenticator
error_t
Error codes.
Definition: error.h:43
error_t authenticatorSetReAuthPeriod(AuthenticatorContext *context, uint_t portIndex, uint_t reAuthPeriod)
Set the value of the reAuthPeriod parameter.
AuthenticatorBackendState
Backend authentication states.
error_t authenticatorGetReauthTimerState(AuthenticatorContext *context, uint_t portIndex, AuthenticatorReauthTimerState *reauthTimerState)
Get the current state of the reauthentication timer state machine.
void(* OsTaskCode)(void *arg)
Task routine.
IpAddr serverIpAddr
RADIUS server's IP address.
error_t authenticatorGetEapFullAuthState(AuthenticatorContext *context, uint_t portIndex, EapFullAuthState *eapFullAuthState)
Get the current state of the EAP full authenticator state machine.
error_t authenticatorSetServerKey(AuthenticatorContext *context, const uint8_t *key, size_t keyLen)
Set RADIUS server's key.
void osDeleteEvent(OsEvent *event)
Delete an event object.
@ ERROR_INVALID_LENGTH
Definition: error.h:111
AuthenticatorPaeStateChangeCallback paeStateChangeCallback
Authenticator PAE state change callback function.
const PrngAlgo * prngAlgo
Pseudo-random number generator to be used.
const OsTaskParameters OS_TASK_DEFAULT_PARAMS
RADIUS (Remote Authentication Dial In User Service)
error_t authenticatorInit(AuthenticatorContext *context, const AuthenticatorSettings *settings)
Initialize 802.1X authenticator context.
error_t authenticatorMgmtSetReAuthPeriod(AuthenticatorContext *context, uint_t portIndex, uint_t reAuthPeriod, bool_t commit)
Set the value of the reAuthPeriod parameter.
#define TRACE_INFO(...)
Definition: debug.h:105
@ ETH_TYPE_EAPOL
Definition: ethernet.h:171
error_t authenticatorMgmtSetReauthenticate(AuthenticatorContext *context, uint_t portIndex, bool_t reAuthenticate, bool_t commit)
Force the value of the reAuthenticate variable.
AuthenticatorReauthTimerStateChangeCallback reauthTimerStateChangeCallback
Reauthentication timer state change callback function.
#define osEnterTask()
Authenticator state machine.
uint_t eventFlags
Returned events.
Definition: socket.h:436
error_t authenticatorGetReAuthPeriod(AuthenticatorContext *context, uint_t portIndex, uint_t *reAuthPeriod)
Get the current value of the reAuthPeriod parameter.
error_t socketPoll(SocketEventDesc *eventDesc, uint_t size, OsEvent *extEvent, systime_t timeout)
Wait for one of a set of sockets to become ready to perform I/O.
Definition: socket.c:2182
#define socketBindToInterface
Definition: net_legacy.h:193
Management of the 802.1X authenticator.
error_t authenticatorSetServerTimeout(AuthenticatorContext *context, uint_t portIndex, uint_t serverTimeout)
Set the value of the serverTimeout parameter.
error_t authenticatorAcceptPaeGroupAddr(AuthenticatorContext *context)
Add the PAE group address to the static MAC table.
uint32_t systime_t
System time.
uint16_t port
Definition: dns_common.h:270
error_t authenticatorGetPortStatus(AuthenticatorContext *context, uint_t portIndex, AuthenticatorPortStatus *portStatus)
Get the current value of the AuthControlledPortStatus variable.
AuthenticatorPortMode
Port modes.
#define AuthenticatorContext
Definition: authenticator.h:36
uint32_t time
void osDeleteMutex(OsMutex *mutex)
Delete a mutex object.
error_t authenticatorMgmtSetReAuthEnabled(AuthenticatorContext *context, uint_t portIndex, bool_t reAuthEnabled, bool_t commit)
Set the value of the reAuthEnabled parameter.
@ SOCKET_EVENT_RX_READY
Definition: socket.h:179
error_t authenticatorGetReAuthEnabled(AuthenticatorContext *context, uint_t portIndex, bool_t *reAuthEnabled)
Get the current value of the reAuthEnabled parameter.
void authenticatorTick(AuthenticatorContext *context)
Handle periodic operations.
#define AUTHENTICATOR_DEFAULT_QUIET_PERIOD
Definition: authenticator.h:99
#define AUTHENTICATOR_DEFAULT_REAUTH_PERIOD
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
Socket * socketOpenEx(NetContext *context, uint_t type, uint_t protocol)
Create a socket.
Definition: socket.c:146
#define AUTHENTICATOR_TICK_INTERVAL
Definition: authenticator.h:71
bool_t osCreateEvent(OsEvent *event)
Create an event object.
error_t authenticatorSetQuietPeriod(AuthenticatorContext *context, uint_t portIndex, uint_t quietPeriod)
Set the value of the quietPeriod parameter.
#define AUTHENTICATOR_STACK_SIZE
Definition: authenticator.h:59
@ SOCKET_TYPE_RAW_ETH
Definition: socket.h:95
void * prngContext
Pseudo-random number generator context.
void osDelayTask(systime_t delay)
Delay routine.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
void authenticatorGetDefaultSettings(AuthenticatorSettings *settings)
Initialize settings with default values.
Definition: authenticator.c:51
void authenticatorProcessEapolPdu(AuthenticatorContext *context)
Process incoming EAPOL PDU.
error_t authenticatorReauthenticate(AuthenticatorContext *context, uint_t portIndex)
Force the authenticator to reauthenticate the supplicant.
AuthenticatorReauthTimerState
Reauthentication timer states.
Socket * socket
Handle to a socket to monitor.
Definition: socket.h:434
unsigned int uint_t
Definition: compiler_port.h:57
#define osMemset(p, value, length)
Definition: os_port.h:138
uint16_t serverPort
RADIUS server's port.
#define AuthenticatorPort
Definition: authenticator.h:40
EapFullAuthStateChangeCallback eapFullAuthStateChangeCallback
EAP full authenticator state change callback function.
error_t socketSetTimeout(Socket *socket, systime_t timeout)
Set timeout value for blocking operations.
Definition: socket.c:169
uint_t eventMask
Requested events.
Definition: socket.h:435
@ ERROR_ALREADY_RUNNING
Definition: error.h:294
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
void authenticatorDeinit(AuthenticatorContext *context)
Release 802.1X authenticator context.
systime_t osGetSystemTime(void)
Retrieve system time.
void authenticatorTask(AuthenticatorContext *context)
802.1X authenticator task