Deleted Added
full compact
radius_client.c (209158) radius_client.c (214734)
1/*
1/*
2 * hostapd / RADIUS client
3 * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
2 * RADIUS client
3 * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
4 *
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.
8 *
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
11 *
12 * See README and COPYING for more details.
13 */
14
15#include "includes.h"
16
17#include "common.h"
18#include "radius.h"
19#include "radius_client.h"
20#include "eloop.h"
21
22/* Defaults for RADIUS retransmit values (exponential backoff) */
4 *
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.
8 *
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
11 *
12 * See README and COPYING for more details.
13 */
14
15#include "includes.h"
16
17#include "common.h"
18#include "radius.h"
19#include "radius_client.h"
20#include "eloop.h"
21
22/* Defaults for RADIUS retransmit values (exponential backoff) */
23#define RADIUS_CLIENT_FIRST_WAIT 3 /* seconds */
24#define RADIUS_CLIENT_MAX_WAIT 120 /* seconds */
25#define RADIUS_CLIENT_MAX_RETRIES 10 /* maximum number of retransmit attempts
26 * before entry is removed from retransmit
27 * list */
28#define RADIUS_CLIENT_MAX_ENTRIES 30 /* maximum number of entries in retransmit
29 * list (oldest will be removed, if this
30 * limit is exceeded) */
31#define RADIUS_CLIENT_NUM_FAILOVER 4 /* try to change RADIUS server after this
32 * many failed retry attempts */
33
23
24/**
25 * RADIUS_CLIENT_FIRST_WAIT - RADIUS client timeout for first retry in seconds
26 */
27#define RADIUS_CLIENT_FIRST_WAIT 3
34
28
29/**
30 * RADIUS_CLIENT_MAX_WAIT - RADIUS client maximum retry timeout in seconds
31 */
32#define RADIUS_CLIENT_MAX_WAIT 120
33
34/**
35 * RADIUS_CLIENT_MAX_RETRIES - RADIUS client maximum retries
36 *
37 * Maximum number of retransmit attempts before the entry is removed from
38 * retransmit list.
39 */
40#define RADIUS_CLIENT_MAX_RETRIES 10
41
42/**
43 * RADIUS_CLIENT_MAX_ENTRIES - RADIUS client maximum pending messages
44 *
45 * Maximum number of entries in retransmit list (oldest entries will be
46 * removed, if this limit is exceeded).
47 */
48#define RADIUS_CLIENT_MAX_ENTRIES 30
49
50/**
51 * RADIUS_CLIENT_NUM_FAILOVER - RADIUS client failover point
52 *
53 * The number of failed retry attempts after which the RADIUS server will be
54 * changed (if one of more backup servers are configured).
55 */
56#define RADIUS_CLIENT_NUM_FAILOVER 4
57
58
59/**
60 * struct radius_rx_handler - RADIUS client RX handler
61 *
62 * This data structure is used internally inside the RADIUS client module to
63 * store registered RX handlers. These handlers are registered by calls to
64 * radius_client_register() and unregistered when the RADIUS client is
65 * deinitialized with a call to radius_client_deinit().
66 */
35struct radius_rx_handler {
67struct radius_rx_handler {
68 /**
69 * handler - Received RADIUS message handler
70 */
36 RadiusRxResult (*handler)(struct radius_msg *msg,
37 struct radius_msg *req,
38 const u8 *shared_secret,
39 size_t shared_secret_len,
40 void *data);
71 RadiusRxResult (*handler)(struct radius_msg *msg,
72 struct radius_msg *req,
73 const u8 *shared_secret,
74 size_t shared_secret_len,
75 void *data);
76
77 /**
78 * data - Context data for the handler
79 */
41 void *data;
42};
43
44
80 void *data;
81};
82
83
45/* RADIUS message retransmit list */
84/**
85 * struct radius_msg_list - RADIUS client message retransmit list
86 *
87 * This data structure is used internally inside the RADIUS client module to
88 * store pending RADIUS requests that may still need to be retransmitted.
89 */
46struct radius_msg_list {
90struct radius_msg_list {
47 u8 addr[ETH_ALEN]; /* STA/client address; used to find RADIUS messages
48 * for the same STA. */
91 /**
92 * addr - STA/client address
93 *
94 * This is used to find RADIUS messages for the same STA.
95 */
96 u8 addr[ETH_ALEN];
97
98 /**
99 * msg - RADIUS message
100 */
49 struct radius_msg *msg;
101 struct radius_msg *msg;
102
103 /**
104 * msg_type - Message type
105 */
50 RadiusType msg_type;
106 RadiusType msg_type;
107
108 /**
109 * first_try - Time of the first transmission attempt
110 */
51 os_time_t first_try;
111 os_time_t first_try;
112
113 /**
114 * next_try - Time for the next transmission attempt
115 */
52 os_time_t next_try;
116 os_time_t next_try;
117
118 /**
119 * attempts - Number of transmission attempts
120 */
53 int attempts;
121 int attempts;
122
123 /**
124 * next_wait - Next retransmission wait time in seconds
125 */
54 int next_wait;
126 int next_wait;
127
128 /**
129 * last_attempt - Time of the last transmission attempt
130 */
55 struct os_time last_attempt;
56
131 struct os_time last_attempt;
132
57 u8 *shared_secret;
133 /**
134 * shared_secret - Shared secret with the target RADIUS server
135 */
136 const u8 *shared_secret;
137
138 /**
139 * shared_secret_len - shared_secret length in octets
140 */
58 size_t shared_secret_len;
59
60 /* TODO: server config with failover to backup server(s) */
61
141 size_t shared_secret_len;
142
143 /* TODO: server config with failover to backup server(s) */
144
145 /**
146 * next - Next message in the list
147 */
62 struct radius_msg_list *next;
63};
64
65
148 struct radius_msg_list *next;
149};
150
151
152/**
153 * struct radius_client_data - Internal RADIUS client data
154 *
155 * This data structure is used internally inside the RADIUS client module.
156 * External users allocate this by calling radius_client_init() and free it by
157 * calling radius_client_deinit(). The pointer to this opaque data is used in
158 * calls to other functions as an identifier for the RADIUS client instance.
159 */
66struct radius_client_data {
160struct radius_client_data {
161 /**
162 * ctx - Context pointer for hostapd_logger() callbacks
163 */
67 void *ctx;
164 void *ctx;
165
166 /**
167 * conf - RADIUS client configuration (list of RADIUS servers to use)
168 */
68 struct hostapd_radius_servers *conf;
69
169 struct hostapd_radius_servers *conf;
170
70 int auth_serv_sock; /* socket for authentication RADIUS messages */
71 int acct_serv_sock; /* socket for accounting RADIUS messages */
171 /**
172 * auth_serv_sock - IPv4 socket for RADIUS authentication messages
173 */
174 int auth_serv_sock;
175
176 /**
177 * acct_serv_sock - IPv4 socket for RADIUS accounting messages
178 */
179 int acct_serv_sock;
180
181 /**
182 * auth_serv_sock6 - IPv6 socket for RADIUS authentication messages
183 */
72 int auth_serv_sock6;
184 int auth_serv_sock6;
185
186 /**
187 * acct_serv_sock6 - IPv6 socket for RADIUS accounting messages
188 */
73 int acct_serv_sock6;
189 int acct_serv_sock6;
74 int auth_sock; /* currently used socket */
75 int acct_sock; /* currently used socket */
76
190
191 /**
192 * auth_sock - Currently used socket for RADIUS authentication server
193 */
194 int auth_sock;
195
196 /**
197 * acct_sock - Currently used socket for RADIUS accounting server
198 */
199 int acct_sock;
200
201 /**
202 * auth_handlers - Authentication message handlers
203 */
77 struct radius_rx_handler *auth_handlers;
204 struct radius_rx_handler *auth_handlers;
205
206 /**
207 * num_auth_handlers - Number of handlers in auth_handlers
208 */
78 size_t num_auth_handlers;
209 size_t num_auth_handlers;
210
211 /**
212 * acct_handlers - Accounting message handlers
213 */
79 struct radius_rx_handler *acct_handlers;
214 struct radius_rx_handler *acct_handlers;
215
216 /**
217 * num_acct_handlers - Number of handlers in acct_handlers
218 */
80 size_t num_acct_handlers;
81
219 size_t num_acct_handlers;
220
221 /**
222 * msgs - Pending outgoing RADIUS messages
223 */
82 struct radius_msg_list *msgs;
224 struct radius_msg_list *msgs;
225
226 /**
227 * num_msgs - Number of pending messages in the msgs list
228 */
83 size_t num_msgs;
84
229 size_t num_msgs;
230
231 /**
232 * next_radius_identifier - Next RADIUS message identifier to use
233 */
85 u8 next_radius_identifier;
86};
87
88
89static int
90radius_change_server(struct radius_client_data *radius,
91 struct hostapd_radius_server *nserv,
92 struct hostapd_radius_server *oserv,
93 int sock, int sock6, int auth);
94static int radius_client_init_acct(struct radius_client_data *radius);
95static int radius_client_init_auth(struct radius_client_data *radius);
96
97
98static void radius_client_msg_free(struct radius_msg_list *req)
99{
100 radius_msg_free(req->msg);
234 u8 next_radius_identifier;
235};
236
237
238static int
239radius_change_server(struct radius_client_data *radius,
240 struct hostapd_radius_server *nserv,
241 struct hostapd_radius_server *oserv,
242 int sock, int sock6, int auth);
243static int radius_client_init_acct(struct radius_client_data *radius);
244static int radius_client_init_auth(struct radius_client_data *radius);
245
246
247static void radius_client_msg_free(struct radius_msg_list *req)
248{
249 radius_msg_free(req->msg);
101 os_free(req->msg);
102 os_free(req);
103}
104
105
250 os_free(req);
251}
252
253
254/**
255 * radius_client_register - Register a RADIUS client RX handler
256 * @radius: RADIUS client context from radius_client_init()
257 * @msg_type: RADIUS client type (RADIUS_AUTH or RADIUS_ACCT)
258 * @handler: Handler for received RADIUS messages
259 * @data: Context pointer for handler callbacks
260 * Returns: 0 on success, -1 on failure
261 *
262 * This function is used to register a handler for processing received RADIUS
263 * authentication and accounting messages. The handler() callback function will
264 * be called whenever a RADIUS message is received from the active server.
265 *
266 * There can be multiple registered RADIUS message handlers. The handlers will
267 * be called in order until one of them indicates that it has processed or
268 * queued the message.
269 */
106int radius_client_register(struct radius_client_data *radius,
107 RadiusType msg_type,
108 RadiusRxResult (*handler)(struct radius_msg *msg,
109 struct radius_msg *req,
110 const u8 *shared_secret,
111 size_t shared_secret_len,
112 void *data),
113 void *data)

--- 47 unchanged lines hidden (view full) ---

161
162
163static int radius_client_retransmit(struct radius_client_data *radius,
164 struct radius_msg_list *entry,
165 os_time_t now)
166{
167 struct hostapd_radius_servers *conf = radius->conf;
168 int s;
270int radius_client_register(struct radius_client_data *radius,
271 RadiusType msg_type,
272 RadiusRxResult (*handler)(struct radius_msg *msg,
273 struct radius_msg *req,
274 const u8 *shared_secret,
275 size_t shared_secret_len,
276 void *data),
277 void *data)

--- 47 unchanged lines hidden (view full) ---

325
326
327static int radius_client_retransmit(struct radius_client_data *radius,
328 struct radius_msg_list *entry,
329 os_time_t now)
330{
331 struct hostapd_radius_servers *conf = radius->conf;
332 int s;
333 struct wpabuf *buf;
169
170 if (entry->msg_type == RADIUS_ACCT ||
171 entry->msg_type == RADIUS_ACCT_INTERIM) {
172 s = radius->acct_sock;
173 if (entry->attempts == 0)
174 conf->acct_server->requests++;
175 else {
176 conf->acct_server->timeouts++;

--- 8 unchanged lines hidden (view full) ---

185 conf->auth_server->retransmissions++;
186 }
187 }
188
189 /* retransmit; remove entry if too many attempts */
190 entry->attempts++;
191 hostapd_logger(radius->ctx, entry->addr, HOSTAPD_MODULE_RADIUS,
192 HOSTAPD_LEVEL_DEBUG, "Resending RADIUS message (id=%d)",
334
335 if (entry->msg_type == RADIUS_ACCT ||
336 entry->msg_type == RADIUS_ACCT_INTERIM) {
337 s = radius->acct_sock;
338 if (entry->attempts == 0)
339 conf->acct_server->requests++;
340 else {
341 conf->acct_server->timeouts++;

--- 8 unchanged lines hidden (view full) ---

350 conf->auth_server->retransmissions++;
351 }
352 }
353
354 /* retransmit; remove entry if too many attempts */
355 entry->attempts++;
356 hostapd_logger(radius->ctx, entry->addr, HOSTAPD_MODULE_RADIUS,
357 HOSTAPD_LEVEL_DEBUG, "Resending RADIUS message (id=%d)",
193 entry->msg->hdr->identifier);
358 radius_msg_get_hdr(entry->msg)->identifier);
194
195 os_get_time(&entry->last_attempt);
359
360 os_get_time(&entry->last_attempt);
196 if (send(s, entry->msg->buf, entry->msg->buf_used, 0) < 0)
361 buf = radius_msg_get_buf(entry->msg);
362 if (send(s, wpabuf_head(buf), wpabuf_len(buf), 0) < 0)
197 radius_client_handle_send_error(radius, s, entry->msg_type);
198
199 entry->next_try = now + entry->next_wait;
200 entry->next_wait *= 2;
201 if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT)
202 entry->next_wait = RADIUS_CLIENT_MAX_WAIT;
203 if (entry->attempts >= RADIUS_CLIENT_MAX_RETRIES) {
204 printf("Removing un-ACKed RADIUS message due to too many "

--- 141 unchanged lines hidden (view full) ---

346 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
347 HOSTAPD_LEVEL_DEBUG, "Next RADIUS client retransmit in"
348 " %ld seconds\n", (long int) (first - now.sec));
349}
350
351
352static void radius_client_list_add(struct radius_client_data *radius,
353 struct radius_msg *msg,
363 radius_client_handle_send_error(radius, s, entry->msg_type);
364
365 entry->next_try = now + entry->next_wait;
366 entry->next_wait *= 2;
367 if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT)
368 entry->next_wait = RADIUS_CLIENT_MAX_WAIT;
369 if (entry->attempts >= RADIUS_CLIENT_MAX_RETRIES) {
370 printf("Removing un-ACKed RADIUS message due to too many "

--- 141 unchanged lines hidden (view full) ---

512 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
513 HOSTAPD_LEVEL_DEBUG, "Next RADIUS client retransmit in"
514 " %ld seconds\n", (long int) (first - now.sec));
515}
516
517
518static void radius_client_list_add(struct radius_client_data *radius,
519 struct radius_msg *msg,
354 RadiusType msg_type, u8 *shared_secret,
520 RadiusType msg_type,
521 const u8 *shared_secret,
355 size_t shared_secret_len, const u8 *addr)
356{
357 struct radius_msg_list *entry, *prev;
358
359 if (eloop_terminated()) {
360 /* No point in adding entries to retransmit queue since event
361 * loop has already been terminated. */
362 radius_msg_free(msg);
522 size_t shared_secret_len, const u8 *addr)
523{
524 struct radius_msg_list *entry, *prev;
525
526 if (eloop_terminated()) {
527 /* No point in adding entries to retransmit queue since event
528 * loop has already been terminated. */
529 radius_msg_free(msg);
363 os_free(msg);
364 return;
365 }
366
367 entry = os_zalloc(sizeof(*entry));
368 if (entry == NULL) {
369 printf("Failed to add RADIUS packet into retransmit list\n");
370 radius_msg_free(msg);
530 return;
531 }
532
533 entry = os_zalloc(sizeof(*entry));
534 if (entry == NULL) {
535 printf("Failed to add RADIUS packet into retransmit list\n");
536 radius_msg_free(msg);
371 os_free(msg);
372 return;
373 }
374
375 if (addr)
376 os_memcpy(entry->addr, addr, ETH_ALEN);
377 entry->msg = msg;
378 entry->msg_type = msg_type;
379 entry->shared_secret = shared_secret;

--- 52 unchanged lines hidden (view full) ---

432 continue;
433 }
434 prev = entry;
435 entry = entry->next;
436 }
437}
438
439
537 return;
538 }
539
540 if (addr)
541 os_memcpy(entry->addr, addr, ETH_ALEN);
542 entry->msg = msg;
543 entry->msg_type = msg_type;
544 entry->shared_secret = shared_secret;

--- 52 unchanged lines hidden (view full) ---

597 continue;
598 }
599 prev = entry;
600 entry = entry->next;
601 }
602}
603
604
605/**
606 * radius_client_send - Send a RADIUS request
607 * @radius: RADIUS client context from radius_client_init()
608 * @msg: RADIUS message to be sent
609 * @msg_type: Message type (RADIUS_AUTH, RADIUS_ACCT, RADIUS_ACCT_INTERIM)
610 * @addr: MAC address of the device related to this message or %NULL
611 * Returns: 0 on success, -1 on failure
612 *
613 * This function is used to transmit a RADIUS authentication (RADIUS_AUTH) or
614 * accounting request (RADIUS_ACCT or RADIUS_ACCT_INTERIM). The only difference
615 * between accounting and interim accounting messages is that the interim
616 * message will override any pending interim accounting updates while a new
617 * accounting message does not remove any pending messages.
618 *
619 * The message is added on the retransmission queue and will be retransmitted
620 * automatically until a response is received or maximum number of retries
621 * (RADIUS_CLIENT_MAX_RETRIES) is reached.
622 *
623 * The related device MAC address can be used to identify pending messages that
624 * can be removed with radius_client_flush_auth() or with interim accounting
625 * updates.
626 */
440int radius_client_send(struct radius_client_data *radius,
441 struct radius_msg *msg, RadiusType msg_type,
442 const u8 *addr)
443{
444 struct hostapd_radius_servers *conf = radius->conf;
627int radius_client_send(struct radius_client_data *radius,
628 struct radius_msg *msg, RadiusType msg_type,
629 const u8 *addr)
630{
631 struct hostapd_radius_servers *conf = radius->conf;
445 u8 *shared_secret;
632 const u8 *shared_secret;
446 size_t shared_secret_len;
447 char *name;
448 int s, res;
633 size_t shared_secret_len;
634 char *name;
635 int s, res;
636 struct wpabuf *buf;
449
450 if (msg_type == RADIUS_ACCT_INTERIM) {
451 /* Remove any pending interim acct update for the same STA. */
452 radius_client_list_del(radius, msg_type, addr);
453 }
454
455 if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) {
456 if (conf->acct_server == NULL) {

--- 26 unchanged lines hidden (view full) ---

483 }
484
485 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
486 HOSTAPD_LEVEL_DEBUG, "Sending RADIUS message to %s "
487 "server", name);
488 if (conf->msg_dumps)
489 radius_msg_dump(msg);
490
637
638 if (msg_type == RADIUS_ACCT_INTERIM) {
639 /* Remove any pending interim acct update for the same STA. */
640 radius_client_list_del(radius, msg_type, addr);
641 }
642
643 if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) {
644 if (conf->acct_server == NULL) {

--- 26 unchanged lines hidden (view full) ---

671 }
672
673 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
674 HOSTAPD_LEVEL_DEBUG, "Sending RADIUS message to %s "
675 "server", name);
676 if (conf->msg_dumps)
677 radius_msg_dump(msg);
678
491 res = send(s, msg->buf, msg->buf_used, 0);
679 buf = radius_msg_get_buf(msg);
680 res = send(s, wpabuf_head(buf), wpabuf_len(buf), 0);
492 if (res < 0)
493 radius_client_handle_send_error(radius, s, msg_type);
494
495 radius_client_list_add(radius, msg, msg_type, shared_secret,
496 shared_secret_len, addr);
497
498 return res;
499}
500
501
502static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx)
503{
504 struct radius_client_data *radius = eloop_ctx;
505 struct hostapd_radius_servers *conf = radius->conf;
506 RadiusType msg_type = (RadiusType) sock_ctx;
507 int len, roundtrip;
508 unsigned char buf[3000];
509 struct radius_msg *msg;
681 if (res < 0)
682 radius_client_handle_send_error(radius, s, msg_type);
683
684 radius_client_list_add(radius, msg, msg_type, shared_secret,
685 shared_secret_len, addr);
686
687 return res;
688}
689
690
691static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx)
692{
693 struct radius_client_data *radius = eloop_ctx;
694 struct hostapd_radius_servers *conf = radius->conf;
695 RadiusType msg_type = (RadiusType) sock_ctx;
696 int len, roundtrip;
697 unsigned char buf[3000];
698 struct radius_msg *msg;
699 struct radius_hdr *hdr;
510 struct radius_rx_handler *handlers;
511 size_t num_handlers, i;
512 struct radius_msg_list *req, *prev_req;
513 struct os_time now;
514 struct hostapd_radius_server *rconf;
515 int invalid_authenticator = 0;
516
517 if (msg_type == RADIUS_ACCT) {

--- 21 unchanged lines hidden (view full) ---

539 }
540
541 msg = radius_msg_parse(buf, len);
542 if (msg == NULL) {
543 printf("Parsing incoming RADIUS frame failed\n");
544 rconf->malformed_responses++;
545 return;
546 }
700 struct radius_rx_handler *handlers;
701 size_t num_handlers, i;
702 struct radius_msg_list *req, *prev_req;
703 struct os_time now;
704 struct hostapd_radius_server *rconf;
705 int invalid_authenticator = 0;
706
707 if (msg_type == RADIUS_ACCT) {

--- 21 unchanged lines hidden (view full) ---

729 }
730
731 msg = radius_msg_parse(buf, len);
732 if (msg == NULL) {
733 printf("Parsing incoming RADIUS frame failed\n");
734 rconf->malformed_responses++;
735 return;
736 }
737 hdr = radius_msg_get_hdr(msg);
547
548 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
549 HOSTAPD_LEVEL_DEBUG, "Received RADIUS message");
550 if (conf->msg_dumps)
551 radius_msg_dump(msg);
552
738
739 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
740 HOSTAPD_LEVEL_DEBUG, "Received RADIUS message");
741 if (conf->msg_dumps)
742 radius_msg_dump(msg);
743
553 switch (msg->hdr->code) {
744 switch (hdr->code) {
554 case RADIUS_CODE_ACCESS_ACCEPT:
555 rconf->access_accepts++;
556 break;
557 case RADIUS_CODE_ACCESS_REJECT:
558 rconf->access_rejects++;
559 break;
560 case RADIUS_CODE_ACCESS_CHALLENGE:
561 rconf->access_challenges++;

--- 6 unchanged lines hidden (view full) ---

568 prev_req = NULL;
569 req = radius->msgs;
570 while (req) {
571 /* TODO: also match by src addr:port of the packet when using
572 * alternative RADIUS servers (?) */
573 if ((req->msg_type == msg_type ||
574 (req->msg_type == RADIUS_ACCT_INTERIM &&
575 msg_type == RADIUS_ACCT)) &&
745 case RADIUS_CODE_ACCESS_ACCEPT:
746 rconf->access_accepts++;
747 break;
748 case RADIUS_CODE_ACCESS_REJECT:
749 rconf->access_rejects++;
750 break;
751 case RADIUS_CODE_ACCESS_CHALLENGE:
752 rconf->access_challenges++;

--- 6 unchanged lines hidden (view full) ---

759 prev_req = NULL;
760 req = radius->msgs;
761 while (req) {
762 /* TODO: also match by src addr:port of the packet when using
763 * alternative RADIUS servers (?) */
764 if ((req->msg_type == msg_type ||
765 (req->msg_type == RADIUS_ACCT_INTERIM &&
766 msg_type == RADIUS_ACCT)) &&
576 req->msg->hdr->identifier == msg->hdr->identifier)
767 radius_msg_get_hdr(req->msg)->identifier ==
768 hdr->identifier)
577 break;
578
579 prev_req = req;
580 req = req->next;
581 }
582
583 if (req == NULL) {
584 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
585 HOSTAPD_LEVEL_DEBUG,
586 "No matching RADIUS request found (type=%d "
587 "id=%d) - dropping packet",
769 break;
770
771 prev_req = req;
772 req = req->next;
773 }
774
775 if (req == NULL) {
776 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
777 HOSTAPD_LEVEL_DEBUG,
778 "No matching RADIUS request found (type=%d "
779 "id=%d) - dropping packet",
588 msg_type, msg->hdr->identifier);
780 msg_type, hdr->identifier);
589 goto fail;
590 }
591
592 os_get_time(&now);
593 roundtrip = (now.sec - req->last_attempt.sec) * 100 +
594 (now.usec - req->last_attempt.usec) / 10000;
595 hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS,
596 HOSTAPD_LEVEL_DEBUG,

--- 12 unchanged lines hidden (view full) ---

609 for (i = 0; i < num_handlers; i++) {
610 RadiusRxResult res;
611 res = handlers[i].handler(msg, req->msg, req->shared_secret,
612 req->shared_secret_len,
613 handlers[i].data);
614 switch (res) {
615 case RADIUS_RX_PROCESSED:
616 radius_msg_free(msg);
781 goto fail;
782 }
783
784 os_get_time(&now);
785 roundtrip = (now.sec - req->last_attempt.sec) * 100 +
786 (now.usec - req->last_attempt.usec) / 10000;
787 hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS,
788 HOSTAPD_LEVEL_DEBUG,

--- 12 unchanged lines hidden (view full) ---

801 for (i = 0; i < num_handlers; i++) {
802 RadiusRxResult res;
803 res = handlers[i].handler(msg, req->msg, req->shared_secret,
804 req->shared_secret_len,
805 handlers[i].data);
806 switch (res) {
807 case RADIUS_RX_PROCESSED:
808 radius_msg_free(msg);
617 os_free(msg);
618 /* continue */
619 case RADIUS_RX_QUEUED:
620 radius_client_msg_free(req);
621 return;
622 case RADIUS_RX_INVALID_AUTHENTICATOR:
623 invalid_authenticator++;
624 /* continue */
625 case RADIUS_RX_UNKNOWN:

--- 4 unchanged lines hidden (view full) ---

630
631 if (invalid_authenticator)
632 rconf->bad_authenticators++;
633 else
634 rconf->unknown_types++;
635 hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS,
636 HOSTAPD_LEVEL_DEBUG, "No RADIUS RX handler found "
637 "(type=%d code=%d id=%d)%s - dropping packet",
809 /* continue */
810 case RADIUS_RX_QUEUED:
811 radius_client_msg_free(req);
812 return;
813 case RADIUS_RX_INVALID_AUTHENTICATOR:
814 invalid_authenticator++;
815 /* continue */
816 case RADIUS_RX_UNKNOWN:

--- 4 unchanged lines hidden (view full) ---

821
822 if (invalid_authenticator)
823 rconf->bad_authenticators++;
824 else
825 rconf->unknown_types++;
826 hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS,
827 HOSTAPD_LEVEL_DEBUG, "No RADIUS RX handler found "
828 "(type=%d code=%d id=%d)%s - dropping packet",
638 msg_type, msg->hdr->code, msg->hdr->identifier,
829 msg_type, hdr->code, hdr->identifier,
639 invalid_authenticator ? " [INVALID AUTHENTICATOR]" :
640 "");
641 radius_client_msg_free(req);
642
643 fail:
644 radius_msg_free(msg);
830 invalid_authenticator ? " [INVALID AUTHENTICATOR]" :
831 "");
832 radius_client_msg_free(req);
833
834 fail:
835 radius_msg_free(msg);
645 os_free(msg);
646}
647
648
836}
837
838
839/**
840 * radius_client_get_id - Get an identifier for a new RADIUS message
841 * @radius: RADIUS client context from radius_client_init()
842 * Returns: Allocated identifier
843 *
844 * This function is used to fetch a unique (among pending requests) identifier
845 * for a new RADIUS message.
846 */
649u8 radius_client_get_id(struct radius_client_data *radius)
650{
651 struct radius_msg_list *entry, *prev, *_remove;
652 u8 id = radius->next_radius_identifier++;
653
654 /* remove entries with matching id from retransmit list to avoid
655 * using new reply from the RADIUS server with an old request */
656 entry = radius->msgs;
657 prev = NULL;
658 while (entry) {
847u8 radius_client_get_id(struct radius_client_data *radius)
848{
849 struct radius_msg_list *entry, *prev, *_remove;
850 u8 id = radius->next_radius_identifier++;
851
852 /* remove entries with matching id from retransmit list to avoid
853 * using new reply from the RADIUS server with an old request */
854 entry = radius->msgs;
855 prev = NULL;
856 while (entry) {
659 if (entry->msg->hdr->identifier == id) {
857 if (radius_msg_get_hdr(entry->msg)->identifier == id) {
660 hostapd_logger(radius->ctx, entry->addr,
661 HOSTAPD_MODULE_RADIUS,
662 HOSTAPD_LEVEL_DEBUG,
663 "Removing pending RADIUS message, "
664 "since its id (%d) is reused", id);
665 if (prev)
666 prev->next = entry->next;
667 else

--- 8 unchanged lines hidden (view full) ---

676 if (_remove)
677 radius_client_msg_free(_remove);
678 }
679
680 return id;
681}
682
683
858 hostapd_logger(radius->ctx, entry->addr,
859 HOSTAPD_MODULE_RADIUS,
860 HOSTAPD_LEVEL_DEBUG,
861 "Removing pending RADIUS message, "
862 "since its id (%d) is reused", id);
863 if (prev)
864 prev->next = entry->next;
865 else

--- 8 unchanged lines hidden (view full) ---

874 if (_remove)
875 radius_client_msg_free(_remove);
876 }
877
878 return id;
879}
880
881
882/**
883 * radius_client_flush - Flush all pending RADIUS client messages
884 * @radius: RADIUS client context from radius_client_init()
885 * @only_auth: Whether only authentication messages are removed
886 */
684void radius_client_flush(struct radius_client_data *radius, int only_auth)
685{
686 struct radius_msg_list *entry, *prev, *tmp;
687
688 if (!radius)
689 return;
690
691 prev = NULL;

--- 17 unchanged lines hidden (view full) ---

709 }
710
711 if (radius->msgs == NULL)
712 eloop_cancel_timeout(radius_client_timer, radius, NULL);
713}
714
715
716static void radius_client_update_acct_msgs(struct radius_client_data *radius,
887void radius_client_flush(struct radius_client_data *radius, int only_auth)
888{
889 struct radius_msg_list *entry, *prev, *tmp;
890
891 if (!radius)
892 return;
893
894 prev = NULL;

--- 17 unchanged lines hidden (view full) ---

912 }
913
914 if (radius->msgs == NULL)
915 eloop_cancel_timeout(radius_client_timer, radius, NULL);
916}
917
918
919static void radius_client_update_acct_msgs(struct radius_client_data *radius,
717 u8 *shared_secret,
920 const u8 *shared_secret,
718 size_t shared_secret_len)
719{
720 struct radius_msg_list *entry;
721
722 if (!radius)
723 return;
724
725 for (entry = radius->msgs; entry; entry = entry->next) {

--- 306 unchanged lines hidden (view full) ---

1032 return -1;
1033 }
1034#endif /* CONFIG_IPV6 */
1035
1036 return 0;
1037}
1038
1039
921 size_t shared_secret_len)
922{
923 struct radius_msg_list *entry;
924
925 if (!radius)
926 return;
927
928 for (entry = radius->msgs; entry; entry = entry->next) {

--- 306 unchanged lines hidden (view full) ---

1235 return -1;
1236 }
1237#endif /* CONFIG_IPV6 */
1238
1239 return 0;
1240}
1241
1242
1243/**
1244 * radius_client_init - Initialize RADIUS client
1245 * @ctx: Callback context to be used in hostapd_logger() calls
1246 * @conf: RADIUS client configuration (RADIUS servers)
1247 * Returns: Pointer to private RADIUS client context or %NULL on failure
1248 *
1249 * The caller is responsible for keeping the configuration data available for
1250 * the lifetime of the RADIUS client, i.e., until radius_client_deinit() is
1251 * called for the returned context pointer.
1252 */
1040struct radius_client_data *
1041radius_client_init(void *ctx, struct hostapd_radius_servers *conf)
1042{
1043 struct radius_client_data *radius;
1044
1045 radius = os_zalloc(sizeof(struct radius_client_data));
1046 if (radius == NULL)
1047 return NULL;

--- 18 unchanged lines hidden (view full) ---

1066 eloop_register_timeout(conf->retry_primary_interval, 0,
1067 radius_retry_primary_timer, radius,
1068 NULL);
1069
1070 return radius;
1071}
1072
1073
1253struct radius_client_data *
1254radius_client_init(void *ctx, struct hostapd_radius_servers *conf)
1255{
1256 struct radius_client_data *radius;
1257
1258 radius = os_zalloc(sizeof(struct radius_client_data));
1259 if (radius == NULL)
1260 return NULL;

--- 18 unchanged lines hidden (view full) ---

1279 eloop_register_timeout(conf->retry_primary_interval, 0,
1280 radius_retry_primary_timer, radius,
1281 NULL);
1282
1283 return radius;
1284}
1285
1286
1287/**
1288 * radius_client_deinit - Deinitialize RADIUS client
1289 * @radius: RADIUS client context from radius_client_init()
1290 */
1074void radius_client_deinit(struct radius_client_data *radius)
1075{
1076 if (!radius)
1077 return;
1078
1079 if (radius->auth_serv_sock >= 0)
1080 eloop_unregister_read_sock(radius->auth_serv_sock);
1081 if (radius->acct_serv_sock >= 0)

--- 9 unchanged lines hidden (view full) ---

1091
1092 radius_client_flush(radius, 0);
1093 os_free(radius->auth_handlers);
1094 os_free(radius->acct_handlers);
1095 os_free(radius);
1096}
1097
1098
1291void radius_client_deinit(struct radius_client_data *radius)
1292{
1293 if (!radius)
1294 return;
1295
1296 if (radius->auth_serv_sock >= 0)
1297 eloop_unregister_read_sock(radius->auth_serv_sock);
1298 if (radius->acct_serv_sock >= 0)

--- 9 unchanged lines hidden (view full) ---

1308
1309 radius_client_flush(radius, 0);
1310 os_free(radius->auth_handlers);
1311 os_free(radius->acct_handlers);
1312 os_free(radius);
1313}
1314
1315
1099void radius_client_flush_auth(struct radius_client_data *radius, u8 *addr)
1316/**
1317 * radius_client_flush_auth - Flush pending RADIUS messages for an address
1318 * @radius: RADIUS client context from radius_client_init()
1319 * @addr: MAC address of the related device
1320 *
1321 * This function can be used to remove pending RADIUS authentication messages
1322 * that are related to a specific device. The addr parameter is matched with
1323 * the one used in radius_client_send() call that was used to transmit the
1324 * authentication request.
1325 */
1326void radius_client_flush_auth(struct radius_client_data *radius,
1327 const u8 *addr)
1100{
1101 struct radius_msg_list *entry, *prev, *tmp;
1102
1103 prev = NULL;
1104 entry = radius->msgs;
1105 while (entry) {
1106 if (entry->msg_type == RADIUS_AUTH &&
1107 os_memcmp(entry->addr, addr, ETH_ALEN) == 0) {

--- 111 unchanged lines hidden (view full) ---

1219 serv->bad_authenticators,
1220 pending,
1221 serv->timeouts,
1222 serv->unknown_types,
1223 serv->packets_dropped);
1224}
1225
1226
1328{
1329 struct radius_msg_list *entry, *prev, *tmp;
1330
1331 prev = NULL;
1332 entry = radius->msgs;
1333 while (entry) {
1334 if (entry->msg_type == RADIUS_AUTH &&
1335 os_memcmp(entry->addr, addr, ETH_ALEN) == 0) {

--- 111 unchanged lines hidden (view full) ---

1447 serv->bad_authenticators,
1448 pending,
1449 serv->timeouts,
1450 serv->unknown_types,
1451 serv->packets_dropped);
1452}
1453
1454
1455/**
1456 * radius_client_get_mib - Get RADIUS client MIB information
1457 * @radius: RADIUS client context from radius_client_init()
1458 * @buf: Buffer for returning MIB data in text format
1459 * @buflen: Maximum buf length in octets
1460 * Returns: Number of octets written into the buffer
1461 */
1227int radius_client_get_mib(struct radius_client_data *radius, char *buf,
1228 size_t buflen)
1229{
1230 struct hostapd_radius_servers *conf = radius->conf;
1231 int i;
1232 struct hostapd_radius_server *serv;
1233 int count = 0;
1234

--- 14 unchanged lines hidden (view full) ---

1249 buf + count, buflen - count, serv,
1250 serv == conf->acct_server ?
1251 radius : NULL);
1252 }
1253 }
1254
1255 return count;
1256}
1462int radius_client_get_mib(struct radius_client_data *radius, char *buf,
1463 size_t buflen)
1464{
1465 struct hostapd_radius_servers *conf = radius->conf;
1466 int i;
1467 struct hostapd_radius_server *serv;
1468 int count = 0;
1469

--- 14 unchanged lines hidden (view full) ---

1484 buf + count, buflen - count, serv,
1485 serv == conf->acct_server ?
1486 radius : NULL);
1487 }
1488 }
1489
1490 return count;
1491}
1257
1258
1259static int radius_servers_diff(struct hostapd_radius_server *nserv,
1260 struct hostapd_radius_server *oserv,
1261 int num)
1262{
1263 int i;
1264
1265 for (i = 0; i < num; i++) {
1266 if (hostapd_ip_diff(&nserv[i].addr, &oserv[i].addr) ||
1267 nserv[i].port != oserv[i].port ||
1268 nserv[i].shared_secret_len != oserv[i].shared_secret_len ||
1269 os_memcmp(nserv[i].shared_secret, oserv[i].shared_secret,
1270 nserv[i].shared_secret_len) != 0)
1271 return 1;
1272 }
1273
1274 return 0;
1275}
1276
1277
1278struct radius_client_data *
1279radius_client_reconfig(struct radius_client_data *old, void *ctx,
1280 struct hostapd_radius_servers *oldconf,
1281 struct hostapd_radius_servers *newconf)
1282{
1283 radius_client_flush(old, 0);
1284
1285 if (newconf->retry_primary_interval !=
1286 oldconf->retry_primary_interval ||
1287 newconf->num_auth_servers != oldconf->num_auth_servers ||
1288 newconf->num_acct_servers != oldconf->num_acct_servers ||
1289 radius_servers_diff(newconf->auth_servers, oldconf->auth_servers,
1290 newconf->num_auth_servers) ||
1291 radius_servers_diff(newconf->acct_servers, oldconf->acct_servers,
1292 newconf->num_acct_servers)) {
1293 hostapd_logger(ctx, NULL, HOSTAPD_MODULE_RADIUS,
1294 HOSTAPD_LEVEL_DEBUG,
1295 "Reconfiguring RADIUS client");
1296 radius_client_deinit(old);
1297 return radius_client_init(ctx, newconf);
1298 }
1299
1300 return old;
1301}