2 * RADIUS authentication server
3 * Copyright (c) 2005-2009, 2011, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
15 #include "eap_server/eap.h"
16 #include "radius_server.h"
19 * RADIUS_SESSION_TIMEOUT - Session timeout in seconds
21 #define RADIUS_SESSION_TIMEOUT 60
24 * RADIUS_MAX_SESSION - Maximum number of active sessions
26 #define RADIUS_MAX_SESSION 100
29 * RADIUS_MAX_MSG_LEN - Maximum message length for incoming RADIUS messages
31 #define RADIUS_MAX_MSG_LEN 3000
33 static struct eapol_callbacks radius_server_eapol_cb
;
36 struct radius_server_data
;
39 * struct radius_server_counters - RADIUS server statistics counters
41 struct radius_server_counters
{
44 u32 dup_access_requests
;
47 u32 access_challenges
;
48 u32 malformed_access_requests
;
49 u32 bad_authenticators
;
55 * struct radius_session - Internal RADIUS server data for a session
57 struct radius_session
{
58 struct radius_session
*next
;
59 struct radius_client
*client
;
60 struct radius_server_data
*server
;
63 struct eap_eapol_interface
*eap_if
;
65 struct radius_msg
*last_msg
;
68 struct sockaddr_storage last_from
;
69 socklen_t last_fromlen
;
71 struct radius_msg
*last_reply
;
72 u8 last_authenticator
[16];
76 * struct radius_client - Internal RADIUS server data for a client
78 struct radius_client
{
79 struct radius_client
*next
;
83 struct in6_addr addr6
;
84 struct in6_addr mask6
;
85 #endif /* CONFIG_IPV6 */
87 int shared_secret_len
;
88 struct radius_session
*sessions
;
89 struct radius_server_counters counters
;
93 * struct radius_server_data - Internal RADIUS server data
95 struct radius_server_data
{
97 * auth_sock - Socket for RADIUS authentication messages
102 * clients - List of authorized RADIUS clients
104 struct radius_client
*clients
;
107 * next_sess_id - Next session identifier
109 unsigned int next_sess_id
;
112 * conf_ctx - Context pointer for callbacks
114 * This is used as the ctx argument in get_eap_user() calls.
119 * num_sess - Number of active sessions
124 * eap_sim_db_priv - EAP-SIM/AKA database context
126 * This is passed to the EAP-SIM/AKA server implementation as a
129 void *eap_sim_db_priv
;
132 * ssl_ctx - TLS context
134 * This is passed to the EAP server implementation as a callback
135 * context for TLS operations.
140 * pac_opaque_encr_key - PAC-Opaque encryption key for EAP-FAST
142 * This parameter is used to set a key for EAP-FAST to encrypt the
143 * PAC-Opaque data. It can be set to %NULL if EAP-FAST is not used. If
144 * set, must point to a 16-octet key.
146 u8
*pac_opaque_encr_key
;
149 * eap_fast_a_id - EAP-FAST authority identity (A-ID)
151 * If EAP-FAST is not used, this can be set to %NULL. In theory, this
152 * is a variable length field, but due to some existing implementations
153 * requiring A-ID to be 16 octets in length, it is recommended to use
154 * that length for the field to provide interoperability with deployed
155 * peer implementations.
160 * eap_fast_a_id_len - Length of eap_fast_a_id buffer in octets
162 size_t eap_fast_a_id_len
;
165 * eap_fast_a_id_info - EAP-FAST authority identifier information
167 * This A-ID-Info contains a user-friendly name for the A-ID. For
168 * example, this could be the enterprise and server names in
169 * human-readable format. This field is encoded as UTF-8. If EAP-FAST
170 * is not used, this can be set to %NULL.
172 char *eap_fast_a_id_info
;
175 * eap_fast_prov - EAP-FAST provisioning modes
177 * 0 = provisioning disabled, 1 = only anonymous provisioning allowed,
178 * 2 = only authenticated provisioning allowed, 3 = both provisioning
184 * pac_key_lifetime - EAP-FAST PAC-Key lifetime in seconds
186 * This is the hard limit on how long a provisioned PAC-Key can be
189 int pac_key_lifetime
;
192 * pac_key_refresh_time - EAP-FAST PAC-Key refresh time in seconds
194 * This is a soft limit on the PAC-Key. The server will automatically
195 * generate a new PAC-Key when this number of seconds (or fewer) of the
198 int pac_key_refresh_time
;
201 * eap_sim_aka_result_ind - EAP-SIM/AKA protected success indication
203 * This controls whether the protected success/failure indication
204 * (AT_RESULT_IND) is used with EAP-SIM and EAP-AKA.
206 int eap_sim_aka_result_ind
;
209 * tnc - Trusted Network Connect (TNC)
211 * This controls whether TNC is enabled and will be required before the
212 * peer is allowed to connect. Note: This is only used with EAP-TTLS
213 * and EAP-FAST. If any other EAP method is enabled, the peer will be
214 * allowed to connect without TNC.
219 * pwd_group - The D-H group assigned for EAP-pwd
221 * If EAP-pwd is not used it can be set to zero.
226 * wps - Wi-Fi Protected Setup context
228 * If WPS is used with an external RADIUS server (which is quite
229 * unlikely configuration), this is used to provide a pointer to WPS
230 * context data. Normally, this can be set to %NULL.
232 struct wps_context
*wps
;
235 * ipv6 - Whether to enable IPv6 support in the RADIUS server
240 * start_time - Timestamp of server start
242 struct os_time start_time
;
245 * counters - Statistics counters for server operations
247 * These counters are the sum over all clients.
249 struct radius_server_counters counters
;
252 * get_eap_user - Callback for fetching EAP user information
253 * @ctx: Context data from conf_ctx
254 * @identity: User identity
255 * @identity_len: identity buffer length in octets
256 * @phase2: Whether this is for Phase 2 identity
257 * @user: Data structure for filling in the user information
258 * Returns: 0 on success, -1 on failure
260 * This is used to fetch information from user database. The callback
261 * will fill in information about allowed EAP methods and the user
262 * password. The password field will be an allocated copy of the
263 * password data and RADIUS server will free it after use.
265 int (*get_eap_user
)(void *ctx
, const u8
*identity
, size_t identity_len
,
266 int phase2
, struct eap_user
*user
);
269 * eap_req_id_text - Optional data for EAP-Request/Identity
271 * This can be used to configure an optional, displayable message that
272 * will be sent in EAP-Request/Identity. This string can contain an
273 * ASCII-0 character (nul) to separate network infromation per RFC
274 * 4284. The actual string length is explicit provided in
275 * eap_req_id_text_len since nul character will not be used as a string
278 char *eap_req_id_text
;
281 * eap_req_id_text_len - Length of eap_req_id_text buffer in octets
283 size_t eap_req_id_text_len
;
286 * msg_ctx - Context data for wpa_msg() calls
290 #ifdef CONFIG_RADIUS_TEST
292 #endif /* CONFIG_RADIUS_TEST */
296 extern int wpa_debug_level
;
298 #define RADIUS_DEBUG(args...) \
299 wpa_printf(MSG_DEBUG, "RADIUS SRV: " args)
300 #define RADIUS_ERROR(args...) \
301 wpa_printf(MSG_ERROR, "RADIUS SRV: " args)
302 #define RADIUS_DUMP(args...) \
303 wpa_hexdump(MSG_MSGDUMP, "RADIUS SRV: " args)
304 #define RADIUS_DUMP_ASCII(args...) \
305 wpa_hexdump_ascii(MSG_MSGDUMP, "RADIUS SRV: " args)
308 static void radius_server_session_timeout(void *eloop_ctx
, void *timeout_ctx
);
309 static void radius_server_session_remove_timeout(void *eloop_ctx
,
313 static struct radius_client
*
314 radius_server_get_client(struct radius_server_data
*data
, struct in_addr
*addr
,
317 struct radius_client
*client
= data
->clients
;
322 struct in6_addr
*addr6
;
325 addr6
= (struct in6_addr
*) addr
;
326 for (i
= 0; i
< 16; i
++) {
327 if ((addr6
->s6_addr
[i
] &
328 client
->mask6
.s6_addr
[i
]) !=
329 (client
->addr6
.s6_addr
[i
] &
330 client
->mask6
.s6_addr
[i
])) {
339 #endif /* CONFIG_IPV6 */
340 if (!ipv6
&& (client
->addr
.s_addr
& client
->mask
.s_addr
) ==
341 (addr
->s_addr
& client
->mask
.s_addr
)) {
345 client
= client
->next
;
352 static struct radius_session
*
353 radius_server_get_session(struct radius_client
*client
, unsigned int sess_id
)
355 struct radius_session
*sess
= client
->sessions
;
358 if (sess
->sess_id
== sess_id
) {
368 static void radius_server_session_free(struct radius_server_data
*data
,
369 struct radius_session
*sess
)
371 eloop_cancel_timeout(radius_server_session_timeout
, data
, sess
);
372 eloop_cancel_timeout(radius_server_session_remove_timeout
, data
, sess
);
373 eap_server_sm_deinit(sess
->eap
);
374 radius_msg_free(sess
->last_msg
);
375 os_free(sess
->last_from_addr
);
376 radius_msg_free(sess
->last_reply
);
382 static void radius_server_session_remove(struct radius_server_data
*data
,
383 struct radius_session
*sess
)
385 struct radius_client
*client
= sess
->client
;
386 struct radius_session
*session
, *prev
;
388 eloop_cancel_timeout(radius_server_session_remove_timeout
, data
, sess
);
391 session
= client
->sessions
;
393 if (session
== sess
) {
395 client
->sessions
= sess
->next
;
397 prev
->next
= sess
->next
;
399 radius_server_session_free(data
, sess
);
403 session
= session
->next
;
408 static void radius_server_session_remove_timeout(void *eloop_ctx
,
411 struct radius_server_data
*data
= eloop_ctx
;
412 struct radius_session
*sess
= timeout_ctx
;
413 RADIUS_DEBUG("Removing completed session 0x%x", sess
->sess_id
);
414 radius_server_session_remove(data
, sess
);
418 static void radius_server_session_timeout(void *eloop_ctx
, void *timeout_ctx
)
420 struct radius_server_data
*data
= eloop_ctx
;
421 struct radius_session
*sess
= timeout_ctx
;
423 RADIUS_DEBUG("Timing out authentication session 0x%x", sess
->sess_id
);
424 radius_server_session_remove(data
, sess
);
428 static struct radius_session
*
429 radius_server_new_session(struct radius_server_data
*data
,
430 struct radius_client
*client
)
432 struct radius_session
*sess
;
434 if (data
->num_sess
>= RADIUS_MAX_SESSION
) {
435 RADIUS_DEBUG("Maximum number of existing session - no room "
436 "for a new session");
440 sess
= os_zalloc(sizeof(*sess
));
445 sess
->client
= client
;
446 sess
->sess_id
= data
->next_sess_id
++;
447 sess
->next
= client
->sessions
;
448 client
->sessions
= sess
;
449 eloop_register_timeout(RADIUS_SESSION_TIMEOUT
, 0,
450 radius_server_session_timeout
, data
, sess
);
456 static struct radius_session
*
457 radius_server_get_new_session(struct radius_server_data
*data
,
458 struct radius_client
*client
,
459 struct radius_msg
*msg
)
464 struct radius_session
*sess
;
465 struct eap_config eap_conf
;
467 RADIUS_DEBUG("Creating a new session");
469 user
= os_malloc(256);
473 res
= radius_msg_get_attr(msg
, RADIUS_ATTR_USER_NAME
, user
, 256);
474 if (res
< 0 || res
> 256) {
475 RADIUS_DEBUG("Could not get User-Name");
480 RADIUS_DUMP_ASCII("User-Name", user
, user_len
);
482 res
= data
->get_eap_user(data
->conf_ctx
, user
, user_len
, 0, NULL
);
486 RADIUS_DEBUG("Matching user entry found");
487 sess
= radius_server_new_session(data
, client
);
489 RADIUS_DEBUG("Failed to create a new session");
493 RADIUS_DEBUG("User-Name not found from user database");
497 os_memset(&eap_conf
, 0, sizeof(eap_conf
));
498 eap_conf
.ssl_ctx
= data
->ssl_ctx
;
499 eap_conf
.msg_ctx
= data
->msg_ctx
;
500 eap_conf
.eap_sim_db_priv
= data
->eap_sim_db_priv
;
501 eap_conf
.backend_auth
= TRUE
;
502 eap_conf
.eap_server
= 1;
503 eap_conf
.pac_opaque_encr_key
= data
->pac_opaque_encr_key
;
504 eap_conf
.eap_fast_a_id
= data
->eap_fast_a_id
;
505 eap_conf
.eap_fast_a_id_len
= data
->eap_fast_a_id_len
;
506 eap_conf
.eap_fast_a_id_info
= data
->eap_fast_a_id_info
;
507 eap_conf
.eap_fast_prov
= data
->eap_fast_prov
;
508 eap_conf
.pac_key_lifetime
= data
->pac_key_lifetime
;
509 eap_conf
.pac_key_refresh_time
= data
->pac_key_refresh_time
;
510 eap_conf
.eap_sim_aka_result_ind
= data
->eap_sim_aka_result_ind
;
511 eap_conf
.tnc
= data
->tnc
;
512 eap_conf
.wps
= data
->wps
;
513 eap_conf
.pwd_group
= data
->pwd_group
;
514 sess
->eap
= eap_server_sm_init(sess
, &radius_server_eapol_cb
,
516 if (sess
->eap
== NULL
) {
517 RADIUS_DEBUG("Failed to initialize EAP state machine for the "
519 radius_server_session_free(data
, sess
);
522 sess
->eap_if
= eap_get_interface(sess
->eap
);
523 sess
->eap_if
->eapRestart
= TRUE
;
524 sess
->eap_if
->portEnabled
= TRUE
;
526 RADIUS_DEBUG("New session 0x%x initialized", sess
->sess_id
);
532 static struct radius_msg
*
533 radius_server_encapsulate_eap(struct radius_server_data
*data
,
534 struct radius_client
*client
,
535 struct radius_session
*sess
,
536 struct radius_msg
*request
)
538 struct radius_msg
*msg
;
540 unsigned int sess_id
;
541 struct radius_hdr
*hdr
= radius_msg_get_hdr(request
);
543 if (sess
->eap_if
->eapFail
) {
544 sess
->eap_if
->eapFail
= FALSE
;
545 code
= RADIUS_CODE_ACCESS_REJECT
;
546 } else if (sess
->eap_if
->eapSuccess
) {
547 sess
->eap_if
->eapSuccess
= FALSE
;
548 code
= RADIUS_CODE_ACCESS_ACCEPT
;
550 sess
->eap_if
->eapReq
= FALSE
;
551 code
= RADIUS_CODE_ACCESS_CHALLENGE
;
554 msg
= radius_msg_new(code
, hdr
->identifier
);
556 RADIUS_DEBUG("Failed to allocate reply message");
560 sess_id
= htonl(sess
->sess_id
);
561 if (code
== RADIUS_CODE_ACCESS_CHALLENGE
&&
562 !radius_msg_add_attr(msg
, RADIUS_ATTR_STATE
,
563 (u8
*) &sess_id
, sizeof(sess_id
))) {
564 RADIUS_DEBUG("Failed to add State attribute");
567 if (sess
->eap_if
->eapReqData
&&
568 !radius_msg_add_eap(msg
, wpabuf_head(sess
->eap_if
->eapReqData
),
569 wpabuf_len(sess
->eap_if
->eapReqData
))) {
570 RADIUS_DEBUG("Failed to add EAP-Message attribute");
573 if (code
== RADIUS_CODE_ACCESS_ACCEPT
&& sess
->eap_if
->eapKeyData
) {
575 #ifdef CONFIG_RADIUS_TEST
576 if (data
->dump_msk_file
) {
578 char buf
[2 * 64 + 1];
579 f
= fopen(data
->dump_msk_file
, "a");
581 len
= sess
->eap_if
->eapKeyDataLen
;
584 len
= wpa_snprintf_hex(
586 sess
->eap_if
->eapKeyData
, len
);
588 fprintf(f
, "%s\n", buf
);
592 #endif /* CONFIG_RADIUS_TEST */
593 if (sess
->eap_if
->eapKeyDataLen
> 64) {
596 len
= sess
->eap_if
->eapKeyDataLen
/ 2;
598 if (!radius_msg_add_mppe_keys(msg
, hdr
->authenticator
,
599 (u8
*) client
->shared_secret
,
600 client
->shared_secret_len
,
601 sess
->eap_if
->eapKeyData
+ len
,
602 len
, sess
->eap_if
->eapKeyData
,
604 RADIUS_DEBUG("Failed to add MPPE key attributes");
608 if (radius_msg_copy_attr(msg
, request
, RADIUS_ATTR_PROXY_STATE
) < 0) {
609 RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
610 radius_msg_free(msg
);
614 if (radius_msg_finish_srv(msg
, (u8
*) client
->shared_secret
,
615 client
->shared_secret_len
,
616 hdr
->authenticator
) < 0) {
617 RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
624 static int radius_server_reject(struct radius_server_data
*data
,
625 struct radius_client
*client
,
626 struct radius_msg
*request
,
627 struct sockaddr
*from
, socklen_t fromlen
,
628 const char *from_addr
, int from_port
)
630 struct radius_msg
*msg
;
632 struct eap_hdr eapfail
;
634 struct radius_hdr
*hdr
= radius_msg_get_hdr(request
);
636 RADIUS_DEBUG("Reject invalid request from %s:%d",
637 from_addr
, from_port
);
639 msg
= radius_msg_new(RADIUS_CODE_ACCESS_REJECT
, hdr
->identifier
);
644 os_memset(&eapfail
, 0, sizeof(eapfail
));
645 eapfail
.code
= EAP_CODE_FAILURE
;
646 eapfail
.identifier
= 0;
647 eapfail
.length
= host_to_be16(sizeof(eapfail
));
649 if (!radius_msg_add_eap(msg
, (u8
*) &eapfail
, sizeof(eapfail
))) {
650 RADIUS_DEBUG("Failed to add EAP-Message attribute");
653 if (radius_msg_copy_attr(msg
, request
, RADIUS_ATTR_PROXY_STATE
) < 0) {
654 RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
655 radius_msg_free(msg
);
659 if (radius_msg_finish_srv(msg
, (u8
*) client
->shared_secret
,
660 client
->shared_secret_len
,
661 hdr
->authenticator
) <
663 RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
666 if (wpa_debug_level
<= MSG_MSGDUMP
) {
667 radius_msg_dump(msg
);
670 data
->counters
.access_rejects
++;
671 client
->counters
.access_rejects
++;
672 buf
= radius_msg_get_buf(msg
);
673 if (sendto(data
->auth_sock
, wpabuf_head(buf
), wpabuf_len(buf
), 0,
674 (struct sockaddr
*) from
, sizeof(*from
)) < 0) {
675 perror("sendto[RADIUS SRV]");
679 radius_msg_free(msg
);
685 static int radius_server_request(struct radius_server_data
*data
,
686 struct radius_msg
*msg
,
687 struct sockaddr
*from
, socklen_t fromlen
,
688 struct radius_client
*client
,
689 const char *from_addr
, int from_port
,
690 struct radius_session
*force_sess
)
694 int res
, state_included
= 0;
697 struct radius_session
*sess
;
698 struct radius_msg
*reply
;
704 res
= radius_msg_get_attr(msg
, RADIUS_ATTR_STATE
, statebuf
,
706 state_included
= res
>= 0;
707 if (res
== sizeof(statebuf
)) {
708 state
= WPA_GET_BE32(statebuf
);
709 sess
= radius_server_get_session(client
, state
);
716 RADIUS_DEBUG("Request for session 0x%x", sess
->sess_id
);
717 } else if (state_included
) {
718 RADIUS_DEBUG("State attribute included but no session found");
719 radius_server_reject(data
, client
, msg
, from
, fromlen
,
720 from_addr
, from_port
);
723 sess
= radius_server_get_new_session(data
, client
, msg
);
725 RADIUS_DEBUG("Could not create a new session");
726 radius_server_reject(data
, client
, msg
, from
, fromlen
,
727 from_addr
, from_port
);
732 if (sess
->last_from_port
== from_port
&&
733 sess
->last_identifier
== radius_msg_get_hdr(msg
)->identifier
&&
734 os_memcmp(sess
->last_authenticator
,
735 radius_msg_get_hdr(msg
)->authenticator
, 16) == 0) {
736 RADIUS_DEBUG("Duplicate message from %s", from_addr
);
737 data
->counters
.dup_access_requests
++;
738 client
->counters
.dup_access_requests
++;
740 if (sess
->last_reply
) {
742 buf
= radius_msg_get_buf(sess
->last_reply
);
743 res
= sendto(data
->auth_sock
, wpabuf_head(buf
),
745 (struct sockaddr
*) from
, fromlen
);
747 perror("sendto[RADIUS SRV]");
752 RADIUS_DEBUG("No previous reply available for duplicate "
757 eap
= radius_msg_get_eap(msg
, &eap_len
);
759 RADIUS_DEBUG("No EAP-Message in RADIUS packet from %s",
761 data
->counters
.packets_dropped
++;
762 client
->counters
.packets_dropped
++;
766 RADIUS_DUMP("Received EAP data", eap
, eap_len
);
768 /* FIX: if Code is Request, Success, or Failure, send Access-Reject;
769 * RFC3579 Sect. 2.6.2.
770 * Include EAP-Response/Nak with no preferred method if
772 * If code is not 1-4, discard the packet silently.
773 * Or is this already done by the EAP state machine? */
775 wpabuf_free(sess
->eap_if
->eapRespData
);
776 sess
->eap_if
->eapRespData
= wpabuf_alloc_ext_data(eap
, eap_len
);
777 if (sess
->eap_if
->eapRespData
== NULL
)
780 sess
->eap_if
->eapResp
= TRUE
;
781 eap_server_sm_step(sess
->eap
);
783 if ((sess
->eap_if
->eapReq
|| sess
->eap_if
->eapSuccess
||
784 sess
->eap_if
->eapFail
) && sess
->eap_if
->eapReqData
) {
785 RADIUS_DUMP("EAP data from the state machine",
786 wpabuf_head(sess
->eap_if
->eapReqData
),
787 wpabuf_len(sess
->eap_if
->eapReqData
));
788 } else if (sess
->eap_if
->eapFail
) {
789 RADIUS_DEBUG("No EAP data from the state machine, but eapFail "
791 } else if (eap_sm_method_pending(sess
->eap
)) {
792 radius_msg_free(sess
->last_msg
);
793 sess
->last_msg
= msg
;
794 sess
->last_from_port
= from_port
;
795 os_free(sess
->last_from_addr
);
796 sess
->last_from_addr
= os_strdup(from_addr
);
797 sess
->last_fromlen
= fromlen
;
798 os_memcpy(&sess
->last_from
, from
, fromlen
);
801 RADIUS_DEBUG("No EAP data from the state machine - ignore this"
802 " Access-Request silently (assuming it was a "
804 data
->counters
.packets_dropped
++;
805 client
->counters
.packets_dropped
++;
809 if (sess
->eap_if
->eapSuccess
|| sess
->eap_if
->eapFail
)
812 reply
= radius_server_encapsulate_eap(data
, client
, sess
, msg
);
816 struct radius_hdr
*hdr
;
818 RADIUS_DEBUG("Reply to %s:%d", from_addr
, from_port
);
819 if (wpa_debug_level
<= MSG_MSGDUMP
) {
820 radius_msg_dump(reply
);
823 switch (radius_msg_get_hdr(reply
)->code
) {
824 case RADIUS_CODE_ACCESS_ACCEPT
:
825 data
->counters
.access_accepts
++;
826 client
->counters
.access_accepts
++;
828 case RADIUS_CODE_ACCESS_REJECT
:
829 data
->counters
.access_rejects
++;
830 client
->counters
.access_rejects
++;
832 case RADIUS_CODE_ACCESS_CHALLENGE
:
833 data
->counters
.access_challenges
++;
834 client
->counters
.access_challenges
++;
837 buf
= radius_msg_get_buf(reply
);
838 res
= sendto(data
->auth_sock
, wpabuf_head(buf
),
840 (struct sockaddr
*) from
, fromlen
);
842 perror("sendto[RADIUS SRV]");
844 radius_msg_free(sess
->last_reply
);
845 sess
->last_reply
= reply
;
846 sess
->last_from_port
= from_port
;
847 hdr
= radius_msg_get_hdr(msg
);
848 sess
->last_identifier
= hdr
->identifier
;
849 os_memcpy(sess
->last_authenticator
, hdr
->authenticator
, 16);
851 data
->counters
.packets_dropped
++;
852 client
->counters
.packets_dropped
++;
856 RADIUS_DEBUG("Removing completed session 0x%x after timeout",
858 eloop_cancel_timeout(radius_server_session_remove_timeout
,
860 eloop_register_timeout(10, 0,
861 radius_server_session_remove_timeout
,
869 static void radius_server_receive_auth(int sock
, void *eloop_ctx
,
872 struct radius_server_data
*data
= eloop_ctx
;
875 struct sockaddr_storage ss
;
876 struct sockaddr_in sin
;
878 struct sockaddr_in6 sin6
;
879 #endif /* CONFIG_IPV6 */
883 struct radius_client
*client
= NULL
;
884 struct radius_msg
*msg
= NULL
;
888 buf
= os_malloc(RADIUS_MAX_MSG_LEN
);
893 fromlen
= sizeof(from
);
894 len
= recvfrom(sock
, buf
, RADIUS_MAX_MSG_LEN
, 0,
895 (struct sockaddr
*) &from
.ss
, &fromlen
);
897 perror("recvfrom[radius_server]");
903 if (inet_ntop(AF_INET6
, &from
.sin6
.sin6_addr
, abuf
,
904 sizeof(abuf
)) == NULL
)
906 from_port
= ntohs(from
.sin6
.sin6_port
);
907 RADIUS_DEBUG("Received %d bytes from %s:%d",
908 len
, abuf
, from_port
);
910 client
= radius_server_get_client(data
,
912 &from
.sin6
.sin6_addr
, 1);
914 #endif /* CONFIG_IPV6 */
917 os_strlcpy(abuf
, inet_ntoa(from
.sin
.sin_addr
), sizeof(abuf
));
918 from_port
= ntohs(from
.sin
.sin_port
);
919 RADIUS_DEBUG("Received %d bytes from %s:%d",
920 len
, abuf
, from_port
);
922 client
= radius_server_get_client(data
, &from
.sin
.sin_addr
, 0);
925 RADIUS_DUMP("Received data", buf
, len
);
927 if (client
== NULL
) {
928 RADIUS_DEBUG("Unknown client %s - packet ignored", abuf
);
929 data
->counters
.invalid_requests
++;
933 msg
= radius_msg_parse(buf
, len
);
935 RADIUS_DEBUG("Parsing incoming RADIUS frame failed");
936 data
->counters
.malformed_access_requests
++;
937 client
->counters
.malformed_access_requests
++;
944 if (wpa_debug_level
<= MSG_MSGDUMP
) {
945 radius_msg_dump(msg
);
948 if (radius_msg_get_hdr(msg
)->code
!= RADIUS_CODE_ACCESS_REQUEST
) {
949 RADIUS_DEBUG("Unexpected RADIUS code %d",
950 radius_msg_get_hdr(msg
)->code
);
951 data
->counters
.unknown_types
++;
952 client
->counters
.unknown_types
++;
956 data
->counters
.access_requests
++;
957 client
->counters
.access_requests
++;
959 if (radius_msg_verify_msg_auth(msg
, (u8
*) client
->shared_secret
,
960 client
->shared_secret_len
, NULL
)) {
961 RADIUS_DEBUG("Invalid Message-Authenticator from %s", abuf
);
962 data
->counters
.bad_authenticators
++;
963 client
->counters
.bad_authenticators
++;
967 if (radius_server_request(data
, msg
, (struct sockaddr
*) &from
,
968 fromlen
, client
, abuf
, from_port
, NULL
) ==
970 return; /* msg was stored with the session */
973 radius_msg_free(msg
);
978 static int radius_server_disable_pmtu_discovery(int s
)
981 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
982 /* Turn off Path MTU discovery on IPv4/UDP sockets. */
983 int action
= IP_PMTUDISC_DONT
;
984 r
= setsockopt(s
, IPPROTO_IP
, IP_MTU_DISCOVER
, &action
,
987 wpa_printf(MSG_ERROR
, "Failed to set IP_MTU_DISCOVER: "
988 "%s", strerror(errno
));
994 static int radius_server_open_socket(int port
)
997 struct sockaddr_in addr
;
999 s
= socket(PF_INET
, SOCK_DGRAM
, 0);
1005 radius_server_disable_pmtu_discovery(s
);
1007 os_memset(&addr
, 0, sizeof(addr
));
1008 addr
.sin_family
= AF_INET
;
1009 addr
.sin_port
= htons(port
);
1010 if (bind(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
1021 static int radius_server_open_socket6(int port
)
1024 struct sockaddr_in6 addr
;
1026 s
= socket(PF_INET6
, SOCK_DGRAM
, 0);
1028 perror("socket[IPv6]");
1032 os_memset(&addr
, 0, sizeof(addr
));
1033 addr
.sin6_family
= AF_INET6
;
1034 os_memcpy(&addr
.sin6_addr
, &in6addr_any
, sizeof(in6addr_any
));
1035 addr
.sin6_port
= htons(port
);
1036 if (bind(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
1044 #endif /* CONFIG_IPV6 */
1047 static void radius_server_free_sessions(struct radius_server_data
*data
,
1048 struct radius_session
*sessions
)
1050 struct radius_session
*session
, *prev
;
1055 session
= session
->next
;
1056 radius_server_session_free(data
, prev
);
1061 static void radius_server_free_clients(struct radius_server_data
*data
,
1062 struct radius_client
*clients
)
1064 struct radius_client
*client
, *prev
;
1069 client
= client
->next
;
1071 radius_server_free_sessions(data
, prev
->sessions
);
1072 os_free(prev
->shared_secret
);
1078 static struct radius_client
*
1079 radius_server_read_clients(const char *client_file
, int ipv6
)
1082 const int buf_size
= 1024;
1084 struct radius_client
*clients
, *tail
, *entry
;
1085 int line
= 0, mask
, failed
= 0, i
;
1086 struct in_addr addr
;
1088 struct in6_addr addr6
;
1089 #endif /* CONFIG_IPV6 */
1092 f
= fopen(client_file
, "r");
1094 RADIUS_ERROR("Could not open client file '%s'", client_file
);
1098 buf
= os_malloc(buf_size
);
1104 clients
= tail
= NULL
;
1105 while (fgets(buf
, buf_size
, f
)) {
1106 /* Configuration file format:
1107 * 192.168.1.0/24 secret
1108 * 192.168.1.2 secret
1109 * fe80::211:22ff:fe33:4455/64 secretipv6
1112 buf
[buf_size
- 1] = '\0';
1114 while (*pos
!= '\0' && *pos
!= '\n')
1118 if (*buf
== '\0' || *buf
== '#')
1122 while ((*pos
>= '0' && *pos
<= '9') || *pos
== '.' ||
1123 (*pos
>= 'a' && *pos
<= 'f') || *pos
== ':' ||
1124 (*pos
>= 'A' && *pos
<= 'F')) {
1136 mask
= strtol(pos
, &end
, 10);
1138 (mask
< 0 || mask
> (ipv6
? 128 : 32))) {
1144 mask
= ipv6
? 128 : 32;
1148 if (!ipv6
&& inet_aton(buf
, &addr
) == 0) {
1153 if (ipv6
&& inet_pton(AF_INET6
, buf
, &addr6
) <= 0) {
1154 if (inet_pton(AF_INET
, buf
, &addr
) <= 0) {
1158 /* Convert IPv4 address to IPv6 */
1161 os_memset(addr6
.s6_addr
, 0, 10);
1162 addr6
.s6_addr
[10] = 0xff;
1163 addr6
.s6_addr
[11] = 0xff;
1164 os_memcpy(addr6
.s6_addr
+ 12, (char *) &addr
.s_addr
,
1167 #endif /* CONFIG_IPV6 */
1169 while (*pos
== ' ' || *pos
== '\t') {
1178 entry
= os_zalloc(sizeof(*entry
));
1179 if (entry
== NULL
) {
1183 entry
->shared_secret
= os_strdup(pos
);
1184 if (entry
->shared_secret
== NULL
) {
1189 entry
->shared_secret_len
= os_strlen(entry
->shared_secret
);
1190 entry
->addr
.s_addr
= addr
.s_addr
;
1193 for (i
= 0; i
< mask
; i
++)
1194 val
|= 1 << (31 - i
);
1195 entry
->mask
.s_addr
= htonl(val
);
1199 int offset
= mask
/ 8;
1201 os_memcpy(entry
->addr6
.s6_addr
, addr6
.s6_addr
, 16);
1202 os_memset(entry
->mask6
.s6_addr
, 0xff, offset
);
1204 for (i
= 0; i
< (mask
% 8); i
++)
1205 val
|= 1 << (7 - i
);
1207 entry
->mask6
.s6_addr
[offset
] = val
;
1209 #endif /* CONFIG_IPV6 */
1212 clients
= tail
= entry
;
1220 RADIUS_ERROR("Invalid line %d in '%s'", line
, client_file
);
1221 radius_server_free_clients(NULL
, clients
);
1233 * radius_server_init - Initialize RADIUS server
1234 * @conf: Configuration for the RADIUS server
1235 * Returns: Pointer to private RADIUS server context or %NULL on failure
1237 * This initializes a RADIUS server instance and returns a context pointer that
1238 * will be used in other calls to the RADIUS server module. The server can be
1239 * deinitialize by calling radius_server_deinit().
1241 struct radius_server_data
*
1242 radius_server_init(struct radius_server_conf
*conf
)
1244 struct radius_server_data
*data
;
1248 fprintf(stderr
, "RADIUS server compiled without IPv6 "
1252 #endif /* CONFIG_IPV6 */
1254 data
= os_zalloc(sizeof(*data
));
1258 os_get_time(&data
->start_time
);
1259 data
->conf_ctx
= conf
->conf_ctx
;
1260 data
->eap_sim_db_priv
= conf
->eap_sim_db_priv
;
1261 data
->ssl_ctx
= conf
->ssl_ctx
;
1262 data
->msg_ctx
= conf
->msg_ctx
;
1263 data
->ipv6
= conf
->ipv6
;
1264 if (conf
->pac_opaque_encr_key
) {
1265 data
->pac_opaque_encr_key
= os_malloc(16);
1266 os_memcpy(data
->pac_opaque_encr_key
, conf
->pac_opaque_encr_key
,
1269 if (conf
->eap_fast_a_id
) {
1270 data
->eap_fast_a_id
= os_malloc(conf
->eap_fast_a_id_len
);
1271 if (data
->eap_fast_a_id
) {
1272 os_memcpy(data
->eap_fast_a_id
, conf
->eap_fast_a_id
,
1273 conf
->eap_fast_a_id_len
);
1274 data
->eap_fast_a_id_len
= conf
->eap_fast_a_id_len
;
1277 if (conf
->eap_fast_a_id_info
)
1278 data
->eap_fast_a_id_info
= os_strdup(conf
->eap_fast_a_id_info
);
1279 data
->eap_fast_prov
= conf
->eap_fast_prov
;
1280 data
->pac_key_lifetime
= conf
->pac_key_lifetime
;
1281 data
->pac_key_refresh_time
= conf
->pac_key_refresh_time
;
1282 data
->get_eap_user
= conf
->get_eap_user
;
1283 data
->eap_sim_aka_result_ind
= conf
->eap_sim_aka_result_ind
;
1284 data
->tnc
= conf
->tnc
;
1285 data
->wps
= conf
->wps
;
1286 data
->pwd_group
= conf
->pwd_group
;
1287 if (conf
->eap_req_id_text
) {
1288 data
->eap_req_id_text
= os_malloc(conf
->eap_req_id_text_len
);
1289 if (data
->eap_req_id_text
) {
1290 os_memcpy(data
->eap_req_id_text
, conf
->eap_req_id_text
,
1291 conf
->eap_req_id_text_len
);
1292 data
->eap_req_id_text_len
= conf
->eap_req_id_text_len
;
1296 #ifdef CONFIG_RADIUS_TEST
1297 if (conf
->dump_msk_file
)
1298 data
->dump_msk_file
= os_strdup(conf
->dump_msk_file
);
1299 #endif /* CONFIG_RADIUS_TEST */
1301 data
->clients
= radius_server_read_clients(conf
->client_file
,
1303 if (data
->clients
== NULL
) {
1304 printf("No RADIUS clients configured.\n");
1305 radius_server_deinit(data
);
1311 data
->auth_sock
= radius_server_open_socket6(conf
->auth_port
);
1313 #endif /* CONFIG_IPV6 */
1314 data
->auth_sock
= radius_server_open_socket(conf
->auth_port
);
1315 if (data
->auth_sock
< 0) {
1316 printf("Failed to open UDP socket for RADIUS authentication "
1318 radius_server_deinit(data
);
1321 if (eloop_register_read_sock(data
->auth_sock
,
1322 radius_server_receive_auth
,
1324 radius_server_deinit(data
);
1333 * radius_server_deinit - Deinitialize RADIUS server
1334 * @data: RADIUS server context from radius_server_init()
1336 void radius_server_deinit(struct radius_server_data
*data
)
1341 if (data
->auth_sock
>= 0) {
1342 eloop_unregister_read_sock(data
->auth_sock
);
1343 close(data
->auth_sock
);
1346 radius_server_free_clients(data
, data
->clients
);
1348 os_free(data
->pac_opaque_encr_key
);
1349 os_free(data
->eap_fast_a_id
);
1350 os_free(data
->eap_fast_a_id_info
);
1351 os_free(data
->eap_req_id_text
);
1352 #ifdef CONFIG_RADIUS_TEST
1353 os_free(data
->dump_msk_file
);
1354 #endif /* CONFIG_RADIUS_TEST */
1360 * radius_server_get_mib - Get RADIUS server MIB information
1361 * @data: RADIUS server context from radius_server_init()
1362 * @buf: Buffer for returning the MIB data in text format
1363 * @buflen: buf length in octets
1364 * Returns: Number of octets written into buf
1366 int radius_server_get_mib(struct radius_server_data
*data
, char *buf
,
1373 struct radius_client
*cli
;
1375 /* RFC 2619 - RADIUS Authentication Server MIB */
1377 if (data
== NULL
|| buflen
== 0)
1384 uptime
= (now
.sec
- data
->start_time
.sec
) * 100 +
1385 ((now
.usec
- data
->start_time
.usec
) / 10000) % 100;
1386 ret
= os_snprintf(pos
, end
- pos
,
1387 "RADIUS-AUTH-SERVER-MIB\n"
1388 "radiusAuthServIdent=hostapd\n"
1389 "radiusAuthServUpTime=%d\n"
1390 "radiusAuthServResetTime=0\n"
1391 "radiusAuthServConfigReset=4\n",
1393 if (ret
< 0 || ret
>= end
- pos
) {
1399 ret
= os_snprintf(pos
, end
- pos
,
1400 "radiusAuthServTotalAccessRequests=%u\n"
1401 "radiusAuthServTotalInvalidRequests=%u\n"
1402 "radiusAuthServTotalDupAccessRequests=%u\n"
1403 "radiusAuthServTotalAccessAccepts=%u\n"
1404 "radiusAuthServTotalAccessRejects=%u\n"
1405 "radiusAuthServTotalAccessChallenges=%u\n"
1406 "radiusAuthServTotalMalformedAccessRequests=%u\n"
1407 "radiusAuthServTotalBadAuthenticators=%u\n"
1408 "radiusAuthServTotalPacketsDropped=%u\n"
1409 "radiusAuthServTotalUnknownTypes=%u\n",
1410 data
->counters
.access_requests
,
1411 data
->counters
.invalid_requests
,
1412 data
->counters
.dup_access_requests
,
1413 data
->counters
.access_accepts
,
1414 data
->counters
.access_rejects
,
1415 data
->counters
.access_challenges
,
1416 data
->counters
.malformed_access_requests
,
1417 data
->counters
.bad_authenticators
,
1418 data
->counters
.packets_dropped
,
1419 data
->counters
.unknown_types
);
1420 if (ret
< 0 || ret
>= end
- pos
) {
1426 for (cli
= data
->clients
, idx
= 0; cli
; cli
= cli
->next
, idx
++) {
1427 char abuf
[50], mbuf
[50];
1430 if (inet_ntop(AF_INET6
, &cli
->addr6
, abuf
,
1431 sizeof(abuf
)) == NULL
)
1433 if (inet_ntop(AF_INET6
, &cli
->mask6
, abuf
,
1434 sizeof(mbuf
)) == NULL
)
1437 #endif /* CONFIG_IPV6 */
1439 os_strlcpy(abuf
, inet_ntoa(cli
->addr
), sizeof(abuf
));
1440 os_strlcpy(mbuf
, inet_ntoa(cli
->mask
), sizeof(mbuf
));
1443 ret
= os_snprintf(pos
, end
- pos
,
1444 "radiusAuthClientIndex=%u\n"
1445 "radiusAuthClientAddress=%s/%s\n"
1446 "radiusAuthServAccessRequests=%u\n"
1447 "radiusAuthServDupAccessRequests=%u\n"
1448 "radiusAuthServAccessAccepts=%u\n"
1449 "radiusAuthServAccessRejects=%u\n"
1450 "radiusAuthServAccessChallenges=%u\n"
1451 "radiusAuthServMalformedAccessRequests=%u\n"
1452 "radiusAuthServBadAuthenticators=%u\n"
1453 "radiusAuthServPacketsDropped=%u\n"
1454 "radiusAuthServUnknownTypes=%u\n",
1457 cli
->counters
.access_requests
,
1458 cli
->counters
.dup_access_requests
,
1459 cli
->counters
.access_accepts
,
1460 cli
->counters
.access_rejects
,
1461 cli
->counters
.access_challenges
,
1462 cli
->counters
.malformed_access_requests
,
1463 cli
->counters
.bad_authenticators
,
1464 cli
->counters
.packets_dropped
,
1465 cli
->counters
.unknown_types
);
1466 if (ret
< 0 || ret
>= end
- pos
) {
1477 static int radius_server_get_eap_user(void *ctx
, const u8
*identity
,
1478 size_t identity_len
, int phase2
,
1479 struct eap_user
*user
)
1481 struct radius_session
*sess
= ctx
;
1482 struct radius_server_data
*data
= sess
->server
;
1484 return data
->get_eap_user(data
->conf_ctx
, identity
, identity_len
,
1489 static const char * radius_server_get_eap_req_id_text(void *ctx
, size_t *len
)
1491 struct radius_session
*sess
= ctx
;
1492 struct radius_server_data
*data
= sess
->server
;
1493 *len
= data
->eap_req_id_text_len
;
1494 return data
->eap_req_id_text
;
1498 static struct eapol_callbacks radius_server_eapol_cb
=
1500 .get_eap_user
= radius_server_get_eap_user
,
1501 .get_eap_req_id_text
= radius_server_get_eap_req_id_text
,
1506 * radius_server_eap_pending_cb - Pending EAP data notification
1507 * @data: RADIUS server context from radius_server_init()
1508 * @ctx: Pending EAP context pointer
1510 * This function is used to notify EAP server module that a pending operation
1511 * has been completed and processing of the EAP session can proceed.
1513 void radius_server_eap_pending_cb(struct radius_server_data
*data
, void *ctx
)
1515 struct radius_client
*cli
;
1516 struct radius_session
*s
, *sess
= NULL
;
1517 struct radius_msg
*msg
;
1522 for (cli
= data
->clients
; cli
; cli
= cli
->next
) {
1523 for (s
= cli
->sessions
; s
; s
= s
->next
) {
1524 if (s
->eap
== ctx
&& s
->last_msg
) {
1536 RADIUS_DEBUG("No session matched callback ctx");
1540 msg
= sess
->last_msg
;
1541 sess
->last_msg
= NULL
;
1542 eap_sm_pending_cb(sess
->eap
);
1543 if (radius_server_request(data
, msg
,
1544 (struct sockaddr
*) &sess
->last_from
,
1545 sess
->last_fromlen
, cli
,
1546 sess
->last_from_addr
,
1547 sess
->last_from_port
, sess
) == -2)
1548 return; /* msg was stored with the session */
1550 radius_msg_free(msg
);