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-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 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  //Initialize authenticator context
131  context->interface = settings->interface;
132  context->numPorts = settings->numPorts;
133  context->ports = settings->ports;
134  context->serverPortIndex = settings->serverPortIndex;
135  context->serverIpAddr = settings->serverIpAddr;
136  context->serverPort = settings->serverPort;
137  context->prngAlgo = settings->prngAlgo;
138  context->prngContext = settings->prngContext;
139  context->paeStateChangeCallback = settings->paeStateChangeCallback;
140  context->backendStateChangeCallback = settings->backendStateChangeCallback;
141  context->reauthTimerStateChangeCallback = settings->reauthTimerStateChangeCallback;
142  context->eapFullAuthStateChangeCallback = settings->eapFullAuthStateChangeCallback;
143  context->tickCallback = settings->tickCallback;
144 
145  //Select the interface used to reach the RADIUS server
146  if(settings->serverInterface != NULL)
147  {
148  context->serverInterface = settings->serverInterface;
149  }
150  else
151  {
152  context->serverInterface = settings->interface;
153  }
154 
155  //Loop through the ports
156  for(i = 0; i < context->numPorts; i++)
157  {
158  //Point to the current port
159  port = &context->ports[i];
160 
161  //Clear port context
162  osMemset(port, 0, sizeof(AuthenticatorPort));
163 
164  //Attach authenticator context to each port
165  port->context = context;
166  //Set port index
167  port->portIndex = i + 1;
168 
169  //Default value of parameters
176  port->reAuthEnabled = FALSE;
177  port->keyTxEnabled = FALSE;
178 
179  //Each port must assigned a unique MAC address
181 
182  //The port is down
183  port->sessionStats.sessionTerminateCause =
185  }
186 
187  //Initialize authenticator state machine
188  authenticatorInitFsm(context);
189 
190  //Start of exception handling block
191  do
192  {
193  //Create a mutex to prevent simultaneous access to 802.1X authenticator
194  //context
195  if(!osCreateMutex(&context->mutex))
196  {
197  //Failed to create mutex
198  error = ERROR_OUT_OF_RESOURCES;
199  break;
200  }
201 
202  //Create an event object to poll the state of sockets
203  if(!osCreateEvent(&context->event))
204  {
205  //Failed to create event
206  error = ERROR_OUT_OF_RESOURCES;
207  break;
208  }
209 
210  //Successful initialization
211  error = NO_ERROR;
212 
213  //End of exception handling block
214  } while(0);
215 
216  //Any error to report?
217  if(error)
218  {
219  //Clean up side effects
220  authenticatorDeinit(context);
221  }
222 
223  //Return status code
224  return error;
225 }
226 
227 
228 /**
229  * @brief Specify the IP address of the RADIUS server
230  * @param[in] context Pointer to the 802.1X authenticator context
231  * @param[in] serverIpAddr IP address of the RADIUS server
232  * @param[in] serverPort Port number
233  * @return Error code
234  **/
235 
237  const IpAddr *serverIpAddr, uint16_t serverPort)
238 {
239  //Check parameters
240  if(context == NULL || serverIpAddr == NULL)
242 
243  //Acquire exclusive access to the 802.1X authenticator context
244  osAcquireMutex(&context->mutex);
245 
246  //Save the IP address and the port number of the RADIUS server
247  context->serverIpAddr = *serverIpAddr;
248  context->serverPort = serverPort;
249 
250  //Release exclusive access to the 802.1X authenticator context
251  osReleaseMutex(&context->mutex);
252 
253  //Successful processing
254  return NO_ERROR;
255 }
256 
257 
258 /**
259  * @brief Set RADIUS server's key
260  * @param[in] context Pointer to the 802.1X authenticator context
261  * @param[in] key Pointer to the key
262  * @param[in] keyLen Length of the key, in bytes
263  * @return Error code
264  **/
265 
267  const uint8_t *key, size_t keyLen)
268 {
269  //Make sure the 802.1X authenticator context is valid
270  if(context == NULL)
272 
273  //Check parameters
274  if(key == NULL && keyLen != 0)
276 
277  //Check the length of the key
279  return ERROR_INVALID_LENGTH;
280 
281  //Acquire exclusive access to the 802.1X authenticator context
282  osAcquireMutex(&context->mutex);
283 
284  //Copy key
285  osMemcpy(context->serverKey, key, keyLen);
286  //Save the length of the key
287  context->serverKeyLen = keyLen;
288 
289  //Release exclusive access to the 802.1X authenticator context
290  osReleaseMutex(&context->mutex);
291 
292  //Successful processing
293  return NO_ERROR;
294 }
295 
296 
297 /**
298  * @brief Reinitialize the specified port
299  * @param[in] context Pointer to the 802.1X authenticator context
300  * @param[in] portIndex Port index
301  * @return Error code
302  **/
303 
305  uint_t portIndex)
306 {
307  error_t error;
308 
309  //Make sure the 802.1X authenticator context is valid
310  if(context != NULL)
311  {
312  //Acquire exclusive access to the 802.1X authenticator context
313  osAcquireMutex(&context->mutex);
314 
315  //Perform management operation
316  error = authenticatorMgmtSetInitialize(context, portIndex, TRUE,
317  TRUE);
318 
319  //Release exclusive access to the 802.1X authenticator context
320  osReleaseMutex(&context->mutex);
321  }
322  else
323  {
324  //Report an error
325  error = ERROR_INVALID_PARAMETER;
326  }
327 
328  //Return status code
329  return error;
330 }
331 
332 
333 /**
334  * @brief Force the authenticator to reauthenticate the supplicant
335  * @param[in] context Pointer to the 802.1X authenticator context
336  * @param[in] portIndex Port index
337  * @return Error code
338  **/
339 
341  uint_t portIndex)
342 {
343  error_t error;
344 
345  //Make sure the 802.1X authenticator context is valid
346  if(context != NULL)
347  {
348  //Acquire exclusive access to the 802.1X authenticator context
349  osAcquireMutex(&context->mutex);
350 
351  //Perform management operation
352  error = authenticatorMgmtSetReauthenticate(context, portIndex, TRUE,
353  TRUE);
354 
355  //Release exclusive access to the 802.1X authenticator context
356  osReleaseMutex(&context->mutex);
357  }
358  else
359  {
360  //Report an error
361  error = ERROR_INVALID_PARAMETER;
362  }
363 
364  //Return status code
365  return error;
366 }
367 
368 
369 /**
370  * @brief Set the value of the AuthControlledPortControl parameter
371  * @param[in] context Pointer to the 802.1X authenticator context
372  * @param[in] portIndex Port index
373  * @param[in] portControl Value of the AuthControlledPortControl parameter
374  * @return Error code
375  **/
376 
378  uint_t portIndex, AuthenticatorPortMode portControl)
379 {
380  error_t error;
381 
382  //Make sure the 802.1X authenticator context is valid
383  if(context != NULL)
384  {
385  //Acquire exclusive access to the 802.1X authenticator context
386  osAcquireMutex(&context->mutex);
387 
388  //Perform management operation
389  error = authenticatorMgmtSetPortControl(context, portIndex, portControl,
390  TRUE);
391 
392  //Release exclusive access to the 802.1X authenticator context
393  osReleaseMutex(&context->mutex);
394  }
395  else
396  {
397  //Report an error
398  error = ERROR_INVALID_PARAMETER;
399  }
400 
401  //Return status code
402  return error;
403 }
404 
405 
406 /**
407  * @brief Set the value of the quietPeriod parameter
408  * @param[in] context Pointer to the 802.1X authenticator context
409  * @param[in] portIndex Port index
410  * @param[in] quietPeriod Value of the quietPeriod parameter
411  * @return Error code
412  **/
413 
415  uint_t portIndex, uint_t quietPeriod)
416 {
417  error_t error;
418 
419  //Make sure the 802.1X authenticator context is valid
420  if(context != NULL)
421  {
422  //Acquire exclusive access to the 802.1X authenticator context
423  osAcquireMutex(&context->mutex);
424 
425  //Perform management operation
426  error = authenticatorMgmtSetQuietPeriod(context, portIndex, quietPeriod,
427  TRUE);
428 
429  //Release exclusive access to the 802.1X authenticator context
430  osReleaseMutex(&context->mutex);
431  }
432  else
433  {
434  //Report an error
435  error = ERROR_INVALID_PARAMETER;
436  }
437 
438  //Return status code
439  return error;
440 }
441 
442 
443 /**
444  * @brief Set the value of the serverTimeout parameter
445  * @param[in] context Pointer to the 802.1X authenticator context
446  * @param[in] portIndex Port index
447  * @param[in] serverTimeout Value of the serverTimeout parameter
448  * @return Error code
449  **/
450 
452  uint_t portIndex, uint_t serverTimeout)
453 {
454  error_t error;
455 
456  //Make sure the 802.1X authenticator context is valid
457  if(context != NULL)
458  {
459  //Acquire exclusive access to the 802.1X authenticator context
460  osAcquireMutex(&context->mutex);
461 
462  //Perform management operation
463  error = authenticatorMgmtSetServerTimeout(context, portIndex,
464  serverTimeout, TRUE);
465 
466  //Release exclusive access to the 802.1X authenticator context
467  osReleaseMutex(&context->mutex);
468  }
469  else
470  {
471  //Report an error
472  error = ERROR_INVALID_PARAMETER;
473  }
474 
475  //Return status code
476  return error;
477 }
478 
479 
480 /**
481  * @brief Set the value of the reAuthEnabled parameter
482  * @param[in] context Pointer to the 802.1X authenticator context
483  * @param[in] portIndex Port index
484  * @param[in] reAuthEnabled Value of the reAuthEnabled parameter
485  * @return Error code
486  **/
487 
489  uint_t portIndex, bool_t reAuthEnabled)
490 {
491  error_t error;
492 
493  //Make sure the 802.1X authenticator context is valid
494  if(context != NULL)
495  {
496  //Acquire exclusive access to the 802.1X authenticator context
497  osAcquireMutex(&context->mutex);
498 
499  //Perform management operation
500  error = authenticatorMgmtSetReAuthEnabled(context, portIndex,
501  reAuthEnabled, TRUE);
502 
503  //Release exclusive access to the 802.1X authenticator context
504  osReleaseMutex(&context->mutex);
505  }
506  else
507  {
508  //Report an error
509  error = ERROR_INVALID_PARAMETER;
510  }
511 
512  //Return status code
513  return error;
514 }
515 
516 
517 /**
518  * @brief Set the value of the reAuthPeriod parameter
519  * @param[in] context Pointer to the 802.1X authenticator context
520  * @param[in] portIndex Port index
521  * @param[in] reAuthPeriod Value of the reAuthPeriod parameter
522  * @return Error code
523  **/
524 
526  uint_t portIndex, uint_t reAuthPeriod)
527 {
528  error_t error;
529 
530  //Make sure the 802.1X authenticator context is valid
531  if(context != NULL)
532  {
533  //Acquire exclusive access to the 802.1X authenticator context
534  osAcquireMutex(&context->mutex);
535 
536  //Perform management operation
537  error = authenticatorMgmtSetReAuthPeriod(context, portIndex,
538  reAuthPeriod, TRUE);
539 
540  //Release exclusive access to the 802.1X authenticator context
541  osReleaseMutex(&context->mutex);
542  }
543  else
544  {
545  //Report an error
546  error = ERROR_INVALID_PARAMETER;
547  }
548 
549  //Return status code
550  return error;
551 }
552 
553 
554 /**
555  * @brief Get the current value of the AuthControlledPortControl parameter
556  * @param[in] context Pointer to the 802.1X authenticator context
557  * @param[in] portIndex Port index
558  * @param[out] portControl value of the AuthControlledPortControl parameter
559  * @return Error code
560  **/
561 
563  uint_t portIndex, AuthenticatorPortMode *portControl)
564 {
565  //Check parameters
566  if(context == NULL || portControl == NULL)
568 
569  //Invalid port index?
570  if(portIndex < 1 || portIndex > context->numPorts)
571  return ERROR_INVALID_PORT;
572 
573  //Acquire exclusive access to the 802.1X authenticator context
574  osAcquireMutex(&context->mutex);
575  //Get the current value of the parameter
576  *portControl = context->ports[portIndex - 1].portControl;
577  //Release exclusive access to the 802.1X authenticator context
578  osReleaseMutex(&context->mutex);
579 
580  //Successful processing
581  return NO_ERROR;
582 }
583 
584 
585 /**
586  * @brief Get the current value of the quietPeriod parameter
587  * @param[in] context Pointer to the 802.1X authenticator context
588  * @param[in] portIndex Port index
589  * @param[out] quietPeriod value of the quietPeriod parameter
590  * @return Error code
591  **/
592 
594  uint_t portIndex, uint_t *quietPeriod)
595 {
596  //Check parameters
597  if(context == NULL || quietPeriod == NULL)
599 
600  //Invalid port index?
601  if(portIndex < 1 || portIndex > context->numPorts)
602  return ERROR_INVALID_PORT;
603 
604  //Acquire exclusive access to the 802.1X authenticator context
605  osAcquireMutex(&context->mutex);
606  //Get the current value of the parameter
607  *quietPeriod = context->ports[portIndex - 1].quietPeriod;
608  //Release exclusive access to the 802.1X authenticator context
609  osReleaseMutex(&context->mutex);
610 
611  //Successful processing
612  return NO_ERROR;
613 }
614 
615 
616 /**
617  * @brief Get the current value of the serverTimeout parameter
618  * @param[in] context Pointer to the 802.1X authenticator context
619  * @param[in] portIndex Port index
620  * @param[out] serverTimeout value of the serverTimeout parameter
621  * @return Error code
622  **/
623 
625  uint_t portIndex, uint_t *serverTimeout)
626 {
627  //Check parameters
628  if(context == NULL || serverTimeout == NULL)
630 
631  //Invalid port index?
632  if(portIndex < 1 || portIndex > context->numPorts)
633  return ERROR_INVALID_PORT;
634 
635  //Acquire exclusive access to the 802.1X authenticator context
636  osAcquireMutex(&context->mutex);
637  //Get the current value of the parameter
638  *serverTimeout = context->ports[portIndex - 1].serverTimeout;
639  //Release exclusive access to the 802.1X authenticator context
640  osReleaseMutex(&context->mutex);
641 
642  //Successful processing
643  return NO_ERROR;
644 }
645 
646 
647 /**
648  * @brief Get the current value of the reAuthEnabled parameter
649  * @param[in] context Pointer to the 802.1X authenticator context
650  * @param[in] portIndex Port index
651  * @param[out] reAuthEnabled value of the reAuthEnabled parameter
652  * @return Error code
653  **/
654 
656  uint_t portIndex, bool_t *reAuthEnabled)
657 {
658  //Check parameters
659  if(context == NULL || reAuthEnabled == NULL)
661 
662  //Invalid port index?
663  if(portIndex < 1 || portIndex > context->numPorts)
664  return ERROR_INVALID_PORT;
665 
666  //Acquire exclusive access to the 802.1X authenticator context
667  osAcquireMutex(&context->mutex);
668  //Get the current value of the parameter
669  *reAuthEnabled = context->ports[portIndex - 1].reAuthEnabled;
670  //Release exclusive access to the 802.1X authenticator context
671  osReleaseMutex(&context->mutex);
672 
673  //Successful processing
674  return NO_ERROR;
675 }
676 
677 
678 /**
679  * @brief Get the current value of the reAuthPeriod parameter
680  * @param[in] context Pointer to the 802.1X authenticator context
681  * @param[in] portIndex Port index
682  * @param[out] reAuthPeriod value of the reAuthPeriod parameter
683  * @return Error code
684  **/
685 
687  uint_t portIndex, uint_t *reAuthPeriod)
688 {
689  //Check parameters
690  if(context == NULL || reAuthPeriod == NULL)
692 
693  //Invalid port index?
694  if(portIndex < 1 || portIndex > context->numPorts)
695  return ERROR_INVALID_PORT;
696 
697  //Acquire exclusive access to the 802.1X authenticator context
698  osAcquireMutex(&context->mutex);
699  //Get the current value of the parameter
700  *reAuthPeriod = context->ports[portIndex - 1].reAuthPeriod;
701  //Release exclusive access to the 802.1X authenticator context
702  osReleaseMutex(&context->mutex);
703 
704  //Successful processing
705  return NO_ERROR;
706 }
707 
708 
709 /**
710  * @brief Get the current value of the AuthControlledPortStatus variable
711  * @param[in] context Pointer to the 802.1X authenticator context
712  * @param[in] portIndex Port index
713  * @param[out] portStatus Current value of the AuthControlledPortStatus variable
714  * @return Error code
715  **/
716 
718  uint_t portIndex, AuthenticatorPortStatus *portStatus)
719 {
720  //Check parameters
721  if(context == NULL || portStatus == NULL)
723 
724  //Invalid port index?
725  if(portIndex < 1 || portIndex > context->numPorts)
726  return ERROR_INVALID_PORT;
727 
728  //Acquire exclusive access to the 802.1X authenticator context
729  osAcquireMutex(&context->mutex);
730  //Get the current value of the variable
731  *portStatus = context->ports[portIndex - 1].authPortStatus;
732  //Release exclusive access to the 802.1X authenticator context
733  osReleaseMutex(&context->mutex);
734 
735  //Successful processing
736  return NO_ERROR;
737 }
738 
739 
740 /**
741  * @brief Get the current state of the authenticator PAE state state machine
742  * @param[in] context Pointer to the 802.1X authenticator context
743  * @param[in] portIndex Port index
744  * @param[out] paeState Current state of the authenticator PAE state machine
745  * @return Error code
746  **/
747 
749  uint_t portIndex, AuthenticatorPaeState *paeState)
750 {
751  //Check parameters
752  if(context == NULL || paeState == NULL)
754 
755  //Invalid port index?
756  if(portIndex < 1 || portIndex > context->numPorts)
757  return ERROR_INVALID_PORT;
758 
759  //Acquire exclusive access to the 802.1X authenticator context
760  osAcquireMutex(&context->mutex);
761  //Get the current state
762  *paeState = context->ports[portIndex - 1].authPaeState;
763  //Release exclusive access to the 802.1X authenticator context
764  osReleaseMutex(&context->mutex);
765 
766  //Successful processing
767  return NO_ERROR;
768 }
769 
770 
771 /**
772  * @brief Get the current state of the backend authentication state machine
773  * @param[in] context Pointer to the 802.1X authenticator context
774  * @param[in] portIndex Port index
775  * @param[out] backendState Current state of the backend authentication state
776  * machine
777  * @return Error code
778  **/
779 
781  uint_t portIndex, AuthenticatorBackendState *backendState)
782 {
783  //Check parameters
784  if(context == NULL || backendState == NULL)
786 
787  //Invalid port index?
788  if(portIndex < 1 || portIndex > context->numPorts)
789  return ERROR_INVALID_PORT;
790 
791  //Acquire exclusive access to the 802.1X authenticator context
792  osAcquireMutex(&context->mutex);
793  //Get the current state
794  *backendState = context->ports[portIndex - 1].authBackendState;
795  //Release exclusive access to the 802.1X authenticator context
796  osReleaseMutex(&context->mutex);
797 
798  //Successful processing
799  return NO_ERROR;
800 }
801 
802 
803 /**
804  * @brief Get the current state of the reauthentication timer state machine
805  * @param[in] context Pointer to the 802.1X authenticator context
806  * @param[in] portIndex Port index
807  * @param[out] reauthTimerState Current state of the reauthentication timer state
808  * machine
809  * @return Error code
810  **/
811 
813  uint_t portIndex, AuthenticatorReauthTimerState *reauthTimerState)
814 {
815  //Check parameters
816  if(context == NULL || reauthTimerState == NULL)
818 
819  //Invalid port index?
820  if(portIndex < 1 || portIndex > context->numPorts)
821  return ERROR_INVALID_PORT;
822 
823  //Acquire exclusive access to the 802.1X authenticator context
824  osAcquireMutex(&context->mutex);
825  //Get the current state
826  *reauthTimerState = context->ports[portIndex - 1].reauthTimerState;
827  //Release exclusive access to the 802.1X authenticator context
828  osReleaseMutex(&context->mutex);
829 
830  //Successful processing
831  return NO_ERROR;
832 }
833 
834 
835 /**
836  * @brief Get the current state of the EAP full authenticator state machine
837  * @param[in] context Pointer to the 802.1X authenticator context
838  * @param[in] portIndex Port index
839  * @param[out] eapFullAuthState Current state of the EAP full authenticator state
840  * machine
841  * @return Error code
842  **/
843 
845  uint_t portIndex, EapFullAuthState *eapFullAuthState)
846 {
847  //Check parameters
848  if(context == NULL || eapFullAuthState == NULL)
850 
851  //Invalid port index?
852  if(portIndex < 1 || portIndex > context->numPorts)
853  return ERROR_INVALID_PORT;
854 
855  //Acquire exclusive access to the 802.1X authenticator context
856  osAcquireMutex(&context->mutex);
857  //Get the current state
858  *eapFullAuthState = context->ports[portIndex - 1].eapFullAuthState;
859  //Release exclusive access to the 802.1X authenticator context
860  osReleaseMutex(&context->mutex);
861 
862  //Successful processing
863  return NO_ERROR;
864 }
865 
866 
867 /**
868  * @brief Start 802.1X authenticator
869  * @param[in] context Pointer to the 802.1X authenticator context
870  * @return Error code
871  **/
872 
874 {
875  error_t error;
876 
877  //Make sure the 802.1X authenticator context is valid
878  if(context == NULL)
880 
881  //Debug message
882  TRACE_INFO("Starting 802.1X authenticator...\r\n");
883 
884  //Make sure the authenticator is not already running
885  if(context->running)
886  return ERROR_ALREADY_RUNNING;
887 
888  //Start of exception handling block
889  do
890  {
891  //Open a UDP socket
892  context->serverSocket = socketOpen(SOCKET_TYPE_DGRAM,
894  //Failed to open socket?
895  if(context->serverSocket == NULL)
896  {
897  //Report an error
898  error = ERROR_OPEN_FAILED;
899  break;
900  }
901 
902  //Force the socket to operate in non-blocking mode
903  error = socketSetTimeout(context->serverSocket, 0);
904  //Any error to report?
905  if(error)
906  break;
907 
908  //Associate the socket with the relevant interface
909  error = socketBindToInterface(context->serverSocket,
910  context->serverInterface);
911  //Any error to report?
912  if(error)
913  break;
914 
915  //Open a raw socket
916  context->peerSocket = socketOpen(SOCKET_TYPE_RAW_ETH, ETH_TYPE_EAPOL);
917  //Failed to open socket?
918  if(context->peerSocket == NULL)
919  {
920  //Report an error
921  error = ERROR_OPEN_FAILED;
922  break;
923  }
924 
925  //Force the socket to operate in non-blocking mode
926  error = socketSetTimeout(context->peerSocket, 0);
927  //Any error to report?
928  if(error)
929  break;
930 
931  //Associate the socket with the relevant interface
932  error = socketBindToInterface(context->peerSocket, context->interface);
933  //Any error to report?
934  if(error)
935  break;
936 
937  //The PAE group address is one of the reserved set of group MAC addresses
938  //that are not forwarded by MAC Bridges (refer to IEEE Std 802.1X-2010,
939  //section 7.8)
940  error = authenticatorAcceptPaeGroupAddr(context);
941  //Any error to report?
942  if(error)
943  break;
944 
945  //Start the authenticator
946  context->stop = FALSE;
947  context->running = TRUE;
948 
949  //Save current time
950  context->timestamp = osGetSystemTime();
951 
952  //Reinitialize authenticator state machine
953  authenticatorInitFsm(context);
954 
955  //Create a task
956  context->taskId = osCreateTask("Authenticator", (OsTaskCode) authenticatorTask,
957  context, &context->taskParams);
958 
959  //Failed to create task?
960  if(context->taskId == OS_INVALID_TASK_ID)
961  {
962  //Report an error
963  error = ERROR_OUT_OF_RESOURCES;
964  break;
965  }
966 
967  //End of exception handling block
968  } while(0);
969 
970  //Any error to report?
971  if(error)
972  {
973  //Clean up side effects
974  context->running = FALSE;
975 
976  //Remove the PAE group address from the static MAC table
978 
979  //Close the raw socket
980  if(context->peerSocket != NULL)
981  {
982  socketClose(context->peerSocket);
983  context->peerSocket = NULL;
984  }
985 
986  //Close the UDP socket
987  if(context->serverSocket != NULL)
988  {
989  socketClose(context->serverSocket);
990  context->serverSocket = NULL;
991  }
992  }
993 
994  //Return status code
995  return error;
996 }
997 
998 
999 /**
1000  * @brief Stop 802.1X authenticator
1001  * @param[in] context Pointer to the 802.1X authenticator context
1002  * @return Error code
1003  **/
1004 
1006 {
1007  //Make sure the 802.1X authenticator context is valid
1008  if(context == NULL)
1009  return ERROR_INVALID_PARAMETER;
1010 
1011  //Debug message
1012  TRACE_INFO("Stopping 802.1X authenticator...\r\n");
1013 
1014  //Check whether the authenticator is running
1015  if(context->running)
1016  {
1017 #if (NET_RTOS_SUPPORT == ENABLED)
1018  //Stop the authenticator
1019  context->stop = TRUE;
1020  //Send a signal to the task to abort any blocking operation
1021  osSetEvent(&context->event);
1022 
1023  //Wait for the task to terminate
1024  while(context->running)
1025  {
1026  osDelayTask(1);
1027  }
1028 #endif
1029 
1030  //Remove the PAE group address from the static MAC table
1032 
1033  //Close the raw socket
1034  socketClose(context->peerSocket);
1035  context->peerSocket = NULL;
1036 
1037  //Close the UDP socket
1038  socketClose(context->serverSocket);
1039  context->serverSocket = NULL;
1040  }
1041 
1042  //Successful processing
1043  return NO_ERROR;
1044 }
1045 
1046 
1047 /**
1048  * @brief 802.1X authenticator task
1049  * @param[in] context Pointer to the 802.1X authenticator context
1050  **/
1051 
1053 {
1054  systime_t time;
1055  systime_t timeout;
1056  SocketEventDesc eventDesc[2];
1057 
1058 #if (NET_RTOS_SUPPORT == ENABLED)
1059  //Task prologue
1060  osEnterTask();
1061 
1062  //Process events
1063  while(1)
1064  {
1065 #endif
1066  //Get current time
1067  time = osGetSystemTime();
1068 
1069  //Maximum time to wait for an incoming datagram
1070  if((time - context->timestamp) < AUTHENTICATOR_TICK_INTERVAL)
1071  {
1072  timeout = context->timestamp + AUTHENTICATOR_TICK_INTERVAL - time;
1073  }
1074  else
1075  {
1076  timeout = 0;
1077  }
1078 
1079  //Specify the events the application is interested in
1080  eventDesc[0].socket = context->peerSocket;
1081  eventDesc[0].eventMask = SOCKET_EVENT_RX_READY;
1082  eventDesc[0].eventFlags = 0;
1083  eventDesc[1].socket = context->serverSocket;
1084  eventDesc[1].eventMask = SOCKET_EVENT_RX_READY;
1085  eventDesc[1].eventFlags = 0;
1086 
1087  //Wait for an event
1088  socketPoll(eventDesc, 2, &context->event, timeout);
1089 
1090  //Stop request?
1091  if(context->stop)
1092  {
1093  //Stop authenticator operation
1094  context->running = FALSE;
1095  //Task epilogue
1096  osExitTask();
1097  //Kill ourselves
1099  }
1100 
1101  //Any EAPOL packet received?
1102  if(eventDesc[0].eventFlags != 0)
1103  {
1104  //Acquire exclusive access to the 802.1X authenticator context
1105  osAcquireMutex(&context->mutex);
1106  //Process incoming EAPOL packet
1108  //Release exclusive access to the 802.1X authenticator context
1109  osReleaseMutex(&context->mutex);
1110  }
1111 
1112  //Any RADIUS packet received?
1113  if(eventDesc[1].eventFlags != 0)
1114  {
1115  //Acquire exclusive access to the 802.1X authenticator context
1116  osAcquireMutex(&context->mutex);
1117  //Process incoming RADIUS packet
1119  //Release exclusive access to the 802.1X authenticator context
1120  osReleaseMutex(&context->mutex);
1121  }
1122 
1123  //Get current time
1124  time = osGetSystemTime();
1125 
1126  //Timers have a resolution of one second
1127  if((time - context->timestamp) >= AUTHENTICATOR_TICK_INTERVAL)
1128  {
1129  //Acquire exclusive access to the 802.1X authenticator context
1130  osAcquireMutex(&context->mutex);
1131  //Handle periodic operations
1132  authenticatorTick(context);
1133  //Release exclusive access to the 802.1X authenticator context
1134  osReleaseMutex(&context->mutex);
1135 
1136  //Save current time
1137  context->timestamp = time;
1138  }
1139 
1140 #if (NET_RTOS_SUPPORT == ENABLED)
1141  }
1142 #endif
1143 }
1144 
1145 
1146 /**
1147  * @brief Release 802.1X authenticator context
1148  * @param[in] context Pointer to the 802.1X authenticator context
1149  **/
1150 
1152 {
1153  //Make sure the 802.1X authenticator context is valid
1154  if(context != NULL)
1155  {
1156  //Free previously allocated resources
1157  osDeleteMutex(&context->mutex);
1158  osDeleteEvent(&context->event);
1159 
1160  //Clear authenticator context
1161  osMemset(context, 0, sizeof(AuthenticatorContext));
1162  }
1163 }
1164 
1165 #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:53
@ 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:2062
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:426
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:141
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:95
@ ETH_TYPE_EAPOL
Definition: ethernet.h:169
Socket * socketOpen(uint_t type, uint_t protocol)
Create a socket (UDP or TCP)
Definition: socket.c:125
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:429
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:2149
#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:267
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.
#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:427
unsigned int uint_t
Definition: compiler_port.h:50
#define osMemset(p, value, length)
Definition: os_port.h:135
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:148
uint_t eventMask
Requested events.
Definition: socket.h:428
@ ERROR_ALREADY_RUNNING
Definition: error.h:293
@ 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