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.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  //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  return error;
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  //Stop the authenticator
1018  context->stop = TRUE;
1019  //Send a signal to the task to abort any blocking operation
1020  osSetEvent(&context->event);
1021 
1022  //Wait for the task to terminate
1023  while(context->running)
1024  {
1025  osDelayTask(1);
1026  }
1027 
1028  //Remove the PAE group address from the static MAC table
1030 
1031  //Close the raw socket
1032  socketClose(context->peerSocket);
1033  context->peerSocket = NULL;
1034 
1035  //Close the UDP socket
1036  socketClose(context->serverSocket);
1037  context->serverSocket = NULL;
1038  }
1039 
1040  //Successful processing
1041  return NO_ERROR;
1042 }
1043 
1044 
1045 /**
1046  * @brief 802.1X authenticator task
1047  * @param[in] context Pointer to the 802.1X authenticator context
1048  **/
1049 
1051 {
1052  systime_t time;
1053  systime_t timeout;
1054  SocketEventDesc eventDesc[2];
1055 
1056 #if (NET_RTOS_SUPPORT == ENABLED)
1057  //Task prologue
1058  osEnterTask();
1059 
1060  //Process events
1061  while(1)
1062  {
1063 #endif
1064  //Get current time
1065  time = osGetSystemTime();
1066 
1067  //Maximum time to wait for an incoming datagram
1068  if((time - context->timestamp) < AUTHENTICATOR_TICK_INTERVAL)
1069  {
1070  timeout = context->timestamp + AUTHENTICATOR_TICK_INTERVAL - time;
1071  }
1072  else
1073  {
1074  timeout = 0;
1075  }
1076 
1077  //Specify the events the application is interested in
1078  eventDesc[0].socket = context->peerSocket;
1079  eventDesc[0].eventMask = SOCKET_EVENT_RX_READY;
1080  eventDesc[0].eventFlags = 0;
1081  eventDesc[1].socket = context->serverSocket;
1082  eventDesc[1].eventMask = SOCKET_EVENT_RX_READY;
1083  eventDesc[1].eventFlags = 0;
1084 
1085  //Wait for an event
1086  socketPoll(eventDesc, 2, &context->event, timeout);
1087 
1088  //Stop request?
1089  if(context->stop)
1090  {
1091  //Stop authenticator operation
1092  context->running = FALSE;
1093  //Task epilogue
1094  osExitTask();
1095  //Kill ourselves
1097  }
1098 
1099  //Any EAPOL packet received?
1100  if(eventDesc[0].eventFlags != 0)
1101  {
1102  //Acquire exclusive access to the 802.1X authenticator context
1103  osAcquireMutex(&context->mutex);
1104  //Process incoming EAPOL packet
1106  //Release exclusive access to the 802.1X authenticator context
1107  osReleaseMutex(&context->mutex);
1108  }
1109 
1110  //Any RADIUS packet received?
1111  if(eventDesc[1].eventFlags != 0)
1112  {
1113  //Acquire exclusive access to the 802.1X authenticator context
1114  osAcquireMutex(&context->mutex);
1115  //Process incoming RADIUS packet
1117  //Release exclusive access to the 802.1X authenticator context
1118  osReleaseMutex(&context->mutex);
1119  }
1120 
1121  //Get current time
1122  time = osGetSystemTime();
1123 
1124  //Timers have a resolution of one second
1125  if((time - context->timestamp) >= AUTHENTICATOR_TICK_INTERVAL)
1126  {
1127  //Acquire exclusive access to the 802.1X authenticator context
1128  osAcquireMutex(&context->mutex);
1129  //Handle periodic operations
1130  authenticatorTick(context);
1131  //Release exclusive access to the 802.1X authenticator context
1132  osReleaseMutex(&context->mutex);
1133 
1134  //Save current time
1135  context->timestamp = time;
1136  }
1137 
1138 #if (NET_RTOS_SUPPORT == ENABLED)
1139  }
1140 #endif
1141 }
1142 
1143 
1144 /**
1145  * @brief Release 802.1X authenticator context
1146  * @param[in] context Pointer to the 802.1X authenticator context
1147  **/
1148 
1150 {
1151  //Make sure the 802.1X authenticator context is valid
1152  if(context != NULL)
1153  {
1154  //Free previously allocated resources
1155  osDeleteMutex(&context->mutex);
1156  osDeleteEvent(&context->event);
1157 
1158  //Clear authenticator context
1159  osMemset(context, 0, sizeof(AuthenticatorContext));
1160  }
1161 }
1162 
1163 #endif
error_t authenticatorSetReAuthEnabled(AuthenticatorContext *context, uint_t portIndex, bool_t reAuthEnabled)
Set the value of the reAuthEnabled parameter.
error_t authenticatorSetReAuthPeriod(AuthenticatorContext *context, uint_t portIndex, uint_t reAuthPeriod)
Set the value of the reAuthPeriod parameter.
error_t authenticatorSetServerKey(AuthenticatorContext *context, const uint8_t *key, size_t keyLen)
Set RADIUS server's key.
error_t authenticatorSetQuietPeriod(AuthenticatorContext *context, uint_t portIndex, uint_t quietPeriod)
Set the value of the quietPeriod parameter.
error_t authenticatorGetQuietPeriod(AuthenticatorContext *context, uint_t portIndex, uint_t *quietPeriod)
Get the current value of the quietPeriod parameter.
error_t authenticatorGetServerTimeout(AuthenticatorContext *context, uint_t portIndex, uint_t *serverTimeout)
Get the current value of the serverTimeout parameter.
void authenticatorGetDefaultSettings(AuthenticatorSettings *settings)
Initialize settings with default values.
Definition: authenticator.c:51
error_t authenticatorStop(AuthenticatorContext *context)
Stop 802.1X authenticator.
error_t authenticatorStart(AuthenticatorContext *context)
Start 802.1X authenticator.
void authenticatorDeinit(AuthenticatorContext *context)
Release 802.1X authenticator context.
error_t authenticatorGetPaeState(AuthenticatorContext *context, uint_t portIndex, AuthenticatorPaeState *paeState)
Get the current state of the authenticator PAE state state machine.
error_t authenticatorGetReAuthPeriod(AuthenticatorContext *context, uint_t portIndex, uint_t *reAuthPeriod)
Get the current value of the reAuthPeriod parameter.
error_t authenticatorGetReauthTimerState(AuthenticatorContext *context, uint_t portIndex, AuthenticatorReauthTimerState *reauthTimerState)
Get the current state of the reauthentication timer state machine.
error_t authenticatorGetReAuthEnabled(AuthenticatorContext *context, uint_t portIndex, bool_t *reAuthEnabled)
Get the current value of the reAuthEnabled parameter.
error_t authenticatorGetPortControl(AuthenticatorContext *context, uint_t portIndex, AuthenticatorPortMode *portControl)
Get the current value of the AuthControlledPortControl parameter.
error_t authenticatorInit(AuthenticatorContext *context, const AuthenticatorSettings *settings)
Initialize 802.1X authenticator context.
error_t authenticatorGetBackendState(AuthenticatorContext *context, uint_t portIndex, AuthenticatorBackendState *backendState)
Get the current state of the backend authentication state machine.
error_t authenticatorGetEapFullAuthState(AuthenticatorContext *context, uint_t portIndex, EapFullAuthState *eapFullAuthState)
Get the current state of the EAP full authenticator state machine.
error_t authenticatorGetPortStatus(AuthenticatorContext *context, uint_t portIndex, AuthenticatorPortStatus *portStatus)
Get the current value of the AuthControlledPortStatus variable.
error_t authenticatorInitPort(AuthenticatorContext *context, uint_t portIndex)
Reinitialize the specified port.
void authenticatorTask(AuthenticatorContext *context)
802.1X authenticator task
error_t authenticatorSetServerTimeout(AuthenticatorContext *context, uint_t portIndex, uint_t serverTimeout)
Set the value of the serverTimeout parameter.
error_t authenticatorSetPortControl(AuthenticatorContext *context, uint_t portIndex, AuthenticatorPortMode portControl)
Set the value of the AuthControlledPortControl parameter.
error_t authenticatorReauthenticate(AuthenticatorContext *context, uint_t portIndex)
Force the authenticator to reauthenticate the supplicant.
error_t authenticatorSetServerAddr(AuthenticatorContext *context, const IpAddr *serverIpAddr, uint16_t serverPort)
Specify the IP address of the RADIUS server.
802.1X authenticator
#define AUTHENTICATOR_DEFAULT_REAUTH_PERIOD
#define AUTHENTICATOR_DEFAULT_QUIET_PERIOD
Definition: authenticator.h:99
#define AUTHENTICATOR_DEFAULT_MAX_RETRANS
#define AuthenticatorPort
Definition: authenticator.h:40
@ AUTHENTICATOR_TERMINATE_CAUSE_PORT_FAILURE
#define AUTHENTICATOR_MAX_SERVER_KEY_LEN
Definition: authenticator.h:92
#define AUTHENTICATOR_PRIORITY
Definition: authenticator.h:66
#define AUTHENTICATOR_STACK_SIZE
Definition: authenticator.h:59
#define AuthenticatorContext
Definition: authenticator.h:36
#define AUTHENTICATOR_DEFAULT_SERVER_TIMEOUT
#define AUTHENTICATOR_DEFAULT_REAUTH_MAX
#define AUTHENTICATOR_TICK_INTERVAL
Definition: authenticator.h:71
AuthenticatorBackendState
Backend authentication states.
void authenticatorInitFsm(AuthenticatorContext *context)
Authenticator state machine initialization.
Authenticator state machine.
error_t authenticatorMgmtSetQuietPeriod(AuthenticatorContext *context, uint_t portIndex, uint_t quietPeriod, bool_t commit)
Set the value of the quietPeriod parameter.
error_t authenticatorMgmtSetReauthenticate(AuthenticatorContext *context, uint_t portIndex, bool_t reAuthenticate, bool_t commit)
Force the value of the reAuthenticate variable.
error_t authenticatorMgmtSetServerTimeout(AuthenticatorContext *context, uint_t portIndex, uint_t serverTimeout, bool_t commit)
Set the value of the serverTimeout parameter.
error_t authenticatorMgmtSetPortControl(AuthenticatorContext *context, uint_t portIndex, AuthenticatorPortMode portControl, bool_t commit)
Set the value of the AuthControlledPortControl parameter.
error_t authenticatorMgmtSetInitialize(AuthenticatorContext *context, uint_t portIndex, bool_t initialize, bool_t commit)
Force the value of the initialize variable.
error_t authenticatorMgmtSetReAuthEnabled(AuthenticatorContext *context, uint_t portIndex, bool_t reAuthEnabled, bool_t commit)
Set the value of the reAuthEnabled parameter.
error_t authenticatorMgmtSetReAuthPeriod(AuthenticatorContext *context, uint_t portIndex, uint_t reAuthPeriod, bool_t commit)
Set the value of the reAuthPeriod parameter.
Management of the 802.1X authenticator.
void authenticatorGeneratePortAddr(AuthenticatorPort *port)
Port's MAC address generation.
void authenticatorProcessEapolPdu(AuthenticatorContext *context)
Process incoming EAPOL PDU.
error_t authenticatorDropPaeGroupAddr(AuthenticatorContext *context)
Remove the PAE group address from the static MAC table.
error_t authenticatorAcceptPaeGroupAddr(AuthenticatorContext *context)
Add the PAE group address to the static MAC table.
void authenticatorProcessRadiusPacket(AuthenticatorContext *context)
Process incoming RADIUS packet.
void authenticatorTick(AuthenticatorContext *context)
Handle periodic operations.
Helper functions for 802.1X authenticator.
AuthenticatorPortStatus
Port status.
AuthenticatorPaeState
Authenticator PAE states.
AuthenticatorPortMode
Port modes.
@ AUTHENTICATOR_PORT_MODE_FORCE_AUTH
AuthenticatorReauthTimerState
Reauthentication timer states.
unsigned int uint_t
Definition: compiler_port.h:50
int bool_t
Definition: compiler_port.h:53
Debugging facilities.
#define TRACE_INFO(...)
Definition: debug.h:95
uint32_t time
uint16_t port
Definition: dns_common.h:267
EapFullAuthState
EAP full authenticator states.
error_t
Error codes.
Definition: error.h:43
@ ERROR_INVALID_PORT
Definition: error.h:104
@ ERROR_ALREADY_RUNNING
Definition: error.h:292
@ ERROR_OUT_OF_RESOURCES
Definition: error.h:64
@ ERROR_OPEN_FAILED
Definition: error.h:75
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
@ ETH_TYPE_EAPOL
Definition: ethernet.h:169
const IpAddr IP_ADDR_UNSPECIFIED
Definition: ip.c:52
#define socketBindToInterface
Definition: net_legacy.h:193
#define osMemset(p, value, length)
Definition: os_port.h:135
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
bool_t osCreateMutex(OsMutex *mutex)
Create a mutex object.
void osDeleteEvent(OsEvent *event)
Delete an event object.
void osDeleteMutex(OsMutex *mutex)
Delete a mutex object.
const OsTaskParameters OS_TASK_DEFAULT_PARAMS
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osDelayTask(systime_t delay)
Delay routine.
OsTaskId osCreateTask(const char_t *name, OsTaskCode taskCode, void *arg, const OsTaskParameters *params)
Create a task.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
void osDeleteTask(OsTaskId taskId)
Delete a task.
systime_t osGetSystemTime(void)
Retrieve system time.
bool_t osCreateEvent(OsEvent *event)
Create an event object.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
void(* OsTaskCode)(void *arg)
Task routine.
#define osEnterTask()
#define OS_SELF_TASK_ID
#define OS_INVALID_TASK_ID
uint32_t systime_t
System time.
#define osExitTask()
RADIUS (Remote Authentication Dial In User Service)
#define RADIUS_PORT
Definition: radius.h:45
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:1592
Socket * socketOpen(uint_t type, uint_t protocol)
Create a socket (UDP or TCP)
Definition: socket.c:125
error_t socketSetTimeout(Socket *socket, systime_t timeout)
Set timeout value for blocking operations.
Definition: socket.c:148
void socketClose(Socket *socket)
Close an existing socket.
Definition: socket.c:1517
@ SOCKET_IP_PROTO_UDP
Definition: socket.h:101
@ SOCKET_TYPE_DGRAM
Definition: socket.h:86
@ SOCKET_TYPE_RAW_ETH
Definition: socket.h:88
@ SOCKET_EVENT_RX_READY
Definition: socket.h:169
802.1X authenticator settings
OsTaskParameters task
Task parameters.
NetInterface * serverInterface
RADIUS server interface.
AuthenticatorPort * ports
Ports.
AuthenticatorTickCallback tickCallback
Tick callback function.
AuthenticatorPaeStateChangeCallback paeStateChangeCallback
Authenticator PAE state change callback function.
const PrngAlgo * prngAlgo
Pseudo-random number generator to be used.
uint_t numPorts
Number of ports.
IpAddr serverIpAddr
RADIUS server's IP address.
uint16_t serverPort
RADIUS server's port.
EapFullAuthStateChangeCallback eapFullAuthStateChangeCallback
EAP full authenticator state change callback function.
AuthenticatorReauthTimerStateChangeCallback reauthTimerStateChangeCallback
Reauthentication timer state change callback function.
AuthenticatorBackendStateChangeCallback backendStateChangeCallback
Backend authentication state change callback function.
NetInterface * interface
Underlying network interface.
uint_t serverPortIndex
Switch port used to reach the RADIUS server.
void * prngContext
Pseudo-random number generator context.
IP network address.
Definition: ip.h:79
Structure describing socket events.
Definition: socket.h:398
uint_t eventMask
Requested events.
Definition: socket.h:400
Socket * socket
Handle to a socket to monitor.
Definition: socket.h:399
uint_t eventFlags
Returned events.
Definition: socket.h:401