2 * Host AP (software wireless LAN access point) user space daemon for
3 * Host AP kernel driver / RADIUS client / modified for eapol_test
4 * Copyright (c) 2002-2004, Jouni Malinen <jkmaline@cc.hut.fi>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation. See README and COPYING for
15 #include <netinet/in.h>
18 #include <sys/types.h>
19 #include <sys/socket.h>
20 #include <arpa/inet.h>
24 #include "config_ssid.h"
25 #include "wpa_supplicant.h"
26 #include "wpa_supplicant_i.h"
28 #include "radius_client.h"
30 #include "l2_packet.h"
32 #include "wpa_supplicant.h"
33 #define hostapd_logger(h, a, m, l, t...) wpa_printf(MSG_DEBUG, t)
34 #define HOSTAPD_DEBUG(l, a...) wpa_printf(MSG_DEBUG, a)
35 #define HOSTAPD_DEBUG_COND(l) 1
37 /* Defaults for RADIUS retransmit values (exponential backoff) */
38 #define RADIUS_CLIENT_FIRST_WAIT 1 /* seconds */
39 #define RADIUS_CLIENT_MAX_WAIT 120 /* seconds */
40 #define RADIUS_CLIENT_MAX_RETRIES 10 /* maximum number of retransmit attempts
41 * before entry is removed from retransmit
43 #define RADIUS_CLIENT_MAX_ENTRIES 30 /* maximum number of entries in retransmit
44 * list (oldest will be removed, if this
45 * limit is exceeded) */
46 #define RADIUS_CLIENT_NUM_FAILOVER 4 /* try to change RADIUS server after this
47 * many failed retry attempts */
52 radius_change_server(struct wpa_supplicant *wpa_s, struct hostapd_radius_server *nserv,
53 struct hostapd_radius_server *oserv,
57 static void radius_client_msg_free(struct radius_msg_list *req)
59 radius_msg_free(req->msg);
65 int radius_client_register(struct wpa_supplicant *wpa_s, RadiusType msg_type,
66 RadiusRxResult (*handler)(struct wpa_supplicant *wpa_s,
67 struct radius_msg *msg,
68 struct radius_msg *req,
70 size_t shared_secret_len,
74 struct radius_rx_handler **handlers, *newh;
77 if (msg_type == RADIUS_ACCT) {
78 handlers = &wpa_s->radius->acct_handlers;
79 num = &wpa_s->radius->num_acct_handlers;
81 handlers = &wpa_s->radius->auth_handlers;
82 num = &wpa_s->radius->num_auth_handlers;
85 newh = (struct radius_rx_handler *)
87 (*num + 1) * sizeof(struct radius_rx_handler));
91 newh[*num].handler = handler;
92 newh[*num].data = data;
100 static int radius_client_retransmit(struct wpa_supplicant *wpa_s,
101 struct radius_msg_list *entry, time_t now)
105 if (entry->msg_type == RADIUS_ACCT ||
106 entry->msg_type == RADIUS_ACCT_INTERIM)
107 s = wpa_s->radius->acct_serv_sock;
109 s = wpa_s->radius->auth_serv_sock;
111 /* retransmit; remove entry if too many attempts */
113 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Resending RADIUS message (id=%d)"
114 "\n", entry->msg->hdr->identifier);
116 if (send(s, entry->msg->buf, entry->msg->buf_used, 0) < 0)
117 perror("send[RADIUS]");
119 entry->next_try = now + entry->next_wait;
120 entry->next_wait *= 2;
121 if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT)
122 entry->next_wait = RADIUS_CLIENT_MAX_WAIT;
123 if (entry->attempts >= RADIUS_CLIENT_MAX_RETRIES) {
124 printf("Removing un-ACKed RADIUS message due to too many "
125 "failed retransmit attempts\n");
133 static void radius_client_timer(void *eloop_ctx, void *timeout_ctx)
135 struct wpa_supplicant *wpa_s = eloop_ctx;
137 struct radius_msg_list *entry, *prev, *tmp;
138 int auth_failover = 0, acct_failover = 0;
140 entry = wpa_s->radius->msgs;
149 if (now >= entry->next_try &&
150 radius_client_retransmit(wpa_s, entry, now)) {
152 prev->next = entry->next;
154 wpa_s->radius->msgs = entry->next;
158 radius_client_msg_free(tmp);
159 wpa_s->radius->num_msgs--;
163 if (entry->attempts > RADIUS_CLIENT_NUM_FAILOVER) {
164 if (entry->msg_type == RADIUS_ACCT ||
165 entry->msg_type == RADIUS_ACCT_INTERIM)
171 if (first == 0 || entry->next_try < first)
172 first = entry->next_try;
178 if (wpa_s->radius->msgs) {
181 eloop_register_timeout(first - now, 0,
182 radius_client_timer, wpa_s, NULL);
185 if (auth_failover && wpa_s->num_auth_servers > 1) {
186 struct hostapd_radius_server *next, *old;
187 old = wpa_s->auth_server;
188 hostapd_logger(wpa_s, NULL, HOSTAPD_MODULE_RADIUS,
189 HOSTAPD_LEVEL_NOTICE,
190 "No response from Authentication server "
192 inet_ntoa(old->addr), old->port);
195 if (next > &(wpa_s->auth_servers
196 [wpa_s->num_auth_servers - 1]))
197 next = wpa_s->auth_servers;
198 wpa_s->auth_server = next;
199 radius_change_server(wpa_s, next, old,
200 wpa_s->radius->auth_serv_sock, 1);
203 if (acct_failover && wpa_s->num_acct_servers > 1) {
204 struct hostapd_radius_server *next, *old;
205 old = wpa_s->acct_server;
206 hostapd_logger(wpa_s, NULL, HOSTAPD_MODULE_RADIUS,
207 HOSTAPD_LEVEL_NOTICE,
208 "No response from Accounting server "
210 inet_ntoa(old->addr), old->port);
212 if (next > &wpa_s->acct_servers
213 [wpa_s->num_acct_servers - 1])
214 next = wpa_s->acct_servers;
215 wpa_s->acct_server = next;
216 radius_change_server(wpa_s, next, old,
217 wpa_s->radius->acct_serv_sock, 0);
222 static void radius_client_list_add(struct wpa_supplicant *wpa_s, struct radius_msg *msg,
223 RadiusType msg_type, u8 *shared_secret,
224 size_t shared_secret_len, u8 *addr)
226 struct radius_msg_list *entry, *prev;
228 if (eloop_terminated()) {
229 /* No point in adding entries to retransmit queue since event
230 * loop has already been terminated. */
231 radius_msg_free(msg);
236 entry = malloc(sizeof(*entry));
238 printf("Failed to add RADIUS packet into retransmit list\n");
239 radius_msg_free(msg);
244 memset(entry, 0, sizeof(*entry));
246 memcpy(entry->addr, addr, ETH_ALEN);
248 entry->msg_type = msg_type;
249 entry->shared_secret = shared_secret;
250 entry->shared_secret_len = shared_secret_len;
251 time(&entry->first_try);
252 entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT;
254 entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2;
256 if (!wpa_s->radius->msgs)
257 eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT, 0,
258 radius_client_timer, wpa_s, NULL);
260 entry->next = wpa_s->radius->msgs;
261 wpa_s->radius->msgs = entry;
263 if (wpa_s->radius->num_msgs >= RADIUS_CLIENT_MAX_ENTRIES) {
264 printf("Removing the oldest un-ACKed RADIUS packet due to "
265 "retransmit list limits.\n");
267 while (entry->next) {
273 radius_client_msg_free(entry);
276 wpa_s->radius->num_msgs++;
280 static void radius_client_list_del(struct wpa_supplicant *wpa_s,
281 RadiusType msg_type, u8 *addr)
283 struct radius_msg_list *entry, *prev, *tmp;
288 entry = wpa_s->radius->msgs;
291 if (entry->msg_type == msg_type &&
292 memcmp(entry->addr, addr, ETH_ALEN) == 0) {
294 prev->next = entry->next;
296 wpa_s->radius->msgs = entry->next;
299 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
300 "Removing matching RADIUS message for "
301 MACSTR "\n", MAC2STR(addr));
302 radius_client_msg_free(tmp);
303 wpa_s->radius->num_msgs--;
312 int radius_client_send(struct wpa_supplicant *wpa_s, struct radius_msg *msg,
313 RadiusType msg_type, u8 *addr)
316 size_t shared_secret_len;
320 if (msg_type == RADIUS_ACCT_INTERIM) {
321 /* Remove any pending interim acct update for the same STA. */
322 radius_client_list_del(wpa_s, msg_type, addr);
325 if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) {
326 shared_secret = wpa_s->acct_server->shared_secret;
327 shared_secret_len = wpa_s->acct_server->shared_secret_len;
328 radius_msg_finish_acct(msg, shared_secret, shared_secret_len);
330 s = wpa_s->radius->acct_serv_sock;
332 shared_secret = wpa_s->auth_server->shared_secret;
333 shared_secret_len = wpa_s->auth_server->shared_secret_len;
334 radius_msg_finish(msg, shared_secret, shared_secret_len);
335 name = "authentication";
336 s = wpa_s->radius->auth_serv_sock;
339 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
340 "Sending RADIUS message to %s server\n", name);
341 if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MSGDUMPS))
342 radius_msg_dump(msg);
344 res = send(s, msg->buf, msg->buf_used, 0);
346 perror("send[RADIUS]");
348 radius_client_list_add(wpa_s, msg, msg_type, shared_secret,
349 shared_secret_len, addr);
355 static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx)
357 struct wpa_supplicant *wpa_s = (struct wpa_supplicant *) eloop_ctx;
358 RadiusType msg_type = (RadiusType) sock_ctx;
360 unsigned char buf[3000];
361 struct radius_msg *msg;
362 struct radius_rx_handler *handlers;
364 struct radius_msg_list *req, *prev_req;
366 len = recv(sock, buf, sizeof(buf), 0);
368 perror("recv[RADIUS]");
371 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
372 "Received %d bytes from RADIUS server\n", len);
373 if (len == sizeof(buf)) {
374 printf("Possibly too long UDP frame for our buffer - "
379 msg = radius_msg_parse(buf, len);
381 printf("Parsing incoming RADIUS frame failed\n");
385 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
386 "Received RADIUS message\n");
387 if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MSGDUMPS))
388 radius_msg_dump(msg);
390 if (msg_type == RADIUS_ACCT) {
391 handlers = wpa_s->radius->acct_handlers;
392 num_handlers = wpa_s->radius->num_acct_handlers;
394 handlers = wpa_s->radius->auth_handlers;
395 num_handlers = wpa_s->radius->num_auth_handlers;
399 req = wpa_s->radius->msgs;
401 /* TODO: also match by src addr:port of the packet when using
402 * alternative RADIUS servers (?) */
403 if ((req->msg_type == msg_type ||
404 (req->msg_type == RADIUS_ACCT_INTERIM &&
405 msg_type == RADIUS_ACCT)) &&
406 req->msg->hdr->identifier == msg->hdr->identifier)
414 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
415 "No matching RADIUS request found (type=%d "
416 "id=%d) - dropping packet\n",
417 msg_type, msg->hdr->identifier);
421 /* Remove ACKed RADIUS packet from retransmit list */
423 prev_req->next = req->next;
425 wpa_s->radius->msgs = req->next;
426 wpa_s->radius->num_msgs--;
428 for (i = 0; i < num_handlers; i++) {
430 res = handlers[i].handler(wpa_s, msg, req->msg,
432 req->shared_secret_len,
435 case RADIUS_RX_PROCESSED:
436 radius_msg_free(msg);
439 case RADIUS_RX_QUEUED:
440 radius_client_msg_free(req);
442 case RADIUS_RX_UNKNOWN:
443 /* continue with next handler */
448 printf("No RADIUS RX handler found (type=%d code=%d id=%d) - dropping "
449 "packet\n", msg_type, msg->hdr->code, msg->hdr->identifier);
450 radius_client_msg_free(req);
453 radius_msg_free(msg);
458 u8 radius_client_get_id(struct wpa_supplicant *wpa_s)
460 struct radius_msg_list *entry, *prev, *remove;
461 u8 id = wpa_s->radius->next_radius_identifier++;
463 /* remove entries with matching id from retransmit list to avoid
464 * using new reply from the RADIUS server with an old request */
465 entry = wpa_s->radius->msgs;
468 if (entry->msg->hdr->identifier == id) {
469 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
470 "Removing pending RADIUS message, since "
471 "its id (%d) is reused\n", id);
473 prev->next = entry->next;
475 wpa_s->radius->msgs = entry->next;
483 radius_client_msg_free(remove);
490 void radius_client_flush(struct wpa_supplicant *wpa_s)
492 struct radius_msg_list *entry, *prev;
497 eloop_cancel_timeout(radius_client_timer, wpa_s, NULL);
499 entry = wpa_s->radius->msgs;
500 wpa_s->radius->msgs = NULL;
501 wpa_s->radius->num_msgs = 0;
505 radius_client_msg_free(prev);
511 radius_change_server(struct wpa_supplicant *wpa_s, struct hostapd_radius_server *nserv,
512 struct hostapd_radius_server *oserv,
515 struct sockaddr_in serv;
517 hostapd_logger(wpa_s, NULL, HOSTAPD_MODULE_RADIUS, HOSTAPD_LEVEL_INFO,
519 auth ? "Authentication" : "Accounting",
520 inet_ntoa(nserv->addr), nserv->port);
522 if (!oserv || nserv->shared_secret_len != oserv->shared_secret_len ||
523 memcmp(nserv->shared_secret, oserv->shared_secret,
524 nserv->shared_secret_len) != 0) {
525 /* Pending RADIUS packets used different shared
526 * secret, so they would need to be modified. Could
527 * update all message authenticators and
528 * User-Passwords, etc. and retry with new server. For
529 * now, just drop all pending packets. */
530 radius_client_flush(wpa_s);
532 /* Reset retry counters for the new server */
533 struct radius_msg_list *entry;
534 entry = wpa_s->radius->msgs;
536 entry->next_try = entry->first_try +
537 RADIUS_CLIENT_FIRST_WAIT;
539 entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2;
542 if (wpa_s->radius->msgs) {
543 eloop_cancel_timeout(radius_client_timer, wpa_s, NULL);
544 eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT, 0,
545 radius_client_timer, wpa_s,
550 memset(&serv, 0, sizeof(serv));
551 serv.sin_family = AF_INET;
552 serv.sin_addr.s_addr = nserv->addr.s_addr;
553 serv.sin_port = htons(nserv->port);
555 if (connect(sock, (struct sockaddr *) &serv, sizeof(serv)) < 0) {
556 perror("connect[radius]");
564 static void radius_retry_primary_timer(void *eloop_ctx, void *timeout_ctx)
566 struct wpa_supplicant *wpa_s = eloop_ctx;
567 struct hostapd_radius_server *oserv;
569 if (wpa_s->radius->auth_serv_sock >= 0 && wpa_s->auth_servers &&
570 wpa_s->auth_server != wpa_s->auth_servers) {
571 oserv = wpa_s->auth_server;
572 wpa_s->auth_server = wpa_s->auth_servers;
573 radius_change_server(wpa_s, wpa_s->auth_server, oserv,
574 wpa_s->radius->auth_serv_sock, 1);
577 if (wpa_s->radius->acct_serv_sock >= 0 && wpa_s->acct_servers &&
578 wpa_s->acct_server != wpa_s->acct_servers) {
579 oserv = wpa_s->acct_server;
580 wpa_s->acct_server = wpa_s->acct_servers;
581 radius_change_server(wpa_s, wpa_s->acct_server, oserv,
582 wpa_s->radius->acct_serv_sock, 0);
585 if (wpa_s->radius_retry_primary_interval)
586 eloop_register_timeout(wpa_s->
587 radius_retry_primary_interval, 0,
588 radius_retry_primary_timer, wpa_s, NULL);
592 static int radius_client_init_auth(struct wpa_supplicant *wpa_s)
594 wpa_s->radius->auth_serv_sock = socket(PF_INET, SOCK_DGRAM, 0);
595 if (wpa_s->radius->auth_serv_sock < 0) {
596 perror("socket[PF_INET,SOCK_DGRAM]");
600 radius_change_server(wpa_s, wpa_s->auth_server, NULL,
601 wpa_s->radius->auth_serv_sock, 1);
603 if (eloop_register_read_sock(wpa_s->radius->auth_serv_sock,
604 radius_client_receive, wpa_s,
605 (void *) RADIUS_AUTH)) {
606 printf("Could not register read socket for authentication "
615 static int radius_client_init_acct(struct wpa_supplicant *wpa_s)
617 wpa_s->radius->acct_serv_sock = socket(PF_INET, SOCK_DGRAM, 0);
618 if (wpa_s->radius->acct_serv_sock < 0) {
619 perror("socket[PF_INET,SOCK_DGRAM]");
623 radius_change_server(wpa_s, wpa_s->acct_server, NULL,
624 wpa_s->radius->acct_serv_sock, 0);
626 if (eloop_register_read_sock(wpa_s->radius->acct_serv_sock,
627 radius_client_receive, wpa_s,
628 (void *) RADIUS_ACCT)) {
629 printf("Could not register read socket for accounting "
638 int radius_client_init(struct wpa_supplicant *wpa_s)
640 wpa_s->radius = malloc(sizeof(struct radius_client_data));
641 if (wpa_s->radius == NULL)
644 memset(wpa_s->radius, 0, sizeof(struct radius_client_data));
645 wpa_s->radius->auth_serv_sock = wpa_s->radius->acct_serv_sock = -1;
647 if (wpa_s->auth_server && radius_client_init_auth(wpa_s))
650 if (wpa_s->acct_server && radius_client_init_acct(wpa_s))
653 if (wpa_s->radius_retry_primary_interval)
654 eloop_register_timeout(wpa_s->radius_retry_primary_interval, 0,
655 radius_retry_primary_timer, wpa_s,
662 void radius_client_deinit(struct wpa_supplicant *wpa_s)
667 eloop_cancel_timeout(radius_retry_primary_timer, wpa_s, NULL);
669 radius_client_flush(wpa_s);
670 free(wpa_s->radius->auth_handlers);
671 free(wpa_s->radius->acct_handlers);
673 wpa_s->radius = NULL;