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.
22 #include "eap_server/eap.h"
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 struct eap_eapol_interface *eap_if;
55 struct radius_msg *last_msg;
58 struct sockaddr_storage last_from;
59 socklen_t last_fromlen;
61 struct radius_msg *last_reply;
62 u8 last_authenticator[16];
65 struct radius_client {
66 struct radius_client *next;
70 struct in6_addr addr6;
71 struct in6_addr mask6;
72 #endif /* CONFIG_IPV6 */
74 int shared_secret_len;
75 struct radius_session *sessions;
76 struct radius_server_counters counters;
79 struct radius_server_data {
81 struct radius_client *clients;
82 unsigned int next_sess_id;
85 void *eap_sim_db_priv;
87 u8 *pac_opaque_encr_key;
89 int eap_sim_aka_result_ind;
91 struct os_time start_time;
92 struct radius_server_counters counters;
93 int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len,
94 int phase2, struct eap_user *user);
98 extern int wpa_debug_level;
100 #define RADIUS_DEBUG(args...) \
101 wpa_printf(MSG_DEBUG, "RADIUS SRV: " args)
102 #define RADIUS_ERROR(args...) \
103 wpa_printf(MSG_ERROR, "RADIUS SRV: " args)
104 #define RADIUS_DUMP(args...) \
105 wpa_hexdump(MSG_MSGDUMP, "RADIUS SRV: " args)
106 #define RADIUS_DUMP_ASCII(args...) \
107 wpa_hexdump_ascii(MSG_MSGDUMP, "RADIUS SRV: " args)
110 static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx);
114 static struct radius_client *
115 radius_server_get_client(struct radius_server_data *data, struct in_addr *addr,
118 struct radius_client *client = data->clients;
123 struct in6_addr *addr6;
126 addr6 = (struct in6_addr *) addr;
127 for (i = 0; i < 16; i++) {
128 if ((addr6->s6_addr[i] &
129 client->mask6.s6_addr[i]) !=
130 (client->addr6.s6_addr[i] &
131 client->mask6.s6_addr[i])) {
140 #endif /* CONFIG_IPV6 */
141 if (!ipv6 && (client->addr.s_addr & client->mask.s_addr) ==
142 (addr->s_addr & client->mask.s_addr)) {
146 client = client->next;
153 static struct radius_session *
154 radius_server_get_session(struct radius_client *client, unsigned int sess_id)
156 struct radius_session *sess = client->sessions;
159 if (sess->sess_id == sess_id) {
169 static void radius_server_session_free(struct radius_server_data *data,
170 struct radius_session *sess)
172 eloop_cancel_timeout(radius_server_session_timeout, data, sess);
173 eap_server_sm_deinit(sess->eap);
174 if (sess->last_msg) {
175 radius_msg_free(sess->last_msg);
176 os_free(sess->last_msg);
178 os_free(sess->last_from_addr);
179 if (sess->last_reply) {
180 radius_msg_free(sess->last_reply);
181 os_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 = os_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)
273 struct radius_session *sess;
274 struct eap_config eap_conf;
276 RADIUS_DEBUG("Creating a new session");
278 user = os_malloc(256);
282 res = radius_msg_get_attr(msg, RADIUS_ATTR_USER_NAME, user, 256);
283 if (res < 0 || res > 256) {
284 RADIUS_DEBUG("Could not get User-Name");
289 RADIUS_DUMP_ASCII("User-Name", user, user_len);
291 res = data->get_eap_user(data->conf_ctx, user, user_len, 0, NULL);
295 RADIUS_DEBUG("Matching user entry found");
296 sess = radius_server_new_session(data, client);
298 RADIUS_DEBUG("Failed to create a new session");
302 RADIUS_DEBUG("User-Name not found from user database");
306 os_memset(&eap_conf, 0, sizeof(eap_conf));
307 eap_conf.ssl_ctx = data->ssl_ctx;
308 eap_conf.eap_sim_db_priv = data->eap_sim_db_priv;
309 eap_conf.backend_auth = TRUE;
310 eap_conf.eap_server = 1;
311 eap_conf.pac_opaque_encr_key = data->pac_opaque_encr_key;
312 eap_conf.eap_fast_a_id = data->eap_fast_a_id;
313 eap_conf.eap_sim_aka_result_ind = data->eap_sim_aka_result_ind;
314 sess->eap = eap_server_sm_init(sess, &radius_server_eapol_cb,
316 if (sess->eap == NULL) {
317 RADIUS_DEBUG("Failed to initialize EAP state machine for the "
319 radius_server_session_free(data, sess);
322 sess->eap_if = eap_get_interface(sess->eap);
323 sess->eap_if->eapRestart = TRUE;
324 sess->eap_if->portEnabled = TRUE;
326 RADIUS_DEBUG("New session 0x%x initialized", sess->sess_id);
332 static struct radius_msg *
333 radius_server_encapsulate_eap(struct radius_server_data *data,
334 struct radius_client *client,
335 struct radius_session *sess,
336 struct radius_msg *request)
338 struct radius_msg *msg;
340 unsigned int sess_id;
342 if (sess->eap_if->eapFail) {
343 sess->eap_if->eapFail = FALSE;
344 code = RADIUS_CODE_ACCESS_REJECT;
345 } else if (sess->eap_if->eapSuccess) {
346 sess->eap_if->eapSuccess = FALSE;
347 code = RADIUS_CODE_ACCESS_ACCEPT;
349 sess->eap_if->eapReq = FALSE;
350 code = RADIUS_CODE_ACCESS_CHALLENGE;
353 msg = radius_msg_new(code, request->hdr->identifier);
355 RADIUS_DEBUG("Failed to allocate reply message");
359 sess_id = htonl(sess->sess_id);
360 if (code == RADIUS_CODE_ACCESS_CHALLENGE &&
361 !radius_msg_add_attr(msg, RADIUS_ATTR_STATE,
362 (u8 *) &sess_id, sizeof(sess_id))) {
363 RADIUS_DEBUG("Failed to add State attribute");
366 if (sess->eap_if->eapReqData &&
367 !radius_msg_add_eap(msg, wpabuf_head(sess->eap_if->eapReqData),
368 wpabuf_len(sess->eap_if->eapReqData))) {
369 RADIUS_DEBUG("Failed to add EAP-Message attribute");
372 if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->eap_if->eapKeyData) {
374 if (sess->eap_if->eapKeyDataLen > 64) {
377 len = sess->eap_if->eapKeyDataLen / 2;
379 if (!radius_msg_add_mppe_keys(msg, request->hdr->authenticator,
380 (u8 *) client->shared_secret,
381 client->shared_secret_len,
382 sess->eap_if->eapKeyData + len,
383 len, sess->eap_if->eapKeyData,
385 RADIUS_DEBUG("Failed to add MPPE key attributes");
389 if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) {
390 RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
391 radius_msg_free(msg);
396 if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
397 client->shared_secret_len,
398 request->hdr->authenticator) < 0) {
399 RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
406 static int radius_server_reject(struct radius_server_data *data,
407 struct radius_client *client,
408 struct radius_msg *request,
409 struct sockaddr *from, socklen_t fromlen,
410 const char *from_addr, int from_port)
412 struct radius_msg *msg;
414 struct eap_hdr eapfail;
416 RADIUS_DEBUG("Reject invalid request from %s:%d",
417 from_addr, from_port);
419 msg = radius_msg_new(RADIUS_CODE_ACCESS_REJECT,
420 request->hdr->identifier);
425 os_memset(&eapfail, 0, sizeof(eapfail));
426 eapfail.code = EAP_CODE_FAILURE;
427 eapfail.identifier = 0;
428 eapfail.length = host_to_be16(sizeof(eapfail));
430 if (!radius_msg_add_eap(msg, (u8 *) &eapfail, sizeof(eapfail))) {
431 RADIUS_DEBUG("Failed to add EAP-Message attribute");
434 if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) {
435 RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
436 radius_msg_free(msg);
441 if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
442 client->shared_secret_len,
443 request->hdr->authenticator) < 0) {
444 RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
447 if (wpa_debug_level <= MSG_MSGDUMP) {
448 radius_msg_dump(msg);
451 data->counters.access_rejects++;
452 client->counters.access_rejects++;
453 if (sendto(data->auth_sock, msg->buf, msg->buf_used, 0,
454 (struct sockaddr *) from, sizeof(*from)) < 0) {
455 perror("sendto[RADIUS SRV]");
459 radius_msg_free(msg);
466 static int radius_server_request(struct radius_server_data *data,
467 struct radius_msg *msg,
468 struct sockaddr *from, socklen_t fromlen,
469 struct radius_client *client,
470 const char *from_addr, int from_port,
471 struct radius_session *force_sess)
475 int res, state_included = 0;
478 struct radius_session *sess;
479 struct radius_msg *reply;
484 res = radius_msg_get_attr(msg, RADIUS_ATTR_STATE, statebuf,
486 state_included = res >= 0;
487 if (res == sizeof(statebuf)) {
488 state = WPA_GET_BE32(statebuf);
489 sess = radius_server_get_session(client, state);
496 RADIUS_DEBUG("Request for session 0x%x", sess->sess_id);
497 } else if (state_included) {
498 RADIUS_DEBUG("State attribute included but no session found");
499 radius_server_reject(data, client, msg, from, fromlen,
500 from_addr, from_port);
503 sess = radius_server_get_new_session(data, client, msg);
505 RADIUS_DEBUG("Could not create a new session");
506 radius_server_reject(data, client, msg, from, fromlen,
507 from_addr, from_port);
512 if (sess->last_from_port == from_port &&
513 sess->last_identifier == msg->hdr->identifier &&
514 os_memcmp(sess->last_authenticator, msg->hdr->authenticator, 16) ==
516 RADIUS_DEBUG("Duplicate message from %s", from_addr);
517 data->counters.dup_access_requests++;
518 client->counters.dup_access_requests++;
520 if (sess->last_reply) {
521 res = sendto(data->auth_sock, sess->last_reply->buf,
522 sess->last_reply->buf_used, 0,
523 (struct sockaddr *) from, fromlen);
525 perror("sendto[RADIUS SRV]");
530 RADIUS_DEBUG("No previous reply available for duplicate "
535 eap = radius_msg_get_eap(msg, &eap_len);
537 RADIUS_DEBUG("No EAP-Message in RADIUS packet from %s",
539 data->counters.packets_dropped++;
540 client->counters.packets_dropped++;
544 RADIUS_DUMP("Received EAP data", eap, eap_len);
546 /* FIX: if Code is Request, Success, or Failure, send Access-Reject;
547 * RFC3579 Sect. 2.6.2.
548 * Include EAP-Response/Nak with no preferred method if
550 * If code is not 1-4, discard the packet silently.
551 * Or is this already done by the EAP state machine? */
553 wpabuf_free(sess->eap_if->eapRespData);
554 sess->eap_if->eapRespData = wpabuf_alloc_ext_data(eap, eap_len);
555 if (sess->eap_if->eapRespData == NULL)
558 sess->eap_if->eapResp = TRUE;
559 eap_server_sm_step(sess->eap);
561 if ((sess->eap_if->eapReq || sess->eap_if->eapSuccess ||
562 sess->eap_if->eapFail) && sess->eap_if->eapReqData) {
563 RADIUS_DUMP("EAP data from the state machine",
564 wpabuf_head(sess->eap_if->eapReqData),
565 wpabuf_len(sess->eap_if->eapReqData));
566 } else if (sess->eap_if->eapFail) {
567 RADIUS_DEBUG("No EAP data from the state machine, but eapFail "
569 } else if (eap_sm_method_pending(sess->eap)) {
570 if (sess->last_msg) {
571 radius_msg_free(sess->last_msg);
572 os_free(sess->last_msg);
574 sess->last_msg = msg;
575 sess->last_from_port = from_port;
576 os_free(sess->last_from_addr);
577 sess->last_from_addr = os_strdup(from_addr);
578 sess->last_fromlen = fromlen;
579 os_memcpy(&sess->last_from, from, fromlen);
582 RADIUS_DEBUG("No EAP data from the state machine - ignore this"
583 " Access-Request silently (assuming it was a "
585 data->counters.packets_dropped++;
586 client->counters.packets_dropped++;
590 reply = radius_server_encapsulate_eap(data, client, sess, msg);
593 RADIUS_DEBUG("Reply to %s:%d", from_addr, from_port);
594 if (wpa_debug_level <= MSG_MSGDUMP) {
595 radius_msg_dump(reply);
598 switch (reply->hdr->code) {
599 case RADIUS_CODE_ACCESS_ACCEPT:
600 data->counters.access_accepts++;
601 client->counters.access_accepts++;
603 case RADIUS_CODE_ACCESS_REJECT:
604 data->counters.access_rejects++;
605 client->counters.access_rejects++;
607 case RADIUS_CODE_ACCESS_CHALLENGE:
608 data->counters.access_challenges++;
609 client->counters.access_challenges++;
612 res = sendto(data->auth_sock, reply->buf, reply->buf_used, 0,
613 (struct sockaddr *) from, fromlen);
615 perror("sendto[RADIUS SRV]");
617 if (sess->last_reply) {
618 radius_msg_free(sess->last_reply);
619 os_free(sess->last_reply);
621 sess->last_reply = reply;
622 sess->last_from_port = from_port;
623 sess->last_identifier = msg->hdr->identifier;
624 os_memcpy(sess->last_authenticator, msg->hdr->authenticator,
627 data->counters.packets_dropped++;
628 client->counters.packets_dropped++;
631 if (sess->eap_if->eapSuccess || sess->eap_if->eapFail) {
632 RADIUS_DEBUG("Removing completed session 0x%x after timeout",
634 eloop_cancel_timeout(radius_server_session_remove_timeout,
636 eloop_register_timeout(10, 0,
637 radius_server_session_remove_timeout,
645 static void radius_server_receive_auth(int sock, void *eloop_ctx,
648 struct radius_server_data *data = eloop_ctx;
650 struct sockaddr_storage from;
653 struct radius_client *client = NULL;
654 struct radius_msg *msg = NULL;
658 buf = os_malloc(RADIUS_MAX_MSG_LEN);
663 fromlen = sizeof(from);
664 len = recvfrom(sock, buf, RADIUS_MAX_MSG_LEN, 0,
665 (struct sockaddr *) &from, &fromlen);
667 perror("recvfrom[radius_server]");
673 struct sockaddr_in6 *from6 = (struct sockaddr_in6 *) &from;
674 if (inet_ntop(AF_INET6, &from6->sin6_addr, abuf, sizeof(abuf))
677 from_port = ntohs(from6->sin6_port);
678 RADIUS_DEBUG("Received %d bytes from %s:%d",
679 len, abuf, from_port);
681 client = radius_server_get_client(data,
683 &from6->sin6_addr, 1);
685 #endif /* CONFIG_IPV6 */
688 struct sockaddr_in *from4 = (struct sockaddr_in *) &from;
689 os_strlcpy(abuf, inet_ntoa(from4->sin_addr), sizeof(abuf));
690 from_port = ntohs(from4->sin_port);
691 RADIUS_DEBUG("Received %d bytes from %s:%d",
692 len, abuf, from_port);
694 client = radius_server_get_client(data, &from4->sin_addr, 0);
697 RADIUS_DUMP("Received data", buf, len);
699 if (client == NULL) {
700 RADIUS_DEBUG("Unknown client %s - packet ignored", abuf);
701 data->counters.invalid_requests++;
705 msg = radius_msg_parse(buf, len);
707 RADIUS_DEBUG("Parsing incoming RADIUS frame failed");
708 data->counters.malformed_access_requests++;
709 client->counters.malformed_access_requests++;
716 if (wpa_debug_level <= MSG_MSGDUMP) {
717 radius_msg_dump(msg);
720 if (msg->hdr->code != RADIUS_CODE_ACCESS_REQUEST) {
721 RADIUS_DEBUG("Unexpected RADIUS code %d", msg->hdr->code);
722 data->counters.unknown_types++;
723 client->counters.unknown_types++;
727 data->counters.access_requests++;
728 client->counters.access_requests++;
730 if (radius_msg_verify_msg_auth(msg, (u8 *) client->shared_secret,
731 client->shared_secret_len, NULL)) {
732 RADIUS_DEBUG("Invalid Message-Authenticator from %s", abuf);
733 data->counters.bad_authenticators++;
734 client->counters.bad_authenticators++;
738 if (radius_server_request(data, msg, (struct sockaddr *) &from,
739 fromlen, client, abuf, from_port, NULL) ==
741 return; /* msg was stored with the session */
745 radius_msg_free(msg);
752 static int radius_server_open_socket(int port)
755 struct sockaddr_in addr;
757 s = socket(PF_INET, SOCK_DGRAM, 0);
763 os_memset(&addr, 0, sizeof(addr));
764 addr.sin_family = AF_INET;
765 addr.sin_port = htons(port);
766 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
777 static int radius_server_open_socket6(int port)
780 struct sockaddr_in6 addr;
782 s = socket(PF_INET6, SOCK_DGRAM, 0);
784 perror("socket[IPv6]");
788 os_memset(&addr, 0, sizeof(addr));
789 addr.sin6_family = AF_INET6;
790 os_memcpy(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any));
791 addr.sin6_port = htons(port);
792 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
800 #endif /* CONFIG_IPV6 */
803 static void radius_server_free_sessions(struct radius_server_data *data,
804 struct radius_session *sessions)
806 struct radius_session *session, *prev;
811 session = session->next;
812 radius_server_session_free(data, prev);
817 static void radius_server_free_clients(struct radius_server_data *data,
818 struct radius_client *clients)
820 struct radius_client *client, *prev;
825 client = client->next;
827 radius_server_free_sessions(data, prev->sessions);
828 os_free(prev->shared_secret);
834 static struct radius_client *
835 radius_server_read_clients(const char *client_file, int ipv6)
838 const int buf_size = 1024;
840 struct radius_client *clients, *tail, *entry;
841 int line = 0, mask, failed = 0, i;
844 struct in6_addr addr6;
845 #endif /* CONFIG_IPV6 */
848 f = fopen(client_file, "r");
850 RADIUS_ERROR("Could not open client file '%s'", client_file);
854 buf = os_malloc(buf_size);
860 clients = tail = NULL;
861 while (fgets(buf, buf_size, f)) {
862 /* Configuration file format:
863 * 192.168.1.0/24 secret
865 * fe80::211:22ff:fe33:4455/64 secretipv6
868 buf[buf_size - 1] = '\0';
870 while (*pos != '\0' && *pos != '\n')
874 if (*buf == '\0' || *buf == '#')
878 while ((*pos >= '0' && *pos <= '9') || *pos == '.' ||
879 (*pos >= 'a' && *pos <= 'f') || *pos == ':' ||
880 (*pos >= 'A' && *pos <= 'F')) {
892 mask = strtol(pos, &end, 10);
894 (mask < 0 || mask > (ipv6 ? 128 : 32))) {
900 mask = ipv6 ? 128 : 32;
904 if (!ipv6 && inet_aton(buf, &addr) == 0) {
909 if (ipv6 && inet_pton(AF_INET6, buf, &addr6) <= 0) {
910 if (inet_pton(AF_INET, buf, &addr) <= 0) {
914 /* Convert IPv4 address to IPv6 */
917 os_memset(addr6.s6_addr, 0, 10);
918 addr6.s6_addr[10] = 0xff;
919 addr6.s6_addr[11] = 0xff;
920 os_memcpy(addr6.s6_addr + 12, (char *) &addr.s_addr,
923 #endif /* CONFIG_IPV6 */
925 while (*pos == ' ' || *pos == '\t') {
934 entry = os_zalloc(sizeof(*entry));
939 entry->shared_secret = os_strdup(pos);
940 if (entry->shared_secret == NULL) {
945 entry->shared_secret_len = os_strlen(entry->shared_secret);
946 entry->addr.s_addr = addr.s_addr;
949 for (i = 0; i < mask; i++)
950 val |= 1 << (31 - i);
951 entry->mask.s_addr = htonl(val);
955 int offset = mask / 8;
957 os_memcpy(entry->addr6.s6_addr, addr6.s6_addr, 16);
958 os_memset(entry->mask6.s6_addr, 0xff, offset);
960 for (i = 0; i < (mask % 8); i++)
963 entry->mask6.s6_addr[offset] = val;
965 #endif /* CONFIG_IPV6 */
968 clients = tail = entry;
976 RADIUS_ERROR("Invalid line %d in '%s'", line, client_file);
977 radius_server_free_clients(NULL, clients);
988 struct radius_server_data *
989 radius_server_init(struct radius_server_conf *conf)
991 struct radius_server_data *data;
995 fprintf(stderr, "RADIUS server compiled without IPv6 "
999 #endif /* CONFIG_IPV6 */
1001 data = os_zalloc(sizeof(*data));
1005 os_get_time(&data->start_time);
1006 data->conf_ctx = conf->conf_ctx;
1007 data->eap_sim_db_priv = conf->eap_sim_db_priv;
1008 data->ssl_ctx = conf->ssl_ctx;
1009 data->ipv6 = conf->ipv6;
1010 if (conf->pac_opaque_encr_key) {
1011 data->pac_opaque_encr_key = os_malloc(16);
1012 os_memcpy(data->pac_opaque_encr_key, conf->pac_opaque_encr_key,
1015 if (conf->eap_fast_a_id)
1016 data->eap_fast_a_id = os_strdup(conf->eap_fast_a_id);
1017 data->get_eap_user = conf->get_eap_user;
1018 data->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;
1020 data->clients = radius_server_read_clients(conf->client_file,
1022 if (data->clients == NULL) {
1023 printf("No RADIUS clients configured.\n");
1024 radius_server_deinit(data);
1030 data->auth_sock = radius_server_open_socket6(conf->auth_port);
1032 #endif /* CONFIG_IPV6 */
1033 data->auth_sock = radius_server_open_socket(conf->auth_port);
1034 if (data->auth_sock < 0) {
1035 printf("Failed to open UDP socket for RADIUS authentication "
1037 radius_server_deinit(data);
1040 if (eloop_register_read_sock(data->auth_sock,
1041 radius_server_receive_auth,
1043 radius_server_deinit(data);
1051 void radius_server_deinit(struct radius_server_data *data)
1056 if (data->auth_sock >= 0) {
1057 eloop_unregister_read_sock(data->auth_sock);
1058 close(data->auth_sock);
1061 radius_server_free_clients(data, data->clients);
1063 os_free(data->pac_opaque_encr_key);
1064 os_free(data->eap_fast_a_id);
1069 int radius_server_get_mib(struct radius_server_data *data, char *buf,
1076 struct radius_client *cli;
1078 /* RFC 2619 - RADIUS Authentication Server MIB */
1080 if (data == NULL || buflen == 0)
1087 uptime = (now.sec - data->start_time.sec) * 100 +
1088 ((now.usec - data->start_time.usec) / 10000) % 100;
1089 ret = os_snprintf(pos, end - pos,
1090 "RADIUS-AUTH-SERVER-MIB\n"
1091 "radiusAuthServIdent=hostapd\n"
1092 "radiusAuthServUpTime=%d\n"
1093 "radiusAuthServResetTime=0\n"
1094 "radiusAuthServConfigReset=4\n",
1096 if (ret < 0 || ret >= end - pos) {
1102 ret = os_snprintf(pos, end - pos,
1103 "radiusAuthServTotalAccessRequests=%u\n"
1104 "radiusAuthServTotalInvalidRequests=%u\n"
1105 "radiusAuthServTotalDupAccessRequests=%u\n"
1106 "radiusAuthServTotalAccessAccepts=%u\n"
1107 "radiusAuthServTotalAccessRejects=%u\n"
1108 "radiusAuthServTotalAccessChallenges=%u\n"
1109 "radiusAuthServTotalMalformedAccessRequests=%u\n"
1110 "radiusAuthServTotalBadAuthenticators=%u\n"
1111 "radiusAuthServTotalPacketsDropped=%u\n"
1112 "radiusAuthServTotalUnknownTypes=%u\n",
1113 data->counters.access_requests,
1114 data->counters.invalid_requests,
1115 data->counters.dup_access_requests,
1116 data->counters.access_accepts,
1117 data->counters.access_rejects,
1118 data->counters.access_challenges,
1119 data->counters.malformed_access_requests,
1120 data->counters.bad_authenticators,
1121 data->counters.packets_dropped,
1122 data->counters.unknown_types);
1123 if (ret < 0 || ret >= end - pos) {
1129 for (cli = data->clients, idx = 0; cli; cli = cli->next, idx++) {
1130 char abuf[50], mbuf[50];
1133 if (inet_ntop(AF_INET6, &cli->addr6, abuf,
1134 sizeof(abuf)) == NULL)
1136 if (inet_ntop(AF_INET6, &cli->mask6, abuf,
1137 sizeof(mbuf)) == NULL)
1140 #endif /* CONFIG_IPV6 */
1142 os_strlcpy(abuf, inet_ntoa(cli->addr), sizeof(abuf));
1143 os_strlcpy(mbuf, inet_ntoa(cli->mask), sizeof(mbuf));
1146 ret = os_snprintf(pos, end - pos,
1147 "radiusAuthClientIndex=%u\n"
1148 "radiusAuthClientAddress=%s/%s\n"
1149 "radiusAuthServAccessRequests=%u\n"
1150 "radiusAuthServDupAccessRequests=%u\n"
1151 "radiusAuthServAccessAccepts=%u\n"
1152 "radiusAuthServAccessRejects=%u\n"
1153 "radiusAuthServAccessChallenges=%u\n"
1154 "radiusAuthServMalformedAccessRequests=%u\n"
1155 "radiusAuthServBadAuthenticators=%u\n"
1156 "radiusAuthServPacketsDropped=%u\n"
1157 "radiusAuthServUnknownTypes=%u\n",
1160 cli->counters.access_requests,
1161 cli->counters.dup_access_requests,
1162 cli->counters.access_accepts,
1163 cli->counters.access_rejects,
1164 cli->counters.access_challenges,
1165 cli->counters.malformed_access_requests,
1166 cli->counters.bad_authenticators,
1167 cli->counters.packets_dropped,
1168 cli->counters.unknown_types);
1169 if (ret < 0 || ret >= end - pos) {
1180 static int radius_server_get_eap_user(void *ctx, const u8 *identity,
1181 size_t identity_len, int phase2,
1182 struct eap_user *user)
1184 struct radius_session *sess = ctx;
1185 struct radius_server_data *data = sess->server;
1187 return data->get_eap_user(data->conf_ctx, identity, identity_len,
1192 static struct eapol_callbacks radius_server_eapol_cb =
1194 .get_eap_user = radius_server_get_eap_user,
1198 void radius_server_eap_pending_cb(struct radius_server_data *data, void *ctx)
1200 struct radius_client *cli;
1201 struct radius_session *s, *sess = NULL;
1202 struct radius_msg *msg;
1207 for (cli = data->clients; cli; cli = cli->next) {
1208 for (s = cli->sessions; s; s = s->next) {
1209 if (s->eap == ctx && s->last_msg) {
1221 RADIUS_DEBUG("No session matched callback ctx");
1225 msg = sess->last_msg;
1226 sess->last_msg = NULL;
1227 eap_sm_pending_cb(sess->eap);
1228 if (radius_server_request(data, msg,
1229 (struct sockaddr *) &sess->last_from,
1230 sess->last_fromlen, cli,
1231 sess->last_from_addr,
1232 sess->last_from_port, sess) == -2)
1233 return; /* msg was stored with the session */
1235 radius_msg_free(msg);