2
* hostapd / RADIUS authentication server
3
* Copyright (c) 2005-2007, 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
u8 *eapKeyData, *eapReqData;
54
size_t eapKeyDataLen, eapReqDataLen;
55
Boolean eapSuccess, eapRestart, eapFail, eapResp, eapReq, eapNoReq;
56
Boolean portEnabled, eapTimeout;
58
struct radius_msg *last_msg;
61
struct sockaddr_storage last_from;
62
socklen_t last_fromlen;
64
struct radius_msg *last_reply;
65
u8 last_authenticator[16];
68
struct radius_client {
69
struct radius_client *next;
73
struct in6_addr addr6;
74
struct in6_addr mask6;
75
#endif /* CONFIG_IPV6 */
77
int shared_secret_len;
78
struct radius_session *sessions;
79
struct radius_server_counters counters;
82
struct radius_server_data {
84
struct radius_client *clients;
85
unsigned int next_sess_id;
88
void *eap_sim_db_priv;
91
struct os_time start_time;
92
struct radius_server_counters counters;
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
free(sess->eapKeyData);
174
free(sess->eapReqData);
175
eap_server_sm_deinit(sess->eap);
176
if (sess->last_msg) {
177
radius_msg_free(sess->last_msg);
178
free(sess->last_msg);
180
free(sess->last_from_addr);
181
if (sess->last_reply) {
182
radius_msg_free(sess->last_reply);
183
free(sess->last_reply);
190
static void radius_server_session_remove_timeout(void *eloop_ctx,
193
static void radius_server_session_remove(struct radius_server_data *data,
194
struct radius_session *sess)
196
struct radius_client *client = sess->client;
197
struct radius_session *session, *prev;
199
eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess);
202
session = client->sessions;
204
if (session == sess) {
206
client->sessions = sess->next;
208
prev->next = sess->next;
210
radius_server_session_free(data, sess);
214
session = session->next;
219
static void radius_server_session_remove_timeout(void *eloop_ctx,
222
struct radius_server_data *data = eloop_ctx;
223
struct radius_session *sess = timeout_ctx;
224
RADIUS_DEBUG("Removing completed session 0x%x", sess->sess_id);
225
radius_server_session_remove(data, sess);
229
static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx)
231
struct radius_server_data *data = eloop_ctx;
232
struct radius_session *sess = timeout_ctx;
234
RADIUS_DEBUG("Timing out authentication session 0x%x", sess->sess_id);
235
radius_server_session_remove(data, sess);
239
static struct radius_session *
240
radius_server_new_session(struct radius_server_data *data,
241
struct radius_client *client)
243
struct radius_session *sess;
245
if (data->num_sess >= RADIUS_MAX_SESSION) {
246
RADIUS_DEBUG("Maximum number of existing session - no room "
247
"for a new session");
251
sess = os_zalloc(sizeof(*sess));
256
sess->client = client;
257
sess->sess_id = data->next_sess_id++;
258
sess->next = client->sessions;
259
client->sessions = sess;
260
eloop_register_timeout(RADIUS_SESSION_TIMEOUT, 0,
261
radius_server_session_timeout, data, sess);
267
static struct radius_session *
268
radius_server_get_new_session(struct radius_server_data *data,
269
struct radius_client *client,
270
struct radius_msg *msg)
275
struct radius_session *sess;
276
struct eap_config eap_conf;
278
RADIUS_DEBUG("Creating a new session");
284
res = radius_msg_get_attr(msg, RADIUS_ATTR_USER_NAME, user, 256);
285
if (res < 0 || res > 256) {
286
RADIUS_DEBUG("Could not get User-Name");
291
RADIUS_DUMP_ASCII("User-Name", user, user_len);
293
res = data->get_eap_user(data->conf_ctx, user, user_len, 0, NULL);
297
RADIUS_DEBUG("Matching user entry found");
298
sess = radius_server_new_session(data, client);
300
RADIUS_DEBUG("Failed to create a new session");
304
RADIUS_DEBUG("User-Name not found from user database");
308
memset(&eap_conf, 0, sizeof(eap_conf));
309
eap_conf.ssl_ctx = data->ssl_ctx;
310
eap_conf.eap_sim_db_priv = data->eap_sim_db_priv;
311
eap_conf.backend_auth = TRUE;
312
sess->eap = eap_server_sm_init(sess, &radius_server_eapol_cb,
314
if (sess->eap == NULL) {
315
RADIUS_DEBUG("Failed to initialize EAP state machine for the "
317
radius_server_session_free(data, sess);
320
sess->eapRestart = TRUE;
321
sess->portEnabled = TRUE;
323
RADIUS_DEBUG("New session 0x%x initialized", sess->sess_id);
329
static struct radius_msg *
330
radius_server_encapsulate_eap(struct radius_server_data *data,
331
struct radius_client *client,
332
struct radius_session *sess,
333
struct radius_msg *request)
335
struct radius_msg *msg;
337
unsigned int sess_id;
340
code = RADIUS_CODE_ACCESS_REJECT;
341
} else if (sess->eapSuccess) {
342
code = RADIUS_CODE_ACCESS_ACCEPT;
344
code = RADIUS_CODE_ACCESS_CHALLENGE;
347
msg = radius_msg_new(code, request->hdr->identifier);
349
RADIUS_DEBUG("Failed to allocate reply message");
353
sess_id = htonl(sess->sess_id);
354
if (code == RADIUS_CODE_ACCESS_CHALLENGE &&
355
!radius_msg_add_attr(msg, RADIUS_ATTR_STATE,
356
(u8 *) &sess_id, sizeof(sess_id))) {
357
RADIUS_DEBUG("Failed to add State attribute");
360
if (sess->eapReqData &&
361
!radius_msg_add_eap(msg, sess->eapReqData, sess->eapReqDataLen)) {
362
RADIUS_DEBUG("Failed to add EAP-Message attribute");
365
if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->eapKeyData) {
367
if (sess->eapKeyDataLen > 64) {
370
len = sess->eapKeyDataLen / 2;
372
if (!radius_msg_add_mppe_keys(msg, request->hdr->authenticator,
373
(u8 *) client->shared_secret,
374
client->shared_secret_len,
375
sess->eapKeyData + len, len,
376
sess->eapKeyData, len)) {
377
RADIUS_DEBUG("Failed to add MPPE key attributes");
381
if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
382
client->shared_secret_len,
383
request->hdr->authenticator) < 0) {
384
RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
391
static int radius_server_reject(struct radius_server_data *data,
392
struct radius_client *client,
393
struct radius_msg *request,
394
struct sockaddr *from, socklen_t fromlen,
395
const char *from_addr, int from_port)
397
struct radius_msg *msg;
399
struct eap_hdr eapfail;
401
RADIUS_DEBUG("Reject invalid request from %s:%d",
402
from_addr, from_port);
404
msg = radius_msg_new(RADIUS_CODE_ACCESS_REJECT,
405
request->hdr->identifier);
410
memset(&eapfail, 0, sizeof(eapfail));
411
eapfail.code = EAP_CODE_FAILURE;
412
eapfail.identifier = 0;
413
eapfail.length = host_to_be16(sizeof(eapfail));
415
if (!radius_msg_add_eap(msg, (u8 *) &eapfail, sizeof(eapfail))) {
416
RADIUS_DEBUG("Failed to add EAP-Message attribute");
420
if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
421
client->shared_secret_len,
422
request->hdr->authenticator) < 0) {
423
RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
426
if (wpa_debug_level <= MSG_MSGDUMP) {
427
radius_msg_dump(msg);
430
data->counters.access_rejects++;
431
client->counters.access_rejects++;
432
if (sendto(data->auth_sock, msg->buf, msg->buf_used, 0,
433
(struct sockaddr *) from, sizeof(*from)) < 0) {
434
perror("sendto[RADIUS SRV]");
438
radius_msg_free(msg);
445
static int radius_server_request(struct radius_server_data *data,
446
struct radius_msg *msg,
447
struct sockaddr *from, socklen_t fromlen,
448
struct radius_client *client,
449
const char *from_addr, int from_port,
450
struct radius_session *force_sess)
454
int res, state_included = 0;
455
u8 statebuf[4], resp_id;
457
struct radius_session *sess;
458
struct radius_msg *reply;
464
res = radius_msg_get_attr(msg, RADIUS_ATTR_STATE, statebuf,
466
state_included = res >= 0;
467
if (res == sizeof(statebuf)) {
468
state = WPA_GET_BE32(statebuf);
469
sess = radius_server_get_session(client, state);
476
RADIUS_DEBUG("Request for session 0x%x", sess->sess_id);
477
} else if (state_included) {
478
RADIUS_DEBUG("State attribute included but no session found");
479
radius_server_reject(data, client, msg, from, fromlen,
480
from_addr, from_port);
483
sess = radius_server_get_new_session(data, client, msg);
485
RADIUS_DEBUG("Could not create a new session");
486
radius_server_reject(data, client, msg, from, fromlen,
487
from_addr, from_port);
492
if (sess->last_from_port == from_port &&
493
sess->last_identifier == msg->hdr->identifier &&
494
os_memcmp(sess->last_authenticator, msg->hdr->authenticator, 16) ==
496
RADIUS_DEBUG("Duplicate message from %s", from_addr);
497
data->counters.dup_access_requests++;
498
client->counters.dup_access_requests++;
500
if (sess->last_reply) {
501
res = sendto(data->auth_sock, sess->last_reply->buf,
502
sess->last_reply->buf_used, 0,
503
(struct sockaddr *) from, fromlen);
505
perror("sendto[RADIUS SRV]");
510
RADIUS_DEBUG("No previous reply available for duplicate "
515
eap = radius_msg_get_eap(msg, &eap_len);
517
RADIUS_DEBUG("No EAP-Message in RADIUS packet from %s",
519
data->counters.packets_dropped++;
520
client->counters.packets_dropped++;
524
RADIUS_DUMP("Received EAP data", eap, eap_len);
525
if (eap_len >= sizeof(*hdr)) {
526
hdr = (struct eap_hdr *) eap;
527
resp_id = hdr->identifier;
532
/* FIX: if Code is Request, Success, or Failure, send Access-Reject;
533
* RFC3579 Sect. 2.6.2.
534
* Include EAP-Response/Nak with no preferred method if
536
* If code is not 1-4, discard the packet silently.
537
* Or is this already done by the EAP state machine? */
539
eap_set_eapRespData(sess->eap, eap, eap_len);
542
sess->eapResp = TRUE;
543
eap_server_sm_step(sess->eap);
545
if (sess->eapReqData) {
546
RADIUS_DUMP("EAP data from the state machine",
547
sess->eapReqData, sess->eapReqDataLen);
548
} else if (sess->eapFail) {
549
RADIUS_DEBUG("No EAP data from the state machine, but eapFail "
550
"set - generate EAP-Failure");
551
hdr = os_zalloc(sizeof(*hdr));
553
hdr->identifier = resp_id;
554
hdr->length = host_to_be16(sizeof(*hdr));
555
sess->eapReqData = (u8 *) hdr;
556
sess->eapReqDataLen = sizeof(*hdr);
558
} else if (eap_sm_method_pending(sess->eap)) {
559
if (sess->last_msg) {
560
radius_msg_free(sess->last_msg);
561
free(sess->last_msg);
563
sess->last_msg = msg;
564
sess->last_from_port = from_port;
565
free(sess->last_from_addr);
566
sess->last_from_addr = strdup(from_addr);
567
sess->last_fromlen = fromlen;
568
memcpy(&sess->last_from, from, fromlen);
571
RADIUS_DEBUG("No EAP data from the state machine - ignore this"
572
" Access-Request silently (assuming it was a "
574
data->counters.packets_dropped++;
575
client->counters.packets_dropped++;
579
reply = radius_server_encapsulate_eap(data, client, sess, msg);
581
free(sess->eapReqData);
582
sess->eapReqData = NULL;
583
sess->eapReqDataLen = 0;
586
RADIUS_DEBUG("Reply to %s:%d", from_addr, from_port);
587
if (wpa_debug_level <= MSG_MSGDUMP) {
588
radius_msg_dump(reply);
591
switch (reply->hdr->code) {
592
case RADIUS_CODE_ACCESS_ACCEPT:
593
data->counters.access_accepts++;
594
client->counters.access_accepts++;
596
case RADIUS_CODE_ACCESS_REJECT:
597
data->counters.access_rejects++;
598
client->counters.access_rejects++;
600
case RADIUS_CODE_ACCESS_CHALLENGE:
601
data->counters.access_challenges++;
602
client->counters.access_challenges++;
605
res = sendto(data->auth_sock, reply->buf, reply->buf_used, 0,
606
(struct sockaddr *) from, fromlen);
608
perror("sendto[RADIUS SRV]");
610
if (sess->last_reply) {
611
radius_msg_free(sess->last_reply);
612
free(sess->last_reply);
614
sess->last_reply = reply;
615
sess->last_from_port = from_port;
616
sess->last_identifier = msg->hdr->identifier;
617
os_memcpy(sess->last_authenticator, msg->hdr->authenticator,
620
data->counters.packets_dropped++;
621
client->counters.packets_dropped++;
624
if (sess->eapSuccess || sess->eapFail) {
625
RADIUS_DEBUG("Removing completed session 0x%x after timeout",
627
eloop_cancel_timeout(radius_server_session_remove_timeout,
629
eloop_register_timeout(10, 0,
630
radius_server_session_remove_timeout,
638
static void radius_server_receive_auth(int sock, void *eloop_ctx,
641
struct radius_server_data *data = eloop_ctx;
643
struct sockaddr_storage from;
646
struct radius_client *client = NULL;
647
struct radius_msg *msg = NULL;
651
buf = malloc(RADIUS_MAX_MSG_LEN);
656
fromlen = sizeof(from);
657
len = recvfrom(sock, buf, RADIUS_MAX_MSG_LEN, 0,
658
(struct sockaddr *) &from, &fromlen);
660
perror("recvfrom[radius_server]");
666
struct sockaddr_in6 *from6 = (struct sockaddr_in6 *) &from;
667
if (inet_ntop(AF_INET6, &from6->sin6_addr, abuf, sizeof(abuf))
670
from_port = ntohs(from6->sin6_port);
671
RADIUS_DEBUG("Received %d bytes from %s:%d",
672
len, abuf, from_port);
674
client = radius_server_get_client(data,
676
&from6->sin6_addr, 1);
678
#endif /* CONFIG_IPV6 */
681
struct sockaddr_in *from4 = (struct sockaddr_in *) &from;
682
os_strlcpy(abuf, inet_ntoa(from4->sin_addr), sizeof(abuf));
683
from_port = ntohs(from4->sin_port);
684
RADIUS_DEBUG("Received %d bytes from %s:%d",
685
len, abuf, from_port);
687
client = radius_server_get_client(data, &from4->sin_addr, 0);
690
RADIUS_DUMP("Received data", buf, len);
692
if (client == NULL) {
693
RADIUS_DEBUG("Unknown client %s - packet ignored", abuf);
694
data->counters.invalid_requests++;
698
msg = radius_msg_parse(buf, len);
700
RADIUS_DEBUG("Parsing incoming RADIUS frame failed");
701
data->counters.malformed_access_requests++;
702
client->counters.malformed_access_requests++;
709
if (wpa_debug_level <= MSG_MSGDUMP) {
710
radius_msg_dump(msg);
713
if (msg->hdr->code != RADIUS_CODE_ACCESS_REQUEST) {
714
RADIUS_DEBUG("Unexpected RADIUS code %d", msg->hdr->code);
715
data->counters.unknown_types++;
716
client->counters.unknown_types++;
720
data->counters.access_requests++;
721
client->counters.access_requests++;
723
if (radius_msg_verify_msg_auth(msg, (u8 *) client->shared_secret,
724
client->shared_secret_len, NULL)) {
725
RADIUS_DEBUG("Invalid Message-Authenticator from %s", abuf);
726
data->counters.bad_authenticators++;
727
client->counters.bad_authenticators++;
731
if (radius_server_request(data, msg, (struct sockaddr *) &from,
732
fromlen, client, abuf, from_port, NULL) ==
734
return; /* msg was stored with the session */
738
radius_msg_free(msg);
745
static int radius_server_open_socket(int port)
748
struct sockaddr_in addr;
750
s = socket(PF_INET, SOCK_DGRAM, 0);
756
memset(&addr, 0, sizeof(addr));
757
addr.sin_family = AF_INET;
758
addr.sin_port = htons(port);
759
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
770
static int radius_server_open_socket6(int port)
773
struct sockaddr_in6 addr;
775
s = socket(PF_INET6, SOCK_DGRAM, 0);
777
perror("socket[IPv6]");
781
memset(&addr, 0, sizeof(addr));
782
addr.sin6_family = AF_INET6;
783
memcpy(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any));
784
addr.sin6_port = htons(port);
785
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
793
#endif /* CONFIG_IPV6 */
796
static void radius_server_free_sessions(struct radius_server_data *data,
797
struct radius_session *sessions)
799
struct radius_session *session, *prev;
804
session = session->next;
805
radius_server_session_free(data, prev);
810
static void radius_server_free_clients(struct radius_server_data *data,
811
struct radius_client *clients)
813
struct radius_client *client, *prev;
818
client = client->next;
820
radius_server_free_sessions(data, prev->sessions);
821
free(prev->shared_secret);
827
static struct radius_client *
828
radius_server_read_clients(const char *client_file, int ipv6)
831
const int buf_size = 1024;
833
struct radius_client *clients, *tail, *entry;
834
int line = 0, mask, failed = 0, i;
837
struct in6_addr addr6;
838
#endif /* CONFIG_IPV6 */
841
f = fopen(client_file, "r");
843
RADIUS_ERROR("Could not open client file '%s'", client_file);
847
buf = malloc(buf_size);
853
clients = tail = NULL;
854
while (fgets(buf, buf_size, f)) {
855
/* Configuration file format:
856
* 192.168.1.0/24 secret
858
* fe80::211:22ff:fe33:4455/64 secretipv6
861
buf[buf_size - 1] = '\0';
863
while (*pos != '\0' && *pos != '\n')
867
if (*buf == '\0' || *buf == '#')
871
while ((*pos >= '0' && *pos <= '9') || *pos == '.' ||
872
(*pos >= 'a' && *pos <= 'f') || *pos == ':' ||
873
(*pos >= 'A' && *pos <= 'F')) {
885
mask = strtol(pos, &end, 10);
887
(mask < 0 || mask > (ipv6 ? 128 : 32))) {
893
mask = ipv6 ? 128 : 32;
897
if (!ipv6 && inet_aton(buf, &addr) == 0) {
902
if (ipv6 && inet_pton(AF_INET6, buf, &addr6) <= 0) {
903
if (inet_pton(AF_INET, buf, &addr) <= 0) {
907
/* Convert IPv4 address to IPv6 */
910
memset(addr6.s6_addr, 0, 10);
911
addr6.s6_addr[10] = 0xff;
912
addr6.s6_addr[11] = 0xff;
913
memcpy(addr6.s6_addr + 12, (char *) &addr.s_addr, 4);
915
#endif /* CONFIG_IPV6 */
917
while (*pos == ' ' || *pos == '\t') {
926
entry = os_zalloc(sizeof(*entry));
931
entry->shared_secret = strdup(pos);
932
if (entry->shared_secret == NULL) {
937
entry->shared_secret_len = strlen(entry->shared_secret);
938
entry->addr.s_addr = addr.s_addr;
941
for (i = 0; i < mask; i++)
942
val |= 1 << (31 - i);
943
entry->mask.s_addr = htonl(val);
947
int offset = mask / 8;
949
memcpy(entry->addr6.s6_addr, addr6.s6_addr, 16);
950
memset(entry->mask6.s6_addr, 0xff, offset);
952
for (i = 0; i < (mask % 8); i++)
955
entry->mask6.s6_addr[offset] = val;
957
#endif /* CONFIG_IPV6 */
960
clients = tail = entry;
968
RADIUS_ERROR("Invalid line %d in '%s'", line, client_file);
969
radius_server_free_clients(NULL, clients);
980
struct radius_server_data *
981
radius_server_init(struct radius_server_conf *conf)
983
struct radius_server_data *data;
987
fprintf(stderr, "RADIUS server compiled without IPv6 "
991
#endif /* CONFIG_IPV6 */
993
data = os_zalloc(sizeof(*data));
997
os_get_time(&data->start_time);
998
data->conf_ctx = conf->conf_ctx;
999
data->eap_sim_db_priv = conf->eap_sim_db_priv;
1000
data->ssl_ctx = conf->ssl_ctx;
1001
data->ipv6 = conf->ipv6;
1002
data->get_eap_user = conf->get_eap_user;
1004
data->clients = radius_server_read_clients(conf->client_file,
1006
if (data->clients == NULL) {
1007
printf("No RADIUS clients configured.\n");
1008
radius_server_deinit(data);
1014
data->auth_sock = radius_server_open_socket6(conf->auth_port);
1016
#endif /* CONFIG_IPV6 */
1017
data->auth_sock = radius_server_open_socket(conf->auth_port);
1018
if (data->auth_sock < 0) {
1019
printf("Failed to open UDP socket for RADIUS authentication "
1021
radius_server_deinit(data);
1024
if (eloop_register_read_sock(data->auth_sock,
1025
radius_server_receive_auth,
1027
radius_server_deinit(data);
1035
void radius_server_deinit(struct radius_server_data *data)
1040
if (data->auth_sock >= 0) {
1041
eloop_unregister_read_sock(data->auth_sock);
1042
close(data->auth_sock);
1045
radius_server_free_clients(data, data->clients);
1051
int radius_server_get_mib(struct radius_server_data *data, char *buf,
1058
struct radius_client *cli;
1060
/* RFC 2619 - RADIUS Authentication Server MIB */
1062
if (data == NULL || buflen == 0)
1069
uptime = (now.sec - data->start_time.sec) * 100 +
1070
((now.usec - data->start_time.usec) / 10000) % 100;
1071
ret = snprintf(pos, end - pos,
1072
"RADIUS-AUTH-SERVER-MIB\n"
1073
"radiusAuthServIdent=hostapd\n"
1074
"radiusAuthServUpTime=%d\n"
1075
"radiusAuthServResetTime=0\n"
1076
"radiusAuthServConfigReset=4\n",
1078
if (ret < 0 || ret >= end - pos) {
1084
ret = snprintf(pos, end - pos,
1085
"radiusAuthServTotalAccessRequests=%u\n"
1086
"radiusAuthServTotalInvalidRequests=%u\n"
1087
"radiusAuthServTotalDupAccessRequests=%u\n"
1088
"radiusAuthServTotalAccessAccepts=%u\n"
1089
"radiusAuthServTotalAccessRejects=%u\n"
1090
"radiusAuthServTotalAccessChallenges=%u\n"
1091
"radiusAuthServTotalMalformedAccessRequests=%u\n"
1092
"radiusAuthServTotalBadAuthenticators=%u\n"
1093
"radiusAuthServTotalPacketsDropped=%u\n"
1094
"radiusAuthServTotalUnknownTypes=%u\n",
1095
data->counters.access_requests,
1096
data->counters.invalid_requests,
1097
data->counters.dup_access_requests,
1098
data->counters.access_accepts,
1099
data->counters.access_rejects,
1100
data->counters.access_challenges,
1101
data->counters.malformed_access_requests,
1102
data->counters.bad_authenticators,
1103
data->counters.packets_dropped,
1104
data->counters.unknown_types);
1105
if (ret < 0 || ret >= end - pos) {
1111
for (cli = data->clients, idx = 0; cli; cli = cli->next, idx++) {
1112
char abuf[50], mbuf[50];
1115
if (inet_ntop(AF_INET6, &cli->addr6, abuf,
1116
sizeof(abuf)) == NULL)
1118
if (inet_ntop(AF_INET6, &cli->mask6, abuf,
1119
sizeof(mbuf)) == NULL)
1122
#endif /* CONFIG_IPV6 */
1124
os_strlcpy(abuf, inet_ntoa(cli->addr), sizeof(abuf));
1125
os_strlcpy(mbuf, inet_ntoa(cli->mask), sizeof(mbuf));
1128
ret = snprintf(pos, end - pos,
1129
"radiusAuthClientIndex=%u\n"
1130
"radiusAuthClientAddress=%s/%s\n"
1131
"radiusAuthServAccessRequests=%u\n"
1132
"radiusAuthServDupAccessRequests=%u\n"
1133
"radiusAuthServAccessAccepts=%u\n"
1134
"radiusAuthServAccessRejects=%u\n"
1135
"radiusAuthServAccessChallenges=%u\n"
1136
"radiusAuthServMalformedAccessRequests=%u\n"
1137
"radiusAuthServBadAuthenticators=%u\n"
1138
"radiusAuthServPacketsDropped=%u\n"
1139
"radiusAuthServUnknownTypes=%u\n",
1142
cli->counters.access_requests,
1143
cli->counters.dup_access_requests,
1144
cli->counters.access_accepts,
1145
cli->counters.access_rejects,
1146
cli->counters.access_challenges,
1147
cli->counters.malformed_access_requests,
1148
cli->counters.bad_authenticators,
1149
cli->counters.packets_dropped,
1150
cli->counters.unknown_types);
1151
if (ret < 0 || ret >= end - pos) {
1162
static Boolean radius_server_get_bool(void *ctx, enum eapol_bool_var variable)
1164
struct radius_session *sess = ctx;
1168
case EAPOL_eapSuccess:
1169
return sess->eapSuccess;
1170
case EAPOL_eapRestart:
1171
return sess->eapRestart;
1173
return sess->eapFail;
1175
return sess->eapResp;
1177
return sess->eapReq;
1178
case EAPOL_eapNoReq:
1179
return sess->eapNoReq;
1180
case EAPOL_portEnabled:
1181
return sess->portEnabled;
1182
case EAPOL_eapTimeout:
1183
return sess->eapTimeout;
1189
static void radius_server_set_bool(void *ctx, enum eapol_bool_var variable,
1192
struct radius_session *sess = ctx;
1196
case EAPOL_eapSuccess:
1197
sess->eapSuccess = value;
1199
case EAPOL_eapRestart:
1200
sess->eapRestart = value;
1203
sess->eapFail = value;
1206
sess->eapResp = value;
1209
sess->eapReq = value;
1211
case EAPOL_eapNoReq:
1212
sess->eapNoReq = value;
1214
case EAPOL_portEnabled:
1215
sess->portEnabled = value;
1217
case EAPOL_eapTimeout:
1218
sess->eapTimeout = value;
1224
static void radius_server_set_eapReqData(void *ctx, const u8 *eapReqData,
1225
size_t eapReqDataLen)
1227
struct radius_session *sess = ctx;
1231
free(sess->eapReqData);
1232
sess->eapReqData = malloc(eapReqDataLen);
1233
if (sess->eapReqData) {
1234
memcpy(sess->eapReqData, eapReqData, eapReqDataLen);
1235
sess->eapReqDataLen = eapReqDataLen;
1237
sess->eapReqDataLen = 0;
1242
static void radius_server_set_eapKeyData(void *ctx, const u8 *eapKeyData,
1243
size_t eapKeyDataLen)
1245
struct radius_session *sess = ctx;
1250
free(sess->eapKeyData);
1252
sess->eapKeyData = malloc(eapKeyDataLen);
1253
if (sess->eapKeyData) {
1254
memcpy(sess->eapKeyData, eapKeyData, eapKeyDataLen);
1255
sess->eapKeyDataLen = eapKeyDataLen;
1257
sess->eapKeyDataLen = 0;
1260
sess->eapKeyData = NULL;
1261
sess->eapKeyDataLen = 0;
1266
static int radius_server_get_eap_user(void *ctx, const u8 *identity,
1267
size_t identity_len, int phase2,
1268
struct eap_user *user)
1270
struct radius_session *sess = ctx;
1271
struct radius_server_data *data = sess->server;
1273
return data->get_eap_user(data->conf_ctx, identity, identity_len,
1278
static struct eapol_callbacks radius_server_eapol_cb =
1280
.get_bool = radius_server_get_bool,
1281
.set_bool = radius_server_set_bool,
1282
.set_eapReqData = radius_server_set_eapReqData,
1283
.set_eapKeyData = radius_server_set_eapKeyData,
1284
.get_eap_user = radius_server_get_eap_user,
1288
void radius_server_eap_pending_cb(struct radius_server_data *data, void *ctx)
1290
struct radius_client *cli;
1291
struct radius_session *s, *sess = NULL;
1292
struct radius_msg *msg;
1297
for (cli = data->clients; cli; cli = cli->next) {
1298
for (s = cli->sessions; s; s = s->next) {
1299
if (s->eap == ctx && s->last_msg) {
1311
RADIUS_DEBUG("No session matched callback ctx");
1315
msg = sess->last_msg;
1316
sess->last_msg = NULL;
1317
eap_sm_pending_cb(sess->eap);
1318
if (radius_server_request(data, msg,
1319
(struct sockaddr *) &sess->last_from,
1320
sess->last_fromlen, cli,
1321
sess->last_from_addr,
1322
sess->last_from_port, sess) == -2)
1323
return; /* msg was stored with the session */
1325
radius_msg_free(msg);