1 /*
2 * RADIUS client
3 * Copyright (c) 2002-2024, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9 #include "includes.h"
10 #include <fcntl.h>
11 #include <net/if.h>
12
13 #include "common.h"
14 #include "eloop.h"
15 #include "crypto/tls.h"
16 #include "radius.h"
17 #include "radius_client.h"
18
19 /* Defaults for RADIUS retransmit values (exponential backoff) */
20
21 /**
22 * RADIUS_CLIENT_FIRST_WAIT - RADIUS client timeout for first retry in seconds
23 */
24 #define RADIUS_CLIENT_FIRST_WAIT 3
25
26 /**
27 * RADIUS_CLIENT_MAX_WAIT - RADIUS client maximum retry timeout in seconds
28 */
29 #define RADIUS_CLIENT_MAX_WAIT 120
30
31 /**
32 * RADIUS_CLIENT_MAX_FAILOVER - RADIUS client maximum retries
33 *
34 * Maximum number of server failovers before the entry is removed from
35 * retransmit list.
36 */
37 #define RADIUS_CLIENT_MAX_FAILOVER 3
38
39 /**
40 * RADIUS_CLIENT_MAX_ENTRIES - RADIUS client maximum pending messages
41 *
42 * Maximum number of entries in retransmit list (oldest entries will be
43 * removed, if this limit is exceeded).
44 */
45 #define RADIUS_CLIENT_MAX_ENTRIES 30
46
47 /**
48 * RADIUS_CLIENT_NUM_FAILOVER - RADIUS client failover point
49 *
50 * The number of failed retry attempts after which the RADIUS server will be
51 * changed (if one of more backup servers are configured).
52 */
53 #define RADIUS_CLIENT_NUM_FAILOVER 4
54
55
56 /**
57 * struct radius_rx_handler - RADIUS client RX handler
58 *
59 * This data structure is used internally inside the RADIUS client module to
60 * store registered RX handlers. These handlers are registered by calls to
61 * radius_client_register() and unregistered when the RADIUS client is
62 * deinitialized with a call to radius_client_deinit().
63 */
64 struct radius_rx_handler {
65 /**
66 * handler - Received RADIUS message handler
67 */
68 RadiusRxResult (*handler)(struct radius_msg *msg,
69 struct radius_msg *req,
70 const u8 *shared_secret,
71 size_t shared_secret_len,
72 void *data);
73
74 /**
75 * data - Context data for the handler
76 */
77 void *data;
78 };
79
80
81 /**
82 * struct radius_msg_list - RADIUS client message retransmit list
83 *
84 * This data structure is used internally inside the RADIUS client module to
85 * store pending RADIUS requests that may still need to be retransmitted.
86 */
87 struct radius_msg_list {
88 /**
89 * addr - STA/client address
90 *
91 * This is used to find RADIUS messages for the same STA.
92 */
93 u8 addr[ETH_ALEN];
94
95 /**
96 * msg - RADIUS message
97 */
98 struct radius_msg *msg;
99
100 /**
101 * msg_type - Message type
102 */
103 RadiusType msg_type;
104
105 /**
106 * first_try - Time of the first transmission attempt
107 */
108 os_time_t first_try;
109
110 /**
111 * next_try - Time for the next transmission attempt
112 */
113 os_time_t next_try;
114
115 /**
116 * attempts - Number of transmission attempts for one server
117 */
118 int attempts;
119
120 /**
121 * accu_attempts - Number of accumulated attempts
122 */
123 int accu_attempts;
124
125 /**
126 * next_wait - Next retransmission wait time in seconds
127 */
128 int next_wait;
129
130 /**
131 * last_attempt - Time of the last transmission attempt
132 */
133 struct os_reltime last_attempt;
134
135 /**
136 * shared_secret - Shared secret with the target RADIUS server
137 */
138 const u8 *shared_secret;
139
140 /**
141 * shared_secret_len - shared_secret length in octets
142 */
143 size_t shared_secret_len;
144
145 /* TODO: server config with failover to backup server(s) */
146
147 /**
148 * next - Next message in the list
149 */
150 struct radius_msg_list *next;
151 };
152
153
154 /**
155 * struct radius_client_data - Internal RADIUS client data
156 *
157 * This data structure is used internally inside the RADIUS client module.
158 * External users allocate this by calling radius_client_init() and free it by
159 * calling radius_client_deinit(). The pointer to this opaque data is used in
160 * calls to other functions as an identifier for the RADIUS client instance.
161 */
162 struct radius_client_data {
163 /**
164 * ctx - Context pointer for hostapd_logger() callbacks
165 */
166 void *ctx;
167
168 /**
169 * conf - RADIUS client configuration (list of RADIUS servers to use)
170 */
171 struct hostapd_radius_servers *conf;
172
173 /**
174 * auth_sock - Currently used socket for RADIUS authentication server
175 */
176 int auth_sock;
177
178 /**
179 * auth_tls - Whether current authentication connection uses TLS
180 */
181 bool auth_tls;
182
183 /**
184 * auth_tls_ready - Whether authentication TLS is ready
185 */
186 bool auth_tls_ready;
187
188 /**
189 * acct_sock - Currently used socket for RADIUS accounting server
190 */
191 int acct_sock;
192
193 /**
194 * acct_tls - Whether current accounting connection uses TLS
195 */
196 bool acct_tls;
197
198 /**
199 * acct_tls_ready - Whether accounting TLS is ready
200 */
201 bool acct_tls_ready;
202
203 /**
204 * auth_handlers - Authentication message handlers
205 */
206 struct radius_rx_handler *auth_handlers;
207
208 /**
209 * num_auth_handlers - Number of handlers in auth_handlers
210 */
211 size_t num_auth_handlers;
212
213 /**
214 * acct_handlers - Accounting message handlers
215 */
216 struct radius_rx_handler *acct_handlers;
217
218 /**
219 * num_acct_handlers - Number of handlers in acct_handlers
220 */
221 size_t num_acct_handlers;
222
223 /**
224 * msgs - Pending outgoing RADIUS messages
225 */
226 struct radius_msg_list *msgs;
227
228 /**
229 * num_msgs - Number of pending messages in the msgs list
230 */
231 size_t num_msgs;
232
233 /**
234 * next_radius_identifier - Next RADIUS message identifier to use
235 */
236 u8 next_radius_identifier;
237
238 /**
239 * interim_error_cb - Interim accounting error callback
240 */
241 void (*interim_error_cb)(const u8 *addr, void *ctx);
242
243 /**
244 * interim_error_cb_ctx - interim_error_cb() context data
245 */
246 void *interim_error_cb_ctx;
247
248 #ifdef CONFIG_RADIUS_TLS
249 void *tls_ctx;
250 struct tls_connection *auth_tls_conn;
251 struct tls_connection *acct_tls_conn;
252 #endif /* CONFIG_RADIUS_TLS */
253 };
254
255
256 static int
257 radius_change_server(struct radius_client_data *radius,
258 struct hostapd_radius_server *nserv,
259 struct hostapd_radius_server *oserv,
260 int auth);
261 static int radius_client_init_acct(struct radius_client_data *radius);
262 static int radius_client_init_auth(struct radius_client_data *radius);
263 static void radius_client_auth_failover(struct radius_client_data *radius);
264 static void radius_client_acct_failover(struct radius_client_data *radius);
265
266
radius_client_msg_free(struct radius_msg_list * req)267 static void radius_client_msg_free(struct radius_msg_list *req)
268 {
269 radius_msg_free(req->msg);
270 os_free(req);
271 }
272
273
274 /**
275 * radius_client_register - Register a RADIUS client RX handler
276 * @radius: RADIUS client context from radius_client_init()
277 * @msg_type: RADIUS client type (RADIUS_AUTH or RADIUS_ACCT)
278 * @handler: Handler for received RADIUS messages
279 * @data: Context pointer for handler callbacks
280 * Returns: 0 on success, -1 on failure
281 *
282 * This function is used to register a handler for processing received RADIUS
283 * authentication and accounting messages. The handler() callback function will
284 * be called whenever a RADIUS message is received from the active server.
285 *
286 * There can be multiple registered RADIUS message handlers. The handlers will
287 * be called in order until one of them indicates that it has processed or
288 * queued the message.
289 */
radius_client_register(struct radius_client_data * radius,RadiusType msg_type,RadiusRxResult (* handler)(struct radius_msg * msg,struct radius_msg * req,const u8 * shared_secret,size_t shared_secret_len,void * data),void * data)290 int radius_client_register(struct radius_client_data *radius,
291 RadiusType msg_type,
292 RadiusRxResult (*handler)(struct radius_msg *msg,
293 struct radius_msg *req,
294 const u8 *shared_secret,
295 size_t shared_secret_len,
296 void *data),
297 void *data)
298 {
299 struct radius_rx_handler **handlers, *newh;
300 size_t *num;
301
302 if (msg_type == RADIUS_ACCT) {
303 handlers = &radius->acct_handlers;
304 num = &radius->num_acct_handlers;
305 } else {
306 handlers = &radius->auth_handlers;
307 num = &radius->num_auth_handlers;
308 }
309
310 newh = os_realloc_array(*handlers, *num + 1,
311 sizeof(struct radius_rx_handler));
312 if (newh == NULL)
313 return -1;
314
315 newh[*num].handler = handler;
316 newh[*num].data = data;
317 (*num)++;
318 *handlers = newh;
319
320 return 0;
321 }
322
323
324 /**
325 * radius_client_set_interim_erro_cb - Register an interim acct error callback
326 * @radius: RADIUS client context from radius_client_init()
327 * @addr: Station address from the failed message
328 * @cb: Handler for interim accounting errors
329 * @ctx: Context pointer for handler callbacks
330 *
331 * This function is used to register a handler for processing failed
332 * transmission attempts of interim accounting update messages.
333 */
radius_client_set_interim_error_cb(struct radius_client_data * radius,void (* cb)(const u8 * addr,void * ctx),void * ctx)334 void radius_client_set_interim_error_cb(struct radius_client_data *radius,
335 void (*cb)(const u8 *addr, void *ctx),
336 void *ctx)
337 {
338 radius->interim_error_cb = cb;
339 radius->interim_error_cb_ctx = ctx;
340 }
341
342
343 /*
344 * Returns >0 if message queue was flushed (i.e., the message that triggered
345 * the error is not available anymore)
346 */
radius_client_handle_send_error(struct radius_client_data * radius,int s,RadiusType msg_type)347 static int radius_client_handle_send_error(struct radius_client_data *radius,
348 int s, RadiusType msg_type)
349 {
350 #ifndef CONFIG_NATIVE_WINDOWS
351 int _errno = errno;
352 wpa_printf(MSG_INFO, "send[RADIUS,s=%d]: %s", s, strerror(errno));
353 if (_errno == ENOTCONN || _errno == EDESTADDRREQ || _errno == EINVAL ||
354 _errno == EBADF || _errno == ENETUNREACH || _errno == EACCES) {
355 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
356 HOSTAPD_LEVEL_INFO,
357 "Send failed - maybe interface status changed -"
358 " try to connect again");
359 if (msg_type == RADIUS_ACCT ||
360 msg_type == RADIUS_ACCT_INTERIM) {
361 radius_client_init_acct(radius);
362 return 0;
363 } else {
364 radius_client_init_auth(radius);
365 return 1;
366 }
367 }
368 #endif /* CONFIG_NATIVE_WINDOWS */
369
370 return 0;
371 }
372
373
radius_client_retransmit(struct radius_client_data * radius,struct radius_msg_list * entry,os_time_t now)374 static int radius_client_retransmit(struct radius_client_data *radius,
375 struct radius_msg_list *entry,
376 os_time_t now)
377 {
378 struct hostapd_radius_servers *conf = radius->conf;
379 int s;
380 struct wpabuf *buf;
381 size_t prev_num_msgs;
382 u8 *acct_delay_time;
383 size_t acct_delay_time_len;
384 int num_servers;
385 #ifdef CONFIG_RADIUS_TLS
386 struct wpabuf *out = NULL;
387 struct tls_connection *conn = NULL;
388 bool acct = false;
389 #endif /* CONFIG_RADIUS_TLS */
390
391 if (entry->msg_type == RADIUS_ACCT ||
392 entry->msg_type == RADIUS_ACCT_INTERIM) {
393 #ifdef CONFIG_RADIUS_TLS
394 acct = true;
395 if (radius->acct_tls)
396 conn = radius->acct_tls_conn;
397 #endif /* CONFIG_RADIUS_TLS */
398 num_servers = conf->num_acct_servers;
399 if (radius->acct_sock < 0)
400 radius_client_init_acct(radius);
401 if (radius->acct_sock < 0 && conf->num_acct_servers > 1) {
402 prev_num_msgs = radius->num_msgs;
403 radius_client_acct_failover(radius);
404 if (prev_num_msgs != radius->num_msgs)
405 return 0;
406 }
407 s = radius->acct_sock;
408 if (entry->attempts == 0)
409 conf->acct_server->requests++;
410 else {
411 conf->acct_server->timeouts++;
412 conf->acct_server->retransmissions++;
413 }
414 } else {
415 #ifdef CONFIG_RADIUS_TLS
416 if (radius->auth_tls)
417 conn = radius->auth_tls_conn;
418 #endif /* CONFIG_RADIUS_TLS */
419 num_servers = conf->num_auth_servers;
420 if (radius->auth_sock < 0)
421 radius_client_init_auth(radius);
422 if (radius->auth_sock < 0 && conf->num_auth_servers > 1) {
423 prev_num_msgs = radius->num_msgs;
424 radius_client_auth_failover(radius);
425 if (prev_num_msgs != radius->num_msgs)
426 return 0;
427 }
428 s = radius->auth_sock;
429 if (entry->attempts == 0)
430 conf->auth_server->requests++;
431 else {
432 conf->auth_server->timeouts++;
433 conf->auth_server->retransmissions++;
434 }
435 }
436
437 if (entry->msg_type == RADIUS_ACCT_INTERIM) {
438 wpa_printf(MSG_DEBUG,
439 "RADIUS: Failed to transmit interim accounting update to "
440 MACSTR " - drop message and request a new update",
441 MAC2STR(entry->addr));
442 if (radius->interim_error_cb)
443 radius->interim_error_cb(entry->addr,
444 radius->interim_error_cb_ctx);
445 return 1;
446 }
447
448 if (s < 0) {
449 wpa_printf(MSG_INFO,
450 "RADIUS: No valid socket for retransmission");
451 return 1;
452 }
453
454 #ifdef CONFIG_RADIUS_TLS
455 if ((acct && radius->acct_tls && !radius->acct_tls_ready) ||
456 (!acct && radius->auth_tls && !radius->auth_tls_ready)) {
457 wpa_printf(MSG_DEBUG,
458 "RADIUS: TLS connection not yet ready for TX");
459 goto not_ready;
460 }
461 #endif /* CONFIG_RADIUS_TLS */
462
463 if (entry->msg_type == RADIUS_ACCT &&
464 radius_msg_get_attr_ptr(entry->msg, RADIUS_ATTR_ACCT_DELAY_TIME,
465 &acct_delay_time, &acct_delay_time_len,
466 NULL) == 0 &&
467 acct_delay_time_len == 4) {
468 struct radius_hdr *hdr;
469 u32 delay_time;
470
471 /*
472 * Need to assign a new identifier since attribute contents
473 * changes.
474 */
475 hdr = radius_msg_get_hdr(entry->msg);
476 hdr->identifier = radius_client_get_id(radius);
477
478 /* Update Acct-Delay-Time to show wait time in queue */
479 delay_time = now - entry->first_try;
480 WPA_PUT_BE32(acct_delay_time, delay_time);
481
482 wpa_printf(MSG_DEBUG,
483 "RADIUS: Updated Acct-Delay-Time to %u for retransmission",
484 delay_time);
485 radius_msg_finish_acct(entry->msg, entry->shared_secret,
486 entry->shared_secret_len);
487 if (radius->conf->msg_dumps)
488 radius_msg_dump(entry->msg);
489 }
490
491 /* retransmit; remove entry if too many attempts */
492 if (entry->accu_attempts >= RADIUS_CLIENT_MAX_FAILOVER *
493 RADIUS_CLIENT_NUM_FAILOVER * num_servers) {
494 wpa_printf(MSG_INFO,
495 "RADIUS: Removing un-ACKed message due to too many failed retransmit attempts");
496 return 1;
497 }
498
499 entry->attempts++;
500 entry->accu_attempts++;
501 hostapd_logger(radius->ctx, entry->addr, HOSTAPD_MODULE_RADIUS,
502 HOSTAPD_LEVEL_DEBUG, "Resending RADIUS message (id=%d)",
503 radius_msg_get_hdr(entry->msg)->identifier);
504
505 os_get_reltime(&entry->last_attempt);
506 buf = radius_msg_get_buf(entry->msg);
507 #ifdef CONFIG_RADIUS_TLS
508 if (conn) {
509 out = tls_connection_encrypt(radius->tls_ctx, conn, buf);
510 if (!out) {
511 wpa_printf(MSG_INFO,
512 "RADIUS: Failed to encrypt RADIUS message (TLS)");
513 return -1;
514 }
515 wpa_printf(MSG_DEBUG,
516 "RADIUS: TLS encryption of %zu bytes of plaintext to %zu bytes of ciphertext",
517 wpabuf_len(buf), wpabuf_len(out));
518 buf = out;
519 }
520 #endif /* CONFIG_RADIUS_TLS */
521
522 wpa_printf(MSG_DEBUG, "RADIUS: Send %zu bytes to the server",
523 wpabuf_len(buf));
524 if (send(s, wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
525 if (radius_client_handle_send_error(radius, s, entry->msg_type)
526 > 0) {
527 #ifdef CONFIG_RADIUS_TLS
528 wpabuf_free(out);
529 #endif /* CONFIG_RADIUS_TLS */
530 return 0;
531 }
532 }
533 #ifdef CONFIG_RADIUS_TLS
534 wpabuf_free(out);
535
536 not_ready:
537 #endif /* CONFIG_RADIUS_TLS */
538
539 entry->next_try = now + entry->next_wait;
540 entry->next_wait *= 2;
541 if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT)
542 entry->next_wait = RADIUS_CLIENT_MAX_WAIT;
543
544 return 0;
545 }
546
547
radius_client_timer(void * eloop_ctx,void * timeout_ctx)548 static void radius_client_timer(void *eloop_ctx, void *timeout_ctx)
549 {
550 struct radius_client_data *radius = eloop_ctx;
551 struct os_reltime now;
552 os_time_t first;
553 struct radius_msg_list *entry, *prev, *tmp;
554 int auth_failover = 0, acct_failover = 0;
555 size_t prev_num_msgs;
556 int s;
557
558 entry = radius->msgs;
559 if (!entry)
560 return;
561
562 os_get_reltime(&now);
563
564 while (entry) {
565 if (now.sec >= entry->next_try) {
566 s = entry->msg_type == RADIUS_AUTH ? radius->auth_sock :
567 radius->acct_sock;
568 if (entry->attempts >= RADIUS_CLIENT_NUM_FAILOVER ||
569 (s < 0 && entry->attempts > 0)) {
570 if (entry->msg_type == RADIUS_ACCT ||
571 entry->msg_type == RADIUS_ACCT_INTERIM)
572 acct_failover++;
573 else
574 auth_failover++;
575 }
576 }
577 entry = entry->next;
578 }
579
580 if (auth_failover)
581 radius_client_auth_failover(radius);
582
583 if (acct_failover)
584 radius_client_acct_failover(radius);
585
586 entry = radius->msgs;
587 first = 0;
588
589 prev = NULL;
590 while (entry) {
591 prev_num_msgs = radius->num_msgs;
592 if (now.sec >= entry->next_try &&
593 radius_client_retransmit(radius, entry, now.sec)) {
594 if (prev)
595 prev->next = entry->next;
596 else
597 radius->msgs = entry->next;
598
599 tmp = entry;
600 entry = entry->next;
601 radius_client_msg_free(tmp);
602 radius->num_msgs--;
603 continue;
604 }
605
606 if (prev_num_msgs != radius->num_msgs) {
607 wpa_printf(MSG_DEBUG,
608 "RADIUS: Message removed from queue - restart from beginning");
609 entry = radius->msgs;
610 prev = NULL;
611 continue;
612 }
613
614 if (first == 0 || entry->next_try < first)
615 first = entry->next_try;
616
617 prev = entry;
618 entry = entry->next;
619 }
620
621 if (radius->msgs) {
622 if (first < now.sec)
623 first = now.sec;
624 eloop_cancel_timeout(radius_client_timer, radius, NULL);
625 eloop_register_timeout(first - now.sec, 0,
626 radius_client_timer, radius, NULL);
627 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
628 HOSTAPD_LEVEL_DEBUG, "Next RADIUS client "
629 "retransmit in %ld seconds",
630 (long int) (first - now.sec));
631 }
632 }
633
634
radius_client_auth_failover(struct radius_client_data * radius)635 static void radius_client_auth_failover(struct radius_client_data *radius)
636 {
637 struct hostapd_radius_servers *conf = radius->conf;
638 struct hostapd_radius_server *next, *old;
639 struct radius_msg_list *entry;
640 char abuf[50];
641
642 old = conf->auth_server;
643 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
644 HOSTAPD_LEVEL_NOTICE,
645 "No response from Authentication server %s:%d - failover",
646 hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)),
647 old->port);
648
649 for (entry = radius->msgs; entry; entry = entry->next) {
650 if (entry->msg_type == RADIUS_AUTH)
651 old->timeouts++;
652 }
653
654 next = old + 1;
655 if (next > &(conf->auth_servers[conf->num_auth_servers - 1]))
656 next = conf->auth_servers;
657 conf->auth_server = next;
658 radius_change_server(radius, next, old, 1);
659 }
660
661
radius_client_acct_failover(struct radius_client_data * radius)662 static void radius_client_acct_failover(struct radius_client_data *radius)
663 {
664 struct hostapd_radius_servers *conf = radius->conf;
665 struct hostapd_radius_server *next, *old;
666 struct radius_msg_list *entry;
667 char abuf[50];
668
669 old = conf->acct_server;
670 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
671 HOSTAPD_LEVEL_NOTICE,
672 "No response from Accounting server %s:%d - failover",
673 hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)),
674 old->port);
675
676 for (entry = radius->msgs; entry; entry = entry->next) {
677 if (entry->msg_type == RADIUS_ACCT ||
678 entry->msg_type == RADIUS_ACCT_INTERIM)
679 old->timeouts++;
680 }
681
682 next = old + 1;
683 if (next > &conf->acct_servers[conf->num_acct_servers - 1])
684 next = conf->acct_servers;
685 conf->acct_server = next;
686 radius_change_server(radius, next, old, 0);
687 }
688
689
radius_client_update_timeout(struct radius_client_data * radius)690 static void radius_client_update_timeout(struct radius_client_data *radius)
691 {
692 struct os_reltime now;
693 os_time_t first;
694 struct radius_msg_list *entry;
695
696 eloop_cancel_timeout(radius_client_timer, radius, NULL);
697
698 if (radius->msgs == NULL) {
699 return;
700 }
701
702 first = 0;
703 for (entry = radius->msgs; entry; entry = entry->next) {
704 if (first == 0 || entry->next_try < first)
705 first = entry->next_try;
706 }
707
708 os_get_reltime(&now);
709 if (first < now.sec)
710 first = now.sec;
711 eloop_register_timeout(first - now.sec, 0, radius_client_timer, radius,
712 NULL);
713 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
714 HOSTAPD_LEVEL_DEBUG, "Next RADIUS client retransmit in"
715 " %ld seconds", (long int) (first - now.sec));
716 }
717
718
radius_client_list_add(struct radius_client_data * radius,struct radius_msg * msg,RadiusType msg_type,const u8 * shared_secret,size_t shared_secret_len,const u8 * addr)719 static void radius_client_list_add(struct radius_client_data *radius,
720 struct radius_msg *msg,
721 RadiusType msg_type,
722 const u8 *shared_secret,
723 size_t shared_secret_len, const u8 *addr)
724 {
725 struct radius_msg_list *entry, *prev;
726
727 if (eloop_terminated()) {
728 /* No point in adding entries to retransmit queue since event
729 * loop has already been terminated. */
730 radius_msg_free(msg);
731 return;
732 }
733
734 entry = os_zalloc(sizeof(*entry));
735 if (entry == NULL) {
736 wpa_printf(MSG_INFO, "RADIUS: Failed to add packet into retransmit list");
737 radius_msg_free(msg);
738 return;
739 }
740
741 if (addr)
742 os_memcpy(entry->addr, addr, ETH_ALEN);
743 entry->msg = msg;
744 entry->msg_type = msg_type;
745 entry->shared_secret = shared_secret;
746 entry->shared_secret_len = shared_secret_len;
747 os_get_reltime(&entry->last_attempt);
748 entry->first_try = entry->last_attempt.sec;
749 entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT;
750 entry->attempts = 1;
751 entry->accu_attempts = 1;
752 entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2;
753 if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT)
754 entry->next_wait = RADIUS_CLIENT_MAX_WAIT;
755 entry->next = radius->msgs;
756 radius->msgs = entry;
757 radius_client_update_timeout(radius);
758
759 if (radius->num_msgs >= RADIUS_CLIENT_MAX_ENTRIES) {
760 wpa_printf(MSG_INFO, "RADIUS: Removing the oldest un-ACKed packet due to retransmit list limits");
761 prev = NULL;
762 while (entry->next) {
763 prev = entry;
764 entry = entry->next;
765 }
766 if (prev) {
767 prev->next = NULL;
768 radius_client_msg_free(entry);
769 }
770 } else
771 radius->num_msgs++;
772 }
773
774
radius_client_disable_pmtu_discovery(int s)775 static int radius_client_disable_pmtu_discovery(int s)
776 {
777 int r = -1;
778 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
779 /* Turn off Path MTU discovery on IPv4/UDP sockets. */
780 int action = IP_PMTUDISC_DONT;
781 r = setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &action,
782 sizeof(action));
783 if (r == -1)
784 wpa_printf(MSG_ERROR, "RADIUS: Failed to set IP_MTU_DISCOVER: %s",
785 strerror(errno));
786 #endif
787 return r;
788 }
789
790
radius_close_auth_socket(struct radius_client_data * radius)791 static void radius_close_auth_socket(struct radius_client_data *radius)
792 {
793 if (radius->auth_sock >= 0) {
794 #ifdef CONFIG_RADIUS_TLS
795 if (radius->conf->auth_server->tls)
796 eloop_unregister_sock(radius->auth_sock,
797 EVENT_TYPE_WRITE);
798 #endif /* CONFIG_RADIUS_TLS */
799 eloop_unregister_read_sock(radius->auth_sock);
800 close(radius->auth_sock);
801 radius->auth_sock = -1;
802 }
803 }
804
805
radius_close_acct_socket(struct radius_client_data * radius)806 static void radius_close_acct_socket(struct radius_client_data *radius)
807 {
808 if (radius->acct_sock >= 0) {
809 #ifdef CONFIG_RADIUS_TLS
810 if (radius->conf->acct_server->tls)
811 eloop_unregister_sock(radius->acct_sock,
812 EVENT_TYPE_WRITE);
813 #endif /* CONFIG_RADIUS_TLS */
814 eloop_unregister_read_sock(radius->acct_sock);
815 close(radius->acct_sock);
816 radius->acct_sock = -1;
817 }
818 }
819
820
821 /**
822 * radius_client_send - Send a RADIUS request
823 * @radius: RADIUS client context from radius_client_init()
824 * @msg: RADIUS message to be sent
825 * @msg_type: Message type (RADIUS_AUTH, RADIUS_ACCT, RADIUS_ACCT_INTERIM)
826 * @addr: MAC address of the device related to this message or %NULL
827 * Returns: 0 on success, -1 on failure
828 *
829 * This function is used to transmit a RADIUS authentication (RADIUS_AUTH) or
830 * accounting request (RADIUS_ACCT or RADIUS_ACCT_INTERIM). The only difference
831 * between accounting and interim accounting messages is that the interim
832 * message will not be retransmitted. Instead, a callback is used to indicate
833 * that the transmission failed for the specific station @addr so that a new
834 * interim accounting update message can be generated with up-to-date session
835 * data instead of trying to resend old information.
836 *
837 * The message is added on the retransmission queue and will be retransmitted
838 * automatically until a response is received or maximum number of retries
839 * (RADIUS_CLIENT_MAX_FAILOVER * RADIUS_CLIENT_NUM_FAILOVER) is reached. No
840 * such retries are used with RADIUS_ACCT_INTERIM, i.e., such a pending message
841 * is removed from the queue automatically on transmission failure.
842 *
843 * The related device MAC address can be used to identify pending messages that
844 * can be removed with radius_client_flush_auth().
845 */
radius_client_send(struct radius_client_data * radius,struct radius_msg * msg,RadiusType msg_type,const u8 * addr)846 int radius_client_send(struct radius_client_data *radius,
847 struct radius_msg *msg, RadiusType msg_type,
848 const u8 *addr)
849 {
850 struct hostapd_radius_servers *conf = radius->conf;
851 const u8 *shared_secret;
852 size_t shared_secret_len;
853 char *name;
854 int s, res;
855 struct wpabuf *buf;
856 #ifdef CONFIG_RADIUS_TLS
857 struct wpabuf *out = NULL;
858 struct tls_connection *conn = NULL;
859 bool acct = false;
860 #endif /* CONFIG_RADIUS_TLS */
861
862 if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) {
863 #ifdef CONFIG_RADIUS_TLS
864 acct = true;
865 if (radius->acct_tls)
866 conn = radius->acct_tls_conn;
867 #endif /* CONFIG_RADIUS_TLS */
868 if (conf->acct_server && radius->acct_sock < 0)
869 radius_client_init_acct(radius);
870
871 if (conf->acct_server == NULL || radius->acct_sock < 0 ||
872 conf->acct_server->shared_secret == NULL) {
873 hostapd_logger(radius->ctx, NULL,
874 HOSTAPD_MODULE_RADIUS,
875 HOSTAPD_LEVEL_INFO,
876 "No accounting server configured");
877 return -1;
878 }
879 shared_secret = conf->acct_server->shared_secret;
880 shared_secret_len = conf->acct_server->shared_secret_len;
881 radius_msg_finish_acct(msg, shared_secret, shared_secret_len);
882 name = "accounting";
883 s = radius->acct_sock;
884 conf->acct_server->requests++;
885 } else {
886 #ifdef CONFIG_RADIUS_TLS
887 if (radius->auth_tls)
888 conn = radius->auth_tls_conn;
889 #endif /* CONFIG_RADIUS_TLS */
890 if (conf->auth_server && radius->auth_sock < 0)
891 radius_client_init_auth(radius);
892
893 if (conf->auth_server == NULL || radius->auth_sock < 0 ||
894 conf->auth_server->shared_secret == NULL) {
895 hostapd_logger(radius->ctx, NULL,
896 HOSTAPD_MODULE_RADIUS,
897 HOSTAPD_LEVEL_INFO,
898 "No authentication server configured");
899 return -1;
900 }
901 shared_secret = conf->auth_server->shared_secret;
902 shared_secret_len = conf->auth_server->shared_secret_len;
903 radius_msg_finish(msg, shared_secret, shared_secret_len);
904 name = "authentication";
905 s = radius->auth_sock;
906 conf->auth_server->requests++;
907 }
908
909 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
910 HOSTAPD_LEVEL_DEBUG, "Sending RADIUS message to %s "
911 "server", name);
912 if (conf->msg_dumps)
913 radius_msg_dump(msg);
914
915 #ifdef CONFIG_RADIUS_TLS
916 if ((acct && radius->acct_tls && !radius->acct_tls_ready) ||
917 (!acct && radius->auth_tls && !radius->auth_tls_ready)) {
918 wpa_printf(MSG_DEBUG,
919 "RADIUS: TLS connection not yet ready for TX");
920 goto skip_send;
921 }
922 #endif /* CONFIG_RADIUS_TLS */
923
924 buf = radius_msg_get_buf(msg);
925 #ifdef CONFIG_RADIUS_TLS
926 if (conn) {
927 out = tls_connection_encrypt(radius->tls_ctx, conn, buf);
928 if (!out) {
929 wpa_printf(MSG_INFO,
930 "RADIUS: Failed to encrypt RADIUS message (TLS)");
931 return -1;
932 }
933 wpa_printf(MSG_DEBUG,
934 "RADIUS: TLS encryption of %zu bytes of plaintext to %zu bytes of ciphertext",
935 wpabuf_len(buf), wpabuf_len(out));
936 buf = out;
937 }
938 #endif /* CONFIG_RADIUS_TLS */
939 wpa_printf(MSG_DEBUG, "RADIUS: Send %zu bytes to the server",
940 wpabuf_len(buf));
941 res = send(s, wpabuf_head(buf), wpabuf_len(buf), 0);
942 #ifdef CONFIG_RADIUS_TLS
943 wpabuf_free(out);
944 #endif /* CONFIG_RADIUS_TLS */
945 if (res < 0)
946 radius_client_handle_send_error(radius, s, msg_type);
947
948 #ifdef CONFIG_RADIUS_TLS
949 skip_send:
950 #endif /* CONFIG_RADIUS_TLS */
951 radius_client_list_add(radius, msg, msg_type, shared_secret,
952 shared_secret_len, addr);
953
954 return 0;
955 }
956
957
958 #ifdef CONFIG_RADIUS_TLS
959
radius_client_close_tcp(struct radius_client_data * radius,int sock,RadiusType msg_type)960 static void radius_client_close_tcp(struct radius_client_data *radius,
961 int sock, RadiusType msg_type)
962 {
963 wpa_printf(MSG_DEBUG, "RADIUS: Closing TCP connection (sock %d)",
964 sock);
965 if (msg_type == RADIUS_ACCT) {
966 radius->acct_tls_ready = false;
967 radius_close_acct_socket(radius);
968 } else {
969 radius->auth_tls_ready = false;
970 radius_close_auth_socket(radius);
971 }
972 }
973
974
975 static void
radius_client_process_tls_handshake(struct radius_client_data * radius,int sock,RadiusType msg_type,u8 * buf,size_t len)976 radius_client_process_tls_handshake(struct radius_client_data *radius,
977 int sock, RadiusType msg_type,
978 u8 *buf, size_t len)
979 {
980 struct wpabuf *in, *out = NULL, *appl;
981 struct tls_connection *conn;
982 int res;
983 bool ready = false;
984
985 wpa_printf(MSG_DEBUG,
986 "RADIUS: Process %zu bytes of received TLS handshake message",
987 len);
988
989 if (msg_type == RADIUS_ACCT)
990 conn = radius->acct_tls_conn;
991 else
992 conn = radius->auth_tls_conn;
993
994 in = wpabuf_alloc_copy(buf, len);
995 if (!in)
996 return;
997
998 appl = NULL;
999 out = tls_connection_handshake(radius->tls_ctx, conn, in, &appl);
1000 wpabuf_free(in);
1001 if (!out) {
1002 wpa_printf(MSG_DEBUG,
1003 "RADIUS: Could not generate TLS handshake data");
1004 goto fail;
1005 }
1006
1007 if (tls_connection_get_failed(radius->tls_ctx, conn)) {
1008 wpa_printf(MSG_INFO, "RADIUS: TLS handshake failed");
1009 goto fail;
1010 }
1011
1012 if (tls_connection_established(radius->tls_ctx, conn)) {
1013 wpa_printf(MSG_DEBUG,
1014 "RADIUS: TLS connection established (sock=%d)",
1015 sock);
1016 if (msg_type == RADIUS_ACCT)
1017 radius->acct_tls_ready = true;
1018 else
1019 radius->auth_tls_ready = true;
1020 ready = true;
1021 }
1022
1023 wpa_printf(MSG_DEBUG, "RADIUS: Sending %zu bytes of TLS handshake",
1024 wpabuf_len(out));
1025 res = send(sock, wpabuf_head(out), wpabuf_len(out), 0);
1026 if (res < 0) {
1027 wpa_printf(MSG_INFO, "RADIUS: send: %s", strerror(errno));
1028 goto fail;
1029 }
1030 if ((size_t) res != wpabuf_len(out)) {
1031 wpa_printf(MSG_INFO,
1032 "RADIUS: Could not send all data for TLS handshake: only %d bytes sent",
1033 res);
1034 goto fail;
1035 }
1036 wpabuf_free(out);
1037
1038 if (ready) {
1039 struct radius_msg_list *entry, *prev, *tmp;
1040 struct os_reltime now;
1041
1042 /* Send all pending message of matching type since the TLS
1043 * tunnel has now been established. */
1044
1045 os_get_reltime(&now);
1046
1047 entry = radius->msgs;
1048 prev = NULL;
1049 while (entry) {
1050 if (entry->msg_type != msg_type) {
1051 prev = entry;
1052 entry = entry->next;
1053 continue;
1054 }
1055
1056 if (radius_client_retransmit(radius, entry, now.sec)) {
1057 if (prev)
1058 prev->next = entry->next;
1059 else
1060 radius->msgs = entry->next;
1061
1062 tmp = entry;
1063 entry = entry->next;
1064 radius_client_msg_free(tmp);
1065 radius->num_msgs--;
1066 continue;
1067 }
1068
1069 prev = entry;
1070 entry = entry->next;
1071 }
1072 }
1073
1074 return;
1075
1076 fail:
1077 wpabuf_free(out);
1078 tls_connection_deinit(radius->tls_ctx, conn);
1079 if (msg_type == RADIUS_ACCT)
1080 radius->acct_tls_conn = NULL;
1081 else
1082 radius->auth_tls_conn = NULL;
1083 radius_client_close_tcp(radius, sock, msg_type);
1084 }
1085
1086 #endif /* CONFIG_RADIUS_TLS */
1087
1088
radius_client_receive(int sock,void * eloop_ctx,void * sock_ctx)1089 static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx)
1090 {
1091 struct radius_client_data *radius = eloop_ctx;
1092 struct hostapd_radius_servers *conf = radius->conf;
1093 RadiusType msg_type = (uintptr_t) sock_ctx;
1094 int len, roundtrip;
1095 unsigned char buf[RADIUS_MAX_MSG_LEN];
1096 struct msghdr msghdr = {0};
1097 struct iovec iov;
1098 struct radius_msg *msg;
1099 struct radius_hdr *hdr;
1100 struct radius_rx_handler *handlers;
1101 size_t num_handlers, i;
1102 struct radius_msg_list *req, *prev_req;
1103 struct os_reltime now;
1104 struct hostapd_radius_server *rconf;
1105 int invalid_authenticator = 0;
1106 #ifdef CONFIG_RADIUS_TLS
1107 struct tls_connection *conn = NULL;
1108 bool tls, tls_ready;
1109 #endif /* CONFIG_RADIUS_TLS */
1110
1111 if (msg_type == RADIUS_ACCT) {
1112 #ifdef CONFIG_RADIUS_TLS
1113 if (radius->acct_tls)
1114 conn = radius->acct_tls_conn;
1115 tls = radius->acct_tls;
1116 tls_ready = radius->acct_tls_ready;
1117 #endif /* CONFIG_RADIUS_TLS */
1118 handlers = radius->acct_handlers;
1119 num_handlers = radius->num_acct_handlers;
1120 rconf = conf->acct_server;
1121 } else {
1122 #ifdef CONFIG_RADIUS_TLS
1123 if (radius->auth_tls)
1124 conn = radius->auth_tls_conn;
1125 tls = radius->auth_tls;
1126 tls_ready = radius->auth_tls_ready;
1127 #endif /* CONFIG_RADIUS_TLS */
1128 handlers = radius->auth_handlers;
1129 num_handlers = radius->num_auth_handlers;
1130 rconf = conf->auth_server;
1131 }
1132
1133 iov.iov_base = buf;
1134 iov.iov_len = RADIUS_MAX_MSG_LEN;
1135 msghdr.msg_iov = &iov;
1136 msghdr.msg_iovlen = 1;
1137 msghdr.msg_flags = 0;
1138 len = recvmsg(sock, &msghdr, MSG_DONTWAIT);
1139 if (len < 0) {
1140 wpa_printf(MSG_INFO, "recvmsg[RADIUS]: %s", strerror(errno));
1141 return;
1142 }
1143 #ifdef CONFIG_RADIUS_TLS
1144 if (tls && len == 0) {
1145 wpa_printf(MSG_DEBUG, "RADIUS: No TCP data available");
1146 goto close_tcp;
1147 }
1148
1149 if (tls && !tls_ready) {
1150 radius_client_process_tls_handshake(radius, sock, msg_type,
1151 buf, len);
1152 return;
1153 }
1154
1155 if (conn) {
1156 struct wpabuf *out, *in;
1157
1158 in = wpabuf_alloc_copy(buf, len);
1159 if (!in)
1160 return;
1161 wpa_printf(MSG_DEBUG,
1162 "RADIUS: Process %d bytes of encrypted TLS data",
1163 len);
1164 out = tls_connection_decrypt(radius->tls_ctx, conn, in);
1165 wpabuf_free(in);
1166 if (!out) {
1167 wpa_printf(MSG_INFO,
1168 "RADIUS: Failed to decrypt TLS data");
1169 goto close_tcp;
1170 }
1171 if (wpabuf_len(out) == 0) {
1172 wpa_printf(MSG_DEBUG,
1173 "RADIUS: Full message not yet received - continue waiting for additional TLS data");
1174 wpabuf_free(out);
1175 return;
1176 }
1177 if (wpabuf_len(out) > RADIUS_MAX_MSG_LEN) {
1178 wpa_printf(MSG_INFO,
1179 "RADIUS: Too long RADIUS message from TLS: %zu",
1180 wpabuf_len(out));
1181 wpabuf_free(out);
1182 goto close_tcp;
1183 }
1184 os_memcpy(buf, wpabuf_head(out), wpabuf_len(out));
1185 len = wpabuf_len(out);
1186 wpabuf_free(out);
1187 }
1188 #endif /* CONFIG_RADIUS_TLS */
1189
1190 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
1191 HOSTAPD_LEVEL_DEBUG, "Received %d bytes from RADIUS "
1192 "server", len);
1193
1194 if (msghdr.msg_flags & MSG_TRUNC) {
1195 wpa_printf(MSG_INFO, "RADIUS: Possibly too long UDP frame for our buffer - dropping it");
1196 return;
1197 }
1198
1199 msg = radius_msg_parse(buf, len);
1200 if (msg == NULL) {
1201 wpa_printf(MSG_INFO, "RADIUS: Parsing incoming frame failed");
1202 rconf->malformed_responses++;
1203 return;
1204 }
1205 hdr = radius_msg_get_hdr(msg);
1206
1207 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
1208 HOSTAPD_LEVEL_DEBUG, "Received RADIUS message");
1209 if (conf->msg_dumps)
1210 radius_msg_dump(msg);
1211
1212 switch (hdr->code) {
1213 case RADIUS_CODE_ACCESS_ACCEPT:
1214 rconf->access_accepts++;
1215 break;
1216 case RADIUS_CODE_ACCESS_REJECT:
1217 rconf->access_rejects++;
1218 break;
1219 case RADIUS_CODE_ACCESS_CHALLENGE:
1220 rconf->access_challenges++;
1221 break;
1222 case RADIUS_CODE_ACCOUNTING_RESPONSE:
1223 rconf->responses++;
1224 break;
1225 }
1226
1227 prev_req = NULL;
1228 req = radius->msgs;
1229 while (req) {
1230 /* TODO: also match by src addr:port of the packet when using
1231 * alternative RADIUS servers (?) */
1232 if ((req->msg_type == msg_type ||
1233 (req->msg_type == RADIUS_ACCT_INTERIM &&
1234 msg_type == RADIUS_ACCT)) &&
1235 radius_msg_get_hdr(req->msg)->identifier ==
1236 hdr->identifier)
1237 break;
1238
1239 prev_req = req;
1240 req = req->next;
1241 }
1242
1243 if (req == NULL) {
1244 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
1245 HOSTAPD_LEVEL_DEBUG,
1246 "No matching RADIUS request found (type=%d "
1247 "id=%d) - dropping packet",
1248 msg_type, hdr->identifier);
1249 goto fail;
1250 }
1251
1252 os_get_reltime(&now);
1253 roundtrip = (now.sec - req->last_attempt.sec) * 100 +
1254 (now.usec - req->last_attempt.usec) / 10000;
1255 hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS,
1256 HOSTAPD_LEVEL_DEBUG,
1257 "Received RADIUS packet matched with a pending "
1258 "request, round trip time %d.%02d sec",
1259 roundtrip / 100, roundtrip % 100);
1260 rconf->round_trip_time = roundtrip;
1261
1262 /* Remove ACKed RADIUS packet from retransmit list */
1263 if (prev_req)
1264 prev_req->next = req->next;
1265 else
1266 radius->msgs = req->next;
1267 radius->num_msgs--;
1268
1269 for (i = 0; i < num_handlers; i++) {
1270 RadiusRxResult res;
1271 res = handlers[i].handler(msg, req->msg, req->shared_secret,
1272 req->shared_secret_len,
1273 handlers[i].data);
1274 switch (res) {
1275 case RADIUS_RX_PROCESSED:
1276 radius_msg_free(msg);
1277 /* fall through */
1278 case RADIUS_RX_QUEUED:
1279 radius_client_msg_free(req);
1280 return;
1281 case RADIUS_RX_INVALID_AUTHENTICATOR:
1282 invalid_authenticator++;
1283 /* fall through */
1284 case RADIUS_RX_UNKNOWN:
1285 /* continue with next handler */
1286 break;
1287 }
1288 }
1289
1290 if (invalid_authenticator)
1291 rconf->bad_authenticators++;
1292 else
1293 rconf->unknown_types++;
1294 hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS,
1295 HOSTAPD_LEVEL_DEBUG, "No RADIUS RX handler found "
1296 "(type=%d code=%d id=%d)%s - dropping packet",
1297 msg_type, hdr->code, hdr->identifier,
1298 invalid_authenticator ? " [INVALID AUTHENTICATOR]" :
1299 "");
1300 radius_client_msg_free(req);
1301
1302 fail:
1303 radius_msg_free(msg);
1304 return;
1305
1306 #ifdef CONFIG_RADIUS_TLS
1307 close_tcp:
1308 radius_client_close_tcp(radius, sock, msg_type);
1309 #endif /* CONFIG_RADIUS_TLS */
1310 }
1311
1312
1313 #ifdef CONFIG_RADIUS_TLS
radius_client_write_ready(int sock,void * eloop_ctx,void * sock_ctx)1314 static void radius_client_write_ready(int sock, void *eloop_ctx, void *sock_ctx)
1315 {
1316 struct radius_client_data *radius = eloop_ctx;
1317 RadiusType msg_type = (uintptr_t) sock_ctx;
1318 struct tls_connection *conn = NULL;
1319 struct wpabuf *in, *out = NULL, *appl;
1320 int res = -1;
1321 struct tls_connection_params params;
1322 struct hostapd_radius_server *server;
1323
1324 wpa_printf(MSG_DEBUG, "RADIUS: TCP connection established - start TLS handshake (sock=%d)",
1325 sock);
1326
1327 if (msg_type == RADIUS_ACCT) {
1328 eloop_unregister_sock(sock, EVENT_TYPE_WRITE);
1329 eloop_register_read_sock(sock, radius_client_receive, radius,
1330 (void *) RADIUS_ACCT);
1331 if (radius->acct_tls_conn) {
1332 wpa_printf(MSG_DEBUG,
1333 "RADIUS: Deinit previously used TLS connection");
1334 tls_connection_deinit(radius->tls_ctx,
1335 radius->acct_tls_conn);
1336 radius->acct_tls_conn = NULL;
1337 }
1338 server = radius->conf->acct_server;
1339 } else {
1340 eloop_unregister_sock(sock, EVENT_TYPE_WRITE);
1341 eloop_register_read_sock(sock, radius_client_receive, radius,
1342 (void *) RADIUS_AUTH);
1343 if (radius->auth_tls_conn) {
1344 wpa_printf(MSG_DEBUG,
1345 "RADIUS: Deinit previously used TLS connection");
1346 tls_connection_deinit(radius->tls_ctx,
1347 radius->auth_tls_conn);
1348 radius->auth_tls_conn = NULL;
1349 }
1350 server = radius->conf->auth_server;
1351 }
1352
1353 if (!server)
1354 goto fail;
1355
1356 conn = tls_connection_init(radius->tls_ctx);
1357 if (!conn) {
1358 wpa_printf(MSG_INFO,
1359 "RADIUS: Failed to initiate TLS connection");
1360 goto fail;
1361 }
1362
1363 os_memset(¶ms, 0, sizeof(params));
1364 params.ca_cert = server->ca_cert;
1365 params.client_cert = server->client_cert;
1366 params.private_key = server->private_key;
1367 params.private_key_passwd = server->private_key_passwd;
1368 params.flags = TLS_CONN_DISABLE_TLSv1_0 | TLS_CONN_DISABLE_TLSv1_1;
1369 if (tls_connection_set_params(radius->tls_ctx, conn, ¶ms)) {
1370 wpa_printf(MSG_INFO,
1371 "RADIUS: Failed to set TLS connection parameters");
1372 goto fail;
1373 }
1374
1375 in = NULL;
1376 appl = NULL;
1377 out = tls_connection_handshake(radius->tls_ctx, conn, in, &appl);
1378 if (!out) {
1379 wpa_printf(MSG_DEBUG,
1380 "RADIUS: Could not generate TLS handshake data");
1381 goto fail;
1382 }
1383
1384 if (tls_connection_get_failed(radius->tls_ctx, conn)) {
1385 wpa_printf(MSG_INFO, "RADIUS: TLS handshake failed");
1386 goto fail;
1387 }
1388
1389 wpa_printf(MSG_DEBUG, "RADIUS: Sending %zu bytes of TLS handshake",
1390 wpabuf_len(out));
1391 res = send(sock, wpabuf_head(out), wpabuf_len(out), 0);
1392 if (res < 0) {
1393 wpa_printf(MSG_INFO, "RADIUS: send: %s", strerror(errno));
1394 goto fail;
1395 }
1396 if ((size_t) res != wpabuf_len(out)) {
1397 wpa_printf(MSG_INFO,
1398 "RADIUS: Could not send all data for TLS handshake: only %d bytes sent",
1399 res);
1400 goto fail;
1401 }
1402 wpabuf_free(out);
1403
1404 if (msg_type == RADIUS_ACCT)
1405 radius->acct_tls_conn = conn;
1406 else
1407 radius->auth_tls_conn = conn;
1408 return;
1409
1410 fail:
1411 wpa_printf(MSG_INFO, "RADIUS: Failed to perform TLS handshake");
1412 tls_connection_deinit(radius->tls_ctx, conn);
1413 wpabuf_free(out);
1414 radius_client_close_tcp(radius, sock, msg_type);
1415 }
1416 #endif /* CONFIG_RADIUS_TLS */
1417
1418
1419 /**
1420 * radius_client_get_id - Get an identifier for a new RADIUS message
1421 * @radius: RADIUS client context from radius_client_init()
1422 * Returns: Allocated identifier
1423 *
1424 * This function is used to fetch a unique (among pending requests) identifier
1425 * for a new RADIUS message.
1426 */
radius_client_get_id(struct radius_client_data * radius)1427 u8 radius_client_get_id(struct radius_client_data *radius)
1428 {
1429 struct radius_msg_list *entry, *prev, *_remove;
1430 u8 id = radius->next_radius_identifier++;
1431
1432 /* remove entries with matching id from retransmit list to avoid
1433 * using new reply from the RADIUS server with an old request */
1434 entry = radius->msgs;
1435 prev = NULL;
1436 while (entry) {
1437 if (radius_msg_get_hdr(entry->msg)->identifier == id) {
1438 hostapd_logger(radius->ctx, entry->addr,
1439 HOSTAPD_MODULE_RADIUS,
1440 HOSTAPD_LEVEL_DEBUG,
1441 "Removing pending RADIUS message, "
1442 "since its id (%d) is reused", id);
1443 if (prev)
1444 prev->next = entry->next;
1445 else
1446 radius->msgs = entry->next;
1447 _remove = entry;
1448 } else {
1449 _remove = NULL;
1450 prev = entry;
1451 }
1452 entry = entry->next;
1453
1454 if (_remove)
1455 radius_client_msg_free(_remove);
1456 }
1457
1458 return id;
1459 }
1460
1461
1462 /**
1463 * radius_client_flush - Flush all pending RADIUS client messages
1464 * @radius: RADIUS client context from radius_client_init()
1465 * @only_auth: Whether only authentication messages are removed
1466 */
radius_client_flush(struct radius_client_data * radius,int only_auth)1467 void radius_client_flush(struct radius_client_data *radius, int only_auth)
1468 {
1469 struct radius_msg_list *entry, *prev, *tmp;
1470
1471 if (!radius)
1472 return;
1473
1474 prev = NULL;
1475 entry = radius->msgs;
1476
1477 while (entry) {
1478 if (!only_auth || entry->msg_type == RADIUS_AUTH) {
1479 if (prev)
1480 prev->next = entry->next;
1481 else
1482 radius->msgs = entry->next;
1483
1484 tmp = entry;
1485 entry = entry->next;
1486 radius_client_msg_free(tmp);
1487 radius->num_msgs--;
1488 } else {
1489 prev = entry;
1490 entry = entry->next;
1491 }
1492 }
1493
1494 if (radius->msgs == NULL)
1495 eloop_cancel_timeout(radius_client_timer, radius, NULL);
1496 }
1497
1498
radius_client_update_acct_msgs(struct radius_client_data * radius,const u8 * shared_secret,size_t shared_secret_len)1499 static void radius_client_update_acct_msgs(struct radius_client_data *radius,
1500 const u8 *shared_secret,
1501 size_t shared_secret_len)
1502 {
1503 struct radius_msg_list *entry;
1504
1505 if (!radius)
1506 return;
1507
1508 for (entry = radius->msgs; entry; entry = entry->next) {
1509 if (entry->msg_type == RADIUS_ACCT) {
1510 entry->shared_secret = shared_secret;
1511 entry->shared_secret_len = shared_secret_len;
1512 radius_msg_finish_acct(entry->msg, shared_secret,
1513 shared_secret_len);
1514 }
1515 }
1516 }
1517
1518
1519 static int
radius_change_server(struct radius_client_data * radius,struct hostapd_radius_server * nserv,struct hostapd_radius_server * oserv,int auth)1520 radius_change_server(struct radius_client_data *radius,
1521 struct hostapd_radius_server *nserv,
1522 struct hostapd_radius_server *oserv,
1523 int auth)
1524 {
1525 struct sockaddr_in serv, claddr;
1526 #ifdef CONFIG_IPV6
1527 struct sockaddr_in6 serv6, claddr6;
1528 #endif /* CONFIG_IPV6 */
1529 struct sockaddr *addr, *cl_addr;
1530 socklen_t addrlen, claddrlen;
1531 char abuf[50];
1532 int sel_sock;
1533 struct radius_msg_list *entry;
1534 struct hostapd_radius_servers *conf = radius->conf;
1535 int type = SOCK_DGRAM;
1536 bool tls = nserv->tls;
1537
1538 if (tls) {
1539 #ifdef CONFIG_RADIUS_TLS
1540 type = SOCK_STREAM;
1541 #else /* CONFIG_RADIUS_TLS */
1542 wpa_printf(MSG_ERROR, "RADIUS: TLS not supported");
1543 return -1;
1544 #endif /* CONFIG_RADIUS_TLS */
1545 }
1546
1547 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
1548 HOSTAPD_LEVEL_INFO,
1549 "%s server %s:%d",
1550 auth ? "Authentication" : "Accounting",
1551 hostapd_ip_txt(&nserv->addr, abuf, sizeof(abuf)),
1552 nserv->port);
1553
1554 if (oserv && oserv == nserv) {
1555 /* Reconnect to same server, flush */
1556 if (auth)
1557 radius_client_flush(radius, 1);
1558 }
1559
1560 if (oserv && oserv != nserv &&
1561 (nserv->shared_secret_len != oserv->shared_secret_len ||
1562 os_memcmp(nserv->shared_secret, oserv->shared_secret,
1563 nserv->shared_secret_len) != 0)) {
1564 /* Pending RADIUS packets used different shared secret, so
1565 * they need to be modified. Update accounting message
1566 * authenticators here. Authentication messages are removed
1567 * since they would require more changes and the new RADIUS
1568 * server may not be prepared to receive them anyway due to
1569 * missing state information. Client will likely retry
1570 * authentication, so this should not be an issue. */
1571 if (auth)
1572 radius_client_flush(radius, 1);
1573 else {
1574 radius_client_update_acct_msgs(
1575 radius, nserv->shared_secret,
1576 nserv->shared_secret_len);
1577 }
1578 }
1579
1580 /* Reset retry counters */
1581 for (entry = radius->msgs; oserv && entry; entry = entry->next) {
1582 if ((auth && entry->msg_type != RADIUS_AUTH) ||
1583 (!auth && entry->msg_type != RADIUS_ACCT))
1584 continue;
1585 entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT;
1586 entry->attempts = 0;
1587 entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2;
1588 }
1589
1590 if (radius->msgs) {
1591 eloop_cancel_timeout(radius_client_timer, radius, NULL);
1592 eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT, 0,
1593 radius_client_timer, radius, NULL);
1594 }
1595
1596 switch (nserv->addr.af) {
1597 case AF_INET:
1598 os_memset(&serv, 0, sizeof(serv));
1599 serv.sin_family = AF_INET;
1600 serv.sin_addr.s_addr = nserv->addr.u.v4.s_addr;
1601 serv.sin_port = htons(nserv->port);
1602 addr = (struct sockaddr *) &serv;
1603 addrlen = sizeof(serv);
1604 sel_sock = socket(PF_INET, type, 0);
1605 if (sel_sock >= 0)
1606 radius_client_disable_pmtu_discovery(sel_sock);
1607 break;
1608 #ifdef CONFIG_IPV6
1609 case AF_INET6:
1610 os_memset(&serv6, 0, sizeof(serv6));
1611 serv6.sin6_family = AF_INET6;
1612 os_memcpy(&serv6.sin6_addr, &nserv->addr.u.v6,
1613 sizeof(struct in6_addr));
1614 serv6.sin6_port = htons(nserv->port);
1615 addr = (struct sockaddr *) &serv6;
1616 addrlen = sizeof(serv6);
1617 sel_sock = socket(PF_INET6, type, 0);
1618 break;
1619 #endif /* CONFIG_IPV6 */
1620 default:
1621 return -1;
1622 }
1623
1624 if (sel_sock < 0) {
1625 wpa_printf(MSG_INFO,
1626 "RADIUS: Failed to open server socket (af=%d auth=%d)",
1627 nserv->addr.af, auth);
1628 return -1;
1629 }
1630
1631 #ifdef CONFIG_RADIUS_TLS
1632 if (tls && fcntl(sel_sock, F_SETFL, O_NONBLOCK) != 0) {
1633 wpa_printf(MSG_DEBUG, "RADIUS: fnctl(O_NONBLOCK) failed: %s",
1634 strerror(errno));
1635 close(sel_sock);
1636 return -1;
1637 }
1638 #endif /* CONFIG_RADIUS_TLS */
1639
1640 #ifdef __linux__
1641 if (conf->force_client_dev && conf->force_client_dev[0]) {
1642 if (setsockopt(sel_sock, SOL_SOCKET, SO_BINDTODEVICE,
1643 conf->force_client_dev,
1644 os_strlen(conf->force_client_dev)) < 0) {
1645 wpa_printf(MSG_ERROR,
1646 "RADIUS: setsockopt[SO_BINDTODEVICE]: %s",
1647 strerror(errno));
1648 /* Probably not a critical error; continue on and hope
1649 * for the best. */
1650 } else {
1651 wpa_printf(MSG_DEBUG,
1652 "RADIUS: Bound client socket to device: %s",
1653 conf->force_client_dev);
1654 }
1655 }
1656 #endif /* __linux__ */
1657
1658 if (conf->force_client_addr) {
1659 switch (conf->client_addr.af) {
1660 case AF_INET:
1661 os_memset(&claddr, 0, sizeof(claddr));
1662 claddr.sin_family = AF_INET;
1663 claddr.sin_addr.s_addr = conf->client_addr.u.v4.s_addr;
1664 claddr.sin_port = htons(0);
1665 cl_addr = (struct sockaddr *) &claddr;
1666 claddrlen = sizeof(claddr);
1667 break;
1668 #ifdef CONFIG_IPV6
1669 case AF_INET6:
1670 os_memset(&claddr6, 0, sizeof(claddr6));
1671 claddr6.sin6_family = AF_INET6;
1672 os_memcpy(&claddr6.sin6_addr, &conf->client_addr.u.v6,
1673 sizeof(struct in6_addr));
1674 claddr6.sin6_port = htons(0);
1675 cl_addr = (struct sockaddr *) &claddr6;
1676 claddrlen = sizeof(claddr6);
1677 break;
1678 #endif /* CONFIG_IPV6 */
1679 default:
1680 close(sel_sock);
1681 return -1;
1682 }
1683
1684 if (bind(sel_sock, cl_addr, claddrlen) < 0) {
1685 wpa_printf(MSG_INFO, "bind[radius]: %s",
1686 strerror(errno));
1687 close(sel_sock);
1688 return -2;
1689 }
1690 }
1691
1692 if (connect(sel_sock, addr, addrlen) < 0) {
1693 if (nserv->tls && errno == EINPROGRESS) {
1694 wpa_printf(MSG_DEBUG,
1695 "RADIUS: TCP connection establishment in progress (sock %d)",
1696 sel_sock);
1697 } else {
1698 wpa_printf(MSG_INFO, "connect[radius]: %s",
1699 strerror(errno));
1700 close(sel_sock);
1701 return -2;
1702 }
1703 }
1704
1705 #ifndef CONFIG_NATIVE_WINDOWS
1706 switch (nserv->addr.af) {
1707 case AF_INET:
1708 claddrlen = sizeof(claddr);
1709 if (getsockname(sel_sock, (struct sockaddr *) &claddr,
1710 &claddrlen) == 0) {
1711 wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u",
1712 inet_ntoa(claddr.sin_addr),
1713 ntohs(claddr.sin_port));
1714 }
1715 break;
1716 #ifdef CONFIG_IPV6
1717 case AF_INET6: {
1718 claddrlen = sizeof(claddr6);
1719 if (getsockname(sel_sock, (struct sockaddr *) &claddr6,
1720 &claddrlen) == 0) {
1721 wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u",
1722 inet_ntop(AF_INET6, &claddr6.sin6_addr,
1723 abuf, sizeof(abuf)),
1724 ntohs(claddr6.sin6_port));
1725 }
1726 break;
1727 }
1728 #endif /* CONFIG_IPV6 */
1729 }
1730 #endif /* CONFIG_NATIVE_WINDOWS */
1731
1732 if (auth) {
1733 radius_close_auth_socket(radius);
1734 radius->auth_sock = sel_sock;
1735 } else {
1736 radius_close_acct_socket(radius);
1737 radius->acct_sock = sel_sock;
1738 }
1739
1740 if (!tls)
1741 eloop_register_read_sock(sel_sock, radius_client_receive,
1742 radius,
1743 auth ? (void *) RADIUS_AUTH :
1744 (void *) RADIUS_ACCT);
1745 #ifdef CONFIG_RADIUS_TLS
1746 if (tls)
1747 eloop_register_sock(sel_sock, EVENT_TYPE_WRITE,
1748 radius_client_write_ready, radius,
1749 auth ? (void *) RADIUS_AUTH :
1750 (void *) RADIUS_ACCT);
1751 #endif /* CONFIG_RADIUS_TLS */
1752
1753 if (auth) {
1754 radius->auth_tls = nserv->tls;
1755 radius->auth_tls_ready = false;
1756 } else {
1757 radius->acct_tls = nserv->tls;
1758 radius->acct_tls_ready = false;
1759 }
1760
1761 return 0;
1762 }
1763
1764
radius_retry_primary_timer(void * eloop_ctx,void * timeout_ctx)1765 static void radius_retry_primary_timer(void *eloop_ctx, void *timeout_ctx)
1766 {
1767 struct radius_client_data *radius = eloop_ctx;
1768 struct hostapd_radius_servers *conf = radius->conf;
1769 struct hostapd_radius_server *oserv;
1770
1771 if (radius->auth_sock >= 0 && conf->auth_servers &&
1772 conf->auth_server != conf->auth_servers) {
1773 oserv = conf->auth_server;
1774 conf->auth_server = conf->auth_servers;
1775 if (radius_change_server(radius, conf->auth_server, oserv,
1776 1) < 0) {
1777 conf->auth_server = oserv;
1778 radius_change_server(radius, oserv, conf->auth_server,
1779 1);
1780 }
1781 }
1782
1783 if (radius->acct_sock >= 0 && conf->acct_servers &&
1784 conf->acct_server != conf->acct_servers) {
1785 oserv = conf->acct_server;
1786 conf->acct_server = conf->acct_servers;
1787 if (radius_change_server(radius, conf->acct_server, oserv,
1788 0) < 0) {
1789 conf->acct_server = oserv;
1790 radius_change_server(radius, oserv, conf->acct_server,
1791 0);
1792 }
1793 }
1794
1795 if (conf->retry_primary_interval)
1796 eloop_register_timeout(conf->retry_primary_interval, 0,
1797 radius_retry_primary_timer, radius,
1798 NULL);
1799 }
1800
1801
radius_client_init_auth(struct radius_client_data * radius)1802 static int radius_client_init_auth(struct radius_client_data *radius)
1803 {
1804 radius_close_auth_socket(radius);
1805 return radius_change_server(radius, radius->conf->auth_server, NULL, 1);
1806 }
1807
1808
radius_client_init_acct(struct radius_client_data * radius)1809 static int radius_client_init_acct(struct radius_client_data *radius)
1810 {
1811 radius_close_acct_socket(radius);
1812 return radius_change_server(radius, radius->conf->acct_server, NULL, 0);
1813 }
1814
1815
1816 #ifdef CONFIG_RADIUS_TLS
radius_tls_event_cb(void * ctx,enum tls_event ev,union tls_event_data * data)1817 static void radius_tls_event_cb(void *ctx, enum tls_event ev,
1818 union tls_event_data *data)
1819 {
1820 wpa_printf(MSG_DEBUG, "RADIUS: TLS event %d", ev);
1821 }
1822 #endif /* CONFIG_RADIUS_TLS */
1823
1824
1825 /**
1826 * radius_client_init - Initialize RADIUS client
1827 * @ctx: Callback context to be used in hostapd_logger() calls
1828 * @conf: RADIUS client configuration (RADIUS servers)
1829 * Returns: Pointer to private RADIUS client context or %NULL on failure
1830 *
1831 * The caller is responsible for keeping the configuration data available for
1832 * the lifetime of the RADIUS client, i.e., until radius_client_deinit() is
1833 * called for the returned context pointer.
1834 */
1835 struct radius_client_data *
radius_client_init(void * ctx,struct hostapd_radius_servers * conf)1836 radius_client_init(void *ctx, struct hostapd_radius_servers *conf)
1837 {
1838 struct radius_client_data *radius;
1839
1840 radius = os_zalloc(sizeof(struct radius_client_data));
1841 if (radius == NULL)
1842 return NULL;
1843
1844 radius->ctx = ctx;
1845 radius->conf = conf;
1846 radius->auth_sock = radius->acct_sock = -1;
1847
1848 if (conf->auth_server && radius_client_init_auth(radius) == -1) {
1849 radius_client_deinit(radius);
1850 return NULL;
1851 }
1852
1853 if (conf->acct_server && radius_client_init_acct(radius) == -1) {
1854 radius_client_deinit(radius);
1855 return NULL;
1856 }
1857
1858 if (conf->retry_primary_interval)
1859 eloop_register_timeout(conf->retry_primary_interval, 0,
1860 radius_retry_primary_timer, radius,
1861 NULL);
1862
1863 #ifdef CONFIG_RADIUS_TLS
1864 if ((conf->auth_server && conf->auth_server->tls) ||
1865 (conf->acct_server && conf->acct_server->tls)) {
1866 struct tls_config tls_conf;
1867
1868 os_memset(&tls_conf, 0, sizeof(tls_conf));
1869 tls_conf.event_cb = radius_tls_event_cb;
1870 radius->tls_ctx = tls_init(&tls_conf);
1871 if (!radius->tls_ctx) {
1872 radius_client_deinit(radius);
1873 return NULL;
1874 }
1875 }
1876 #endif /* CONFIG_RADIUS_TLS */
1877
1878
1879 return radius;
1880 }
1881
1882
1883 /**
1884 * radius_client_deinit - Deinitialize RADIUS client
1885 * @radius: RADIUS client context from radius_client_init()
1886 */
radius_client_deinit(struct radius_client_data * radius)1887 void radius_client_deinit(struct radius_client_data *radius)
1888 {
1889 if (!radius)
1890 return;
1891
1892 radius_close_auth_socket(radius);
1893 radius_close_acct_socket(radius);
1894
1895 eloop_cancel_timeout(radius_retry_primary_timer, radius, NULL);
1896
1897 radius_client_flush(radius, 0);
1898 os_free(radius->auth_handlers);
1899 os_free(radius->acct_handlers);
1900 #ifdef CONFIG_RADIUS_TLS
1901 if (radius->tls_ctx) {
1902 tls_connection_deinit(radius->tls_ctx, radius->auth_tls_conn);
1903 tls_connection_deinit(radius->tls_ctx, radius->acct_tls_conn);
1904 tls_deinit(radius->tls_ctx);
1905 }
1906 #endif /* CONFIG_RADIUS_TLS */
1907 os_free(radius);
1908 }
1909
1910
1911 /**
1912 * radius_client_flush_auth - Flush pending RADIUS messages for an address
1913 * @radius: RADIUS client context from radius_client_init()
1914 * @addr: MAC address of the related device
1915 *
1916 * This function can be used to remove pending RADIUS authentication messages
1917 * that are related to a specific device. The addr parameter is matched with
1918 * the one used in radius_client_send() call that was used to transmit the
1919 * authentication request.
1920 */
radius_client_flush_auth(struct radius_client_data * radius,const u8 * addr)1921 void radius_client_flush_auth(struct radius_client_data *radius,
1922 const u8 *addr)
1923 {
1924 struct radius_msg_list *entry, *prev, *tmp;
1925
1926 prev = NULL;
1927 entry = radius->msgs;
1928 while (entry) {
1929 if (entry->msg_type == RADIUS_AUTH &&
1930 ether_addr_equal(entry->addr, addr)) {
1931 hostapd_logger(radius->ctx, addr,
1932 HOSTAPD_MODULE_RADIUS,
1933 HOSTAPD_LEVEL_DEBUG,
1934 "Removing pending RADIUS authentication"
1935 " message for removed client");
1936
1937 if (prev)
1938 prev->next = entry->next;
1939 else
1940 radius->msgs = entry->next;
1941
1942 tmp = entry;
1943 entry = entry->next;
1944 radius_client_msg_free(tmp);
1945 radius->num_msgs--;
1946 continue;
1947 }
1948
1949 prev = entry;
1950 entry = entry->next;
1951 }
1952 }
1953
1954
radius_client_dump_auth_server(char * buf,size_t buflen,struct hostapd_radius_server * serv,struct radius_client_data * cli)1955 static int radius_client_dump_auth_server(char *buf, size_t buflen,
1956 struct hostapd_radius_server *serv,
1957 struct radius_client_data *cli)
1958 {
1959 int pending = 0;
1960 struct radius_msg_list *msg;
1961 char abuf[50];
1962
1963 if (cli) {
1964 for (msg = cli->msgs; msg; msg = msg->next) {
1965 if (msg->msg_type == RADIUS_AUTH)
1966 pending++;
1967 }
1968 }
1969
1970 return os_snprintf(buf, buflen,
1971 "radiusAuthServerIndex=%d\n"
1972 "radiusAuthServerAddress=%s\n"
1973 "radiusAuthClientServerPortNumber=%d\n"
1974 "radiusAuthClientRoundTripTime=%d\n"
1975 "radiusAuthClientAccessRequests=%u\n"
1976 "radiusAuthClientAccessRetransmissions=%u\n"
1977 "radiusAuthClientAccessAccepts=%u\n"
1978 "radiusAuthClientAccessRejects=%u\n"
1979 "radiusAuthClientAccessChallenges=%u\n"
1980 "radiusAuthClientMalformedAccessResponses=%u\n"
1981 "radiusAuthClientBadAuthenticators=%u\n"
1982 "radiusAuthClientPendingRequests=%u\n"
1983 "radiusAuthClientTimeouts=%u\n"
1984 "radiusAuthClientUnknownTypes=%u\n"
1985 "radiusAuthClientPacketsDropped=%u\n",
1986 serv->index,
1987 hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)),
1988 serv->port,
1989 serv->round_trip_time,
1990 serv->requests,
1991 serv->retransmissions,
1992 serv->access_accepts,
1993 serv->access_rejects,
1994 serv->access_challenges,
1995 serv->malformed_responses,
1996 serv->bad_authenticators,
1997 pending,
1998 serv->timeouts,
1999 serv->unknown_types,
2000 serv->packets_dropped);
2001 }
2002
2003
radius_client_dump_acct_server(char * buf,size_t buflen,struct hostapd_radius_server * serv,struct radius_client_data * cli)2004 static int radius_client_dump_acct_server(char *buf, size_t buflen,
2005 struct hostapd_radius_server *serv,
2006 struct radius_client_data *cli)
2007 {
2008 int pending = 0;
2009 struct radius_msg_list *msg;
2010 char abuf[50];
2011
2012 if (cli) {
2013 for (msg = cli->msgs; msg; msg = msg->next) {
2014 if (msg->msg_type == RADIUS_ACCT ||
2015 msg->msg_type == RADIUS_ACCT_INTERIM)
2016 pending++;
2017 }
2018 }
2019
2020 return os_snprintf(buf, buflen,
2021 "radiusAccServerIndex=%d\n"
2022 "radiusAccServerAddress=%s\n"
2023 "radiusAccClientServerPortNumber=%d\n"
2024 "radiusAccClientRoundTripTime=%d\n"
2025 "radiusAccClientRequests=%u\n"
2026 "radiusAccClientRetransmissions=%u\n"
2027 "radiusAccClientResponses=%u\n"
2028 "radiusAccClientMalformedResponses=%u\n"
2029 "radiusAccClientBadAuthenticators=%u\n"
2030 "radiusAccClientPendingRequests=%u\n"
2031 "radiusAccClientTimeouts=%u\n"
2032 "radiusAccClientUnknownTypes=%u\n"
2033 "radiusAccClientPacketsDropped=%u\n",
2034 serv->index,
2035 hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)),
2036 serv->port,
2037 serv->round_trip_time,
2038 serv->requests,
2039 serv->retransmissions,
2040 serv->responses,
2041 serv->malformed_responses,
2042 serv->bad_authenticators,
2043 pending,
2044 serv->timeouts,
2045 serv->unknown_types,
2046 serv->packets_dropped);
2047 }
2048
2049
2050 /**
2051 * radius_client_get_mib - Get RADIUS client MIB information
2052 * @radius: RADIUS client context from radius_client_init()
2053 * @buf: Buffer for returning MIB data in text format
2054 * @buflen: Maximum buf length in octets
2055 * Returns: Number of octets written into the buffer
2056 */
radius_client_get_mib(struct radius_client_data * radius,char * buf,size_t buflen)2057 int radius_client_get_mib(struct radius_client_data *radius, char *buf,
2058 size_t buflen)
2059 {
2060 struct hostapd_radius_servers *conf;
2061 int i;
2062 struct hostapd_radius_server *serv;
2063 int count = 0;
2064
2065 if (!radius)
2066 return 0;
2067
2068 conf = radius->conf;
2069
2070 if (conf->auth_servers) {
2071 for (i = 0; i < conf->num_auth_servers; i++) {
2072 serv = &conf->auth_servers[i];
2073 count += radius_client_dump_auth_server(
2074 buf + count, buflen - count, serv,
2075 serv == conf->auth_server ?
2076 radius : NULL);
2077 }
2078 }
2079
2080 if (conf->acct_servers) {
2081 for (i = 0; i < conf->num_acct_servers; i++) {
2082 serv = &conf->acct_servers[i];
2083 count += radius_client_dump_acct_server(
2084 buf + count, buflen - count, serv,
2085 serv == conf->acct_server ?
2086 radius : NULL);
2087 }
2088 }
2089
2090 return count;
2091 }
2092
2093
radius_client_reconfig(struct radius_client_data * radius,struct hostapd_radius_servers * conf)2094 void radius_client_reconfig(struct radius_client_data *radius,
2095 struct hostapd_radius_servers *conf)
2096 {
2097 if (radius)
2098 radius->conf = conf;
2099 }
2100