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