2 * hostapd / RADIUS authentication server
3 * Copyright (c) 2005, Jouni Malinen <jkmaline@cc.hut.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
19 #include <netinet/in.h>
20 #include <sys/socket.h>
21 #include <arpa/inet.h>
29 #include "radius_server.h"
31 #define RADIUS_SESSION_TIMEOUT 60
32 #define RADIUS_MAX_SESSION 100
33 #define RADIUS_MAX_MSG_LEN 3000
35 static struct eapol_callbacks radius_server_eapol_cb
;
38 struct radius_server_data
;
40 struct radius_session
{
41 struct radius_session
*next
;
42 struct radius_client
*client
;
43 struct radius_server_data
*server
;
46 u8
*eapKeyData
, *eapReqData
;
47 size_t eapKeyDataLen
, eapReqDataLen
;
48 Boolean eapSuccess
, eapRestart
, eapFail
, eapResp
, eapReq
, eapNoReq
;
49 Boolean portEnabled
, eapTimeout
;
52 struct radius_client
{
53 struct radius_client
*next
;
57 struct in6_addr addr6
;
58 struct in6_addr mask6
;
59 #endif /* CONFIG_IPV6 */
61 int shared_secret_len
;
62 struct radius_session
*sessions
;
65 struct radius_server_data
{
67 struct radius_client
*clients
;
68 struct radius_server_session
*sessions
;
69 unsigned int next_sess_id
;
72 void *eap_sim_db_priv
;
78 extern int wpa_debug_level
;
80 #define RADIUS_DEBUG(args...) \
81 wpa_printf(MSG_DEBUG, "RADIUS SRV: " args)
82 #define RADIUS_ERROR(args...) \
83 wpa_printf(MSG_ERROR, "RADIUS SRV: " args)
84 #define RADIUS_DUMP(args...) \
85 wpa_hexdump(MSG_MSGDUMP, "RADIUS SRV: " args)
86 #define RADIUS_DUMP_ASCII(args...) \
87 wpa_hexdump_ascii(MSG_MSGDUMP, "RADIUS SRV: " args)
90 static void radius_server_session_timeout(void *eloop_ctx
, void *timeout_ctx
);
94 static struct radius_client
*
95 radius_server_get_client(struct radius_server_data
*data
, struct in_addr
*addr
,
98 struct radius_client
*client
= data
->clients
;
103 struct in6_addr
*addr6
;
106 addr6
= (struct in6_addr
*) addr
;
107 for (i
= 0; i
< 16; i
++) {
108 if ((addr6
->s6_addr
[i
] &
109 client
->mask6
.s6_addr
[i
]) !=
110 (client
->addr6
.s6_addr
[i
] &
111 client
->mask6
.s6_addr
[i
])) {
120 #endif /* CONFIG_IPV6 */
121 if (!ipv6
&& (client
->addr
.s_addr
& client
->mask
.s_addr
) ==
122 (addr
->s_addr
& client
->mask
.s_addr
)) {
126 client
= client
->next
;
133 static struct radius_session
*
134 radius_server_get_session(struct radius_client
*client
, unsigned int sess_id
)
136 struct radius_session
*sess
= client
->sessions
;
139 if (sess
->sess_id
== sess_id
) {
149 static void radius_server_session_free(struct radius_server_data
*data
,
150 struct radius_session
*sess
)
152 eloop_cancel_timeout(radius_server_session_timeout
, data
, sess
);
153 free(sess
->eapKeyData
);
154 free(sess
->eapReqData
);
155 eap_sm_deinit(sess
->eap
);
161 static void radius_server_session_remove(struct radius_server_data
*data
,
162 struct radius_session
*sess
)
164 struct radius_client
*client
= sess
->client
;
165 struct radius_session
*session
, *prev
;
168 session
= client
->sessions
;
170 if (session
== sess
) {
172 client
->sessions
= sess
->next
;
174 prev
->next
= sess
->next
;
176 radius_server_session_free(data
, sess
);
180 session
= session
->next
;
185 static void radius_server_session_timeout(void *eloop_ctx
, void *timeout_ctx
)
187 struct radius_server_data
*data
= eloop_ctx
;
188 struct radius_session
*sess
= timeout_ctx
;
190 RADIUS_DEBUG("Timing out authentication session 0x%x", sess
->sess_id
);
191 radius_server_session_remove(data
, sess
);
195 static struct radius_session
*
196 radius_server_new_session(struct radius_server_data
*data
,
197 struct radius_client
*client
)
199 struct radius_session
*sess
;
201 if (data
->num_sess
>= RADIUS_MAX_SESSION
) {
202 RADIUS_DEBUG("Maximum number of existing session - no room "
203 "for a new session");
207 sess
= malloc(sizeof(*sess
));
211 memset(sess
, 0, sizeof(*sess
));
213 sess
->client
= client
;
214 sess
->sess_id
= data
->next_sess_id
++;
215 sess
->next
= client
->sessions
;
216 client
->sessions
= sess
;
217 eloop_register_timeout(RADIUS_SESSION_TIMEOUT
, 0,
218 radius_server_session_timeout
, data
, sess
);
224 static struct radius_session
*
225 radius_server_get_new_session(struct radius_server_data
*data
,
226 struct radius_client
*client
,
227 struct radius_msg
*msg
)
231 const struct hostapd_eap_user
*eap_user
;
233 struct radius_session
*sess
;
234 struct eap_config eap_conf
;
236 RADIUS_DEBUG("Creating a new session");
242 res
= radius_msg_get_attr(msg
, RADIUS_ATTR_USER_NAME
, user
, 256);
243 if (res
< 0 || res
> 256) {
244 RADIUS_DEBUG("Could not get User-Name");
249 RADIUS_DUMP_ASCII("User-Name", user
, user_len
);
251 eap_user
= hostapd_get_eap_user(data
->hostapd_conf
, user
, user_len
, 0);
255 RADIUS_DEBUG("Matching user entry found");
256 sess
= radius_server_new_session(data
, client
);
258 RADIUS_DEBUG("Failed to create a new session");
262 RADIUS_DEBUG("User-Name not found from user database");
266 memset(&eap_conf
, 0, sizeof(eap_conf
));
267 eap_conf
.ssl_ctx
= data
->ssl_ctx
;
268 eap_conf
.eap_sim_db_priv
= data
->eap_sim_db_priv
;
269 eap_conf
.backend_auth
= TRUE
;
270 sess
->eap
= eap_sm_init(sess
, &radius_server_eapol_cb
, &eap_conf
);
271 if (sess
->eap
== NULL
) {
272 RADIUS_DEBUG("Failed to initialize EAP state machine for the "
274 radius_server_session_free(data
, sess
);
277 sess
->eapRestart
= TRUE
;
278 sess
->portEnabled
= TRUE
;
280 RADIUS_DEBUG("New session 0x%x initialized", sess
->sess_id
);
286 static struct radius_msg
*
287 radius_server_encapsulate_eap(struct radius_server_data
*data
,
288 struct radius_client
*client
,
289 struct radius_session
*sess
,
290 struct radius_msg
*request
)
292 struct radius_msg
*msg
;
294 unsigned int sess_id
;
297 code
= RADIUS_CODE_ACCESS_REJECT
;
298 } else if (sess
->eapSuccess
) {
299 code
= RADIUS_CODE_ACCESS_ACCEPT
;
301 code
= RADIUS_CODE_ACCESS_CHALLENGE
;
304 msg
= radius_msg_new(code
, request
->hdr
->identifier
);
309 sess_id
= htonl(sess
->sess_id
);
310 if (code
== RADIUS_CODE_ACCESS_CHALLENGE
&&
311 !radius_msg_add_attr(msg
, RADIUS_ATTR_STATE
,
312 (u8
*) &sess_id
, sizeof(sess_id
))) {
313 RADIUS_DEBUG("Failed to add State attribute");
316 if (sess
->eapReqData
&&
317 !radius_msg_add_eap(msg
, sess
->eapReqData
, sess
->eapReqDataLen
)) {
318 RADIUS_DEBUG("Failed to add EAP-Message attribute");
321 if (code
== RADIUS_CODE_ACCESS_ACCEPT
&& sess
->eapKeyData
) {
323 if (sess
->eapKeyDataLen
> 64) {
326 len
= sess
->eapKeyDataLen
/ 2;
328 if (!radius_msg_add_mppe_keys(msg
, request
->hdr
->authenticator
,
329 (u8
*) client
->shared_secret
,
330 client
->shared_secret_len
,
331 sess
->eapKeyData
+ len
, len
,
332 sess
->eapKeyData
, len
)) {
333 RADIUS_DEBUG("Failed to add MPPE key attributes");
337 if (radius_msg_finish_srv(msg
, (u8
*) client
->shared_secret
,
338 client
->shared_secret_len
,
339 request
->hdr
->authenticator
) < 0) {
340 RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
347 static int radius_server_reject(struct radius_server_data
*data
,
348 struct radius_client
*client
,
349 struct radius_msg
*request
,
350 struct sockaddr
*from
, socklen_t fromlen
,
351 const char *from_addr
, int from_port
)
353 struct radius_msg
*msg
;
355 struct eap_hdr eapfail
;
357 RADIUS_DEBUG("Reject invalid request from %s:%d",
358 from_addr
, from_port
);
360 msg
= radius_msg_new(RADIUS_CODE_ACCESS_REJECT
,
361 request
->hdr
->identifier
);
366 memset(&eapfail
, 0, sizeof(eapfail
));
367 eapfail
.code
= EAP_CODE_FAILURE
;
368 eapfail
.identifier
= 0;
369 eapfail
.length
= htons(sizeof(eapfail
));
371 if (!radius_msg_add_eap(msg
, (u8
*) &eapfail
, sizeof(eapfail
))) {
372 RADIUS_DEBUG("Failed to add EAP-Message attribute");
376 if (radius_msg_finish_srv(msg
, (u8
*) client
->shared_secret
,
377 client
->shared_secret_len
,
378 request
->hdr
->authenticator
) < 0) {
379 RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
382 if (wpa_debug_level
<= MSG_MSGDUMP
) {
383 radius_msg_dump(msg
);
386 if (sendto(data
->auth_sock
, msg
->buf
, msg
->buf_used
, 0,
387 (struct sockaddr
*) from
, sizeof(*from
)) < 0) {
388 perror("sendto[RADIUS SRV]");
392 radius_msg_free(msg
);
399 static int radius_server_request(struct radius_server_data
*data
,
400 struct radius_msg
*msg
,
401 struct sockaddr
*from
, socklen_t fromlen
,
402 struct radius_client
*client
,
403 const char *from_addr
, int from_port
)
407 int res
, state_included
= 0;
408 u8 statebuf
[4], resp_id
;
410 struct radius_session
*sess
;
411 struct radius_msg
*reply
;
414 /* TODO: Implement duplicate packet processing */
416 res
= radius_msg_get_attr(msg
, RADIUS_ATTR_STATE
, statebuf
,
418 state_included
= res
>= 0;
419 if (res
== sizeof(statebuf
)) {
420 state
= (statebuf
[0] << 24) | (statebuf
[1] << 16) |
421 (statebuf
[2] << 8) | statebuf
[3];
422 sess
= radius_server_get_session(client
, state
);
428 RADIUS_DEBUG("Request for session 0x%x", sess
->sess_id
);
429 } else if (state_included
) {
430 RADIUS_DEBUG("State attribute included but no session found");
431 radius_server_reject(data
, client
, msg
, from
, fromlen
,
432 from_addr
, from_port
);
435 sess
= radius_server_get_new_session(data
, client
, msg
);
437 RADIUS_DEBUG("Could not create a new session");
438 radius_server_reject(data
, client
, msg
, from
, fromlen
,
439 from_addr
, from_port
);
444 eap
= radius_msg_get_eap(msg
, &eap_len
);
446 RADIUS_DEBUG("No EAP-Message in RADIUS packet from %s",
451 RADIUS_DUMP("Received EAP data", eap
, eap_len
);
452 if (eap_len
>= sizeof(*hdr
)) {
453 hdr
= (struct eap_hdr
*) eap
;
454 resp_id
= hdr
->identifier
;
459 /* FIX: if Code is Request, Success, or Failure, send Access-Reject;
460 * RFC3579 Sect. 2.6.2.
461 * Include EAP-Response/Nak with no preferred method if
463 * If code is not 1-4, discard the packet silently.
464 * Or is this already done by the EAP state machine? */
466 eap_set_eapRespData(sess
->eap
, eap
, eap_len
);
469 sess
->eapResp
= TRUE
;
470 eap_sm_step(sess
->eap
);
472 if (sess
->eapReqData
) {
473 RADIUS_DUMP("EAP data from the state machine",
474 sess
->eapReqData
, sess
->eapReqDataLen
);
475 } else if (sess
->eapFail
) {
476 RADIUS_DEBUG("No EAP data from the state machine, but eapFail "
477 "set - generate EAP-Failure");
478 hdr
= malloc(sizeof(*hdr
));
480 memset(hdr
, 0, sizeof(*hdr
));
481 hdr
->identifier
= resp_id
;
482 hdr
->length
= htons(sizeof(*hdr
));
483 sess
->eapReqData
= (u8
*) hdr
;
484 sess
->eapReqDataLen
= sizeof(*hdr
);
487 RADIUS_DEBUG("No EAP data from the state machine - ignore this"
488 " Access-Request silently (assuming it was a "
493 reply
= radius_server_encapsulate_eap(data
, client
, sess
, msg
);
495 free(sess
->eapReqData
);
496 sess
->eapReqData
= NULL
;
497 sess
->eapReqDataLen
= 0;
500 RADIUS_DEBUG("Reply to %s:%d", from_addr
, from_port
);
501 if (wpa_debug_level
<= MSG_MSGDUMP
) {
502 radius_msg_dump(reply
);
505 res
= sendto(data
->auth_sock
, reply
->buf
, reply
->buf_used
, 0,
506 (struct sockaddr
*) from
, fromlen
);
508 perror("sendto[RADIUS SRV]");
510 radius_msg_free(reply
);
514 if (sess
->eapSuccess
|| sess
->eapFail
) {
515 RADIUS_DEBUG("Removing completed session 0x%x", sess
->sess_id
);
516 radius_server_session_remove(data
, sess
);
523 static void radius_server_receive_auth(int sock
, void *eloop_ctx
,
526 struct radius_server_data
*data
= eloop_ctx
;
528 struct sockaddr_storage from
;
531 struct radius_client
*client
= NULL
;
532 struct radius_msg
*msg
= NULL
;
536 buf
= malloc(RADIUS_MAX_MSG_LEN
);
541 fromlen
= sizeof(from
);
542 len
= recvfrom(sock
, buf
, RADIUS_MAX_MSG_LEN
, 0,
543 (struct sockaddr
*) &from
, &fromlen
);
545 perror("recvfrom[radius_server]");
551 struct sockaddr_in6
*from6
= (struct sockaddr_in6
*) &from
;
552 if (inet_ntop(AF_INET6
, &from6
->sin6_addr
, abuf
, sizeof(abuf
))
555 from_port
= ntohs(from6
->sin6_port
);
556 RADIUS_DEBUG("Received %d bytes from %s:%d",
557 len
, abuf
, from_port
);
559 client
= radius_server_get_client(data
,
561 &from6
->sin6_addr
, 1);
563 #endif /* CONFIG_IPV6 */
566 struct sockaddr_in
*from4
= (struct sockaddr_in
*) &from
;
567 snprintf(abuf
, sizeof(abuf
), "%s", inet_ntoa(from4
->sin_addr
));
568 from_port
= ntohs(from4
->sin_port
);
569 RADIUS_DEBUG("Received %d bytes from %s:%d",
570 len
, abuf
, from_port
);
572 client
= radius_server_get_client(data
, &from4
->sin_addr
, 0);
575 RADIUS_DUMP("Received data", buf
, len
);
577 if (client
== NULL
) {
578 RADIUS_DEBUG("Unknown client %s - packet ignored", abuf
);
582 msg
= radius_msg_parse(buf
, len
);
584 RADIUS_DEBUG("Parsing incoming RADIUS frame failed");
591 if (wpa_debug_level
<= MSG_MSGDUMP
) {
592 radius_msg_dump(msg
);
595 if (msg
->hdr
->code
!= RADIUS_CODE_ACCESS_REQUEST
) {
596 RADIUS_DEBUG("Unexpected RADIUS code %d", msg
->hdr
->code
);
600 if (radius_msg_verify_msg_auth(msg
, (u8
*) client
->shared_secret
,
601 client
->shared_secret_len
, NULL
)) {
602 RADIUS_DEBUG("Invalid Message-Authenticator from %s", abuf
);
606 radius_server_request(data
, msg
, (struct sockaddr
*) &from
, fromlen
,
607 client
, abuf
, from_port
);
611 radius_msg_free(msg
);
618 static int radius_server_open_socket(int port
)
621 struct sockaddr_in addr
;
623 s
= socket(PF_INET
, SOCK_DGRAM
, 0);
629 memset(&addr
, 0, sizeof(addr
));
630 addr
.sin_family
= AF_INET
;
631 addr
.sin_port
= htons(port
);
632 if (bind(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
643 static int radius_server_open_socket6(int port
)
646 struct sockaddr_in6 addr
;
648 s
= socket(PF_INET6
, SOCK_DGRAM
, 0);
650 perror("socket[IPv6]");
654 memset(&addr
, 0, sizeof(addr
));
655 addr
.sin6_family
= AF_INET6
;
656 memcpy(&addr
.sin6_addr
, &in6addr_any
, sizeof(in6addr_any
));
657 addr
.sin6_port
= htons(port
);
658 if (bind(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
666 #endif /* CONFIG_IPV6 */
669 static void radius_server_free_sessions(struct radius_server_data
*data
,
670 struct radius_session
*sessions
)
672 struct radius_session
*session
, *prev
;
677 session
= session
->next
;
678 radius_server_session_free(data
, prev
);
683 static void radius_server_free_clients(struct radius_server_data
*data
,
684 struct radius_client
*clients
)
686 struct radius_client
*client
, *prev
;
691 client
= client
->next
;
693 radius_server_free_sessions(data
, prev
->sessions
);
694 free(prev
->shared_secret
);
700 static struct radius_client
*
701 radius_server_read_clients(const char *client_file
, int ipv6
)
704 const int buf_size
= 1024;
706 struct radius_client
*clients
, *tail
, *entry
;
707 int line
= 0, mask
, failed
= 0, i
;
710 struct in6_addr addr6
;
711 #endif /* CONFIG_IPV6 */
714 f
= fopen(client_file
, "r");
716 RADIUS_ERROR("Could not open client file '%s'", client_file
);
720 buf
= malloc(buf_size
);
726 clients
= tail
= NULL
;
727 while (fgets(buf
, buf_size
, f
)) {
728 /* Configuration file format:
729 * 192.168.1.0/24 secret
731 * fe80::211:22ff:fe33:4455/64 secretipv6
734 buf
[buf_size
- 1] = '\0';
736 while (*pos
!= '\0' && *pos
!= '\n')
740 if (*buf
== '\0' || *buf
== '#')
744 while ((*pos
>= '0' && *pos
<= '9') || *pos
== '.' ||
745 (*pos
>= 'a' && *pos
<= 'f') || *pos
== ':' ||
746 (*pos
>= 'A' && *pos
<= 'F')) {
758 mask
= strtol(pos
, &end
, 10);
760 (mask
< 0 || mask
> (ipv6
? 128 : 32))) {
766 mask
= ipv6
? 128 : 32;
770 if (!ipv6
&& inet_aton(buf
, &addr
) == 0) {
775 if (ipv6
&& inet_pton(AF_INET6
, buf
, &addr6
) <= 0) {
776 if (inet_pton(AF_INET
, buf
, &addr
) <= 0) {
780 /* Convert IPv4 address to IPv6 */
783 memset(addr6
.s6_addr
, 0, 10);
784 addr6
.s6_addr
[10] = 0xff;
785 addr6
.s6_addr
[11] = 0xff;
786 memcpy(addr6
.s6_addr
+ 12, (char *) &addr
.s_addr
, 4);
788 #endif /* CONFIG_IPV6 */
790 while (*pos
== ' ' || *pos
== '\t') {
799 entry
= malloc(sizeof(*entry
));
804 memset(entry
, 0, sizeof(*entry
));
805 entry
->shared_secret
= strdup(pos
);
806 if (entry
->shared_secret
== NULL
) {
811 entry
->shared_secret_len
= strlen(entry
->shared_secret
);
812 entry
->addr
.s_addr
= addr
.s_addr
;
815 for (i
= 0; i
< mask
; i
++)
816 val
|= 1 << (31 - i
);
817 entry
->mask
.s_addr
= htonl(val
);
821 int offset
= mask
/ 8;
823 memcpy(entry
->addr6
.s6_addr
, addr6
.s6_addr
, 16);
824 memset(entry
->mask6
.s6_addr
, 0xff, offset
);
826 for (i
= 0; i
< (mask
% 8); i
++)
829 entry
->mask6
.s6_addr
[offset
] = val
;
831 #endif /* CONFIG_IPV6 */
834 clients
= tail
= entry
;
842 RADIUS_ERROR("Invalid line %d in '%s'", line
, client_file
);
843 radius_server_free_clients(NULL
, clients
);
854 struct radius_server_data
*
855 radius_server_init(struct radius_server_conf
*conf
)
857 struct radius_server_data
*data
;
861 fprintf(stderr
, "RADIUS server compiled without IPv6 "
865 #endif /* CONFIG_IPV6 */
867 data
= malloc(sizeof(*data
));
871 memset(data
, 0, sizeof(*data
));
872 data
->hostapd_conf
= conf
->hostapd_conf
;
873 data
->eap_sim_db_priv
= conf
->eap_sim_db_priv
;
874 data
->ssl_ctx
= conf
->ssl_ctx
;
875 data
->ipv6
= conf
->ipv6
;
877 data
->clients
= radius_server_read_clients(conf
->client_file
,
879 if (data
->clients
== NULL
) {
880 printf("No RADIUS clients configured.\n");
881 radius_server_deinit(data
);
887 data
->auth_sock
= radius_server_open_socket6(conf
->auth_port
);
889 #endif /* CONFIG_IPV6 */
890 data
->auth_sock
= radius_server_open_socket(conf
->auth_port
);
891 if (data
->auth_sock
< 0) {
892 printf("Failed to open UDP socket for RADIUS authentication "
894 radius_server_deinit(data
);
897 if (eloop_register_read_sock(data
->auth_sock
,
898 radius_server_receive_auth
,
900 radius_server_deinit(data
);
908 void radius_server_deinit(struct radius_server_data
*data
)
913 if (data
->auth_sock
>= 0) {
914 eloop_unregister_read_sock(data
->auth_sock
);
915 close(data
->auth_sock
);
918 radius_server_free_clients(data
, data
->clients
);
924 int radius_server_get_mib(struct radius_server_data
*data
, char *buf
,
927 /* TODO: add support for RADIUS authentication server MIB */
932 static Boolean
radius_server_get_bool(void *ctx
, enum eapol_bool_var variable
)
934 struct radius_session
*sess
= ctx
;
938 case EAPOL_eapSuccess
:
939 return sess
->eapSuccess
;
940 case EAPOL_eapRestart
:
941 return sess
->eapRestart
;
943 return sess
->eapFail
;
945 return sess
->eapResp
;
949 return sess
->eapNoReq
;
950 case EAPOL_portEnabled
:
951 return sess
->portEnabled
;
952 case EAPOL_eapTimeout
:
953 return sess
->eapTimeout
;
959 static void radius_server_set_bool(void *ctx
, enum eapol_bool_var variable
,
962 struct radius_session
*sess
= ctx
;
966 case EAPOL_eapSuccess
:
967 sess
->eapSuccess
= value
;
969 case EAPOL_eapRestart
:
970 sess
->eapRestart
= value
;
973 sess
->eapFail
= value
;
976 sess
->eapResp
= value
;
979 sess
->eapReq
= value
;
982 sess
->eapNoReq
= value
;
984 case EAPOL_portEnabled
:
985 sess
->portEnabled
= value
;
987 case EAPOL_eapTimeout
:
988 sess
->eapTimeout
= value
;
994 static void radius_server_set_eapReqData(void *ctx
, const u8
*eapReqData
,
995 size_t eapReqDataLen
)
997 struct radius_session
*sess
= ctx
;
1001 free(sess
->eapReqData
);
1002 sess
->eapReqData
= malloc(eapReqDataLen
);
1003 if (sess
->eapReqData
) {
1004 memcpy(sess
->eapReqData
, eapReqData
, eapReqDataLen
);
1005 sess
->eapReqDataLen
= eapReqDataLen
;
1007 sess
->eapReqDataLen
= 0;
1012 static void radius_server_set_eapKeyData(void *ctx
, const u8
*eapKeyData
,
1013 size_t eapKeyDataLen
)
1015 struct radius_session
*sess
= ctx
;
1020 free(sess
->eapKeyData
);
1022 sess
->eapKeyData
= malloc(eapKeyDataLen
);
1023 if (sess
->eapKeyData
) {
1024 memcpy(sess
->eapKeyData
, eapKeyData
, eapKeyDataLen
);
1025 sess
->eapKeyDataLen
= eapKeyDataLen
;
1027 sess
->eapKeyDataLen
= 0;
1030 sess
->eapKeyData
= NULL
;
1031 sess
->eapKeyDataLen
= 0;
1036 static int radius_server_get_eap_user(void *ctx
, const u8
*identity
,
1037 size_t identity_len
, int phase2
,
1038 struct eap_user
*user
)
1040 struct radius_session
*sess
= ctx
;
1041 const struct hostapd_eap_user
*eap_user
;
1043 eap_user
= hostapd_get_eap_user(sess
->server
->hostapd_conf
, identity
,
1044 identity_len
, phase2
);
1045 if (eap_user
== NULL
)
1048 memset(user
, 0, sizeof(*user
));
1049 memcpy(user
->methods
, eap_user
->methods
,
1050 EAP_USER_MAX_METHODS
> EAP_MAX_METHODS
?
1051 EAP_USER_MAX_METHODS
: EAP_MAX_METHODS
);
1053 if (eap_user
->password
) {
1054 user
->password
= malloc(eap_user
->password_len
);
1055 if (user
->password
== NULL
)
1057 memcpy(user
->password
, eap_user
->password
,
1058 eap_user
->password_len
);
1059 user
->password_len
= eap_user
->password_len
;
1061 user
->force_version
= eap_user
->force_version
;
1067 static struct eapol_callbacks radius_server_eapol_cb
=
1069 .get_bool
= radius_server_get_bool
,
1070 .set_bool
= radius_server_set_bool
,
1071 .set_eapReqData
= radius_server_set_eapReqData
,
1072 .set_eapKeyData
= radius_server_set_eapKeyData
,
1073 .get_eap_user
= radius_server_get_eap_user
,