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