2 * RADIUS authentication server
3 * Copyright (c) 2005-2009, 2011-2014, 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
;
54 u32 invalid_acct_requests
;
56 u32 malformed_acct_requests
;
57 u32 acct_bad_authenticators
;
58 u32 unknown_acct_types
;
62 * struct radius_session - Internal RADIUS server data for a session
64 struct radius_session
{
65 struct radius_session
*next
;
66 struct radius_client
*client
;
67 struct radius_server_data
*server
;
70 struct eap_eapol_interface
*eap_if
;
72 struct radius_msg
*last_msg
;
75 struct sockaddr_storage last_from
;
76 socklen_t last_fromlen
;
78 struct radius_msg
*last_reply
;
79 u8 last_authenticator
[16];
83 * struct radius_client - Internal RADIUS server data for a client
85 struct radius_client
{
86 struct radius_client
*next
;
90 struct in6_addr addr6
;
91 struct in6_addr mask6
;
92 #endif /* CONFIG_IPV6 */
94 int shared_secret_len
;
95 struct radius_session
*sessions
;
96 struct radius_server_counters counters
;
100 * struct radius_server_data - Internal RADIUS server data
102 struct radius_server_data
{
104 * auth_sock - Socket for RADIUS authentication messages
109 * acct_sock - Socket for RADIUS accounting messages
114 * clients - List of authorized RADIUS clients
116 struct radius_client
*clients
;
119 * next_sess_id - Next session identifier
121 unsigned int next_sess_id
;
124 * conf_ctx - Context pointer for callbacks
126 * This is used as the ctx argument in get_eap_user() calls.
131 * num_sess - Number of active sessions
136 * eap_sim_db_priv - EAP-SIM/AKA database context
138 * This is passed to the EAP-SIM/AKA server implementation as a
141 void *eap_sim_db_priv
;
144 * ssl_ctx - TLS context
146 * This is passed to the EAP server implementation as a callback
147 * context for TLS operations.
152 * pac_opaque_encr_key - PAC-Opaque encryption key for EAP-FAST
154 * This parameter is used to set a key for EAP-FAST to encrypt the
155 * PAC-Opaque data. It can be set to %NULL if EAP-FAST is not used. If
156 * set, must point to a 16-octet key.
158 u8
*pac_opaque_encr_key
;
161 * eap_fast_a_id - EAP-FAST authority identity (A-ID)
163 * If EAP-FAST is not used, this can be set to %NULL. In theory, this
164 * is a variable length field, but due to some existing implementations
165 * requiring A-ID to be 16 octets in length, it is recommended to use
166 * that length for the field to provide interoperability with deployed
167 * peer implementations.
172 * eap_fast_a_id_len - Length of eap_fast_a_id buffer in octets
174 size_t eap_fast_a_id_len
;
177 * eap_fast_a_id_info - EAP-FAST authority identifier information
179 * This A-ID-Info contains a user-friendly name for the A-ID. For
180 * example, this could be the enterprise and server names in
181 * human-readable format. This field is encoded as UTF-8. If EAP-FAST
182 * is not used, this can be set to %NULL.
184 char *eap_fast_a_id_info
;
187 * eap_fast_prov - EAP-FAST provisioning modes
189 * 0 = provisioning disabled, 1 = only anonymous provisioning allowed,
190 * 2 = only authenticated provisioning allowed, 3 = both provisioning
196 * pac_key_lifetime - EAP-FAST PAC-Key lifetime in seconds
198 * This is the hard limit on how long a provisioned PAC-Key can be
201 int pac_key_lifetime
;
204 * pac_key_refresh_time - EAP-FAST PAC-Key refresh time in seconds
206 * This is a soft limit on the PAC-Key. The server will automatically
207 * generate a new PAC-Key when this number of seconds (or fewer) of the
210 int pac_key_refresh_time
;
213 * eap_sim_aka_result_ind - EAP-SIM/AKA protected success indication
215 * This controls whether the protected success/failure indication
216 * (AT_RESULT_IND) is used with EAP-SIM and EAP-AKA.
218 int eap_sim_aka_result_ind
;
221 * tnc - Trusted Network Connect (TNC)
223 * This controls whether TNC is enabled and will be required before the
224 * peer is allowed to connect. Note: This is only used with EAP-TTLS
225 * and EAP-FAST. If any other EAP method is enabled, the peer will be
226 * allowed to connect without TNC.
231 * pwd_group - The D-H group assigned for EAP-pwd
233 * If EAP-pwd is not used it can be set to zero.
238 * server_id - Server identity
240 const char *server_id
;
243 * wps - Wi-Fi Protected Setup context
245 * If WPS is used with an external RADIUS server (which is quite
246 * unlikely configuration), this is used to provide a pointer to WPS
247 * context data. Normally, this can be set to %NULL.
249 struct wps_context
*wps
;
252 * ipv6 - Whether to enable IPv6 support in the RADIUS server
257 * start_time - Timestamp of server start
259 struct os_reltime start_time
;
262 * counters - Statistics counters for server operations
264 * These counters are the sum over all clients.
266 struct radius_server_counters counters
;
269 * get_eap_user - Callback for fetching EAP user information
270 * @ctx: Context data from conf_ctx
271 * @identity: User identity
272 * @identity_len: identity buffer length in octets
273 * @phase2: Whether this is for Phase 2 identity
274 * @user: Data structure for filling in the user information
275 * Returns: 0 on success, -1 on failure
277 * This is used to fetch information from user database. The callback
278 * will fill in information about allowed EAP methods and the user
279 * password. The password field will be an allocated copy of the
280 * password data and RADIUS server will free it after use.
282 int (*get_eap_user
)(void *ctx
, const u8
*identity
, size_t identity_len
,
283 int phase2
, struct eap_user
*user
);
286 * eap_req_id_text - Optional data for EAP-Request/Identity
288 * This can be used to configure an optional, displayable message that
289 * will be sent in EAP-Request/Identity. This string can contain an
290 * ASCII-0 character (nul) to separate network infromation per RFC
291 * 4284. The actual string length is explicit provided in
292 * eap_req_id_text_len since nul character will not be used as a string
295 char *eap_req_id_text
;
298 * eap_req_id_text_len - Length of eap_req_id_text buffer in octets
300 size_t eap_req_id_text_len
;
303 * msg_ctx - Context data for wpa_msg() calls
307 #ifdef CONFIG_RADIUS_TEST
309 #endif /* CONFIG_RADIUS_TEST */
313 #define RADIUS_DEBUG(args...) \
314 wpa_printf(MSG_DEBUG, "RADIUS SRV: " args)
315 #define RADIUS_ERROR(args...) \
316 wpa_printf(MSG_ERROR, "RADIUS SRV: " args)
317 #define RADIUS_DUMP(args...) \
318 wpa_hexdump(MSG_MSGDUMP, "RADIUS SRV: " args)
319 #define RADIUS_DUMP_ASCII(args...) \
320 wpa_hexdump_ascii(MSG_MSGDUMP, "RADIUS SRV: " args)
323 static void radius_server_session_timeout(void *eloop_ctx
, void *timeout_ctx
);
324 static void radius_server_session_remove_timeout(void *eloop_ctx
,
328 static struct radius_client
*
329 radius_server_get_client(struct radius_server_data
*data
, struct in_addr
*addr
,
332 struct radius_client
*client
= data
->clients
;
337 struct in6_addr
*addr6
;
340 addr6
= (struct in6_addr
*) addr
;
341 for (i
= 0; i
< 16; i
++) {
342 if ((addr6
->s6_addr
[i
] &
343 client
->mask6
.s6_addr
[i
]) !=
344 (client
->addr6
.s6_addr
[i
] &
345 client
->mask6
.s6_addr
[i
])) {
354 #endif /* CONFIG_IPV6 */
355 if (!ipv6
&& (client
->addr
.s_addr
& client
->mask
.s_addr
) ==
356 (addr
->s_addr
& client
->mask
.s_addr
)) {
360 client
= client
->next
;
367 static struct radius_session
*
368 radius_server_get_session(struct radius_client
*client
, unsigned int sess_id
)
370 struct radius_session
*sess
= client
->sessions
;
373 if (sess
->sess_id
== sess_id
) {
383 static void radius_server_session_free(struct radius_server_data
*data
,
384 struct radius_session
*sess
)
386 eloop_cancel_timeout(radius_server_session_timeout
, data
, sess
);
387 eloop_cancel_timeout(radius_server_session_remove_timeout
, data
, sess
);
388 eap_server_sm_deinit(sess
->eap
);
389 radius_msg_free(sess
->last_msg
);
390 os_free(sess
->last_from_addr
);
391 radius_msg_free(sess
->last_reply
);
397 static void radius_server_session_remove(struct radius_server_data
*data
,
398 struct radius_session
*sess
)
400 struct radius_client
*client
= sess
->client
;
401 struct radius_session
*session
, *prev
;
403 eloop_cancel_timeout(radius_server_session_remove_timeout
, data
, sess
);
406 session
= client
->sessions
;
408 if (session
== sess
) {
410 client
->sessions
= sess
->next
;
412 prev
->next
= sess
->next
;
414 radius_server_session_free(data
, sess
);
418 session
= session
->next
;
423 static void radius_server_session_remove_timeout(void *eloop_ctx
,
426 struct radius_server_data
*data
= eloop_ctx
;
427 struct radius_session
*sess
= timeout_ctx
;
428 RADIUS_DEBUG("Removing completed session 0x%x", sess
->sess_id
);
429 radius_server_session_remove(data
, sess
);
433 static void radius_server_session_timeout(void *eloop_ctx
, void *timeout_ctx
)
435 struct radius_server_data
*data
= eloop_ctx
;
436 struct radius_session
*sess
= timeout_ctx
;
438 RADIUS_DEBUG("Timing out authentication session 0x%x", sess
->sess_id
);
439 radius_server_session_remove(data
, sess
);
443 static struct radius_session
*
444 radius_server_new_session(struct radius_server_data
*data
,
445 struct radius_client
*client
)
447 struct radius_session
*sess
;
449 if (data
->num_sess
>= RADIUS_MAX_SESSION
) {
450 RADIUS_DEBUG("Maximum number of existing session - no room "
451 "for a new session");
455 sess
= os_zalloc(sizeof(*sess
));
460 sess
->client
= client
;
461 sess
->sess_id
= data
->next_sess_id
++;
462 sess
->next
= client
->sessions
;
463 client
->sessions
= sess
;
464 eloop_register_timeout(RADIUS_SESSION_TIMEOUT
, 0,
465 radius_server_session_timeout
, data
, sess
);
471 static struct radius_session
*
472 radius_server_get_new_session(struct radius_server_data
*data
,
473 struct radius_client
*client
,
474 struct radius_msg
*msg
)
479 struct radius_session
*sess
;
480 struct eap_config eap_conf
;
482 RADIUS_DEBUG("Creating a new session");
484 user
= os_malloc(256);
488 res
= radius_msg_get_attr(msg
, RADIUS_ATTR_USER_NAME
, user
, 256);
489 if (res
< 0 || res
> 256) {
490 RADIUS_DEBUG("Could not get User-Name");
495 RADIUS_DUMP_ASCII("User-Name", user
, user_len
);
497 res
= data
->get_eap_user(data
->conf_ctx
, user
, user_len
, 0, NULL
);
501 RADIUS_DEBUG("Matching user entry found");
502 sess
= radius_server_new_session(data
, client
);
504 RADIUS_DEBUG("Failed to create a new session");
508 RADIUS_DEBUG("User-Name not found from user database");
512 os_memset(&eap_conf
, 0, sizeof(eap_conf
));
513 eap_conf
.ssl_ctx
= data
->ssl_ctx
;
514 eap_conf
.msg_ctx
= data
->msg_ctx
;
515 eap_conf
.eap_sim_db_priv
= data
->eap_sim_db_priv
;
516 eap_conf
.backend_auth
= TRUE
;
517 eap_conf
.eap_server
= 1;
518 eap_conf
.pac_opaque_encr_key
= data
->pac_opaque_encr_key
;
519 eap_conf
.eap_fast_a_id
= data
->eap_fast_a_id
;
520 eap_conf
.eap_fast_a_id_len
= data
->eap_fast_a_id_len
;
521 eap_conf
.eap_fast_a_id_info
= data
->eap_fast_a_id_info
;
522 eap_conf
.eap_fast_prov
= data
->eap_fast_prov
;
523 eap_conf
.pac_key_lifetime
= data
->pac_key_lifetime
;
524 eap_conf
.pac_key_refresh_time
= data
->pac_key_refresh_time
;
525 eap_conf
.eap_sim_aka_result_ind
= data
->eap_sim_aka_result_ind
;
526 eap_conf
.tnc
= data
->tnc
;
527 eap_conf
.wps
= data
->wps
;
528 eap_conf
.pwd_group
= data
->pwd_group
;
529 eap_conf
.server_id
= (const u8
*) data
->server_id
;
530 eap_conf
.server_id_len
= os_strlen(data
->server_id
);
531 sess
->eap
= eap_server_sm_init(sess
, &radius_server_eapol_cb
,
533 if (sess
->eap
== NULL
) {
534 RADIUS_DEBUG("Failed to initialize EAP state machine for the "
536 radius_server_session_free(data
, sess
);
539 sess
->eap_if
= eap_get_interface(sess
->eap
);
540 sess
->eap_if
->eapRestart
= TRUE
;
541 sess
->eap_if
->portEnabled
= TRUE
;
543 RADIUS_DEBUG("New session 0x%x initialized", sess
->sess_id
);
549 static struct radius_msg
*
550 radius_server_encapsulate_eap(struct radius_server_data
*data
,
551 struct radius_client
*client
,
552 struct radius_session
*sess
,
553 struct radius_msg
*request
)
555 struct radius_msg
*msg
;
557 unsigned int sess_id
;
558 struct radius_hdr
*hdr
= radius_msg_get_hdr(request
);
560 if (sess
->eap_if
->eapFail
) {
561 sess
->eap_if
->eapFail
= FALSE
;
562 code
= RADIUS_CODE_ACCESS_REJECT
;
563 } else if (sess
->eap_if
->eapSuccess
) {
564 sess
->eap_if
->eapSuccess
= FALSE
;
565 code
= RADIUS_CODE_ACCESS_ACCEPT
;
567 sess
->eap_if
->eapReq
= FALSE
;
568 code
= RADIUS_CODE_ACCESS_CHALLENGE
;
571 msg
= radius_msg_new(code
, hdr
->identifier
);
573 RADIUS_DEBUG("Failed to allocate reply message");
577 sess_id
= htonl(sess
->sess_id
);
578 if (code
== RADIUS_CODE_ACCESS_CHALLENGE
&&
579 !radius_msg_add_attr(msg
, RADIUS_ATTR_STATE
,
580 (u8
*) &sess_id
, sizeof(sess_id
))) {
581 RADIUS_DEBUG("Failed to add State attribute");
584 if (sess
->eap_if
->eapReqData
&&
585 !radius_msg_add_eap(msg
, wpabuf_head(sess
->eap_if
->eapReqData
),
586 wpabuf_len(sess
->eap_if
->eapReqData
))) {
587 RADIUS_DEBUG("Failed to add EAP-Message attribute");
590 if (code
== RADIUS_CODE_ACCESS_ACCEPT
&& sess
->eap_if
->eapKeyData
) {
592 #ifdef CONFIG_RADIUS_TEST
593 if (data
->dump_msk_file
) {
595 char buf
[2 * 64 + 1];
596 f
= fopen(data
->dump_msk_file
, "a");
598 len
= sess
->eap_if
->eapKeyDataLen
;
601 len
= wpa_snprintf_hex(
603 sess
->eap_if
->eapKeyData
, len
);
605 fprintf(f
, "%s\n", buf
);
609 #endif /* CONFIG_RADIUS_TEST */
610 if (sess
->eap_if
->eapKeyDataLen
> 64) {
613 len
= sess
->eap_if
->eapKeyDataLen
/ 2;
615 if (!radius_msg_add_mppe_keys(msg
, hdr
->authenticator
,
616 (u8
*) client
->shared_secret
,
617 client
->shared_secret_len
,
618 sess
->eap_if
->eapKeyData
+ len
,
619 len
, sess
->eap_if
->eapKeyData
,
621 RADIUS_DEBUG("Failed to add MPPE key attributes");
625 if (radius_msg_copy_attr(msg
, request
, RADIUS_ATTR_PROXY_STATE
) < 0) {
626 RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
627 radius_msg_free(msg
);
631 if (radius_msg_finish_srv(msg
, (u8
*) client
->shared_secret
,
632 client
->shared_secret_len
,
633 hdr
->authenticator
) < 0) {
634 RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
641 static int radius_server_reject(struct radius_server_data
*data
,
642 struct radius_client
*client
,
643 struct radius_msg
*request
,
644 struct sockaddr
*from
, socklen_t fromlen
,
645 const char *from_addr
, int from_port
)
647 struct radius_msg
*msg
;
649 struct eap_hdr eapfail
;
651 struct radius_hdr
*hdr
= radius_msg_get_hdr(request
);
653 RADIUS_DEBUG("Reject invalid request from %s:%d",
654 from_addr
, from_port
);
656 msg
= radius_msg_new(RADIUS_CODE_ACCESS_REJECT
, hdr
->identifier
);
661 os_memset(&eapfail
, 0, sizeof(eapfail
));
662 eapfail
.code
= EAP_CODE_FAILURE
;
663 eapfail
.identifier
= 0;
664 eapfail
.length
= host_to_be16(sizeof(eapfail
));
666 if (!radius_msg_add_eap(msg
, (u8
*) &eapfail
, sizeof(eapfail
))) {
667 RADIUS_DEBUG("Failed to add EAP-Message attribute");
670 if (radius_msg_copy_attr(msg
, request
, RADIUS_ATTR_PROXY_STATE
) < 0) {
671 RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
672 radius_msg_free(msg
);
676 if (radius_msg_finish_srv(msg
, (u8
*) client
->shared_secret
,
677 client
->shared_secret_len
,
678 hdr
->authenticator
) <
680 RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
683 if (wpa_debug_level
<= MSG_MSGDUMP
) {
684 radius_msg_dump(msg
);
687 data
->counters
.access_rejects
++;
688 client
->counters
.access_rejects
++;
689 buf
= radius_msg_get_buf(msg
);
690 if (sendto(data
->auth_sock
, wpabuf_head(buf
), wpabuf_len(buf
), 0,
691 (struct sockaddr
*) from
, sizeof(*from
)) < 0) {
692 wpa_printf(MSG_INFO
, "sendto[RADIUS SRV]: %s", strerror(errno
));
696 radius_msg_free(msg
);
702 static int radius_server_request(struct radius_server_data
*data
,
703 struct radius_msg
*msg
,
704 struct sockaddr
*from
, socklen_t fromlen
,
705 struct radius_client
*client
,
706 const char *from_addr
, int from_port
,
707 struct radius_session
*force_sess
)
709 struct wpabuf
*eap
= NULL
;
710 int res
, state_included
= 0;
713 struct radius_session
*sess
;
714 struct radius_msg
*reply
;
720 res
= radius_msg_get_attr(msg
, RADIUS_ATTR_STATE
, statebuf
,
722 state_included
= res
>= 0;
723 if (res
== sizeof(statebuf
)) {
724 state
= WPA_GET_BE32(statebuf
);
725 sess
= radius_server_get_session(client
, state
);
732 RADIUS_DEBUG("Request for session 0x%x", sess
->sess_id
);
733 } else if (state_included
) {
734 RADIUS_DEBUG("State attribute included but no session found");
735 radius_server_reject(data
, client
, msg
, from
, fromlen
,
736 from_addr
, from_port
);
739 sess
= radius_server_get_new_session(data
, client
, msg
);
741 RADIUS_DEBUG("Could not create a new session");
742 radius_server_reject(data
, client
, msg
, from
, fromlen
,
743 from_addr
, from_port
);
748 if (sess
->last_from_port
== from_port
&&
749 sess
->last_identifier
== radius_msg_get_hdr(msg
)->identifier
&&
750 os_memcmp(sess
->last_authenticator
,
751 radius_msg_get_hdr(msg
)->authenticator
, 16) == 0) {
752 RADIUS_DEBUG("Duplicate message from %s", from_addr
);
753 data
->counters
.dup_access_requests
++;
754 client
->counters
.dup_access_requests
++;
756 if (sess
->last_reply
) {
758 buf
= radius_msg_get_buf(sess
->last_reply
);
759 res
= sendto(data
->auth_sock
, wpabuf_head(buf
),
761 (struct sockaddr
*) from
, fromlen
);
763 wpa_printf(MSG_INFO
, "sendto[RADIUS SRV]: %s",
769 RADIUS_DEBUG("No previous reply available for duplicate "
774 eap
= radius_msg_get_eap(msg
);
776 RADIUS_DEBUG("No EAP-Message in RADIUS packet from %s",
778 data
->counters
.packets_dropped
++;
779 client
->counters
.packets_dropped
++;
783 RADIUS_DUMP("Received EAP data", wpabuf_head(eap
), wpabuf_len(eap
));
785 /* FIX: if Code is Request, Success, or Failure, send Access-Reject;
786 * RFC3579 Sect. 2.6.2.
787 * Include EAP-Response/Nak with no preferred method if
789 * If code is not 1-4, discard the packet silently.
790 * Or is this already done by the EAP state machine? */
792 wpabuf_free(sess
->eap_if
->eapRespData
);
793 sess
->eap_if
->eapRespData
= eap
;
794 sess
->eap_if
->eapResp
= TRUE
;
795 eap_server_sm_step(sess
->eap
);
797 if ((sess
->eap_if
->eapReq
|| sess
->eap_if
->eapSuccess
||
798 sess
->eap_if
->eapFail
) && sess
->eap_if
->eapReqData
) {
799 RADIUS_DUMP("EAP data from the state machine",
800 wpabuf_head(sess
->eap_if
->eapReqData
),
801 wpabuf_len(sess
->eap_if
->eapReqData
));
802 } else if (sess
->eap_if
->eapFail
) {
803 RADIUS_DEBUG("No EAP data from the state machine, but eapFail "
805 } else if (eap_sm_method_pending(sess
->eap
)) {
806 radius_msg_free(sess
->last_msg
);
807 sess
->last_msg
= msg
;
808 sess
->last_from_port
= from_port
;
809 os_free(sess
->last_from_addr
);
810 sess
->last_from_addr
= os_strdup(from_addr
);
811 sess
->last_fromlen
= fromlen
;
812 os_memcpy(&sess
->last_from
, from
, fromlen
);
815 RADIUS_DEBUG("No EAP data from the state machine - ignore this"
816 " Access-Request silently (assuming it was a "
818 data
->counters
.packets_dropped
++;
819 client
->counters
.packets_dropped
++;
823 if (sess
->eap_if
->eapSuccess
|| sess
->eap_if
->eapFail
)
826 reply
= radius_server_encapsulate_eap(data
, client
, sess
, msg
);
830 struct radius_hdr
*hdr
;
832 RADIUS_DEBUG("Reply to %s:%d", from_addr
, from_port
);
833 if (wpa_debug_level
<= MSG_MSGDUMP
) {
834 radius_msg_dump(reply
);
837 switch (radius_msg_get_hdr(reply
)->code
) {
838 case RADIUS_CODE_ACCESS_ACCEPT
:
839 data
->counters
.access_accepts
++;
840 client
->counters
.access_accepts
++;
842 case RADIUS_CODE_ACCESS_REJECT
:
843 data
->counters
.access_rejects
++;
844 client
->counters
.access_rejects
++;
846 case RADIUS_CODE_ACCESS_CHALLENGE
:
847 data
->counters
.access_challenges
++;
848 client
->counters
.access_challenges
++;
851 buf
= radius_msg_get_buf(reply
);
852 res
= sendto(data
->auth_sock
, wpabuf_head(buf
),
854 (struct sockaddr
*) from
, fromlen
);
856 wpa_printf(MSG_INFO
, "sendto[RADIUS SRV]: %s",
859 radius_msg_free(sess
->last_reply
);
860 sess
->last_reply
= reply
;
861 sess
->last_from_port
= from_port
;
862 hdr
= radius_msg_get_hdr(msg
);
863 sess
->last_identifier
= hdr
->identifier
;
864 os_memcpy(sess
->last_authenticator
, hdr
->authenticator
, 16);
866 data
->counters
.packets_dropped
++;
867 client
->counters
.packets_dropped
++;
871 RADIUS_DEBUG("Removing completed session 0x%x after timeout",
873 eloop_cancel_timeout(radius_server_session_remove_timeout
,
875 eloop_register_timeout(10, 0,
876 radius_server_session_remove_timeout
,
884 static void radius_server_receive_auth(int sock
, void *eloop_ctx
,
887 struct radius_server_data
*data
= eloop_ctx
;
890 struct sockaddr_storage ss
;
891 struct sockaddr_in sin
;
893 struct sockaddr_in6 sin6
;
894 #endif /* CONFIG_IPV6 */
898 struct radius_client
*client
= NULL
;
899 struct radius_msg
*msg
= NULL
;
903 buf
= os_malloc(RADIUS_MAX_MSG_LEN
);
908 fromlen
= sizeof(from
);
909 len
= recvfrom(sock
, buf
, RADIUS_MAX_MSG_LEN
, 0,
910 (struct sockaddr
*) &from
.ss
, &fromlen
);
912 wpa_printf(MSG_INFO
, "recvfrom[radius_server]: %s",
919 if (inet_ntop(AF_INET6
, &from
.sin6
.sin6_addr
, abuf
,
920 sizeof(abuf
)) == NULL
)
922 from_port
= ntohs(from
.sin6
.sin6_port
);
923 RADIUS_DEBUG("Received %d bytes from %s:%d",
924 len
, abuf
, from_port
);
926 client
= radius_server_get_client(data
,
928 &from
.sin6
.sin6_addr
, 1);
930 #endif /* CONFIG_IPV6 */
933 os_strlcpy(abuf
, inet_ntoa(from
.sin
.sin_addr
), sizeof(abuf
));
934 from_port
= ntohs(from
.sin
.sin_port
);
935 RADIUS_DEBUG("Received %d bytes from %s:%d",
936 len
, abuf
, from_port
);
938 client
= radius_server_get_client(data
, &from
.sin
.sin_addr
, 0);
941 RADIUS_DUMP("Received data", buf
, len
);
943 if (client
== NULL
) {
944 RADIUS_DEBUG("Unknown client %s - packet ignored", abuf
);
945 data
->counters
.invalid_requests
++;
949 msg
= radius_msg_parse(buf
, len
);
951 RADIUS_DEBUG("Parsing incoming RADIUS frame failed");
952 data
->counters
.malformed_access_requests
++;
953 client
->counters
.malformed_access_requests
++;
960 if (wpa_debug_level
<= MSG_MSGDUMP
) {
961 radius_msg_dump(msg
);
964 if (radius_msg_get_hdr(msg
)->code
!= RADIUS_CODE_ACCESS_REQUEST
) {
965 RADIUS_DEBUG("Unexpected RADIUS code %d",
966 radius_msg_get_hdr(msg
)->code
);
967 data
->counters
.unknown_types
++;
968 client
->counters
.unknown_types
++;
972 data
->counters
.access_requests
++;
973 client
->counters
.access_requests
++;
975 if (radius_msg_verify_msg_auth(msg
, (u8
*) client
->shared_secret
,
976 client
->shared_secret_len
, NULL
)) {
977 RADIUS_DEBUG("Invalid Message-Authenticator from %s", abuf
);
978 data
->counters
.bad_authenticators
++;
979 client
->counters
.bad_authenticators
++;
983 if (radius_server_request(data
, msg
, (struct sockaddr
*) &from
,
984 fromlen
, client
, abuf
, from_port
, NULL
) ==
986 return; /* msg was stored with the session */
989 radius_msg_free(msg
);
994 static void radius_server_receive_acct(int sock
, void *eloop_ctx
,
997 struct radius_server_data
*data
= eloop_ctx
;
1000 struct sockaddr_storage ss
;
1001 struct sockaddr_in sin
;
1003 struct sockaddr_in6 sin6
;
1004 #endif /* CONFIG_IPV6 */
1008 struct radius_client
*client
= NULL
;
1009 struct radius_msg
*msg
= NULL
, *resp
= NULL
;
1012 struct radius_hdr
*hdr
;
1013 struct wpabuf
*rbuf
;
1015 buf
= os_malloc(RADIUS_MAX_MSG_LEN
);
1020 fromlen
= sizeof(from
);
1021 len
= recvfrom(sock
, buf
, RADIUS_MAX_MSG_LEN
, 0,
1022 (struct sockaddr
*) &from
.ss
, &fromlen
);
1024 wpa_printf(MSG_INFO
, "recvfrom[radius_server]: %s",
1031 if (inet_ntop(AF_INET6
, &from
.sin6
.sin6_addr
, abuf
,
1032 sizeof(abuf
)) == NULL
)
1034 from_port
= ntohs(from
.sin6
.sin6_port
);
1035 RADIUS_DEBUG("Received %d bytes from %s:%d",
1036 len
, abuf
, from_port
);
1038 client
= radius_server_get_client(data
,
1040 &from
.sin6
.sin6_addr
, 1);
1042 #endif /* CONFIG_IPV6 */
1045 os_strlcpy(abuf
, inet_ntoa(from
.sin
.sin_addr
), sizeof(abuf
));
1046 from_port
= ntohs(from
.sin
.sin_port
);
1047 RADIUS_DEBUG("Received %d bytes from %s:%d",
1048 len
, abuf
, from_port
);
1050 client
= radius_server_get_client(data
, &from
.sin
.sin_addr
, 0);
1053 RADIUS_DUMP("Received data", buf
, len
);
1055 if (client
== NULL
) {
1056 RADIUS_DEBUG("Unknown client %s - packet ignored", abuf
);
1057 data
->counters
.invalid_acct_requests
++;
1061 msg
= radius_msg_parse(buf
, len
);
1063 RADIUS_DEBUG("Parsing incoming RADIUS frame failed");
1064 data
->counters
.malformed_acct_requests
++;
1065 client
->counters
.malformed_acct_requests
++;
1072 if (wpa_debug_level
<= MSG_MSGDUMP
) {
1073 radius_msg_dump(msg
);
1076 if (radius_msg_get_hdr(msg
)->code
!= RADIUS_CODE_ACCOUNTING_REQUEST
) {
1077 RADIUS_DEBUG("Unexpected RADIUS code %d",
1078 radius_msg_get_hdr(msg
)->code
);
1079 data
->counters
.unknown_acct_types
++;
1080 client
->counters
.unknown_acct_types
++;
1084 data
->counters
.acct_requests
++;
1085 client
->counters
.acct_requests
++;
1087 if (radius_msg_verify_acct_req(msg
, (u8
*) client
->shared_secret
,
1088 client
->shared_secret_len
)) {
1089 RADIUS_DEBUG("Invalid Authenticator from %s", abuf
);
1090 data
->counters
.acct_bad_authenticators
++;
1091 client
->counters
.acct_bad_authenticators
++;
1095 /* TODO: Write accounting information to a file or database */
1097 hdr
= radius_msg_get_hdr(msg
);
1099 resp
= radius_msg_new(RADIUS_CODE_ACCOUNTING_RESPONSE
, hdr
->identifier
);
1103 radius_msg_finish_acct_resp(resp
, (u8
*) client
->shared_secret
,
1104 client
->shared_secret_len
,
1105 hdr
->authenticator
);
1107 RADIUS_DEBUG("Reply to %s:%d", abuf
, from_port
);
1108 if (wpa_debug_level
<= MSG_MSGDUMP
) {
1109 radius_msg_dump(resp
);
1111 rbuf
= radius_msg_get_buf(resp
);
1112 data
->counters
.acct_responses
++;
1113 client
->counters
.acct_responses
++;
1114 res
= sendto(data
->acct_sock
, wpabuf_head(rbuf
), wpabuf_len(rbuf
), 0,
1115 (struct sockaddr
*) &from
.ss
, fromlen
);
1117 wpa_printf(MSG_INFO
, "sendto[RADIUS SRV]: %s",
1122 radius_msg_free(resp
);
1123 radius_msg_free(msg
);
1128 static int radius_server_disable_pmtu_discovery(int s
)
1131 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
1132 /* Turn off Path MTU discovery on IPv4/UDP sockets. */
1133 int action
= IP_PMTUDISC_DONT
;
1134 r
= setsockopt(s
, IPPROTO_IP
, IP_MTU_DISCOVER
, &action
,
1137 wpa_printf(MSG_ERROR
, "Failed to set IP_MTU_DISCOVER: "
1138 "%s", strerror(errno
));
1144 static int radius_server_open_socket(int port
)
1147 struct sockaddr_in addr
;
1149 s
= socket(PF_INET
, SOCK_DGRAM
, 0);
1151 wpa_printf(MSG_INFO
, "RADIUS: socket: %s", strerror(errno
));
1155 radius_server_disable_pmtu_discovery(s
);
1157 os_memset(&addr
, 0, sizeof(addr
));
1158 addr
.sin_family
= AF_INET
;
1159 addr
.sin_port
= htons(port
);
1160 if (bind(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
1161 wpa_printf(MSG_INFO
, "RADIUS: bind: %s", strerror(errno
));
1171 static int radius_server_open_socket6(int port
)
1174 struct sockaddr_in6 addr
;
1176 s
= socket(PF_INET6
, SOCK_DGRAM
, 0);
1178 wpa_printf(MSG_INFO
, "RADIUS: socket[IPv6]: %s",
1183 os_memset(&addr
, 0, sizeof(addr
));
1184 addr
.sin6_family
= AF_INET6
;
1185 os_memcpy(&addr
.sin6_addr
, &in6addr_any
, sizeof(in6addr_any
));
1186 addr
.sin6_port
= htons(port
);
1187 if (bind(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
1188 wpa_printf(MSG_INFO
, "RADIUS: bind: %s", strerror(errno
));
1195 #endif /* CONFIG_IPV6 */
1198 static void radius_server_free_sessions(struct radius_server_data
*data
,
1199 struct radius_session
*sessions
)
1201 struct radius_session
*session
, *prev
;
1206 session
= session
->next
;
1207 radius_server_session_free(data
, prev
);
1212 static void radius_server_free_clients(struct radius_server_data
*data
,
1213 struct radius_client
*clients
)
1215 struct radius_client
*client
, *prev
;
1220 client
= client
->next
;
1222 radius_server_free_sessions(data
, prev
->sessions
);
1223 os_free(prev
->shared_secret
);
1229 static struct radius_client
*
1230 radius_server_read_clients(const char *client_file
, int ipv6
)
1233 const int buf_size
= 1024;
1235 struct radius_client
*clients
, *tail
, *entry
;
1236 int line
= 0, mask
, failed
= 0, i
;
1237 struct in_addr addr
;
1239 struct in6_addr addr6
;
1240 #endif /* CONFIG_IPV6 */
1243 f
= fopen(client_file
, "r");
1245 RADIUS_ERROR("Could not open client file '%s'", client_file
);
1249 buf
= os_malloc(buf_size
);
1255 clients
= tail
= NULL
;
1256 while (fgets(buf
, buf_size
, f
)) {
1257 /* Configuration file format:
1258 * 192.168.1.0/24 secret
1259 * 192.168.1.2 secret
1260 * fe80::211:22ff:fe33:4455/64 secretipv6
1263 buf
[buf_size
- 1] = '\0';
1265 while (*pos
!= '\0' && *pos
!= '\n')
1269 if (*buf
== '\0' || *buf
== '#')
1273 while ((*pos
>= '0' && *pos
<= '9') || *pos
== '.' ||
1274 (*pos
>= 'a' && *pos
<= 'f') || *pos
== ':' ||
1275 (*pos
>= 'A' && *pos
<= 'F')) {
1287 mask
= strtol(pos
, &end
, 10);
1289 (mask
< 0 || mask
> (ipv6
? 128 : 32))) {
1295 mask
= ipv6
? 128 : 32;
1299 if (!ipv6
&& inet_aton(buf
, &addr
) == 0) {
1304 if (ipv6
&& inet_pton(AF_INET6
, buf
, &addr6
) <= 0) {
1305 if (inet_pton(AF_INET
, buf
, &addr
) <= 0) {
1309 /* Convert IPv4 address to IPv6 */
1312 os_memset(addr6
.s6_addr
, 0, 10);
1313 addr6
.s6_addr
[10] = 0xff;
1314 addr6
.s6_addr
[11] = 0xff;
1315 os_memcpy(addr6
.s6_addr
+ 12, (char *) &addr
.s_addr
,
1318 #endif /* CONFIG_IPV6 */
1320 while (*pos
== ' ' || *pos
== '\t') {
1329 entry
= os_zalloc(sizeof(*entry
));
1330 if (entry
== NULL
) {
1334 entry
->shared_secret
= os_strdup(pos
);
1335 if (entry
->shared_secret
== NULL
) {
1340 entry
->shared_secret_len
= os_strlen(entry
->shared_secret
);
1341 entry
->addr
.s_addr
= addr
.s_addr
;
1344 for (i
= 0; i
< mask
; i
++)
1345 val
|= 1 << (31 - i
);
1346 entry
->mask
.s_addr
= htonl(val
);
1350 int offset
= mask
/ 8;
1352 os_memcpy(entry
->addr6
.s6_addr
, addr6
.s6_addr
, 16);
1353 os_memset(entry
->mask6
.s6_addr
, 0xff, offset
);
1355 for (i
= 0; i
< (mask
% 8); i
++)
1356 val
|= 1 << (7 - i
);
1358 entry
->mask6
.s6_addr
[offset
] = val
;
1360 #endif /* CONFIG_IPV6 */
1363 clients
= tail
= entry
;
1371 RADIUS_ERROR("Invalid line %d in '%s'", line
, client_file
);
1372 radius_server_free_clients(NULL
, clients
);
1384 * radius_server_init - Initialize RADIUS server
1385 * @conf: Configuration for the RADIUS server
1386 * Returns: Pointer to private RADIUS server context or %NULL on failure
1388 * This initializes a RADIUS server instance and returns a context pointer that
1389 * will be used in other calls to the RADIUS server module. The server can be
1390 * deinitialize by calling radius_server_deinit().
1392 struct radius_server_data
*
1393 radius_server_init(struct radius_server_conf
*conf
)
1395 struct radius_server_data
*data
;
1399 wpa_printf(MSG_ERROR
, "RADIUS server compiled without IPv6 support");
1402 #endif /* CONFIG_IPV6 */
1404 data
= os_zalloc(sizeof(*data
));
1408 os_get_reltime(&data
->start_time
);
1409 data
->conf_ctx
= conf
->conf_ctx
;
1410 data
->eap_sim_db_priv
= conf
->eap_sim_db_priv
;
1411 data
->ssl_ctx
= conf
->ssl_ctx
;
1412 data
->msg_ctx
= conf
->msg_ctx
;
1413 data
->ipv6
= conf
->ipv6
;
1414 if (conf
->pac_opaque_encr_key
) {
1415 data
->pac_opaque_encr_key
= os_malloc(16);
1416 os_memcpy(data
->pac_opaque_encr_key
, conf
->pac_opaque_encr_key
,
1419 if (conf
->eap_fast_a_id
) {
1420 data
->eap_fast_a_id
= os_malloc(conf
->eap_fast_a_id_len
);
1421 if (data
->eap_fast_a_id
) {
1422 os_memcpy(data
->eap_fast_a_id
, conf
->eap_fast_a_id
,
1423 conf
->eap_fast_a_id_len
);
1424 data
->eap_fast_a_id_len
= conf
->eap_fast_a_id_len
;
1427 if (conf
->eap_fast_a_id_info
)
1428 data
->eap_fast_a_id_info
= os_strdup(conf
->eap_fast_a_id_info
);
1429 data
->eap_fast_prov
= conf
->eap_fast_prov
;
1430 data
->pac_key_lifetime
= conf
->pac_key_lifetime
;
1431 data
->pac_key_refresh_time
= conf
->pac_key_refresh_time
;
1432 data
->get_eap_user
= conf
->get_eap_user
;
1433 data
->eap_sim_aka_result_ind
= conf
->eap_sim_aka_result_ind
;
1434 data
->tnc
= conf
->tnc
;
1435 data
->wps
= conf
->wps
;
1436 data
->pwd_group
= conf
->pwd_group
;
1437 data
->server_id
= conf
->server_id
;
1438 if (conf
->eap_req_id_text
) {
1439 data
->eap_req_id_text
= os_malloc(conf
->eap_req_id_text_len
);
1440 if (data
->eap_req_id_text
) {
1441 os_memcpy(data
->eap_req_id_text
, conf
->eap_req_id_text
,
1442 conf
->eap_req_id_text_len
);
1443 data
->eap_req_id_text_len
= conf
->eap_req_id_text_len
;
1447 #ifdef CONFIG_RADIUS_TEST
1448 if (conf
->dump_msk_file
)
1449 data
->dump_msk_file
= os_strdup(conf
->dump_msk_file
);
1450 #endif /* CONFIG_RADIUS_TEST */
1452 data
->clients
= radius_server_read_clients(conf
->client_file
,
1454 if (data
->clients
== NULL
) {
1455 wpa_printf(MSG_ERROR
, "No RADIUS clients configured");
1456 radius_server_deinit(data
);
1462 data
->auth_sock
= radius_server_open_socket6(conf
->auth_port
);
1464 #endif /* CONFIG_IPV6 */
1465 data
->auth_sock
= radius_server_open_socket(conf
->auth_port
);
1466 if (data
->auth_sock
< 0) {
1467 wpa_printf(MSG_ERROR
, "Failed to open UDP socket for RADIUS authentication server");
1468 radius_server_deinit(data
);
1471 if (eloop_register_read_sock(data
->auth_sock
,
1472 radius_server_receive_auth
,
1474 radius_server_deinit(data
);
1478 if (conf
->acct_port
) {
1481 data
->acct_sock
= radius_server_open_socket6(
1484 #endif /* CONFIG_IPV6 */
1485 data
->acct_sock
= radius_server_open_socket(conf
->acct_port
);
1486 if (data
->acct_sock
< 0) {
1487 wpa_printf(MSG_ERROR
, "Failed to open UDP socket for RADIUS accounting server");
1488 radius_server_deinit(data
);
1491 if (eloop_register_read_sock(data
->acct_sock
,
1492 radius_server_receive_acct
,
1494 radius_server_deinit(data
);
1498 data
->acct_sock
= -1;
1506 * radius_server_deinit - Deinitialize RADIUS server
1507 * @data: RADIUS server context from radius_server_init()
1509 void radius_server_deinit(struct radius_server_data
*data
)
1514 if (data
->auth_sock
>= 0) {
1515 eloop_unregister_read_sock(data
->auth_sock
);
1516 close(data
->auth_sock
);
1519 if (data
->acct_sock
>= 0) {
1520 eloop_unregister_read_sock(data
->acct_sock
);
1521 close(data
->acct_sock
);
1524 radius_server_free_clients(data
, data
->clients
);
1526 os_free(data
->pac_opaque_encr_key
);
1527 os_free(data
->eap_fast_a_id
);
1528 os_free(data
->eap_fast_a_id_info
);
1529 os_free(data
->eap_req_id_text
);
1530 #ifdef CONFIG_RADIUS_TEST
1531 os_free(data
->dump_msk_file
);
1532 #endif /* CONFIG_RADIUS_TEST */
1538 * radius_server_get_mib - Get RADIUS server MIB information
1539 * @data: RADIUS server context from radius_server_init()
1540 * @buf: Buffer for returning the MIB data in text format
1541 * @buflen: buf length in octets
1542 * Returns: Number of octets written into buf
1544 int radius_server_get_mib(struct radius_server_data
*data
, char *buf
,
1550 struct os_reltime now
;
1551 struct radius_client
*cli
;
1553 /* RFC 2619 - RADIUS Authentication Server MIB */
1555 if (data
== NULL
|| buflen
== 0)
1561 os_get_reltime(&now
);
1562 uptime
= (now
.sec
- data
->start_time
.sec
) * 100 +
1563 ((now
.usec
- data
->start_time
.usec
) / 10000) % 100;
1564 ret
= os_snprintf(pos
, end
- pos
,
1565 "RADIUS-AUTH-SERVER-MIB\n"
1566 "radiusAuthServIdent=hostapd\n"
1567 "radiusAuthServUpTime=%d\n"
1568 "radiusAuthServResetTime=0\n"
1569 "radiusAuthServConfigReset=4\n",
1571 if (ret
< 0 || ret
>= end
- pos
) {
1577 ret
= os_snprintf(pos
, end
- pos
,
1578 "radiusAuthServTotalAccessRequests=%u\n"
1579 "radiusAuthServTotalInvalidRequests=%u\n"
1580 "radiusAuthServTotalDupAccessRequests=%u\n"
1581 "radiusAuthServTotalAccessAccepts=%u\n"
1582 "radiusAuthServTotalAccessRejects=%u\n"
1583 "radiusAuthServTotalAccessChallenges=%u\n"
1584 "radiusAuthServTotalMalformedAccessRequests=%u\n"
1585 "radiusAuthServTotalBadAuthenticators=%u\n"
1586 "radiusAuthServTotalPacketsDropped=%u\n"
1587 "radiusAuthServTotalUnknownTypes=%u\n"
1588 "radiusAccServTotalRequests=%u\n"
1589 "radiusAccServTotalInvalidRequests=%u\n"
1590 "radiusAccServTotalResponses=%u\n"
1591 "radiusAccServTotalMalformedRequests=%u\n"
1592 "radiusAccServTotalBadAuthenticators=%u\n"
1593 "radiusAccServTotalUnknownTypes=%u\n",
1594 data
->counters
.access_requests
,
1595 data
->counters
.invalid_requests
,
1596 data
->counters
.dup_access_requests
,
1597 data
->counters
.access_accepts
,
1598 data
->counters
.access_rejects
,
1599 data
->counters
.access_challenges
,
1600 data
->counters
.malformed_access_requests
,
1601 data
->counters
.bad_authenticators
,
1602 data
->counters
.packets_dropped
,
1603 data
->counters
.unknown_types
,
1604 data
->counters
.acct_requests
,
1605 data
->counters
.invalid_acct_requests
,
1606 data
->counters
.acct_responses
,
1607 data
->counters
.malformed_acct_requests
,
1608 data
->counters
.acct_bad_authenticators
,
1609 data
->counters
.unknown_acct_types
);
1610 if (ret
< 0 || ret
>= end
- pos
) {
1616 for (cli
= data
->clients
, idx
= 0; cli
; cli
= cli
->next
, idx
++) {
1617 char abuf
[50], mbuf
[50];
1620 if (inet_ntop(AF_INET6
, &cli
->addr6
, abuf
,
1621 sizeof(abuf
)) == NULL
)
1623 if (inet_ntop(AF_INET6
, &cli
->mask6
, abuf
,
1624 sizeof(mbuf
)) == NULL
)
1627 #endif /* CONFIG_IPV6 */
1629 os_strlcpy(abuf
, inet_ntoa(cli
->addr
), sizeof(abuf
));
1630 os_strlcpy(mbuf
, inet_ntoa(cli
->mask
), sizeof(mbuf
));
1633 ret
= os_snprintf(pos
, end
- pos
,
1634 "radiusAuthClientIndex=%u\n"
1635 "radiusAuthClientAddress=%s/%s\n"
1636 "radiusAuthServAccessRequests=%u\n"
1637 "radiusAuthServDupAccessRequests=%u\n"
1638 "radiusAuthServAccessAccepts=%u\n"
1639 "radiusAuthServAccessRejects=%u\n"
1640 "radiusAuthServAccessChallenges=%u\n"
1641 "radiusAuthServMalformedAccessRequests=%u\n"
1642 "radiusAuthServBadAuthenticators=%u\n"
1643 "radiusAuthServPacketsDropped=%u\n"
1644 "radiusAuthServUnknownTypes=%u\n"
1645 "radiusAccServTotalRequests=%u\n"
1646 "radiusAccServTotalInvalidRequests=%u\n"
1647 "radiusAccServTotalResponses=%u\n"
1648 "radiusAccServTotalMalformedRequests=%u\n"
1649 "radiusAccServTotalBadAuthenticators=%u\n"
1650 "radiusAccServTotalUnknownTypes=%u\n",
1653 cli
->counters
.access_requests
,
1654 cli
->counters
.dup_access_requests
,
1655 cli
->counters
.access_accepts
,
1656 cli
->counters
.access_rejects
,
1657 cli
->counters
.access_challenges
,
1658 cli
->counters
.malformed_access_requests
,
1659 cli
->counters
.bad_authenticators
,
1660 cli
->counters
.packets_dropped
,
1661 cli
->counters
.unknown_types
,
1662 cli
->counters
.acct_requests
,
1663 cli
->counters
.invalid_acct_requests
,
1664 cli
->counters
.acct_responses
,
1665 cli
->counters
.malformed_acct_requests
,
1666 cli
->counters
.acct_bad_authenticators
,
1667 cli
->counters
.unknown_acct_types
);
1668 if (ret
< 0 || ret
>= end
- pos
) {
1679 static int radius_server_get_eap_user(void *ctx
, const u8
*identity
,
1680 size_t identity_len
, int phase2
,
1681 struct eap_user
*user
)
1683 struct radius_session
*sess
= ctx
;
1684 struct radius_server_data
*data
= sess
->server
;
1686 return data
->get_eap_user(data
->conf_ctx
, identity
, identity_len
,
1691 static const char * radius_server_get_eap_req_id_text(void *ctx
, size_t *len
)
1693 struct radius_session
*sess
= ctx
;
1694 struct radius_server_data
*data
= sess
->server
;
1695 *len
= data
->eap_req_id_text_len
;
1696 return data
->eap_req_id_text
;
1700 static struct eapol_callbacks radius_server_eapol_cb
=
1702 .get_eap_user
= radius_server_get_eap_user
,
1703 .get_eap_req_id_text
= radius_server_get_eap_req_id_text
,
1708 * radius_server_eap_pending_cb - Pending EAP data notification
1709 * @data: RADIUS server context from radius_server_init()
1710 * @ctx: Pending EAP context pointer
1712 * This function is used to notify EAP server module that a pending operation
1713 * has been completed and processing of the EAP session can proceed.
1715 void radius_server_eap_pending_cb(struct radius_server_data
*data
, void *ctx
)
1717 struct radius_client
*cli
;
1718 struct radius_session
*s
, *sess
= NULL
;
1719 struct radius_msg
*msg
;
1724 for (cli
= data
->clients
; cli
; cli
= cli
->next
) {
1725 for (s
= cli
->sessions
; s
; s
= s
->next
) {
1726 if (s
->eap
== ctx
&& s
->last_msg
) {
1738 RADIUS_DEBUG("No session matched callback ctx");
1742 msg
= sess
->last_msg
;
1743 sess
->last_msg
= NULL
;
1744 eap_sm_pending_cb(sess
->eap
);
1745 if (radius_server_request(data
, msg
,
1746 (struct sockaddr
*) &sess
->last_from
,
1747 sess
->last_fromlen
, cli
,
1748 sess
->last_from_addr
,
1749 sess
->last_from_port
, sess
) == -2)
1750 return; /* msg was stored with the session */
1752 radius_msg_free(msg
);