2 * hostapd / RADIUS authentication server
3 * Copyright (c) 2005-2008, Jouni Malinen <j@w1.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.
23 #include "radius_server.h"
25 #define RADIUS_SESSION_TIMEOUT 60
26 #define RADIUS_MAX_SESSION 100
27 #define RADIUS_MAX_MSG_LEN 3000
29 static struct eapol_callbacks radius_server_eapol_cb
;
32 struct radius_server_data
;
34 struct radius_server_counters
{
37 u32 dup_access_requests
;
40 u32 access_challenges
;
41 u32 malformed_access_requests
;
42 u32 bad_authenticators
;
47 struct radius_session
{
48 struct radius_session
*next
;
49 struct radius_client
*client
;
50 struct radius_server_data
*server
;
53 u8
*eapKeyData
, *eapReqData
;
54 size_t eapKeyDataLen
, eapReqDataLen
;
55 Boolean eapSuccess
, eapRestart
, eapFail
, eapResp
, eapReq
, eapNoReq
;
56 Boolean portEnabled
, eapTimeout
;
58 struct radius_msg
*last_msg
;
61 struct sockaddr_storage last_from
;
62 socklen_t last_fromlen
;
64 struct radius_msg
*last_reply
;
65 u8 last_authenticator
[16];
68 struct radius_client
{
69 struct radius_client
*next
;
73 struct in6_addr addr6
;
74 struct in6_addr mask6
;
75 #endif /* CONFIG_IPV6 */
77 int shared_secret_len
;
78 struct radius_session
*sessions
;
79 struct radius_server_counters counters
;
82 struct radius_server_data
{
84 struct radius_client
*clients
;
85 unsigned int next_sess_id
;
88 void *eap_sim_db_priv
;
91 struct os_time start_time
;
92 struct radius_server_counters counters
;
96 extern int wpa_debug_level
;
98 #define RADIUS_DEBUG(args...) \
99 wpa_printf(MSG_DEBUG, "RADIUS SRV: " args)
100 #define RADIUS_ERROR(args...) \
101 wpa_printf(MSG_ERROR, "RADIUS SRV: " args)
102 #define RADIUS_DUMP(args...) \
103 wpa_hexdump(MSG_MSGDUMP, "RADIUS SRV: " args)
104 #define RADIUS_DUMP_ASCII(args...) \
105 wpa_hexdump_ascii(MSG_MSGDUMP, "RADIUS SRV: " args)
108 static void radius_server_session_timeout(void *eloop_ctx
, void *timeout_ctx
);
112 static struct radius_client
*
113 radius_server_get_client(struct radius_server_data
*data
, struct in_addr
*addr
,
116 struct radius_client
*client
= data
->clients
;
121 struct in6_addr
*addr6
;
124 addr6
= (struct in6_addr
*) addr
;
125 for (i
= 0; i
< 16; i
++) {
126 if ((addr6
->s6_addr
[i
] &
127 client
->mask6
.s6_addr
[i
]) !=
128 (client
->addr6
.s6_addr
[i
] &
129 client
->mask6
.s6_addr
[i
])) {
138 #endif /* CONFIG_IPV6 */
139 if (!ipv6
&& (client
->addr
.s_addr
& client
->mask
.s_addr
) ==
140 (addr
->s_addr
& client
->mask
.s_addr
)) {
144 client
= client
->next
;
151 static struct radius_session
*
152 radius_server_get_session(struct radius_client
*client
, unsigned int sess_id
)
154 struct radius_session
*sess
= client
->sessions
;
157 if (sess
->sess_id
== sess_id
) {
167 static void radius_server_session_free(struct radius_server_data
*data
,
168 struct radius_session
*sess
)
170 eloop_cancel_timeout(radius_server_session_timeout
, data
, sess
);
171 free(sess
->eapKeyData
);
172 free(sess
->eapReqData
);
173 eap_sm_deinit(sess
->eap
);
174 if (sess
->last_msg
) {
175 radius_msg_free(sess
->last_msg
);
176 free(sess
->last_msg
);
178 free(sess
->last_from_addr
);
179 if (sess
->last_reply
) {
180 radius_msg_free(sess
->last_reply
);
181 free(sess
->last_reply
);
188 static void radius_server_session_remove_timeout(void *eloop_ctx
,
191 static void radius_server_session_remove(struct radius_server_data
*data
,
192 struct radius_session
*sess
)
194 struct radius_client
*client
= sess
->client
;
195 struct radius_session
*session
, *prev
;
197 eloop_cancel_timeout(radius_server_session_remove_timeout
, data
, sess
);
200 session
= client
->sessions
;
202 if (session
== sess
) {
204 client
->sessions
= sess
->next
;
206 prev
->next
= sess
->next
;
208 radius_server_session_free(data
, sess
);
212 session
= session
->next
;
217 static void radius_server_session_remove_timeout(void *eloop_ctx
,
220 struct radius_server_data
*data
= eloop_ctx
;
221 struct radius_session
*sess
= timeout_ctx
;
222 RADIUS_DEBUG("Removing completed session 0x%x", sess
->sess_id
);
223 radius_server_session_remove(data
, sess
);
227 static void radius_server_session_timeout(void *eloop_ctx
, void *timeout_ctx
)
229 struct radius_server_data
*data
= eloop_ctx
;
230 struct radius_session
*sess
= timeout_ctx
;
232 RADIUS_DEBUG("Timing out authentication session 0x%x", sess
->sess_id
);
233 radius_server_session_remove(data
, sess
);
237 static struct radius_session
*
238 radius_server_new_session(struct radius_server_data
*data
,
239 struct radius_client
*client
)
241 struct radius_session
*sess
;
243 if (data
->num_sess
>= RADIUS_MAX_SESSION
) {
244 RADIUS_DEBUG("Maximum number of existing session - no room "
245 "for a new session");
249 sess
= wpa_zalloc(sizeof(*sess
));
254 sess
->client
= client
;
255 sess
->sess_id
= data
->next_sess_id
++;
256 sess
->next
= client
->sessions
;
257 client
->sessions
= sess
;
258 eloop_register_timeout(RADIUS_SESSION_TIMEOUT
, 0,
259 radius_server_session_timeout
, data
, sess
);
265 static struct radius_session
*
266 radius_server_get_new_session(struct radius_server_data
*data
,
267 struct radius_client
*client
,
268 struct radius_msg
*msg
)
272 const struct hostapd_eap_user
*eap_user
;
274 struct radius_session
*sess
;
275 struct eap_config eap_conf
;
277 RADIUS_DEBUG("Creating a new session");
283 res
= radius_msg_get_attr(msg
, RADIUS_ATTR_USER_NAME
, user
, 256);
284 if (res
< 0 || res
> 256) {
285 RADIUS_DEBUG("Could not get User-Name");
290 RADIUS_DUMP_ASCII("User-Name", user
, user_len
);
292 eap_user
= hostapd_get_eap_user(data
->hostapd_conf
, user
, user_len
, 0);
296 RADIUS_DEBUG("Matching user entry found");
297 sess
= radius_server_new_session(data
, client
);
299 RADIUS_DEBUG("Failed to create a new session");
303 RADIUS_DEBUG("User-Name not found from user database");
307 memset(&eap_conf
, 0, sizeof(eap_conf
));
308 eap_conf
.ssl_ctx
= data
->ssl_ctx
;
309 eap_conf
.eap_sim_db_priv
= data
->eap_sim_db_priv
;
310 eap_conf
.backend_auth
= TRUE
;
311 sess
->eap
= eap_sm_init(sess
, &radius_server_eapol_cb
, &eap_conf
);
312 if (sess
->eap
== NULL
) {
313 RADIUS_DEBUG("Failed to initialize EAP state machine for the "
315 radius_server_session_free(data
, sess
);
318 sess
->eapRestart
= TRUE
;
319 sess
->portEnabled
= TRUE
;
321 RADIUS_DEBUG("New session 0x%x initialized", sess
->sess_id
);
327 static struct radius_msg
*
328 radius_server_encapsulate_eap(struct radius_server_data
*data
,
329 struct radius_client
*client
,
330 struct radius_session
*sess
,
331 struct radius_msg
*request
)
333 struct radius_msg
*msg
;
335 unsigned int sess_id
;
338 code
= RADIUS_CODE_ACCESS_REJECT
;
339 } else if (sess
->eapSuccess
) {
340 code
= RADIUS_CODE_ACCESS_ACCEPT
;
342 code
= RADIUS_CODE_ACCESS_CHALLENGE
;
345 msg
= radius_msg_new(code
, request
->hdr
->identifier
);
347 RADIUS_DEBUG("Failed to allocate reply message");
351 sess_id
= htonl(sess
->sess_id
);
352 if (code
== RADIUS_CODE_ACCESS_CHALLENGE
&&
353 !radius_msg_add_attr(msg
, RADIUS_ATTR_STATE
,
354 (u8
*) &sess_id
, sizeof(sess_id
))) {
355 RADIUS_DEBUG("Failed to add State attribute");
358 if (sess
->eapReqData
&&
359 !radius_msg_add_eap(msg
, sess
->eapReqData
, sess
->eapReqDataLen
)) {
360 RADIUS_DEBUG("Failed to add EAP-Message attribute");
363 if (code
== RADIUS_CODE_ACCESS_ACCEPT
&& sess
->eapKeyData
) {
365 if (sess
->eapKeyDataLen
> 64) {
368 len
= sess
->eapKeyDataLen
/ 2;
370 if (!radius_msg_add_mppe_keys(msg
, request
->hdr
->authenticator
,
371 (u8
*) client
->shared_secret
,
372 client
->shared_secret_len
,
373 sess
->eapKeyData
+ len
, len
,
374 sess
->eapKeyData
, len
)) {
375 RADIUS_DEBUG("Failed to add MPPE key attributes");
379 if (radius_msg_copy_attr(msg
, request
, RADIUS_ATTR_PROXY_STATE
) < 0) {
380 RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
381 radius_msg_free(msg
);
386 if (radius_msg_finish_srv(msg
, (u8
*) client
->shared_secret
,
387 client
->shared_secret_len
,
388 request
->hdr
->authenticator
) < 0) {
389 RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
396 static int radius_server_reject(struct radius_server_data
*data
,
397 struct radius_client
*client
,
398 struct radius_msg
*request
,
399 struct sockaddr
*from
, socklen_t fromlen
,
400 const char *from_addr
, int from_port
)
402 struct radius_msg
*msg
;
404 struct eap_hdr eapfail
;
406 RADIUS_DEBUG("Reject invalid request from %s:%d",
407 from_addr
, from_port
);
409 msg
= radius_msg_new(RADIUS_CODE_ACCESS_REJECT
,
410 request
->hdr
->identifier
);
415 memset(&eapfail
, 0, sizeof(eapfail
));
416 eapfail
.code
= EAP_CODE_FAILURE
;
417 eapfail
.identifier
= 0;
418 eapfail
.length
= htons(sizeof(eapfail
));
420 if (!radius_msg_add_eap(msg
, (u8
*) &eapfail
, sizeof(eapfail
))) {
421 RADIUS_DEBUG("Failed to add EAP-Message attribute");
424 if (radius_msg_copy_attr(msg
, request
, RADIUS_ATTR_PROXY_STATE
) < 0) {
425 RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
426 radius_msg_free(msg
);
431 if (radius_msg_finish_srv(msg
, (u8
*) client
->shared_secret
,
432 client
->shared_secret_len
,
433 request
->hdr
->authenticator
) < 0) {
434 RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
437 if (wpa_debug_level
<= MSG_MSGDUMP
) {
438 radius_msg_dump(msg
);
441 data
->counters
.access_rejects
++;
442 client
->counters
.access_rejects
++;
443 if (sendto(data
->auth_sock
, msg
->buf
, msg
->buf_used
, 0,
444 (struct sockaddr
*) from
, sizeof(*from
)) < 0) {
445 perror("sendto[RADIUS SRV]");
449 radius_msg_free(msg
);
456 static int radius_server_request(struct radius_server_data
*data
,
457 struct radius_msg
*msg
,
458 struct sockaddr
*from
, socklen_t fromlen
,
459 struct radius_client
*client
,
460 const char *from_addr
, int from_port
,
461 struct radius_session
*force_sess
)
465 int res
, state_included
= 0;
466 u8 statebuf
[4], resp_id
;
468 struct radius_session
*sess
;
469 struct radius_msg
*reply
;
475 res
= radius_msg_get_attr(msg
, RADIUS_ATTR_STATE
, statebuf
,
477 state_included
= res
>= 0;
478 if (res
== sizeof(statebuf
)) {
479 state
= (statebuf
[0] << 24) | (statebuf
[1] << 16) |
480 (statebuf
[2] << 8) | statebuf
[3];
481 sess
= radius_server_get_session(client
, state
);
488 RADIUS_DEBUG("Request for session 0x%x", sess
->sess_id
);
489 } else if (state_included
) {
490 RADIUS_DEBUG("State attribute included but no session found");
491 radius_server_reject(data
, client
, msg
, from
, fromlen
,
492 from_addr
, from_port
);
495 sess
= radius_server_get_new_session(data
, client
, msg
);
497 RADIUS_DEBUG("Could not create a new session");
498 radius_server_reject(data
, client
, msg
, from
, fromlen
,
499 from_addr
, from_port
);
504 if (sess
->last_from_port
== from_port
&&
505 sess
->last_identifier
== msg
->hdr
->identifier
&&
506 os_memcmp(sess
->last_authenticator
, msg
->hdr
->authenticator
, 16) ==
508 RADIUS_DEBUG("Duplicate message from %s", from_addr
);
509 data
->counters
.dup_access_requests
++;
510 client
->counters
.dup_access_requests
++;
512 if (sess
->last_reply
) {
513 res
= sendto(data
->auth_sock
, sess
->last_reply
->buf
,
514 sess
->last_reply
->buf_used
, 0,
515 (struct sockaddr
*) from
, fromlen
);
517 perror("sendto[RADIUS SRV]");
522 RADIUS_DEBUG("No previous reply available for duplicate "
527 eap
= radius_msg_get_eap(msg
, &eap_len
);
529 RADIUS_DEBUG("No EAP-Message in RADIUS packet from %s",
531 data
->counters
.packets_dropped
++;
532 client
->counters
.packets_dropped
++;
536 RADIUS_DUMP("Received EAP data", eap
, eap_len
);
537 if (eap_len
>= sizeof(*hdr
)) {
538 hdr
= (struct eap_hdr
*) eap
;
539 resp_id
= hdr
->identifier
;
544 /* FIX: if Code is Request, Success, or Failure, send Access-Reject;
545 * RFC3579 Sect. 2.6.2.
546 * Include EAP-Response/Nak with no preferred method if
548 * If code is not 1-4, discard the packet silently.
549 * Or is this already done by the EAP state machine? */
551 eap_set_eapRespData(sess
->eap
, eap
, eap_len
);
554 sess
->eapResp
= TRUE
;
555 eap_sm_step(sess
->eap
);
557 if (sess
->eapReqData
) {
558 RADIUS_DUMP("EAP data from the state machine",
559 sess
->eapReqData
, sess
->eapReqDataLen
);
560 } else if (sess
->eapFail
) {
561 RADIUS_DEBUG("No EAP data from the state machine, but eapFail "
562 "set - generate EAP-Failure");
563 hdr
= wpa_zalloc(sizeof(*hdr
));
565 hdr
->identifier
= resp_id
;
566 hdr
->length
= htons(sizeof(*hdr
));
567 sess
->eapReqData
= (u8
*) hdr
;
568 sess
->eapReqDataLen
= sizeof(*hdr
);
570 } else if (eap_sm_method_pending(sess
->eap
)) {
571 if (sess
->last_msg
) {
572 radius_msg_free(sess
->last_msg
);
573 free(sess
->last_msg
);
575 sess
->last_msg
= msg
;
576 sess
->last_from_port
= from_port
;
577 free(sess
->last_from_addr
);
578 sess
->last_from_addr
= strdup(from_addr
);
579 sess
->last_fromlen
= fromlen
;
580 memcpy(&sess
->last_from
, from
, fromlen
);
583 RADIUS_DEBUG("No EAP data from the state machine - ignore this"
584 " Access-Request silently (assuming it was a "
586 data
->counters
.packets_dropped
++;
587 client
->counters
.packets_dropped
++;
591 reply
= radius_server_encapsulate_eap(data
, client
, sess
, msg
);
593 free(sess
->eapReqData
);
594 sess
->eapReqData
= NULL
;
595 sess
->eapReqDataLen
= 0;
598 RADIUS_DEBUG("Reply to %s:%d", from_addr
, from_port
);
599 if (wpa_debug_level
<= MSG_MSGDUMP
) {
600 radius_msg_dump(reply
);
603 switch (reply
->hdr
->code
) {
604 case RADIUS_CODE_ACCESS_ACCEPT
:
605 data
->counters
.access_accepts
++;
606 client
->counters
.access_accepts
++;
608 case RADIUS_CODE_ACCESS_REJECT
:
609 data
->counters
.access_rejects
++;
610 client
->counters
.access_rejects
++;
612 case RADIUS_CODE_ACCESS_CHALLENGE
:
613 data
->counters
.access_challenges
++;
614 client
->counters
.access_challenges
++;
617 res
= sendto(data
->auth_sock
, reply
->buf
, reply
->buf_used
, 0,
618 (struct sockaddr
*) from
, fromlen
);
620 perror("sendto[RADIUS SRV]");
622 if (sess
->last_reply
) {
623 radius_msg_free(sess
->last_reply
);
624 free(sess
->last_reply
);
626 sess
->last_reply
= reply
;
627 sess
->last_from_port
= from_port
;
628 sess
->last_identifier
= msg
->hdr
->identifier
;
629 os_memcpy(sess
->last_authenticator
, msg
->hdr
->authenticator
,
632 data
->counters
.packets_dropped
++;
633 client
->counters
.packets_dropped
++;
636 if (sess
->eapSuccess
|| sess
->eapFail
) {
637 RADIUS_DEBUG("Removing completed session 0x%x after timeout",
639 eloop_cancel_timeout(radius_server_session_remove_timeout
,
641 eloop_register_timeout(10, 0,
642 radius_server_session_remove_timeout
,
650 static void radius_server_receive_auth(int sock
, void *eloop_ctx
,
653 struct radius_server_data
*data
= eloop_ctx
;
655 struct sockaddr_storage from
;
658 struct radius_client
*client
= NULL
;
659 struct radius_msg
*msg
= NULL
;
663 buf
= malloc(RADIUS_MAX_MSG_LEN
);
668 fromlen
= sizeof(from
);
669 len
= recvfrom(sock
, buf
, RADIUS_MAX_MSG_LEN
, 0,
670 (struct sockaddr
*) &from
, &fromlen
);
672 perror("recvfrom[radius_server]");
678 struct sockaddr_in6
*from6
= (struct sockaddr_in6
*) &from
;
679 if (inet_ntop(AF_INET6
, &from6
->sin6_addr
, abuf
, sizeof(abuf
))
682 from_port
= ntohs(from6
->sin6_port
);
683 RADIUS_DEBUG("Received %d bytes from %s:%d",
684 len
, abuf
, from_port
);
686 client
= radius_server_get_client(data
,
688 &from6
->sin6_addr
, 1);
690 #endif /* CONFIG_IPV6 */
693 struct sockaddr_in
*from4
= (struct sockaddr_in
*) &from
;
694 snprintf(abuf
, sizeof(abuf
), "%s", inet_ntoa(from4
->sin_addr
));
695 from_port
= ntohs(from4
->sin_port
);
696 RADIUS_DEBUG("Received %d bytes from %s:%d",
697 len
, abuf
, from_port
);
699 client
= radius_server_get_client(data
, &from4
->sin_addr
, 0);
702 RADIUS_DUMP("Received data", buf
, len
);
704 if (client
== NULL
) {
705 RADIUS_DEBUG("Unknown client %s - packet ignored", abuf
);
706 data
->counters
.invalid_requests
++;
710 msg
= radius_msg_parse(buf
, len
);
712 RADIUS_DEBUG("Parsing incoming RADIUS frame failed");
713 data
->counters
.malformed_access_requests
++;
714 client
->counters
.malformed_access_requests
++;
721 if (wpa_debug_level
<= MSG_MSGDUMP
) {
722 radius_msg_dump(msg
);
725 if (msg
->hdr
->code
!= RADIUS_CODE_ACCESS_REQUEST
) {
726 RADIUS_DEBUG("Unexpected RADIUS code %d", msg
->hdr
->code
);
727 data
->counters
.unknown_types
++;
728 client
->counters
.unknown_types
++;
732 data
->counters
.access_requests
++;
733 client
->counters
.access_requests
++;
735 if (radius_msg_verify_msg_auth(msg
, (u8
*) client
->shared_secret
,
736 client
->shared_secret_len
, NULL
)) {
737 RADIUS_DEBUG("Invalid Message-Authenticator from %s", abuf
);
738 data
->counters
.bad_authenticators
++;
739 client
->counters
.bad_authenticators
++;
743 if (radius_server_request(data
, msg
, (struct sockaddr
*) &from
,
744 fromlen
, client
, abuf
, from_port
, NULL
) ==
746 return; /* msg was stored with the session */
750 radius_msg_free(msg
);
757 static int radius_server_open_socket(int port
)
760 struct sockaddr_in addr
;
762 s
= socket(PF_INET
, SOCK_DGRAM
, 0);
768 memset(&addr
, 0, sizeof(addr
));
769 addr
.sin_family
= AF_INET
;
770 addr
.sin_port
= htons(port
);
771 if (bind(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
782 static int radius_server_open_socket6(int port
)
785 struct sockaddr_in6 addr
;
787 s
= socket(PF_INET6
, SOCK_DGRAM
, 0);
789 perror("socket[IPv6]");
793 memset(&addr
, 0, sizeof(addr
));
794 addr
.sin6_family
= AF_INET6
;
795 memcpy(&addr
.sin6_addr
, &in6addr_any
, sizeof(in6addr_any
));
796 addr
.sin6_port
= htons(port
);
797 if (bind(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
805 #endif /* CONFIG_IPV6 */
808 static void radius_server_free_sessions(struct radius_server_data
*data
,
809 struct radius_session
*sessions
)
811 struct radius_session
*session
, *prev
;
816 session
= session
->next
;
817 radius_server_session_free(data
, prev
);
822 static void radius_server_free_clients(struct radius_server_data
*data
,
823 struct radius_client
*clients
)
825 struct radius_client
*client
, *prev
;
830 client
= client
->next
;
832 radius_server_free_sessions(data
, prev
->sessions
);
833 free(prev
->shared_secret
);
839 static struct radius_client
*
840 radius_server_read_clients(const char *client_file
, int ipv6
)
843 const int buf_size
= 1024;
845 struct radius_client
*clients
, *tail
, *entry
;
846 int line
= 0, mask
, failed
= 0, i
;
849 struct in6_addr addr6
;
850 #endif /* CONFIG_IPV6 */
853 f
= fopen(client_file
, "r");
855 RADIUS_ERROR("Could not open client file '%s'", client_file
);
859 buf
= malloc(buf_size
);
865 clients
= tail
= NULL
;
866 while (fgets(buf
, buf_size
, f
)) {
867 /* Configuration file format:
868 * 192.168.1.0/24 secret
870 * fe80::211:22ff:fe33:4455/64 secretipv6
873 buf
[buf_size
- 1] = '\0';
875 while (*pos
!= '\0' && *pos
!= '\n')
879 if (*buf
== '\0' || *buf
== '#')
883 while ((*pos
>= '0' && *pos
<= '9') || *pos
== '.' ||
884 (*pos
>= 'a' && *pos
<= 'f') || *pos
== ':' ||
885 (*pos
>= 'A' && *pos
<= 'F')) {
897 mask
= strtol(pos
, &end
, 10);
899 (mask
< 0 || mask
> (ipv6
? 128 : 32))) {
905 mask
= ipv6
? 128 : 32;
909 if (!ipv6
&& inet_aton(buf
, &addr
) == 0) {
914 if (ipv6
&& inet_pton(AF_INET6
, buf
, &addr6
) <= 0) {
915 if (inet_pton(AF_INET
, buf
, &addr
) <= 0) {
919 /* Convert IPv4 address to IPv6 */
922 memset(addr6
.s6_addr
, 0, 10);
923 addr6
.s6_addr
[10] = 0xff;
924 addr6
.s6_addr
[11] = 0xff;
925 memcpy(addr6
.s6_addr
+ 12, (char *) &addr
.s_addr
, 4);
927 #endif /* CONFIG_IPV6 */
929 while (*pos
== ' ' || *pos
== '\t') {
938 entry
= wpa_zalloc(sizeof(*entry
));
943 entry
->shared_secret
= strdup(pos
);
944 if (entry
->shared_secret
== NULL
) {
949 entry
->shared_secret_len
= strlen(entry
->shared_secret
);
950 entry
->addr
.s_addr
= addr
.s_addr
;
953 for (i
= 0; i
< mask
; i
++)
954 val
|= 1 << (31 - i
);
955 entry
->mask
.s_addr
= htonl(val
);
959 int offset
= mask
/ 8;
961 memcpy(entry
->addr6
.s6_addr
, addr6
.s6_addr
, 16);
962 memset(entry
->mask6
.s6_addr
, 0xff, offset
);
964 for (i
= 0; i
< (mask
% 8); i
++)
967 entry
->mask6
.s6_addr
[offset
] = val
;
969 #endif /* CONFIG_IPV6 */
972 clients
= tail
= entry
;
980 RADIUS_ERROR("Invalid line %d in '%s'", line
, client_file
);
981 radius_server_free_clients(NULL
, clients
);
992 struct radius_server_data
*
993 radius_server_init(struct radius_server_conf
*conf
)
995 struct radius_server_data
*data
;
999 fprintf(stderr
, "RADIUS server compiled without IPv6 "
1003 #endif /* CONFIG_IPV6 */
1005 data
= wpa_zalloc(sizeof(*data
));
1009 os_get_time(&data
->start_time
);
1010 data
->hostapd_conf
= conf
->hostapd_conf
;
1011 data
->eap_sim_db_priv
= conf
->eap_sim_db_priv
;
1012 data
->ssl_ctx
= conf
->ssl_ctx
;
1013 data
->ipv6
= conf
->ipv6
;
1015 data
->clients
= radius_server_read_clients(conf
->client_file
,
1017 if (data
->clients
== NULL
) {
1018 printf("No RADIUS clients configured.\n");
1019 radius_server_deinit(data
);
1025 data
->auth_sock
= radius_server_open_socket6(conf
->auth_port
);
1027 #endif /* CONFIG_IPV6 */
1028 data
->auth_sock
= radius_server_open_socket(conf
->auth_port
);
1029 if (data
->auth_sock
< 0) {
1030 printf("Failed to open UDP socket for RADIUS authentication "
1032 radius_server_deinit(data
);
1035 if (eloop_register_read_sock(data
->auth_sock
,
1036 radius_server_receive_auth
,
1038 radius_server_deinit(data
);
1046 void radius_server_deinit(struct radius_server_data
*data
)
1051 if (data
->auth_sock
>= 0) {
1052 eloop_unregister_read_sock(data
->auth_sock
);
1053 close(data
->auth_sock
);
1056 radius_server_free_clients(data
, data
->clients
);
1062 int radius_server_get_mib(struct radius_server_data
*data
, char *buf
,
1069 struct radius_client
*cli
;
1071 /* RFC 2619 - RADIUS Authentication Server MIB */
1073 if (data
== NULL
|| buflen
== 0)
1080 uptime
= (now
.sec
- data
->start_time
.sec
) * 100 +
1081 ((now
.usec
- data
->start_time
.usec
) / 10000) % 100;
1082 ret
= snprintf(pos
, end
- pos
,
1083 "RADIUS-AUTH-SERVER-MIB\n"
1084 "radiusAuthServIdent=hostapd\n"
1085 "radiusAuthServUpTime=%d\n"
1086 "radiusAuthServResetTime=0\n"
1087 "radiusAuthServConfigReset=4\n",
1089 if (ret
< 0 || ret
>= end
- pos
) {
1095 ret
= snprintf(pos
, end
- pos
,
1096 "radiusAuthServTotalAccessRequests=%u\n"
1097 "radiusAuthServTotalInvalidRequests=%u\n"
1098 "radiusAuthServTotalDupAccessRequests=%u\n"
1099 "radiusAuthServTotalAccessAccepts=%u\n"
1100 "radiusAuthServTotalAccessRejects=%u\n"
1101 "radiusAuthServTotalAccessChallenges=%u\n"
1102 "radiusAuthServTotalMalformedAccessRequests=%u\n"
1103 "radiusAuthServTotalBadAuthenticators=%u\n"
1104 "radiusAuthServTotalPacketsDropped=%u\n"
1105 "radiusAuthServTotalUnknownTypes=%u\n",
1106 data
->counters
.access_requests
,
1107 data
->counters
.invalid_requests
,
1108 data
->counters
.dup_access_requests
,
1109 data
->counters
.access_accepts
,
1110 data
->counters
.access_rejects
,
1111 data
->counters
.access_challenges
,
1112 data
->counters
.malformed_access_requests
,
1113 data
->counters
.bad_authenticators
,
1114 data
->counters
.packets_dropped
,
1115 data
->counters
.unknown_types
);
1116 if (ret
< 0 || ret
>= end
- pos
) {
1122 for (cli
= data
->clients
, idx
= 0; cli
; cli
= cli
->next
, idx
++) {
1123 char abuf
[50], mbuf
[50];
1126 if (inet_ntop(AF_INET6
, &cli
->addr6
, abuf
,
1127 sizeof(abuf
)) == NULL
)
1129 if (inet_ntop(AF_INET6
, &cli
->mask6
, abuf
,
1130 sizeof(mbuf
)) == NULL
)
1133 #endif /* CONFIG_IPV6 */
1135 snprintf(abuf
, sizeof(abuf
), "%s",
1136 inet_ntoa(cli
->addr
));
1137 snprintf(mbuf
, sizeof(mbuf
), "%s",
1138 inet_ntoa(cli
->mask
));
1141 ret
= snprintf(pos
, end
- pos
,
1142 "radiusAuthClientIndex=%u\n"
1143 "radiusAuthClientAddress=%s/%s\n"
1144 "radiusAuthServAccessRequests=%u\n"
1145 "radiusAuthServDupAccessRequests=%u\n"
1146 "radiusAuthServAccessAccepts=%u\n"
1147 "radiusAuthServAccessRejects=%u\n"
1148 "radiusAuthServAccessChallenges=%u\n"
1149 "radiusAuthServMalformedAccessRequests=%u\n"
1150 "radiusAuthServBadAuthenticators=%u\n"
1151 "radiusAuthServPacketsDropped=%u\n"
1152 "radiusAuthServUnknownTypes=%u\n",
1155 cli
->counters
.access_requests
,
1156 cli
->counters
.dup_access_requests
,
1157 cli
->counters
.access_accepts
,
1158 cli
->counters
.access_rejects
,
1159 cli
->counters
.access_challenges
,
1160 cli
->counters
.malformed_access_requests
,
1161 cli
->counters
.bad_authenticators
,
1162 cli
->counters
.packets_dropped
,
1163 cli
->counters
.unknown_types
);
1164 if (ret
< 0 || ret
>= end
- pos
) {
1175 static Boolean
radius_server_get_bool(void *ctx
, enum eapol_bool_var variable
)
1177 struct radius_session
*sess
= ctx
;
1181 case EAPOL_eapSuccess
:
1182 return sess
->eapSuccess
;
1183 case EAPOL_eapRestart
:
1184 return sess
->eapRestart
;
1186 return sess
->eapFail
;
1188 return sess
->eapResp
;
1190 return sess
->eapReq
;
1191 case EAPOL_eapNoReq
:
1192 return sess
->eapNoReq
;
1193 case EAPOL_portEnabled
:
1194 return sess
->portEnabled
;
1195 case EAPOL_eapTimeout
:
1196 return sess
->eapTimeout
;
1202 static void radius_server_set_bool(void *ctx
, enum eapol_bool_var variable
,
1205 struct radius_session
*sess
= ctx
;
1209 case EAPOL_eapSuccess
:
1210 sess
->eapSuccess
= value
;
1212 case EAPOL_eapRestart
:
1213 sess
->eapRestart
= value
;
1216 sess
->eapFail
= value
;
1219 sess
->eapResp
= value
;
1222 sess
->eapReq
= value
;
1224 case EAPOL_eapNoReq
:
1225 sess
->eapNoReq
= value
;
1227 case EAPOL_portEnabled
:
1228 sess
->portEnabled
= value
;
1230 case EAPOL_eapTimeout
:
1231 sess
->eapTimeout
= value
;
1237 static void radius_server_set_eapReqData(void *ctx
, const u8
*eapReqData
,
1238 size_t eapReqDataLen
)
1240 struct radius_session
*sess
= ctx
;
1244 free(sess
->eapReqData
);
1245 sess
->eapReqData
= malloc(eapReqDataLen
);
1246 if (sess
->eapReqData
) {
1247 memcpy(sess
->eapReqData
, eapReqData
, eapReqDataLen
);
1248 sess
->eapReqDataLen
= eapReqDataLen
;
1250 sess
->eapReqDataLen
= 0;
1255 static void radius_server_set_eapKeyData(void *ctx
, const u8
*eapKeyData
,
1256 size_t eapKeyDataLen
)
1258 struct radius_session
*sess
= ctx
;
1263 free(sess
->eapKeyData
);
1265 sess
->eapKeyData
= malloc(eapKeyDataLen
);
1266 if (sess
->eapKeyData
) {
1267 memcpy(sess
->eapKeyData
, eapKeyData
, eapKeyDataLen
);
1268 sess
->eapKeyDataLen
= eapKeyDataLen
;
1270 sess
->eapKeyDataLen
= 0;
1273 sess
->eapKeyData
= NULL
;
1274 sess
->eapKeyDataLen
= 0;
1279 static int radius_server_get_eap_user(void *ctx
, const u8
*identity
,
1280 size_t identity_len
, int phase2
,
1281 struct eap_user
*user
)
1283 struct radius_session
*sess
= ctx
;
1284 const struct hostapd_eap_user
*eap_user
;
1287 eap_user
= hostapd_get_eap_user(sess
->server
->hostapd_conf
, identity
,
1288 identity_len
, phase2
);
1289 if (eap_user
== NULL
)
1292 memset(user
, 0, sizeof(*user
));
1293 count
= EAP_USER_MAX_METHODS
;
1294 if (count
> EAP_MAX_METHODS
)
1295 count
= EAP_MAX_METHODS
;
1296 for (i
= 0; i
< count
; i
++) {
1297 user
->methods
[i
].vendor
= eap_user
->methods
[i
].vendor
;
1298 user
->methods
[i
].method
= eap_user
->methods
[i
].method
;
1301 if (eap_user
->password
) {
1302 user
->password
= malloc(eap_user
->password_len
);
1303 if (user
->password
== NULL
)
1305 memcpy(user
->password
, eap_user
->password
,
1306 eap_user
->password_len
);
1307 user
->password_len
= eap_user
->password_len
;
1308 user
->password_hash
= eap_user
->password_hash
;
1310 user
->force_version
= eap_user
->force_version
;
1316 static struct eapol_callbacks radius_server_eapol_cb
=
1318 .get_bool
= radius_server_get_bool
,
1319 .set_bool
= radius_server_set_bool
,
1320 .set_eapReqData
= radius_server_set_eapReqData
,
1321 .set_eapKeyData
= radius_server_set_eapKeyData
,
1322 .get_eap_user
= radius_server_get_eap_user
,
1326 void radius_server_eap_pending_cb(struct radius_server_data
*data
, void *ctx
)
1328 struct radius_client
*cli
;
1329 struct radius_session
*s
, *sess
= NULL
;
1330 struct radius_msg
*msg
;
1335 for (cli
= data
->clients
; cli
; cli
= cli
->next
) {
1336 for (s
= cli
->sessions
; s
; s
= s
->next
) {
1337 if (s
->eap
== ctx
&& s
->last_msg
) {
1349 RADIUS_DEBUG("No session matched callback ctx");
1353 msg
= sess
->last_msg
;
1354 sess
->last_msg
= NULL
;
1355 eap_sm_pending_cb(sess
->eap
);
1356 if (radius_server_request(data
, msg
,
1357 (struct sockaddr
*) &sess
->last_from
,
1358 sess
->last_fromlen
, cli
,
1359 sess
->last_from_addr
,
1360 sess
->last_from_port
, sess
) == -2)
1361 return; /* msg was stored with the session */
1363 radius_msg_free(msg
);