• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&params, 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, &params)) {
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