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 if (radius_msg_finish_acct(entry->msg, entry->shared_secret,
486 entry->shared_secret_len) < 0) {
487 wpa_printf(MSG_INFO, "Failed to build RADIUS message");
488 return -1;
489 }
490 if (radius->conf->msg_dumps)
491 radius_msg_dump(entry->msg);
492 }
493
494 /* retransmit; remove entry if too many attempts */
495 if (entry->accu_attempts >= RADIUS_CLIENT_MAX_FAILOVER *
496 RADIUS_CLIENT_NUM_FAILOVER * num_servers) {
497 wpa_printf(MSG_INFO,
498 "RADIUS: Removing un-ACKed message due to too many failed retransmit attempts");
499 return 1;
500 }
501
502 entry->attempts++;
503 entry->accu_attempts++;
504 hostapd_logger(radius->ctx, entry->addr, HOSTAPD_MODULE_RADIUS,
505 HOSTAPD_LEVEL_DEBUG, "Resending RADIUS message (id=%d)",
506 radius_msg_get_hdr(entry->msg)->identifier);
507
508 os_get_reltime(&entry->last_attempt);
509 buf = radius_msg_get_buf(entry->msg);
510 #ifdef CONFIG_RADIUS_TLS
511 if (conn) {
512 out = tls_connection_encrypt(radius->tls_ctx, conn, buf);
513 if (!out) {
514 wpa_printf(MSG_INFO,
515 "RADIUS: Failed to encrypt RADIUS message (TLS)");
516 return -1;
517 }
518 wpa_printf(MSG_DEBUG,
519 "RADIUS: TLS encryption of %zu bytes of plaintext to %zu bytes of ciphertext",
520 wpabuf_len(buf), wpabuf_len(out));
521 buf = out;
522 }
523 #endif /* CONFIG_RADIUS_TLS */
524
525 wpa_printf(MSG_DEBUG, "RADIUS: Send %zu bytes to the server",
526 wpabuf_len(buf));
527 if (send(s, wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
528 if (radius_client_handle_send_error(radius, s, entry->msg_type)
529 > 0) {
530 #ifdef CONFIG_RADIUS_TLS
531 wpabuf_free(out);
532 #endif /* CONFIG_RADIUS_TLS */
533 return 0;
534 }
535 }
536 #ifdef CONFIG_RADIUS_TLS
537 wpabuf_free(out);
538
539 not_ready:
540 #endif /* CONFIG_RADIUS_TLS */
541
542 entry->next_try = now + entry->next_wait;
543 entry->next_wait *= 2;
544 if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT)
545 entry->next_wait = RADIUS_CLIENT_MAX_WAIT;
546
547 return 0;
548 }
549
550
radius_client_timer(void * eloop_ctx,void * timeout_ctx)551 static void radius_client_timer(void *eloop_ctx, void *timeout_ctx)
552 {
553 struct radius_client_data *radius = eloop_ctx;
554 struct os_reltime now;
555 os_time_t first;
556 struct radius_msg_list *entry, *prev, *tmp;
557 int auth_failover = 0, acct_failover = 0;
558 size_t prev_num_msgs;
559 int s;
560
561 entry = radius->msgs;
562 if (!entry)
563 return;
564
565 os_get_reltime(&now);
566
567 while (entry) {
568 if (now.sec >= entry->next_try) {
569 s = entry->msg_type == RADIUS_AUTH ? radius->auth_sock :
570 radius->acct_sock;
571 if (entry->attempts >= RADIUS_CLIENT_NUM_FAILOVER ||
572 (s < 0 && entry->attempts > 0)) {
573 if (entry->msg_type == RADIUS_ACCT ||
574 entry->msg_type == RADIUS_ACCT_INTERIM)
575 acct_failover++;
576 else
577 auth_failover++;
578 }
579 }
580 entry = entry->next;
581 }
582
583 if (auth_failover)
584 radius_client_auth_failover(radius);
585
586 if (acct_failover)
587 radius_client_acct_failover(radius);
588
589 entry = radius->msgs;
590 first = 0;
591
592 prev = NULL;
593 while (entry) {
594 prev_num_msgs = radius->num_msgs;
595 if (now.sec >= entry->next_try &&
596 radius_client_retransmit(radius, entry, now.sec)) {
597 if (prev)
598 prev->next = entry->next;
599 else
600 radius->msgs = entry->next;
601
602 tmp = entry;
603 entry = entry->next;
604 radius_client_msg_free(tmp);
605 radius->num_msgs--;
606 continue;
607 }
608
609 if (prev_num_msgs != radius->num_msgs) {
610 wpa_printf(MSG_DEBUG,
611 "RADIUS: Message removed from queue - restart from beginning");
612 entry = radius->msgs;
613 prev = NULL;
614 continue;
615 }
616
617 if (first == 0 || entry->next_try < first)
618 first = entry->next_try;
619
620 prev = entry;
621 entry = entry->next;
622 }
623
624 if (radius->msgs) {
625 if (first < now.sec)
626 first = now.sec;
627 eloop_cancel_timeout(radius_client_timer, radius, NULL);
628 eloop_register_timeout(first - now.sec, 0,
629 radius_client_timer, radius, NULL);
630 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
631 HOSTAPD_LEVEL_DEBUG, "Next RADIUS client "
632 "retransmit in %ld seconds",
633 (long int) (first - now.sec));
634 }
635 }
636
637
radius_client_auth_failover(struct radius_client_data * radius)638 static void radius_client_auth_failover(struct radius_client_data *radius)
639 {
640 struct hostapd_radius_servers *conf = radius->conf;
641 struct hostapd_radius_server *next, *old;
642 struct radius_msg_list *entry;
643 char abuf[50];
644
645 old = conf->auth_server;
646 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
647 HOSTAPD_LEVEL_NOTICE,
648 "No response from Authentication server %s:%d - failover",
649 hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)),
650 old->port);
651
652 for (entry = radius->msgs; entry; entry = entry->next) {
653 if (entry->msg_type == RADIUS_AUTH)
654 old->timeouts++;
655 }
656
657 next = old + 1;
658 if (next > &(conf->auth_servers[conf->num_auth_servers - 1]))
659 next = conf->auth_servers;
660 conf->auth_server = next;
661 radius_change_server(radius, next, old, 1);
662 }
663
664
radius_client_acct_failover(struct radius_client_data * radius)665 static void radius_client_acct_failover(struct radius_client_data *radius)
666 {
667 struct hostapd_radius_servers *conf = radius->conf;
668 struct hostapd_radius_server *next, *old;
669 struct radius_msg_list *entry;
670 char abuf[50];
671
672 old = conf->acct_server;
673 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
674 HOSTAPD_LEVEL_NOTICE,
675 "No response from Accounting server %s:%d - failover",
676 hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)),
677 old->port);
678
679 for (entry = radius->msgs; entry; entry = entry->next) {
680 if (entry->msg_type == RADIUS_ACCT ||
681 entry->msg_type == RADIUS_ACCT_INTERIM)
682 old->timeouts++;
683 }
684
685 next = old + 1;
686 if (next > &conf->acct_servers[conf->num_acct_servers - 1])
687 next = conf->acct_servers;
688 conf->acct_server = next;
689 radius_change_server(radius, next, old, 0);
690 }
691
692
radius_client_update_timeout(struct radius_client_data * radius)693 static void radius_client_update_timeout(struct radius_client_data *radius)
694 {
695 struct os_reltime now;
696 os_time_t first;
697 struct radius_msg_list *entry;
698
699 eloop_cancel_timeout(radius_client_timer, radius, NULL);
700
701 if (radius->msgs == NULL) {
702 return;
703 }
704
705 first = 0;
706 for (entry = radius->msgs; entry; entry = entry->next) {
707 if (first == 0 || entry->next_try < first)
708 first = entry->next_try;
709 }
710
711 os_get_reltime(&now);
712 if (first < now.sec)
713 first = now.sec;
714 eloop_register_timeout(first - now.sec, 0, radius_client_timer, radius,
715 NULL);
716 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
717 HOSTAPD_LEVEL_DEBUG, "Next RADIUS client retransmit in"
718 " %ld seconds", (long int) (first - now.sec));
719 }
720
721
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)722 static void radius_client_list_add(struct radius_client_data *radius,
723 struct radius_msg *msg,
724 RadiusType msg_type,
725 const u8 *shared_secret,
726 size_t shared_secret_len, const u8 *addr)
727 {
728 struct radius_msg_list *entry, *prev;
729
730 if (eloop_terminated()) {
731 /* No point in adding entries to retransmit queue since event
732 * loop has already been terminated. */
733 radius_msg_free(msg);
734 return;
735 }
736
737 entry = os_zalloc(sizeof(*entry));
738 if (entry == NULL) {
739 wpa_printf(MSG_INFO, "RADIUS: Failed to add packet into retransmit list");
740 radius_msg_free(msg);
741 return;
742 }
743
744 if (addr)
745 os_memcpy(entry->addr, addr, ETH_ALEN);
746 entry->msg = msg;
747 entry->msg_type = msg_type;
748 entry->shared_secret = shared_secret;
749 entry->shared_secret_len = shared_secret_len;
750 os_get_reltime(&entry->last_attempt);
751 entry->first_try = entry->last_attempt.sec;
752 entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT;
753 entry->attempts = 1;
754 entry->accu_attempts = 1;
755 entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2;
756 if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT)
757 entry->next_wait = RADIUS_CLIENT_MAX_WAIT;
758 entry->next = radius->msgs;
759 radius->msgs = entry;
760 radius_client_update_timeout(radius);
761
762 if (radius->num_msgs >= RADIUS_CLIENT_MAX_ENTRIES) {
763 wpa_printf(MSG_INFO, "RADIUS: Removing the oldest un-ACKed packet due to retransmit list limits");
764 prev = NULL;
765 while (entry->next) {
766 prev = entry;
767 entry = entry->next;
768 }
769 if (prev) {
770 prev->next = NULL;
771 radius_client_msg_free(entry);
772 }
773 } else
774 radius->num_msgs++;
775 }
776
777
radius_client_disable_pmtu_discovery(int s)778 static int radius_client_disable_pmtu_discovery(int s)
779 {
780 int r = -1;
781 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
782 /* Turn off Path MTU discovery on IPv4/UDP sockets. */
783 int action = IP_PMTUDISC_DONT;
784 r = setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &action,
785 sizeof(action));
786 if (r == -1)
787 wpa_printf(MSG_ERROR, "RADIUS: Failed to set IP_MTU_DISCOVER: %s",
788 strerror(errno));
789 #endif
790 return r;
791 }
792
793
radius_close_auth_socket(struct radius_client_data * radius)794 static void radius_close_auth_socket(struct radius_client_data *radius)
795 {
796 if (radius->auth_sock >= 0) {
797 #ifdef CONFIG_RADIUS_TLS
798 if (radius->conf->auth_server->tls)
799 eloop_unregister_sock(radius->auth_sock,
800 EVENT_TYPE_WRITE);
801 #endif /* CONFIG_RADIUS_TLS */
802 eloop_unregister_read_sock(radius->auth_sock);
803 close(radius->auth_sock);
804 radius->auth_sock = -1;
805 }
806 }
807
808
radius_close_acct_socket(struct radius_client_data * radius)809 static void radius_close_acct_socket(struct radius_client_data *radius)
810 {
811 if (radius->acct_sock >= 0) {
812 #ifdef CONFIG_RADIUS_TLS
813 if (radius->conf->acct_server->tls)
814 eloop_unregister_sock(radius->acct_sock,
815 EVENT_TYPE_WRITE);
816 #endif /* CONFIG_RADIUS_TLS */
817 eloop_unregister_read_sock(radius->acct_sock);
818 close(radius->acct_sock);
819 radius->acct_sock = -1;
820 }
821 }
822
823
824 /**
825 * radius_client_send - Send a RADIUS request
826 * @radius: RADIUS client context from radius_client_init()
827 * @msg: RADIUS message to be sent
828 * @msg_type: Message type (RADIUS_AUTH, RADIUS_ACCT, RADIUS_ACCT_INTERIM)
829 * @addr: MAC address of the device related to this message or %NULL
830 * Returns: 0 on success, -1 on failure
831 *
832 * This function is used to transmit a RADIUS authentication (RADIUS_AUTH) or
833 * accounting request (RADIUS_ACCT or RADIUS_ACCT_INTERIM). The only difference
834 * between accounting and interim accounting messages is that the interim
835 * message will not be retransmitted. Instead, a callback is used to indicate
836 * that the transmission failed for the specific station @addr so that a new
837 * interim accounting update message can be generated with up-to-date session
838 * data instead of trying to resend old information.
839 *
840 * The message is added on the retransmission queue and will be retransmitted
841 * automatically until a response is received or maximum number of retries
842 * (RADIUS_CLIENT_MAX_FAILOVER * RADIUS_CLIENT_NUM_FAILOVER) is reached. No
843 * such retries are used with RADIUS_ACCT_INTERIM, i.e., such a pending message
844 * is removed from the queue automatically on transmission failure.
845 *
846 * The related device MAC address can be used to identify pending messages that
847 * can be removed with radius_client_flush_auth().
848 */
radius_client_send(struct radius_client_data * radius,struct radius_msg * msg,RadiusType msg_type,const u8 * addr)849 int radius_client_send(struct radius_client_data *radius,
850 struct radius_msg *msg, RadiusType msg_type,
851 const u8 *addr)
852 {
853 struct hostapd_radius_servers *conf = radius->conf;
854 const u8 *shared_secret;
855 size_t shared_secret_len;
856 char *name;
857 int s, res;
858 struct wpabuf *buf;
859 #ifdef CONFIG_RADIUS_TLS
860 struct wpabuf *out = NULL;
861 struct tls_connection *conn = NULL;
862 bool acct = false;
863 #endif /* CONFIG_RADIUS_TLS */
864
865 if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) {
866 #ifdef CONFIG_RADIUS_TLS
867 acct = true;
868 if (radius->acct_tls)
869 conn = radius->acct_tls_conn;
870 #endif /* CONFIG_RADIUS_TLS */
871 if (conf->acct_server && radius->acct_sock < 0)
872 radius_client_init_acct(radius);
873
874 if (conf->acct_server == NULL || radius->acct_sock < 0 ||
875 conf->acct_server->shared_secret == NULL) {
876 hostapd_logger(radius->ctx, NULL,
877 HOSTAPD_MODULE_RADIUS,
878 HOSTAPD_LEVEL_INFO,
879 "No accounting server configured");
880 return -1;
881 }
882 shared_secret = conf->acct_server->shared_secret;
883 shared_secret_len = conf->acct_server->shared_secret_len;
884 if (radius_msg_finish_acct(msg, shared_secret,
885 shared_secret_len) < 0) {
886 hostapd_logger(radius->ctx, NULL,
887 HOSTAPD_MODULE_RADIUS,
888 HOSTAPD_LEVEL_INFO,
889 "Failed to build RADIUS accounting message");
890 return -1;
891 }
892 name = "accounting";
893 s = radius->acct_sock;
894 conf->acct_server->requests++;
895 } else {
896 #ifdef CONFIG_RADIUS_TLS
897 if (radius->auth_tls)
898 conn = radius->auth_tls_conn;
899 #endif /* CONFIG_RADIUS_TLS */
900 if (conf->auth_server && radius->auth_sock < 0)
901 radius_client_init_auth(radius);
902
903 if (conf->auth_server == NULL || radius->auth_sock < 0 ||
904 conf->auth_server->shared_secret == NULL) {
905 hostapd_logger(radius->ctx, NULL,
906 HOSTAPD_MODULE_RADIUS,
907 HOSTAPD_LEVEL_INFO,
908 "No authentication server configured");
909 return -1;
910 }
911 shared_secret = conf->auth_server->shared_secret;
912 shared_secret_len = conf->auth_server->shared_secret_len;
913 if (radius_msg_finish(msg, shared_secret, shared_secret_len) <
914 0) {
915 hostapd_logger(radius->ctx, NULL,
916 HOSTAPD_MODULE_RADIUS,
917 HOSTAPD_LEVEL_INFO,
918 "Failed to build RADIUS authentication message");
919 return -1;
920 }
921 name = "authentication";
922 s = radius->auth_sock;
923 conf->auth_server->requests++;
924 }
925
926 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
927 HOSTAPD_LEVEL_DEBUG, "Sending RADIUS message to %s "
928 "server", name);
929 if (conf->msg_dumps)
930 radius_msg_dump(msg);
931
932 #ifdef CONFIG_RADIUS_TLS
933 if ((acct && radius->acct_tls && !radius->acct_tls_ready) ||
934 (!acct && radius->auth_tls && !radius->auth_tls_ready)) {
935 wpa_printf(MSG_DEBUG,
936 "RADIUS: TLS connection not yet ready for TX");
937 goto skip_send;
938 }
939 #endif /* CONFIG_RADIUS_TLS */
940
941 buf = radius_msg_get_buf(msg);
942 #ifdef CONFIG_RADIUS_TLS
943 if (conn) {
944 out = tls_connection_encrypt(radius->tls_ctx, conn, buf);
945 if (!out) {
946 wpa_printf(MSG_INFO,
947 "RADIUS: Failed to encrypt RADIUS message (TLS)");
948 return -1;
949 }
950 wpa_printf(MSG_DEBUG,
951 "RADIUS: TLS encryption of %zu bytes of plaintext to %zu bytes of ciphertext",
952 wpabuf_len(buf), wpabuf_len(out));
953 buf = out;
954 }
955 #endif /* CONFIG_RADIUS_TLS */
956 wpa_printf(MSG_DEBUG, "RADIUS: Send %zu bytes to the server",
957 wpabuf_len(buf));
958 res = send(s, wpabuf_head(buf), wpabuf_len(buf), 0);
959 #ifdef CONFIG_RADIUS_TLS
960 wpabuf_free(out);
961 #endif /* CONFIG_RADIUS_TLS */
962 if (res < 0)
963 radius_client_handle_send_error(radius, s, msg_type);
964
965 #ifdef CONFIG_RADIUS_TLS
966 skip_send:
967 #endif /* CONFIG_RADIUS_TLS */
968 radius_client_list_add(radius, msg, msg_type, shared_secret,
969 shared_secret_len, addr);
970
971 return 0;
972 }
973
974
975 #ifdef CONFIG_RADIUS_TLS
976
radius_client_close_tcp(struct radius_client_data * radius,int sock,RadiusType msg_type)977 static void radius_client_close_tcp(struct radius_client_data *radius,
978 int sock, RadiusType msg_type)
979 {
980 wpa_printf(MSG_DEBUG, "RADIUS: Closing TCP connection (sock %d)",
981 sock);
982 if (msg_type == RADIUS_ACCT) {
983 radius->acct_tls_ready = false;
984 radius_close_acct_socket(radius);
985 } else {
986 radius->auth_tls_ready = false;
987 radius_close_auth_socket(radius);
988 }
989 }
990
991
992 static void
radius_client_process_tls_handshake(struct radius_client_data * radius,int sock,RadiusType msg_type,u8 * buf,size_t len)993 radius_client_process_tls_handshake(struct radius_client_data *radius,
994 int sock, RadiusType msg_type,
995 u8 *buf, size_t len)
996 {
997 struct wpabuf *in, *out = NULL, *appl;
998 struct tls_connection *conn;
999 int res;
1000 bool ready = false;
1001
1002 wpa_printf(MSG_DEBUG,
1003 "RADIUS: Process %zu bytes of received TLS handshake message",
1004 len);
1005
1006 if (msg_type == RADIUS_ACCT)
1007 conn = radius->acct_tls_conn;
1008 else
1009 conn = radius->auth_tls_conn;
1010
1011 in = wpabuf_alloc_copy(buf, len);
1012 if (!in)
1013 return;
1014
1015 appl = NULL;
1016 out = tls_connection_handshake(radius->tls_ctx, conn, in, &appl);
1017 wpabuf_free(in);
1018 if (!out) {
1019 wpa_printf(MSG_DEBUG,
1020 "RADIUS: Could not generate TLS handshake data");
1021 goto fail;
1022 }
1023
1024 if (tls_connection_get_failed(radius->tls_ctx, conn)) {
1025 wpa_printf(MSG_INFO, "RADIUS: TLS handshake failed");
1026 goto fail;
1027 }
1028
1029 if (tls_connection_established(radius->tls_ctx, conn)) {
1030 wpa_printf(MSG_DEBUG,
1031 "RADIUS: TLS connection established (sock=%d)",
1032 sock);
1033 if (msg_type == RADIUS_ACCT)
1034 radius->acct_tls_ready = true;
1035 else
1036 radius->auth_tls_ready = true;
1037 ready = true;
1038 }
1039
1040 wpa_printf(MSG_DEBUG, "RADIUS: Sending %zu bytes of TLS handshake",
1041 wpabuf_len(out));
1042 res = send(sock, wpabuf_head(out), wpabuf_len(out), 0);
1043 if (res < 0) {
1044 wpa_printf(MSG_INFO, "RADIUS: send: %s", strerror(errno));
1045 goto fail;
1046 }
1047 if ((size_t) res != wpabuf_len(out)) {
1048 wpa_printf(MSG_INFO,
1049 "RADIUS: Could not send all data for TLS handshake: only %d bytes sent",
1050 res);
1051 goto fail;
1052 }
1053 wpabuf_free(out);
1054
1055 if (ready) {
1056 struct radius_msg_list *entry, *prev, *tmp;
1057 struct os_reltime now;
1058
1059 /* Send all pending message of matching type since the TLS
1060 * tunnel has now been established. */
1061
1062 os_get_reltime(&now);
1063
1064 entry = radius->msgs;
1065 prev = NULL;
1066 while (entry) {
1067 if (entry->msg_type != msg_type) {
1068 prev = entry;
1069 entry = entry->next;
1070 continue;
1071 }
1072
1073 if (radius_client_retransmit(radius, entry, now.sec)) {
1074 if (prev)
1075 prev->next = entry->next;
1076 else
1077 radius->msgs = entry->next;
1078
1079 tmp = entry;
1080 entry = entry->next;
1081 radius_client_msg_free(tmp);
1082 radius->num_msgs--;
1083 continue;
1084 }
1085
1086 prev = entry;
1087 entry = entry->next;
1088 }
1089 }
1090
1091 return;
1092
1093 fail:
1094 wpabuf_free(out);
1095 tls_connection_deinit(radius->tls_ctx, conn);
1096 if (msg_type == RADIUS_ACCT)
1097 radius->acct_tls_conn = NULL;
1098 else
1099 radius->auth_tls_conn = NULL;
1100 radius_client_close_tcp(radius, sock, msg_type);
1101 }
1102
1103 #endif /* CONFIG_RADIUS_TLS */
1104
1105
radius_client_receive(int sock,void * eloop_ctx,void * sock_ctx)1106 static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx)
1107 {
1108 struct radius_client_data *radius = eloop_ctx;
1109 struct hostapd_radius_servers *conf = radius->conf;
1110 RadiusType msg_type = (uintptr_t) sock_ctx;
1111 int len, roundtrip;
1112 unsigned char buf[RADIUS_MAX_MSG_LEN];
1113 struct msghdr msghdr = {0};
1114 struct iovec iov;
1115 struct radius_msg *msg;
1116 struct radius_hdr *hdr;
1117 struct radius_rx_handler *handlers;
1118 size_t num_handlers, i;
1119 struct radius_msg_list *req, *prev_req, *r;
1120 struct os_reltime now;
1121 struct hostapd_radius_server *rconf;
1122 int invalid_authenticator = 0;
1123 #ifdef CONFIG_RADIUS_TLS
1124 struct tls_connection *conn = NULL;
1125 bool tls, tls_ready;
1126 #endif /* CONFIG_RADIUS_TLS */
1127
1128 if (msg_type == RADIUS_ACCT) {
1129 #ifdef CONFIG_RADIUS_TLS
1130 if (radius->acct_tls)
1131 conn = radius->acct_tls_conn;
1132 tls = radius->acct_tls;
1133 tls_ready = radius->acct_tls_ready;
1134 #endif /* CONFIG_RADIUS_TLS */
1135 handlers = radius->acct_handlers;
1136 num_handlers = radius->num_acct_handlers;
1137 rconf = conf->acct_server;
1138 } else {
1139 #ifdef CONFIG_RADIUS_TLS
1140 if (radius->auth_tls)
1141 conn = radius->auth_tls_conn;
1142 tls = radius->auth_tls;
1143 tls_ready = radius->auth_tls_ready;
1144 #endif /* CONFIG_RADIUS_TLS */
1145 handlers = radius->auth_handlers;
1146 num_handlers = radius->num_auth_handlers;
1147 rconf = conf->auth_server;
1148 }
1149
1150 iov.iov_base = buf;
1151 iov.iov_len = RADIUS_MAX_MSG_LEN;
1152 msghdr.msg_iov = &iov;
1153 msghdr.msg_iovlen = 1;
1154 msghdr.msg_flags = 0;
1155 len = recvmsg(sock, &msghdr, MSG_DONTWAIT);
1156 if (len < 0) {
1157 wpa_printf(MSG_INFO, "recvmsg[RADIUS]: %s", strerror(errno));
1158 return;
1159 }
1160 #ifdef CONFIG_RADIUS_TLS
1161 if (tls && len == 0) {
1162 wpa_printf(MSG_DEBUG, "RADIUS: No TCP data available");
1163 goto close_tcp;
1164 }
1165
1166 if (tls && !tls_ready) {
1167 radius_client_process_tls_handshake(radius, sock, msg_type,
1168 buf, len);
1169 return;
1170 }
1171
1172 if (conn) {
1173 struct wpabuf *out, *in;
1174
1175 in = wpabuf_alloc_copy(buf, len);
1176 if (!in)
1177 return;
1178 wpa_printf(MSG_DEBUG,
1179 "RADIUS: Process %d bytes of encrypted TLS data",
1180 len);
1181 out = tls_connection_decrypt(radius->tls_ctx, conn, in);
1182 wpabuf_free(in);
1183 if (!out) {
1184 wpa_printf(MSG_INFO,
1185 "RADIUS: Failed to decrypt TLS data");
1186 goto close_tcp;
1187 }
1188 if (wpabuf_len(out) == 0) {
1189 wpa_printf(MSG_DEBUG,
1190 "RADIUS: Full message not yet received - continue waiting for additional TLS data");
1191 wpabuf_free(out);
1192 return;
1193 }
1194 if (wpabuf_len(out) > RADIUS_MAX_MSG_LEN) {
1195 wpa_printf(MSG_INFO,
1196 "RADIUS: Too long RADIUS message from TLS: %zu",
1197 wpabuf_len(out));
1198 wpabuf_free(out);
1199 goto close_tcp;
1200 }
1201 os_memcpy(buf, wpabuf_head(out), wpabuf_len(out));
1202 len = wpabuf_len(out);
1203 wpabuf_free(out);
1204 }
1205 #endif /* CONFIG_RADIUS_TLS */
1206
1207 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
1208 HOSTAPD_LEVEL_DEBUG, "Received %d bytes from RADIUS "
1209 "server", len);
1210
1211 if (msghdr.msg_flags & MSG_TRUNC) {
1212 wpa_printf(MSG_INFO, "RADIUS: Possibly too long UDP frame for our buffer - dropping it");
1213 return;
1214 }
1215
1216 msg = radius_msg_parse(buf, len);
1217 if (msg == NULL) {
1218 wpa_printf(MSG_INFO, "RADIUS: Parsing incoming frame failed");
1219 rconf->malformed_responses++;
1220 return;
1221 }
1222 hdr = radius_msg_get_hdr(msg);
1223
1224 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
1225 HOSTAPD_LEVEL_DEBUG, "Received RADIUS message");
1226 if (conf->msg_dumps)
1227 radius_msg_dump(msg);
1228
1229 switch (hdr->code) {
1230 case RADIUS_CODE_ACCESS_ACCEPT:
1231 rconf->access_accepts++;
1232 break;
1233 case RADIUS_CODE_ACCESS_REJECT:
1234 rconf->access_rejects++;
1235 break;
1236 case RADIUS_CODE_ACCESS_CHALLENGE:
1237 rconf->access_challenges++;
1238 break;
1239 case RADIUS_CODE_ACCOUNTING_RESPONSE:
1240 rconf->responses++;
1241 break;
1242 }
1243
1244 req = radius->msgs;
1245 while (req) {
1246 /* TODO: also match by src addr:port of the packet when using
1247 * alternative RADIUS servers (?) */
1248 if ((req->msg_type == msg_type ||
1249 (req->msg_type == RADIUS_ACCT_INTERIM &&
1250 msg_type == RADIUS_ACCT)) &&
1251 radius_msg_get_hdr(req->msg)->identifier ==
1252 hdr->identifier)
1253 break;
1254
1255 req = req->next;
1256 }
1257
1258 if (req == NULL) {
1259 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
1260 HOSTAPD_LEVEL_DEBUG,
1261 "No matching RADIUS request found (type=%d "
1262 "id=%d) - dropping packet",
1263 msg_type, hdr->identifier);
1264 goto fail;
1265 }
1266
1267 os_get_reltime(&now);
1268 roundtrip = (now.sec - req->last_attempt.sec) * 100 +
1269 (now.usec - req->last_attempt.usec) / 10000;
1270 hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS,
1271 HOSTAPD_LEVEL_DEBUG,
1272 "Received RADIUS packet matched with a pending "
1273 "request, round trip time %d.%02d sec",
1274 roundtrip / 100, roundtrip % 100);
1275 rconf->round_trip_time = roundtrip;
1276
1277 for (i = 0; i < num_handlers; i++) {
1278 RadiusRxResult res;
1279 res = handlers[i].handler(msg, req->msg, req->shared_secret,
1280 req->shared_secret_len,
1281 handlers[i].data);
1282 switch (res) {
1283 case RADIUS_RX_PROCESSED:
1284 radius_msg_free(msg);
1285 /* fall through */
1286 case RADIUS_RX_QUEUED:
1287 /* Remove ACKed RADIUS packet from retransmit list */
1288 prev_req = NULL;
1289 for (r = radius->msgs; r; r = r->next) {
1290 if (r == req)
1291 break;
1292 prev_req = r;
1293 }
1294 if (prev_req)
1295 prev_req->next = req->next;
1296 else
1297 radius->msgs = req->next;
1298 radius->num_msgs--;
1299
1300 radius_client_msg_free(req);
1301 return;
1302 case RADIUS_RX_INVALID_AUTHENTICATOR:
1303 invalid_authenticator++;
1304 /* fall through */
1305 case RADIUS_RX_UNKNOWN:
1306 /* continue with next handler */
1307 break;
1308 }
1309 }
1310
1311 if (invalid_authenticator)
1312 rconf->bad_authenticators++;
1313 else
1314 rconf->unknown_types++;
1315 hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS,
1316 HOSTAPD_LEVEL_DEBUG, "No RADIUS RX handler found "
1317 "(type=%d code=%d id=%d)%s - dropping packet",
1318 msg_type, hdr->code, hdr->identifier,
1319 invalid_authenticator ? " [INVALID AUTHENTICATOR]" :
1320 "");
1321
1322 fail:
1323 radius_msg_free(msg);
1324 return;
1325
1326 #ifdef CONFIG_RADIUS_TLS
1327 close_tcp:
1328 radius_client_close_tcp(radius, sock, msg_type);
1329 #endif /* CONFIG_RADIUS_TLS */
1330 }
1331
1332
1333 #ifdef CONFIG_RADIUS_TLS
radius_client_write_ready(int sock,void * eloop_ctx,void * sock_ctx)1334 static void radius_client_write_ready(int sock, void *eloop_ctx, void *sock_ctx)
1335 {
1336 struct radius_client_data *radius = eloop_ctx;
1337 RadiusType msg_type = (uintptr_t) sock_ctx;
1338 struct tls_connection *conn = NULL;
1339 struct wpabuf *in, *out = NULL, *appl;
1340 int res = -1;
1341 struct tls_connection_params params;
1342 struct hostapd_radius_server *server;
1343
1344 wpa_printf(MSG_DEBUG, "RADIUS: TCP connection established - start TLS handshake (sock=%d)",
1345 sock);
1346
1347 if (msg_type == RADIUS_ACCT) {
1348 eloop_unregister_sock(sock, EVENT_TYPE_WRITE);
1349 eloop_register_read_sock(sock, radius_client_receive, radius,
1350 (void *) RADIUS_ACCT);
1351 if (radius->acct_tls_conn) {
1352 wpa_printf(MSG_DEBUG,
1353 "RADIUS: Deinit previously used TLS connection");
1354 tls_connection_deinit(radius->tls_ctx,
1355 radius->acct_tls_conn);
1356 radius->acct_tls_conn = NULL;
1357 }
1358 server = radius->conf->acct_server;
1359 } else {
1360 eloop_unregister_sock(sock, EVENT_TYPE_WRITE);
1361 eloop_register_read_sock(sock, radius_client_receive, radius,
1362 (void *) RADIUS_AUTH);
1363 if (radius->auth_tls_conn) {
1364 wpa_printf(MSG_DEBUG,
1365 "RADIUS: Deinit previously used TLS connection");
1366 tls_connection_deinit(radius->tls_ctx,
1367 radius->auth_tls_conn);
1368 radius->auth_tls_conn = NULL;
1369 }
1370 server = radius->conf->auth_server;
1371 }
1372
1373 if (!server)
1374 goto fail;
1375
1376 conn = tls_connection_init(radius->tls_ctx);
1377 if (!conn) {
1378 wpa_printf(MSG_INFO,
1379 "RADIUS: Failed to initiate TLS connection");
1380 goto fail;
1381 }
1382
1383 os_memset(¶ms, 0, sizeof(params));
1384 params.ca_cert = server->ca_cert;
1385 params.client_cert = server->client_cert;
1386 params.private_key = server->private_key;
1387 params.private_key_passwd = server->private_key_passwd;
1388 params.flags = TLS_CONN_DISABLE_TLSv1_0 | TLS_CONN_DISABLE_TLSv1_1;
1389 if (tls_connection_set_params(radius->tls_ctx, conn, ¶ms)) {
1390 wpa_printf(MSG_INFO,
1391 "RADIUS: Failed to set TLS connection parameters");
1392 goto fail;
1393 }
1394
1395 in = NULL;
1396 appl = NULL;
1397 out = tls_connection_handshake(radius->tls_ctx, conn, in, &appl);
1398 if (!out) {
1399 wpa_printf(MSG_DEBUG,
1400 "RADIUS: Could not generate TLS handshake data");
1401 goto fail;
1402 }
1403
1404 if (tls_connection_get_failed(radius->tls_ctx, conn)) {
1405 wpa_printf(MSG_INFO, "RADIUS: TLS handshake failed");
1406 goto fail;
1407 }
1408
1409 wpa_printf(MSG_DEBUG, "RADIUS: Sending %zu bytes of TLS handshake",
1410 wpabuf_len(out));
1411 res = send(sock, wpabuf_head(out), wpabuf_len(out), 0);
1412 if (res < 0) {
1413 wpa_printf(MSG_INFO, "RADIUS: send: %s", strerror(errno));
1414 goto fail;
1415 }
1416 if ((size_t) res != wpabuf_len(out)) {
1417 wpa_printf(MSG_INFO,
1418 "RADIUS: Could not send all data for TLS handshake: only %d bytes sent",
1419 res);
1420 goto fail;
1421 }
1422 wpabuf_free(out);
1423
1424 if (msg_type == RADIUS_ACCT)
1425 radius->acct_tls_conn = conn;
1426 else
1427 radius->auth_tls_conn = conn;
1428 return;
1429
1430 fail:
1431 wpa_printf(MSG_INFO, "RADIUS: Failed to perform TLS handshake");
1432 tls_connection_deinit(radius->tls_ctx, conn);
1433 wpabuf_free(out);
1434 radius_client_close_tcp(radius, sock, msg_type);
1435 }
1436 #endif /* CONFIG_RADIUS_TLS */
1437
1438
1439 /**
1440 * radius_client_get_id - Get an identifier for a new RADIUS message
1441 * @radius: RADIUS client context from radius_client_init()
1442 * Returns: Allocated identifier
1443 *
1444 * This function is used to fetch a unique (among pending requests) identifier
1445 * for a new RADIUS message.
1446 */
radius_client_get_id(struct radius_client_data * radius)1447 u8 radius_client_get_id(struct radius_client_data *radius)
1448 {
1449 struct radius_msg_list *entry, *prev, *_remove;
1450 u8 id = radius->next_radius_identifier++;
1451
1452 /* remove entries with matching id from retransmit list to avoid
1453 * using new reply from the RADIUS server with an old request */
1454 entry = radius->msgs;
1455 prev = NULL;
1456 while (entry) {
1457 if (radius_msg_get_hdr(entry->msg)->identifier == id) {
1458 hostapd_logger(radius->ctx, entry->addr,
1459 HOSTAPD_MODULE_RADIUS,
1460 HOSTAPD_LEVEL_DEBUG,
1461 "Removing pending RADIUS message, "
1462 "since its id (%d) is reused", id);
1463 if (prev)
1464 prev->next = entry->next;
1465 else
1466 radius->msgs = entry->next;
1467 _remove = entry;
1468 } else {
1469 _remove = NULL;
1470 prev = entry;
1471 }
1472 entry = entry->next;
1473
1474 if (_remove)
1475 radius_client_msg_free(_remove);
1476 }
1477
1478 return id;
1479 }
1480
1481
1482 /**
1483 * radius_client_flush - Flush all pending RADIUS client messages
1484 * @radius: RADIUS client context from radius_client_init()
1485 * @only_auth: Whether only authentication messages are removed
1486 */
radius_client_flush(struct radius_client_data * radius,int only_auth)1487 void radius_client_flush(struct radius_client_data *radius, int only_auth)
1488 {
1489 struct radius_msg_list *entry, *prev, *tmp;
1490
1491 if (!radius)
1492 return;
1493
1494 prev = NULL;
1495 entry = radius->msgs;
1496
1497 while (entry) {
1498 if (!only_auth || entry->msg_type == RADIUS_AUTH) {
1499 if (prev)
1500 prev->next = entry->next;
1501 else
1502 radius->msgs = entry->next;
1503
1504 tmp = entry;
1505 entry = entry->next;
1506 radius_client_msg_free(tmp);
1507 radius->num_msgs--;
1508 } else {
1509 prev = entry;
1510 entry = entry->next;
1511 }
1512 }
1513
1514 if (radius->msgs == NULL)
1515 eloop_cancel_timeout(radius_client_timer, radius, NULL);
1516 }
1517
1518
radius_client_update_acct_msgs(struct radius_client_data * radius,const u8 * shared_secret,size_t shared_secret_len)1519 static void radius_client_update_acct_msgs(struct radius_client_data *radius,
1520 const u8 *shared_secret,
1521 size_t shared_secret_len)
1522 {
1523 struct radius_msg_list *entry;
1524
1525 if (!radius)
1526 return;
1527
1528 for (entry = radius->msgs; entry; entry = entry->next) {
1529 if (entry->msg_type == RADIUS_ACCT) {
1530 entry->shared_secret = shared_secret;
1531 entry->shared_secret_len = shared_secret_len;
1532 if (radius_msg_finish_acct(entry->msg, shared_secret,
1533 shared_secret_len) < 0)
1534 wpa_printf(MSG_INFO,
1535 "RADIUS: Failed to update accounting message");
1536 }
1537 }
1538 }
1539
1540
1541 static int
radius_change_server(struct radius_client_data * radius,struct hostapd_radius_server * nserv,struct hostapd_radius_server * oserv,int auth)1542 radius_change_server(struct radius_client_data *radius,
1543 struct hostapd_radius_server *nserv,
1544 struct hostapd_radius_server *oserv,
1545 int auth)
1546 {
1547 struct sockaddr_in serv, claddr;
1548 #ifdef CONFIG_IPV6
1549 struct sockaddr_in6 serv6, claddr6;
1550 #endif /* CONFIG_IPV6 */
1551 struct sockaddr *addr, *cl_addr;
1552 socklen_t addrlen, claddrlen;
1553 char abuf[50];
1554 int sel_sock;
1555 struct radius_msg_list *entry;
1556 struct hostapd_radius_servers *conf = radius->conf;
1557 int type = SOCK_DGRAM;
1558 bool tls = nserv->tls;
1559
1560 if (tls) {
1561 #ifdef CONFIG_RADIUS_TLS
1562 type = SOCK_STREAM;
1563 #else /* CONFIG_RADIUS_TLS */
1564 wpa_printf(MSG_ERROR, "RADIUS: TLS not supported");
1565 return -1;
1566 #endif /* CONFIG_RADIUS_TLS */
1567 }
1568
1569 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
1570 HOSTAPD_LEVEL_INFO,
1571 "%s server %s:%d",
1572 auth ? "Authentication" : "Accounting",
1573 hostapd_ip_txt(&nserv->addr, abuf, sizeof(abuf)),
1574 nserv->port);
1575
1576 if (oserv && oserv == nserv) {
1577 /* Reconnect to same server, flush */
1578 if (auth)
1579 radius_client_flush(radius, 1);
1580 }
1581
1582 if (oserv && oserv != nserv &&
1583 (nserv->shared_secret_len != oserv->shared_secret_len ||
1584 os_memcmp(nserv->shared_secret, oserv->shared_secret,
1585 nserv->shared_secret_len) != 0)) {
1586 /* Pending RADIUS packets used different shared secret, so
1587 * they need to be modified. Update accounting message
1588 * authenticators here. Authentication messages are removed
1589 * since they would require more changes and the new RADIUS
1590 * server may not be prepared to receive them anyway due to
1591 * missing state information. Client will likely retry
1592 * authentication, so this should not be an issue. */
1593 if (auth)
1594 radius_client_flush(radius, 1);
1595 else {
1596 radius_client_update_acct_msgs(
1597 radius, nserv->shared_secret,
1598 nserv->shared_secret_len);
1599 }
1600 }
1601
1602 /* Reset retry counters */
1603 for (entry = radius->msgs; oserv && entry; entry = entry->next) {
1604 if ((auth && entry->msg_type != RADIUS_AUTH) ||
1605 (!auth && entry->msg_type != RADIUS_ACCT))
1606 continue;
1607 entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT;
1608 entry->attempts = 0;
1609 entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2;
1610 }
1611
1612 if (radius->msgs) {
1613 eloop_cancel_timeout(radius_client_timer, radius, NULL);
1614 eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT, 0,
1615 radius_client_timer, radius, NULL);
1616 }
1617
1618 switch (nserv->addr.af) {
1619 case AF_INET:
1620 os_memset(&serv, 0, sizeof(serv));
1621 serv.sin_family = AF_INET;
1622 serv.sin_addr.s_addr = nserv->addr.u.v4.s_addr;
1623 serv.sin_port = htons(nserv->port);
1624 addr = (struct sockaddr *) &serv;
1625 addrlen = sizeof(serv);
1626 sel_sock = socket(PF_INET, type, 0);
1627 if (sel_sock >= 0)
1628 radius_client_disable_pmtu_discovery(sel_sock);
1629 break;
1630 #ifdef CONFIG_IPV6
1631 case AF_INET6:
1632 os_memset(&serv6, 0, sizeof(serv6));
1633 serv6.sin6_family = AF_INET6;
1634 os_memcpy(&serv6.sin6_addr, &nserv->addr.u.v6,
1635 sizeof(struct in6_addr));
1636 serv6.sin6_port = htons(nserv->port);
1637 addr = (struct sockaddr *) &serv6;
1638 addrlen = sizeof(serv6);
1639 sel_sock = socket(PF_INET6, type, 0);
1640 break;
1641 #endif /* CONFIG_IPV6 */
1642 default:
1643 return -1;
1644 }
1645
1646 if (sel_sock < 0) {
1647 wpa_printf(MSG_INFO,
1648 "RADIUS: Failed to open server socket (af=%d auth=%d)",
1649 nserv->addr.af, auth);
1650 return -1;
1651 }
1652
1653 #ifdef CONFIG_RADIUS_TLS
1654 if (tls && fcntl(sel_sock, F_SETFL, O_NONBLOCK) != 0) {
1655 wpa_printf(MSG_DEBUG, "RADIUS: fnctl(O_NONBLOCK) failed: %s",
1656 strerror(errno));
1657 close(sel_sock);
1658 return -1;
1659 }
1660 #endif /* CONFIG_RADIUS_TLS */
1661
1662 #ifdef __linux__
1663 if (conf->force_client_dev && conf->force_client_dev[0]) {
1664 if (setsockopt(sel_sock, SOL_SOCKET, SO_BINDTODEVICE,
1665 conf->force_client_dev,
1666 os_strlen(conf->force_client_dev)) < 0) {
1667 wpa_printf(MSG_ERROR,
1668 "RADIUS: setsockopt[SO_BINDTODEVICE]: %s",
1669 strerror(errno));
1670 /* Probably not a critical error; continue on and hope
1671 * for the best. */
1672 } else {
1673 wpa_printf(MSG_DEBUG,
1674 "RADIUS: Bound client socket to device: %s",
1675 conf->force_client_dev);
1676 }
1677 }
1678 #endif /* __linux__ */
1679
1680 if (conf->force_client_addr) {
1681 switch (conf->client_addr.af) {
1682 case AF_INET:
1683 os_memset(&claddr, 0, sizeof(claddr));
1684 claddr.sin_family = AF_INET;
1685 claddr.sin_addr.s_addr = conf->client_addr.u.v4.s_addr;
1686 claddr.sin_port = htons(0);
1687 cl_addr = (struct sockaddr *) &claddr;
1688 claddrlen = sizeof(claddr);
1689 break;
1690 #ifdef CONFIG_IPV6
1691 case AF_INET6:
1692 os_memset(&claddr6, 0, sizeof(claddr6));
1693 claddr6.sin6_family = AF_INET6;
1694 os_memcpy(&claddr6.sin6_addr, &conf->client_addr.u.v6,
1695 sizeof(struct in6_addr));
1696 claddr6.sin6_port = htons(0);
1697 cl_addr = (struct sockaddr *) &claddr6;
1698 claddrlen = sizeof(claddr6);
1699 break;
1700 #endif /* CONFIG_IPV6 */
1701 default:
1702 close(sel_sock);
1703 return -1;
1704 }
1705
1706 if (bind(sel_sock, cl_addr, claddrlen) < 0) {
1707 wpa_printf(MSG_INFO, "bind[radius]: %s",
1708 strerror(errno));
1709 close(sel_sock);
1710 return -2;
1711 }
1712 }
1713
1714 if (connect(sel_sock, addr, addrlen) < 0) {
1715 if (nserv->tls && errno == EINPROGRESS) {
1716 wpa_printf(MSG_DEBUG,
1717 "RADIUS: TCP connection establishment in progress (sock %d)",
1718 sel_sock);
1719 } else {
1720 wpa_printf(MSG_INFO, "connect[radius]: %s",
1721 strerror(errno));
1722 close(sel_sock);
1723 return -2;
1724 }
1725 }
1726
1727 #ifndef CONFIG_NATIVE_WINDOWS
1728 switch (nserv->addr.af) {
1729 case AF_INET:
1730 claddrlen = sizeof(claddr);
1731 if (getsockname(sel_sock, (struct sockaddr *) &claddr,
1732 &claddrlen) == 0) {
1733 wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u",
1734 inet_ntoa(claddr.sin_addr),
1735 ntohs(claddr.sin_port));
1736 }
1737 break;
1738 #ifdef CONFIG_IPV6
1739 case AF_INET6: {
1740 claddrlen = sizeof(claddr6);
1741 if (getsockname(sel_sock, (struct sockaddr *) &claddr6,
1742 &claddrlen) == 0) {
1743 wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u",
1744 inet_ntop(AF_INET6, &claddr6.sin6_addr,
1745 abuf, sizeof(abuf)),
1746 ntohs(claddr6.sin6_port));
1747 }
1748 break;
1749 }
1750 #endif /* CONFIG_IPV6 */
1751 }
1752 #endif /* CONFIG_NATIVE_WINDOWS */
1753
1754 if (auth) {
1755 radius_close_auth_socket(radius);
1756 radius->auth_sock = sel_sock;
1757 } else {
1758 radius_close_acct_socket(radius);
1759 radius->acct_sock = sel_sock;
1760 }
1761
1762 if (!tls)
1763 eloop_register_read_sock(sel_sock, radius_client_receive,
1764 radius,
1765 auth ? (void *) RADIUS_AUTH :
1766 (void *) RADIUS_ACCT);
1767 #ifdef CONFIG_RADIUS_TLS
1768 if (tls)
1769 eloop_register_sock(sel_sock, EVENT_TYPE_WRITE,
1770 radius_client_write_ready, radius,
1771 auth ? (void *) RADIUS_AUTH :
1772 (void *) RADIUS_ACCT);
1773 #endif /* CONFIG_RADIUS_TLS */
1774
1775 if (auth) {
1776 radius->auth_tls = nserv->tls;
1777 radius->auth_tls_ready = false;
1778 } else {
1779 radius->acct_tls = nserv->tls;
1780 radius->acct_tls_ready = false;
1781 }
1782
1783 return 0;
1784 }
1785
1786
radius_retry_primary_timer(void * eloop_ctx,void * timeout_ctx)1787 static void radius_retry_primary_timer(void *eloop_ctx, void *timeout_ctx)
1788 {
1789 struct radius_client_data *radius = eloop_ctx;
1790 struct hostapd_radius_servers *conf = radius->conf;
1791 struct hostapd_radius_server *oserv;
1792
1793 if (radius->auth_sock >= 0 && conf->auth_servers &&
1794 conf->auth_server != conf->auth_servers) {
1795 oserv = conf->auth_server;
1796 conf->auth_server = conf->auth_servers;
1797 if (radius_change_server(radius, conf->auth_server, oserv,
1798 1) < 0) {
1799 conf->auth_server = oserv;
1800 radius_change_server(radius, oserv, conf->auth_server,
1801 1);
1802 }
1803 }
1804
1805 if (radius->acct_sock >= 0 && conf->acct_servers &&
1806 conf->acct_server != conf->acct_servers) {
1807 oserv = conf->acct_server;
1808 conf->acct_server = conf->acct_servers;
1809 if (radius_change_server(radius, conf->acct_server, oserv,
1810 0) < 0) {
1811 conf->acct_server = oserv;
1812 radius_change_server(radius, oserv, conf->acct_server,
1813 0);
1814 }
1815 }
1816
1817 if (conf->retry_primary_interval)
1818 eloop_register_timeout(conf->retry_primary_interval, 0,
1819 radius_retry_primary_timer, radius,
1820 NULL);
1821 }
1822
1823
radius_client_init_auth(struct radius_client_data * radius)1824 static int radius_client_init_auth(struct radius_client_data *radius)
1825 {
1826 radius_close_auth_socket(radius);
1827 return radius_change_server(radius, radius->conf->auth_server, NULL, 1);
1828 }
1829
1830
radius_client_init_acct(struct radius_client_data * radius)1831 static int radius_client_init_acct(struct radius_client_data *radius)
1832 {
1833 radius_close_acct_socket(radius);
1834 return radius_change_server(radius, radius->conf->acct_server, NULL, 0);
1835 }
1836
1837
1838 #ifdef CONFIG_RADIUS_TLS
radius_tls_event_cb(void * ctx,enum tls_event ev,union tls_event_data * data)1839 static void radius_tls_event_cb(void *ctx, enum tls_event ev,
1840 union tls_event_data *data)
1841 {
1842 wpa_printf(MSG_DEBUG, "RADIUS: TLS event %d", ev);
1843 }
1844 #endif /* CONFIG_RADIUS_TLS */
1845
1846
1847 /**
1848 * radius_client_init - Initialize RADIUS client
1849 * @ctx: Callback context to be used in hostapd_logger() calls
1850 * @conf: RADIUS client configuration (RADIUS servers)
1851 * Returns: Pointer to private RADIUS client context or %NULL on failure
1852 *
1853 * The caller is responsible for keeping the configuration data available for
1854 * the lifetime of the RADIUS client, i.e., until radius_client_deinit() is
1855 * called for the returned context pointer.
1856 */
1857 struct radius_client_data *
radius_client_init(void * ctx,struct hostapd_radius_servers * conf)1858 radius_client_init(void *ctx, struct hostapd_radius_servers *conf)
1859 {
1860 struct radius_client_data *radius;
1861
1862 radius = os_zalloc(sizeof(struct radius_client_data));
1863 if (radius == NULL)
1864 return NULL;
1865
1866 radius->ctx = ctx;
1867 radius->conf = conf;
1868 radius->auth_sock = radius->acct_sock = -1;
1869
1870 if (conf->auth_server && radius_client_init_auth(radius) == -1) {
1871 radius_client_deinit(radius);
1872 return NULL;
1873 }
1874
1875 if (conf->acct_server && radius_client_init_acct(radius) == -1) {
1876 radius_client_deinit(radius);
1877 return NULL;
1878 }
1879
1880 if (conf->retry_primary_interval)
1881 eloop_register_timeout(conf->retry_primary_interval, 0,
1882 radius_retry_primary_timer, radius,
1883 NULL);
1884
1885 #ifdef CONFIG_RADIUS_TLS
1886 if ((conf->auth_server && conf->auth_server->tls) ||
1887 (conf->acct_server && conf->acct_server->tls)) {
1888 struct tls_config tls_conf;
1889
1890 os_memset(&tls_conf, 0, sizeof(tls_conf));
1891 tls_conf.event_cb = radius_tls_event_cb;
1892 radius->tls_ctx = tls_init(&tls_conf);
1893 if (!radius->tls_ctx) {
1894 radius_client_deinit(radius);
1895 return NULL;
1896 }
1897 }
1898 #endif /* CONFIG_RADIUS_TLS */
1899
1900
1901 return radius;
1902 }
1903
1904
1905 /**
1906 * radius_client_deinit - Deinitialize RADIUS client
1907 * @radius: RADIUS client context from radius_client_init()
1908 */
radius_client_deinit(struct radius_client_data * radius)1909 void radius_client_deinit(struct radius_client_data *radius)
1910 {
1911 if (!radius)
1912 return;
1913
1914 radius_close_auth_socket(radius);
1915 radius_close_acct_socket(radius);
1916
1917 eloop_cancel_timeout(radius_retry_primary_timer, radius, NULL);
1918
1919 radius_client_flush(radius, 0);
1920 os_free(radius->auth_handlers);
1921 os_free(radius->acct_handlers);
1922 #ifdef CONFIG_RADIUS_TLS
1923 if (radius->tls_ctx) {
1924 tls_connection_deinit(radius->tls_ctx, radius->auth_tls_conn);
1925 tls_connection_deinit(radius->tls_ctx, radius->acct_tls_conn);
1926 tls_deinit(radius->tls_ctx);
1927 }
1928 #endif /* CONFIG_RADIUS_TLS */
1929 os_free(radius);
1930 }
1931
1932
1933 /**
1934 * radius_client_flush_auth - Flush pending RADIUS messages for an address
1935 * @radius: RADIUS client context from radius_client_init()
1936 * @addr: MAC address of the related device
1937 *
1938 * This function can be used to remove pending RADIUS authentication messages
1939 * that are related to a specific device. The addr parameter is matched with
1940 * the one used in radius_client_send() call that was used to transmit the
1941 * authentication request.
1942 */
radius_client_flush_auth(struct radius_client_data * radius,const u8 * addr)1943 void radius_client_flush_auth(struct radius_client_data *radius,
1944 const u8 *addr)
1945 {
1946 struct radius_msg_list *entry, *prev, *tmp;
1947
1948 prev = NULL;
1949 entry = radius->msgs;
1950 while (entry) {
1951 if (entry->msg_type == RADIUS_AUTH &&
1952 ether_addr_equal(entry->addr, addr)) {
1953 hostapd_logger(radius->ctx, addr,
1954 HOSTAPD_MODULE_RADIUS,
1955 HOSTAPD_LEVEL_DEBUG,
1956 "Removing pending RADIUS authentication"
1957 " message for removed client");
1958
1959 if (prev)
1960 prev->next = entry->next;
1961 else
1962 radius->msgs = entry->next;
1963
1964 tmp = entry;
1965 entry = entry->next;
1966 radius_client_msg_free(tmp);
1967 radius->num_msgs--;
1968 continue;
1969 }
1970
1971 prev = entry;
1972 entry = entry->next;
1973 }
1974 }
1975
1976
radius_client_dump_auth_server(char * buf,size_t buflen,struct hostapd_radius_server * serv,struct radius_client_data * cli)1977 static int radius_client_dump_auth_server(char *buf, size_t buflen,
1978 struct hostapd_radius_server *serv,
1979 struct radius_client_data *cli)
1980 {
1981 int pending = 0;
1982 struct radius_msg_list *msg;
1983 char abuf[50];
1984
1985 if (cli) {
1986 for (msg = cli->msgs; msg; msg = msg->next) {
1987 if (msg->msg_type == RADIUS_AUTH)
1988 pending++;
1989 }
1990 }
1991
1992 return os_snprintf(buf, buflen,
1993 "radiusAuthServerIndex=%d\n"
1994 "radiusAuthServerAddress=%s\n"
1995 "radiusAuthClientServerPortNumber=%d\n"
1996 "radiusAuthClientRoundTripTime=%d\n"
1997 "radiusAuthClientAccessRequests=%u\n"
1998 "radiusAuthClientAccessRetransmissions=%u\n"
1999 "radiusAuthClientAccessAccepts=%u\n"
2000 "radiusAuthClientAccessRejects=%u\n"
2001 "radiusAuthClientAccessChallenges=%u\n"
2002 "radiusAuthClientMalformedAccessResponses=%u\n"
2003 "radiusAuthClientBadAuthenticators=%u\n"
2004 "radiusAuthClientPendingRequests=%u\n"
2005 "radiusAuthClientTimeouts=%u\n"
2006 "radiusAuthClientUnknownTypes=%u\n"
2007 "radiusAuthClientPacketsDropped=%u\n",
2008 serv->index,
2009 hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)),
2010 serv->port,
2011 serv->round_trip_time,
2012 serv->requests,
2013 serv->retransmissions,
2014 serv->access_accepts,
2015 serv->access_rejects,
2016 serv->access_challenges,
2017 serv->malformed_responses,
2018 serv->bad_authenticators,
2019 pending,
2020 serv->timeouts,
2021 serv->unknown_types,
2022 serv->packets_dropped);
2023 }
2024
2025
radius_client_dump_acct_server(char * buf,size_t buflen,struct hostapd_radius_server * serv,struct radius_client_data * cli)2026 static int radius_client_dump_acct_server(char *buf, size_t buflen,
2027 struct hostapd_radius_server *serv,
2028 struct radius_client_data *cli)
2029 {
2030 int pending = 0;
2031 struct radius_msg_list *msg;
2032 char abuf[50];
2033
2034 if (cli) {
2035 for (msg = cli->msgs; msg; msg = msg->next) {
2036 if (msg->msg_type == RADIUS_ACCT ||
2037 msg->msg_type == RADIUS_ACCT_INTERIM)
2038 pending++;
2039 }
2040 }
2041
2042 return os_snprintf(buf, buflen,
2043 "radiusAccServerIndex=%d\n"
2044 "radiusAccServerAddress=%s\n"
2045 "radiusAccClientServerPortNumber=%d\n"
2046 "radiusAccClientRoundTripTime=%d\n"
2047 "radiusAccClientRequests=%u\n"
2048 "radiusAccClientRetransmissions=%u\n"
2049 "radiusAccClientResponses=%u\n"
2050 "radiusAccClientMalformedResponses=%u\n"
2051 "radiusAccClientBadAuthenticators=%u\n"
2052 "radiusAccClientPendingRequests=%u\n"
2053 "radiusAccClientTimeouts=%u\n"
2054 "radiusAccClientUnknownTypes=%u\n"
2055 "radiusAccClientPacketsDropped=%u\n",
2056 serv->index,
2057 hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)),
2058 serv->port,
2059 serv->round_trip_time,
2060 serv->requests,
2061 serv->retransmissions,
2062 serv->responses,
2063 serv->malformed_responses,
2064 serv->bad_authenticators,
2065 pending,
2066 serv->timeouts,
2067 serv->unknown_types,
2068 serv->packets_dropped);
2069 }
2070
2071
2072 /**
2073 * radius_client_get_mib - Get RADIUS client MIB information
2074 * @radius: RADIUS client context from radius_client_init()
2075 * @buf: Buffer for returning MIB data in text format
2076 * @buflen: Maximum buf length in octets
2077 * Returns: Number of octets written into the buffer
2078 */
radius_client_get_mib(struct radius_client_data * radius,char * buf,size_t buflen)2079 int radius_client_get_mib(struct radius_client_data *radius, char *buf,
2080 size_t buflen)
2081 {
2082 struct hostapd_radius_servers *conf;
2083 int i;
2084 struct hostapd_radius_server *serv;
2085 int count = 0;
2086
2087 if (!radius)
2088 return 0;
2089
2090 conf = radius->conf;
2091
2092 if (conf->auth_servers) {
2093 for (i = 0; i < conf->num_auth_servers; i++) {
2094 serv = &conf->auth_servers[i];
2095 count += radius_client_dump_auth_server(
2096 buf + count, buflen - count, serv,
2097 serv == conf->auth_server ?
2098 radius : NULL);
2099 }
2100 }
2101
2102 if (conf->acct_servers) {
2103 for (i = 0; i < conf->num_acct_servers; i++) {
2104 serv = &conf->acct_servers[i];
2105 count += radius_client_dump_acct_server(
2106 buf + count, buflen - count, serv,
2107 serv == conf->acct_server ?
2108 radius : NULL);
2109 }
2110 }
2111
2112 return count;
2113 }
2114
2115
radius_client_reconfig(struct radius_client_data * radius,struct hostapd_radius_servers * conf)2116 void radius_client_reconfig(struct radius_client_data *radius,
2117 struct hostapd_radius_servers *conf)
2118 {
2119 if (radius)
2120 radius->conf = conf;
2121 }
2122