• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * RADIUS authentication server
3  * Copyright (c) 2005-2009, 2011-2019, 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 <net/if.h>
11 #ifdef CONFIG_SQLITE
12 #include <sqlite3.h>
13 #endif /* CONFIG_SQLITE */
14 
15 #include "common.h"
16 #include "radius.h"
17 #include "eloop.h"
18 #include "eap_server/eap.h"
19 #include "ap/ap_config.h"
20 #include "crypto/tls.h"
21 #include "radius_server.h"
22 
23 /**
24  * RADIUS_SESSION_TIMEOUT - Session timeout in seconds
25  */
26 #define RADIUS_SESSION_TIMEOUT 60
27 
28 /**
29  * RADIUS_SESSION_MAINTAIN - Completed session expiration timeout in seconds
30  */
31 #define RADIUS_SESSION_MAINTAIN 5
32 
33 /**
34  * RADIUS_MAX_SESSION - Maximum number of active sessions
35  */
36 #define RADIUS_MAX_SESSION 1000
37 
38 /**
39  * RADIUS_MAX_MSG_LEN - Maximum message length for incoming RADIUS messages
40  */
41 #define RADIUS_MAX_MSG_LEN 3000
42 
43 static const struct eapol_callbacks radius_server_eapol_cb;
44 
45 struct radius_client;
46 struct radius_server_data;
47 
48 /**
49  * struct radius_server_counters - RADIUS server statistics counters
50  */
51 struct radius_server_counters {
52 	u32 access_requests;
53 	u32 invalid_requests;
54 	u32 dup_access_requests;
55 	u32 access_accepts;
56 	u32 access_rejects;
57 	u32 access_challenges;
58 	u32 malformed_access_requests;
59 	u32 bad_authenticators;
60 	u32 packets_dropped;
61 	u32 unknown_types;
62 
63 	u32 acct_requests;
64 	u32 invalid_acct_requests;
65 	u32 acct_responses;
66 	u32 malformed_acct_requests;
67 	u32 acct_bad_authenticators;
68 	u32 unknown_acct_types;
69 };
70 
71 /**
72  * struct radius_session - Internal RADIUS server data for a session
73  */
74 struct radius_session {
75 	struct radius_session *next;
76 	struct radius_client *client;
77 	struct radius_server_data *server;
78 	unsigned int sess_id;
79 	struct eap_sm *eap;
80 	struct eap_eapol_interface *eap_if;
81 	char *username; /* from User-Name attribute */
82 	char *nas_ip;
83 	u8 mac_addr[ETH_ALEN]; /* from Calling-Station-Id attribute */
84 
85 	struct radius_msg *last_msg;
86 	char *last_from_addr;
87 	int last_from_port;
88 	struct sockaddr_storage last_from;
89 	socklen_t last_fromlen;
90 	u8 last_identifier;
91 	struct radius_msg *last_reply;
92 	u8 last_authenticator[16];
93 
94 	unsigned int remediation:1;
95 	unsigned int macacl:1;
96 	unsigned int t_c_filtering:1;
97 
98 	struct hostapd_radius_attr *accept_attr;
99 
100 	u32 t_c_timestamp; /* Last read T&C timestamp from user DB */
101 };
102 
103 /**
104  * struct radius_client - Internal RADIUS server data for a client
105  */
106 struct radius_client {
107 	struct radius_client *next;
108 	struct in_addr addr;
109 	struct in_addr mask;
110 #ifdef CONFIG_IPV6
111 	struct in6_addr addr6;
112 	struct in6_addr mask6;
113 #endif /* CONFIG_IPV6 */
114 	char *shared_secret;
115 	int shared_secret_len;
116 	struct radius_session *sessions;
117 	struct radius_server_counters counters;
118 
119 	u8 next_dac_identifier;
120 	struct radius_msg *pending_dac_coa_req;
121 	u8 pending_dac_coa_id;
122 	u8 pending_dac_coa_addr[ETH_ALEN];
123 	struct radius_msg *pending_dac_disconnect_req;
124 	u8 pending_dac_disconnect_id;
125 	u8 pending_dac_disconnect_addr[ETH_ALEN];
126 };
127 
128 /**
129  * struct radius_server_data - Internal RADIUS server data
130  */
131 struct radius_server_data {
132 	/**
133 	 * auth_sock - Socket for RADIUS authentication messages
134 	 */
135 	int auth_sock;
136 
137 	/**
138 	 * acct_sock - Socket for RADIUS accounting messages
139 	 */
140 	int acct_sock;
141 
142 	/**
143 	 * clients - List of authorized RADIUS clients
144 	 */
145 	struct radius_client *clients;
146 
147 	/**
148 	 * next_sess_id - Next session identifier
149 	 */
150 	unsigned int next_sess_id;
151 
152 	/**
153 	 * conf_ctx - Context pointer for callbacks
154 	 *
155 	 * This is used as the ctx argument in get_eap_user() calls.
156 	 */
157 	void *conf_ctx;
158 
159 	/**
160 	 * num_sess - Number of active sessions
161 	 */
162 	int num_sess;
163 
164 	const char *erp_domain;
165 
166 	struct dl_list erp_keys; /* struct eap_server_erp_key */
167 
168 	/**
169 	 * ipv6 - Whether to enable IPv6 support in the RADIUS server
170 	 */
171 	int ipv6;
172 
173 	/**
174 	 * start_time - Timestamp of server start
175 	 */
176 	struct os_reltime start_time;
177 
178 	/**
179 	 * counters - Statistics counters for server operations
180 	 *
181 	 * These counters are the sum over all clients.
182 	 */
183 	struct radius_server_counters counters;
184 
185 	/**
186 	 * get_eap_user - Callback for fetching EAP user information
187 	 * @ctx: Context data from conf_ctx
188 	 * @identity: User identity
189 	 * @identity_len: identity buffer length in octets
190 	 * @phase2: Whether this is for Phase 2 identity
191 	 * @user: Data structure for filling in the user information
192 	 * Returns: 0 on success, -1 on failure
193 	 *
194 	 * This is used to fetch information from user database. The callback
195 	 * will fill in information about allowed EAP methods and the user
196 	 * password. The password field will be an allocated copy of the
197 	 * password data and RADIUS server will free it after use.
198 	 */
199 	int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len,
200 			    int phase2, struct eap_user *user);
201 
202 	/**
203 	 * eap_req_id_text - Optional data for EAP-Request/Identity
204 	 *
205 	 * This can be used to configure an optional, displayable message that
206 	 * will be sent in EAP-Request/Identity. This string can contain an
207 	 * ASCII-0 character (nul) to separate network infromation per RFC
208 	 * 4284. The actual string length is explicit provided in
209 	 * eap_req_id_text_len since nul character will not be used as a string
210 	 * terminator.
211 	 */
212 	char *eap_req_id_text;
213 
214 	/**
215 	 * eap_req_id_text_len - Length of eap_req_id_text buffer in octets
216 	 */
217 	size_t eap_req_id_text_len;
218 
219 #ifdef CONFIG_RADIUS_TEST
220 	char *dump_msk_file;
221 #endif /* CONFIG_RADIUS_TEST */
222 
223 	char *subscr_remediation_url;
224 	u8 subscr_remediation_method;
225 	char *hs20_sim_provisioning_url;
226 
227 	char *t_c_server_url;
228 
229 #ifdef CONFIG_SQLITE
230 	sqlite3 *db;
231 #endif /* CONFIG_SQLITE */
232 
233 	const struct eap_config *eap_cfg;
234 };
235 
236 
237 #define RADIUS_DEBUG(args...) \
238 wpa_printf(MSG_DEBUG, "RADIUS SRV: " args)
239 #define RADIUS_ERROR(args...) \
240 wpa_printf(MSG_ERROR, "RADIUS SRV: " args)
241 #define RADIUS_DUMP(args...) \
242 wpa_hexdump(MSG_MSGDUMP, "RADIUS SRV: " args)
243 #define RADIUS_DUMP_ASCII(args...) \
244 wpa_hexdump_ascii(MSG_MSGDUMP, "RADIUS SRV: " args)
245 
246 
247 static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx);
248 static void radius_server_session_remove_timeout(void *eloop_ctx,
249 						 void *timeout_ctx);
250 
251 #ifdef CONFIG_SQLITE
252 #ifdef CONFIG_HS20
253 
db_table_exists(sqlite3 * db,const char * name)254 static int db_table_exists(sqlite3 *db, const char *name)
255 {
256 	char cmd[128];
257 
258 	os_snprintf(cmd, sizeof(cmd), "SELECT 1 FROM %s;", name);
259 	return sqlite3_exec(db, cmd, NULL, NULL, NULL) == SQLITE_OK;
260 }
261 
262 
db_table_create_sim_provisioning(sqlite3 * db)263 static int db_table_create_sim_provisioning(sqlite3 *db)
264 {
265 	char *err = NULL;
266 	const char *sql =
267 		"CREATE TABLE sim_provisioning("
268 		" mobile_identifier_hash TEXT PRIMARY KEY,"
269 		" imsi TEXT,"
270 		" mac_addr TEXT,"
271 		" eap_method TEXT,"
272 		" timestamp TEXT"
273 		");";
274 
275 	RADIUS_DEBUG("Adding database table for SIM provisioning information");
276 	if (sqlite3_exec(db, sql, NULL, NULL, &err) != SQLITE_OK) {
277 		RADIUS_ERROR("SQLite error: %s", err);
278 		sqlite3_free(err);
279 		return -1;
280 	}
281 
282 	return 0;
283 }
284 
285 #endif /* CONFIG_HS20 */
286 #endif /* CONFIG_SQLITE */
287 
288 
289 void srv_log(struct radius_session *sess, const char *fmt, ...)
290 PRINTF_FORMAT(2, 3);
291 
srv_log(struct radius_session * sess,const char * fmt,...)292 void srv_log(struct radius_session *sess, const char *fmt, ...)
293 {
294 	va_list ap;
295 	char *buf;
296 	int buflen;
297 
298 	va_start(ap, fmt);
299 	buflen = vsnprintf(NULL, 0, fmt, ap) + 1;
300 	va_end(ap);
301 
302 	buf = os_malloc(buflen);
303 	if (buf == NULL)
304 		return;
305 	va_start(ap, fmt);
306 	vsnprintf(buf, buflen, fmt, ap);
307 	va_end(ap);
308 
309 	RADIUS_DEBUG("[0x%x %s] %s", sess->sess_id, sess->nas_ip, buf);
310 
311 #ifdef CONFIG_SQLITE
312 	if (sess->server->db) {
313 		char *sql;
314 		sql = sqlite3_mprintf("INSERT INTO authlog"
315 				      "(timestamp,session,nas_ip,username,note)"
316 				      " VALUES ("
317 				      "strftime('%%Y-%%m-%%d %%H:%%M:%%f',"
318 				      "'now'),%u,%Q,%Q,%Q)",
319 				      sess->sess_id, sess->nas_ip,
320 				      sess->username, buf);
321 		if (sql) {
322 			if (sqlite3_exec(sess->server->db, sql, NULL, NULL,
323 					 NULL) != SQLITE_OK) {
324 				RADIUS_ERROR("Failed to add authlog entry into sqlite database: %s",
325 					     sqlite3_errmsg(sess->server->db));
326 			}
327 			sqlite3_free(sql);
328 		}
329 	}
330 #endif /* CONFIG_SQLITE */
331 
332 	os_free(buf);
333 }
334 
335 
336 static struct radius_client *
radius_server_get_client(struct radius_server_data * data,struct in_addr * addr,int ipv6)337 radius_server_get_client(struct radius_server_data *data, struct in_addr *addr,
338 			 int ipv6)
339 {
340 	struct radius_client *client = data->clients;
341 
342 	while (client) {
343 #ifdef CONFIG_IPV6
344 		if (ipv6) {
345 			struct in6_addr *addr6;
346 			int i;
347 
348 			addr6 = (struct in6_addr *) addr;
349 			for (i = 0; i < 16; i++) {
350 				if ((addr6->s6_addr[i] &
351 				     client->mask6.s6_addr[i]) !=
352 				    (client->addr6.s6_addr[i] &
353 				     client->mask6.s6_addr[i])) {
354 					i = 17;
355 					break;
356 				}
357 			}
358 			if (i == 16) {
359 				break;
360 			}
361 		}
362 #endif /* CONFIG_IPV6 */
363 		if (!ipv6 && (client->addr.s_addr & client->mask.s_addr) ==
364 		    (addr->s_addr & client->mask.s_addr)) {
365 			break;
366 		}
367 
368 		client = client->next;
369 	}
370 
371 	return client;
372 }
373 
374 
375 static struct radius_session *
radius_server_get_session(struct radius_client * client,unsigned int sess_id)376 radius_server_get_session(struct radius_client *client, unsigned int sess_id)
377 {
378 	struct radius_session *sess = client->sessions;
379 
380 	while (sess) {
381 		if (sess->sess_id == sess_id) {
382 			break;
383 		}
384 		sess = sess->next;
385 	}
386 
387 	return sess;
388 }
389 
390 
radius_server_session_free(struct radius_server_data * data,struct radius_session * sess)391 static void radius_server_session_free(struct radius_server_data *data,
392 				       struct radius_session *sess)
393 {
394 	eloop_cancel_timeout(radius_server_session_timeout, data, sess);
395 	eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess);
396 	eap_server_sm_deinit(sess->eap);
397 	radius_msg_free(sess->last_msg);
398 	os_free(sess->last_from_addr);
399 	radius_msg_free(sess->last_reply);
400 	os_free(sess->username);
401 	os_free(sess->nas_ip);
402 	os_free(sess);
403 	data->num_sess--;
404 }
405 
406 
radius_server_session_remove(struct radius_server_data * data,struct radius_session * sess)407 static void radius_server_session_remove(struct radius_server_data *data,
408 					 struct radius_session *sess)
409 {
410 	struct radius_client *client = sess->client;
411 	struct radius_session *session, *prev;
412 
413 	eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess);
414 
415 	prev = NULL;
416 	session = client->sessions;
417 	while (session) {
418 		if (session == sess) {
419 			if (prev == NULL) {
420 				client->sessions = sess->next;
421 			} else {
422 				prev->next = sess->next;
423 			}
424 			radius_server_session_free(data, sess);
425 			break;
426 		}
427 		prev = session;
428 		session = session->next;
429 	}
430 }
431 
432 
radius_server_session_remove_timeout(void * eloop_ctx,void * timeout_ctx)433 static void radius_server_session_remove_timeout(void *eloop_ctx,
434 						 void *timeout_ctx)
435 {
436 	struct radius_server_data *data = eloop_ctx;
437 	struct radius_session *sess = timeout_ctx;
438 	RADIUS_DEBUG("Removing completed session 0x%x", sess->sess_id);
439 	radius_server_session_remove(data, sess);
440 }
441 
442 
radius_server_session_timeout(void * eloop_ctx,void * timeout_ctx)443 static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx)
444 {
445 	struct radius_server_data *data = eloop_ctx;
446 	struct radius_session *sess = timeout_ctx;
447 
448 	RADIUS_DEBUG("Timing out authentication session 0x%x", sess->sess_id);
449 	radius_server_session_remove(data, sess);
450 }
451 
452 
453 static struct radius_session *
radius_server_new_session(struct radius_server_data * data,struct radius_client * client)454 radius_server_new_session(struct radius_server_data *data,
455 			  struct radius_client *client)
456 {
457 	struct radius_session *sess;
458 
459 	if (data->num_sess >= RADIUS_MAX_SESSION) {
460 		RADIUS_DEBUG("Maximum number of existing session - no room "
461 			     "for a new session");
462 		return NULL;
463 	}
464 
465 	sess = os_zalloc(sizeof(*sess));
466 	if (sess == NULL)
467 		return NULL;
468 
469 	sess->server = data;
470 	sess->client = client;
471 	sess->sess_id = data->next_sess_id++;
472 	sess->next = client->sessions;
473 	client->sessions = sess;
474 	eloop_register_timeout(RADIUS_SESSION_TIMEOUT, 0,
475 			       radius_server_session_timeout, data, sess);
476 	data->num_sess++;
477 	return sess;
478 }
479 
480 
481 #ifdef CONFIG_TESTING_OPTIONS
radius_server_testing_options_tls(struct radius_session * sess,const char * tls,struct eap_session_data * eap_conf)482 static void radius_server_testing_options_tls(struct radius_session *sess,
483 					      const char *tls,
484 					      struct eap_session_data *eap_conf)
485 {
486 	int test = atoi(tls);
487 
488 	switch (test) {
489 	case 1:
490 		srv_log(sess, "TLS test - break VerifyData");
491 		eap_conf->tls_test_flags = TLS_BREAK_VERIFY_DATA;
492 		break;
493 	case 2:
494 		srv_log(sess, "TLS test - break ServerKeyExchange ServerParams hash");
495 		eap_conf->tls_test_flags = TLS_BREAK_SRV_KEY_X_HASH;
496 		break;
497 	case 3:
498 		srv_log(sess, "TLS test - break ServerKeyExchange ServerParams Signature");
499 		eap_conf->tls_test_flags = TLS_BREAK_SRV_KEY_X_SIGNATURE;
500 		break;
501 	case 4:
502 		srv_log(sess, "TLS test - RSA-DHE using a short 511-bit prime");
503 		eap_conf->tls_test_flags = TLS_DHE_PRIME_511B;
504 		break;
505 	case 5:
506 		srv_log(sess, "TLS test - RSA-DHE using a short 767-bit prime");
507 		eap_conf->tls_test_flags = TLS_DHE_PRIME_767B;
508 		break;
509 	case 6:
510 		srv_log(sess, "TLS test - RSA-DHE using a bogus 15 \"prime\"");
511 		eap_conf->tls_test_flags = TLS_DHE_PRIME_15;
512 		break;
513 	case 7:
514 		srv_log(sess, "TLS test - RSA-DHE using a short 58-bit prime in long container");
515 		eap_conf->tls_test_flags = TLS_DHE_PRIME_58B;
516 		break;
517 	case 8:
518 		srv_log(sess, "TLS test - RSA-DHE using a non-prime");
519 		eap_conf->tls_test_flags = TLS_DHE_NON_PRIME;
520 		break;
521 	default:
522 		srv_log(sess, "Unrecognized TLS test");
523 		break;
524 	}
525 }
526 #endif /* CONFIG_TESTING_OPTIONS */
527 
radius_server_testing_options(struct radius_session * sess,struct eap_session_data * eap_conf)528 static void radius_server_testing_options(struct radius_session *sess,
529 					  struct eap_session_data *eap_conf)
530 {
531 #ifdef CONFIG_TESTING_OPTIONS
532 	const char *pos;
533 
534 	pos = os_strstr(sess->username, "@test-");
535 	if (pos == NULL)
536 		return;
537 	pos += 6;
538 	if (os_strncmp(pos, "tls-", 4) == 0)
539 		radius_server_testing_options_tls(sess, pos + 4, eap_conf);
540 	else
541 		srv_log(sess, "Unrecognized test: %s", pos);
542 #endif /* CONFIG_TESTING_OPTIONS */
543 }
544 
545 
546 #ifdef CONFIG_ERP
547 static struct eap_server_erp_key *
radius_server_erp_find_key(struct radius_server_data * data,const char * keyname)548 radius_server_erp_find_key(struct radius_server_data *data, const char *keyname)
549 {
550 	struct eap_server_erp_key *erp;
551 
552 	dl_list_for_each(erp, &data->erp_keys, struct eap_server_erp_key,
553 			 list) {
554 		if (os_strcmp(erp->keyname_nai, keyname) == 0)
555 			return erp;
556 	}
557 
558 	return NULL;
559 }
560 #endif /* CONFIG_ERP */
561 
562 
563 static struct radius_session *
radius_server_get_new_session(struct radius_server_data * data,struct radius_client * client,struct radius_msg * msg,const char * from_addr)564 radius_server_get_new_session(struct radius_server_data *data,
565 			      struct radius_client *client,
566 			      struct radius_msg *msg, const char *from_addr)
567 {
568 	u8 *user, *id;
569 	size_t user_len, id_len;
570 	int res;
571 	struct radius_session *sess;
572 	struct eap_session_data eap_sess;
573 	struct eap_user *tmp;
574 
575 	RADIUS_DEBUG("Creating a new session");
576 
577 	if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME, &user,
578 				    &user_len, NULL) < 0) {
579 		RADIUS_DEBUG("Could not get User-Name");
580 		return NULL;
581 	}
582 	RADIUS_DUMP_ASCII("User-Name", user, user_len);
583 
584 	tmp = os_zalloc(sizeof(*tmp));
585 	if (!tmp)
586 		return NULL;
587 
588 	res = data->get_eap_user(data->conf_ctx, user, user_len, 0, tmp);
589 #ifdef CONFIG_ERP
590 	if (res != 0 && data->eap_cfg->erp) {
591 		char *username;
592 
593 		username = os_zalloc(user_len + 1);
594 		if (username) {
595 			os_memcpy(username, user, user_len);
596 			if (radius_server_erp_find_key(data, username))
597 				res = 0;
598 			os_free(username);
599 		}
600 	}
601 #endif /* CONFIG_ERP */
602 	if (res != 0) {
603 		RADIUS_DEBUG("User-Name not found from user database");
604 		eap_user_free(tmp);
605 		return NULL;
606 	}
607 
608 	RADIUS_DEBUG("Matching user entry found");
609 	sess = radius_server_new_session(data, client);
610 	if (sess == NULL) {
611 		RADIUS_DEBUG("Failed to create a new session");
612 		eap_user_free(tmp);
613 		return NULL;
614 	}
615 	sess->accept_attr = tmp->accept_attr;
616 	sess->macacl = tmp->macacl;
617 	eap_user_free(tmp);
618 
619 	sess->username = os_malloc(user_len * 4 + 1);
620 	if (sess->username == NULL) {
621 		radius_server_session_remove(data, sess);
622 		return NULL;
623 	}
624 	printf_encode(sess->username, user_len * 4 + 1, user, user_len);
625 
626 	sess->nas_ip = os_strdup(from_addr);
627 	if (sess->nas_ip == NULL) {
628 		radius_server_session_remove(data, sess);
629 		return NULL;
630 	}
631 
632 	if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CALLING_STATION_ID, &id,
633 				    &id_len, NULL) == 0) {
634 		char buf[3 * ETH_ALEN];
635 
636 		os_memset(buf, 0, sizeof(buf));
637 		if (id_len >= sizeof(buf))
638 			id_len = sizeof(buf) - 1;
639 		os_memcpy(buf, id, id_len);
640 		if (hwaddr_aton2(buf, sess->mac_addr) < 0)
641 			os_memset(sess->mac_addr, 0, ETH_ALEN);
642 		else
643 			RADIUS_DEBUG("Calling-Station-Id: " MACSTR,
644 				     MAC2STR(sess->mac_addr));
645 	}
646 
647 	srv_log(sess, "New session created");
648 
649 	os_memset(&eap_sess, 0, sizeof(eap_sess));
650 	radius_server_testing_options(sess, &eap_sess);
651 	sess->eap = eap_server_sm_init(sess, &radius_server_eapol_cb,
652 				       data->eap_cfg, &eap_sess);
653 	if (sess->eap == NULL) {
654 		RADIUS_DEBUG("Failed to initialize EAP state machine for the "
655 			     "new session");
656 		radius_server_session_remove(data, sess);
657 		return NULL;
658 	}
659 	sess->eap_if = eap_get_interface(sess->eap);
660 	sess->eap_if->eapRestart = true;
661 	sess->eap_if->portEnabled = true;
662 
663 	RADIUS_DEBUG("New session 0x%x initialized", sess->sess_id);
664 
665 	return sess;
666 }
667 
668 
669 #ifdef CONFIG_HS20
radius_srv_hs20_t_c_pending(struct radius_session * sess)670 static void radius_srv_hs20_t_c_pending(struct radius_session *sess)
671 {
672 #ifdef CONFIG_SQLITE
673 	char *sql;
674 	char addr[3 * ETH_ALEN], *id_str;
675 	const u8 *id;
676 	size_t id_len;
677 
678 	if (!sess->server->db || !sess->eap ||
679 	    is_zero_ether_addr(sess->mac_addr))
680 		return;
681 
682 	os_snprintf(addr, sizeof(addr), MACSTR, MAC2STR(sess->mac_addr));
683 
684 	id = eap_get_identity(sess->eap, &id_len);
685 	if (!id)
686 		return;
687 	id_str = os_malloc(id_len + 1);
688 	if (!id_str)
689 		return;
690 	os_memcpy(id_str, id, id_len);
691 	id_str[id_len] = '\0';
692 
693 	sql = sqlite3_mprintf("INSERT OR REPLACE INTO pending_tc (mac_addr,identity) VALUES (%Q,%Q)",
694 			      addr, id_str);
695 	os_free(id_str);
696 	if (!sql)
697 		return;
698 
699 	if (sqlite3_exec(sess->server->db, sql, NULL, NULL, NULL) !=
700 	    SQLITE_OK) {
701 		RADIUS_ERROR("Failed to add pending_tc entry into sqlite database: %s",
702 			     sqlite3_errmsg(sess->server->db));
703 	}
704 	sqlite3_free(sql);
705 #endif /* CONFIG_SQLITE */
706 }
707 #endif /* CONFIG_HS20 */
708 
709 
radius_server_add_session(struct radius_session * sess)710 static void radius_server_add_session(struct radius_session *sess)
711 {
712 #ifdef CONFIG_SQLITE
713 	char *sql;
714 	char addr_txt[ETH_ALEN * 3];
715 	struct os_time now;
716 
717 	if (!sess->server->db)
718 		return;
719 
720 
721 	os_snprintf(addr_txt, sizeof(addr_txt), MACSTR,
722 		    MAC2STR(sess->mac_addr));
723 
724 	os_get_time(&now);
725 	sql = sqlite3_mprintf("INSERT OR REPLACE INTO current_sessions(mac_addr,identity,start_time,nas,hs20_t_c_filtering) VALUES (%Q,%Q,%d,%Q,%u)",
726 			      addr_txt, sess->username, now.sec,
727 			      sess->nas_ip, sess->t_c_filtering);
728 	if (sql) {
729 			if (sqlite3_exec(sess->server->db, sql, NULL, NULL,
730 					 NULL) != SQLITE_OK) {
731 				RADIUS_ERROR("Failed to add current_sessions entry into sqlite database: %s",
732 					     sqlite3_errmsg(sess->server->db));
733 			}
734 			sqlite3_free(sql);
735 	}
736 #endif /* CONFIG_SQLITE */
737 }
738 
739 
db_update_last_msk(struct radius_session * sess,const char * msk)740 static void db_update_last_msk(struct radius_session *sess, const char *msk)
741 {
742 #ifdef CONFIG_RADIUS_TEST
743 #ifdef CONFIG_SQLITE
744 	char *sql = NULL;
745 	char *id_str = NULL;
746 	const u8 *id;
747 	size_t id_len;
748 	const char *serial_num;
749 
750 	if (!sess->server->db)
751 		return;
752 
753 	serial_num = eap_get_serial_num(sess->eap);
754 	if (serial_num) {
755 		id_len = 5 + os_strlen(serial_num) + 1;
756 		id_str = os_malloc(id_len);
757 		if (!id_str)
758 			return;
759 		os_snprintf(id_str, id_len, "cert-%s", serial_num);
760 	} else {
761 		id = eap_get_identity(sess->eap, &id_len);
762 		if (!id)
763 			return;
764 		id_str = os_malloc(id_len + 1);
765 		if (!id_str)
766 			return;
767 		os_memcpy(id_str, id, id_len);
768 		id_str[id_len] = '\0';
769 	}
770 
771 	sql = sqlite3_mprintf("UPDATE users SET last_msk=%Q WHERE identity=%Q",
772 			      msk, id_str);
773 	os_free(id_str);
774 	if (!sql)
775 		return;
776 
777 	if (sqlite3_exec(sess->server->db, sql, NULL, NULL, NULL) !=
778 	    SQLITE_OK) {
779 		RADIUS_DEBUG("Failed to update last_msk: %s",
780 			     sqlite3_errmsg(sess->server->db));
781 	}
782 	sqlite3_free(sql);
783 #endif /* CONFIG_SQLITE */
784 #endif /* CONFIG_RADIUS_TEST */
785 }
786 
787 
788 #ifdef CONFIG_HS20
789 
radius_server_is_sim_method(struct radius_session * sess)790 static int radius_server_is_sim_method(struct radius_session *sess)
791 {
792 	const char *name;
793 
794 	name = eap_get_method(sess->eap);
795 	return name &&
796 		(os_strcmp(name, "SIM") == 0 ||
797 		 os_strcmp(name, "AKA") == 0 ||
798 		 os_strcmp(name, "AKA'") == 0);
799 }
800 
801 
radius_server_hs20_missing_sim_pps(struct radius_msg * request)802 static int radius_server_hs20_missing_sim_pps(struct radius_msg *request)
803 {
804 	u8 *buf, *pos, *end, type, sublen;
805 	size_t len;
806 
807 	buf = NULL;
808 	for (;;) {
809 		if (radius_msg_get_attr_ptr(request,
810 					    RADIUS_ATTR_VENDOR_SPECIFIC,
811 					    &buf, &len, buf) < 0)
812 			return 0;
813 		if (len < 6)
814 			continue;
815 		pos = buf;
816 		end = buf + len;
817 		if (WPA_GET_BE32(pos) != RADIUS_VENDOR_ID_WFA)
818 			continue;
819 		pos += 4;
820 
821 		type = *pos++;
822 		sublen = *pos++;
823 		if (sublen < 2)
824 			continue; /* invalid length */
825 		sublen -= 2; /* skip header */
826 		if (pos + sublen > end)
827 			continue; /* invalid WFA VSA */
828 
829 		if (type != RADIUS_VENDOR_ATTR_WFA_HS20_STA_VERSION)
830 			continue;
831 
832 		RADIUS_DUMP("HS2.0 mobile device version", pos, sublen);
833 		if (sublen < 1 + 2)
834 			continue;
835 		if (pos[0] == 0)
836 			continue; /* Release 1 STA does not support provisioning
837 
838 				   */
839 		/* UpdateIdentifier 0 indicates no PPS MO */
840 		return WPA_GET_BE16(pos + 1) == 0;
841 	}
842 }
843 
844 
845 #define HS20_MOBILE_ID_HASH_LEN 16
846 
radius_server_sim_provisioning_session(struct radius_session * sess,const u8 * hash)847 static int radius_server_sim_provisioning_session(struct radius_session *sess,
848 						  const u8 *hash)
849 {
850 #ifdef CONFIG_SQLITE
851 	char *sql;
852 	char addr_txt[ETH_ALEN * 3];
853 	char hash_txt[2 * HS20_MOBILE_ID_HASH_LEN + 1];
854 	struct os_time now;
855 	int res;
856 	const char *imsi, *eap_method;
857 
858 	if (!sess->server->db ||
859 	    (!db_table_exists(sess->server->db, "sim_provisioning") &&
860 	     db_table_create_sim_provisioning(sess->server->db) < 0))
861 		return -1;
862 
863 	imsi = eap_get_imsi(sess->eap);
864 	if (!imsi)
865 		return -1;
866 
867 	eap_method = eap_get_method(sess->eap);
868 	if (!eap_method)
869 		return -1;
870 
871 	os_snprintf(addr_txt, sizeof(addr_txt), MACSTR,
872 		    MAC2STR(sess->mac_addr));
873 	wpa_snprintf_hex(hash_txt, sizeof(hash_txt), hash,
874 			 HS20_MOBILE_ID_HASH_LEN);
875 
876 	os_get_time(&now);
877 	sql = sqlite3_mprintf("INSERT INTO sim_provisioning(mobile_identifier_hash,imsi,mac_addr,eap_method,timestamp) VALUES (%Q,%Q,%Q,%Q,%u)",
878 			      hash_txt, imsi, addr_txt, eap_method, now.sec);
879 	if (!sql)
880 		return -1;
881 
882 	if (sqlite3_exec(sess->server->db, sql, NULL, NULL, NULL) !=
883 	    SQLITE_OK) {
884 		RADIUS_ERROR("Failed to add SIM provisioning entry into sqlite database: %s",
885 			     sqlite3_errmsg(sess->server->db));
886 		res = -1;
887 	} else {
888 		res = 0;
889 	}
890 	sqlite3_free(sql);
891 	return res;
892 #endif /* CONFIG_SQLITE */
893 	return -1;
894 }
895 
896 #endif /* CONFIG_HS20 */
897 
898 
899 static struct radius_msg *
radius_server_encapsulate_eap(struct radius_server_data * data,struct radius_client * client,struct radius_session * sess,struct radius_msg * request)900 radius_server_encapsulate_eap(struct radius_server_data *data,
901 			      struct radius_client *client,
902 			      struct radius_session *sess,
903 			      struct radius_msg *request)
904 {
905 	struct radius_msg *msg;
906 	int code;
907 	unsigned int sess_id;
908 	struct radius_hdr *hdr = radius_msg_get_hdr(request);
909 	u16 reason = WLAN_REASON_IEEE_802_1X_AUTH_FAILED;
910 
911 	if (sess->eap_if->eapFail) {
912 		sess->eap_if->eapFail = false;
913 		code = RADIUS_CODE_ACCESS_REJECT;
914 	} else if (sess->eap_if->eapSuccess) {
915 		sess->eap_if->eapSuccess = false;
916 		code = RADIUS_CODE_ACCESS_ACCEPT;
917 	} else {
918 		sess->eap_if->eapReq = false;
919 		code = RADIUS_CODE_ACCESS_CHALLENGE;
920 	}
921 
922 	msg = radius_msg_new(code, hdr->identifier);
923 	if (msg == NULL) {
924 		RADIUS_DEBUG("Failed to allocate reply message");
925 		return NULL;
926 	}
927 
928 	sess_id = htonl(sess->sess_id);
929 	if (code == RADIUS_CODE_ACCESS_CHALLENGE &&
930 	    !radius_msg_add_attr(msg, RADIUS_ATTR_STATE,
931 				 (u8 *) &sess_id, sizeof(sess_id))) {
932 		RADIUS_DEBUG("Failed to add State attribute");
933 	}
934 
935 	if (sess->eap_if->eapReqData &&
936 	    !radius_msg_add_eap(msg, wpabuf_head(sess->eap_if->eapReqData),
937 				wpabuf_len(sess->eap_if->eapReqData))) {
938 		RADIUS_DEBUG("Failed to add EAP-Message attribute");
939 	}
940 
941 	if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->eap_if->eapKeyData) {
942 		int len;
943 #ifdef CONFIG_RADIUS_TEST
944 		char buf[2 * 64 + 1];
945 
946 		len = sess->eap_if->eapKeyDataLen;
947 		if (len > 64)
948 			len = 64;
949 		len = wpa_snprintf_hex(buf, sizeof(buf),
950 				       sess->eap_if->eapKeyData, len);
951 		buf[len] = '\0';
952 
953 		if (data->dump_msk_file) {
954 			FILE *f;
955 
956 			f = fopen(data->dump_msk_file, "a");
957 			if (f) {
958 				len = sess->eap_if->eapKeyDataLen;
959 				if (len > 64)
960 					len = 64;
961 				len = wpa_snprintf_hex(
962 					buf, sizeof(buf),
963 					sess->eap_if->eapKeyData, len);
964 				buf[len] = '\0';
965 				fprintf(f, "%s\n", buf);
966 				fclose(f);
967 			}
968 		}
969 
970 		db_update_last_msk(sess, buf);
971 #endif /* CONFIG_RADIUS_TEST */
972 		if (sess->eap_if->eapKeyDataLen > 64) {
973 			len = 32;
974 		} else {
975 			len = sess->eap_if->eapKeyDataLen / 2;
976 		}
977 		if (!radius_msg_add_mppe_keys(msg, hdr->authenticator,
978 					      (u8 *) client->shared_secret,
979 					      client->shared_secret_len,
980 					      sess->eap_if->eapKeyData + len,
981 					      len, sess->eap_if->eapKeyData,
982 					      len)) {
983 			RADIUS_DEBUG("Failed to add MPPE key attributes");
984 		}
985 
986 		if (sess->eap_if->eapSessionId &&
987 		    !radius_msg_add_attr(msg, RADIUS_ATTR_EAP_KEY_NAME,
988 					 sess->eap_if->eapSessionId,
989 					 sess->eap_if->eapSessionIdLen)) {
990 			RADIUS_DEBUG("Failed to add EAP-Key-Name attribute");
991 		}
992 	}
993 
994 #ifdef CONFIG_HS20
995 	if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->remediation &&
996 	    data->subscr_remediation_url) {
997 		u8 *buf;
998 		size_t url_len = os_strlen(data->subscr_remediation_url);
999 		buf = os_malloc(1 + url_len);
1000 		if (buf == NULL) {
1001 			radius_msg_free(msg);
1002 			return NULL;
1003 		}
1004 		buf[0] = data->subscr_remediation_method;
1005 		os_memcpy(&buf[1], data->subscr_remediation_url, url_len);
1006 		if (!radius_msg_add_wfa(
1007 			    msg, RADIUS_VENDOR_ATTR_WFA_HS20_SUBSCR_REMEDIATION,
1008 			    buf, 1 + url_len)) {
1009 			RADIUS_DEBUG("Failed to add WFA-HS20-SubscrRem");
1010 		}
1011 		os_free(buf);
1012 	} else if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->remediation) {
1013 		u8 buf[1];
1014 		if (!radius_msg_add_wfa(
1015 			    msg, RADIUS_VENDOR_ATTR_WFA_HS20_SUBSCR_REMEDIATION,
1016 			    buf, 0)) {
1017 			RADIUS_DEBUG("Failed to add WFA-HS20-SubscrRem");
1018 		}
1019 	} else if (code == RADIUS_CODE_ACCESS_ACCEPT &&
1020 		   data->hs20_sim_provisioning_url &&
1021 		   radius_server_is_sim_method(sess) &&
1022 		   radius_server_hs20_missing_sim_pps(request)) {
1023 		u8 *buf, *pos, hash[HS20_MOBILE_ID_HASH_LEN];
1024 		size_t prefix_len, url_len;
1025 
1026 		RADIUS_DEBUG("Device needs HS 2.0 SIM provisioning");
1027 
1028 		if (os_get_random(hash, HS20_MOBILE_ID_HASH_LEN) < 0) {
1029 			radius_msg_free(msg);
1030 			return NULL;
1031 		}
1032 		RADIUS_DUMP("hotspot2dot0-mobile-identifier-hash",
1033 			    hash, HS20_MOBILE_ID_HASH_LEN);
1034 
1035 		if (radius_server_sim_provisioning_session(sess, hash) < 0) {
1036 			radius_msg_free(msg);
1037 			return NULL;
1038 		}
1039 
1040 		prefix_len = os_strlen(data->hs20_sim_provisioning_url);
1041 		url_len = prefix_len + 2 * HS20_MOBILE_ID_HASH_LEN;
1042 		buf = os_malloc(1 + url_len + 1);
1043 		if (!buf) {
1044 			radius_msg_free(msg);
1045 			return NULL;
1046 		}
1047 		pos = buf;
1048 		*pos++ = data->subscr_remediation_method;
1049 		os_memcpy(pos, data->hs20_sim_provisioning_url, prefix_len);
1050 		pos += prefix_len;
1051 		wpa_snprintf_hex((char *) pos, 2 * HS20_MOBILE_ID_HASH_LEN + 1,
1052 				 hash, HS20_MOBILE_ID_HASH_LEN);
1053 		RADIUS_DEBUG("HS 2.0 subscription remediation URL: %s",
1054 			     (char *) &buf[1]);
1055 		if (!radius_msg_add_wfa(
1056 			    msg, RADIUS_VENDOR_ATTR_WFA_HS20_SUBSCR_REMEDIATION,
1057 			    buf, 1 + url_len)) {
1058 			RADIUS_DEBUG("Failed to add WFA-HS20-SubscrRem");
1059 		}
1060 		os_free(buf);
1061 	}
1062 
1063 	if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->t_c_filtering) {
1064 		u8 buf[4] = { 0x01, 0x00, 0x00, 0x00 }; /* E=1 */
1065 		const char *url = data->t_c_server_url, *pos;
1066 		char *url2, *end2, *pos2;
1067 		size_t url_len;
1068 
1069 		if (!radius_msg_add_wfa(
1070 			    msg, RADIUS_VENDOR_ATTR_WFA_HS20_T_C_FILTERING,
1071 			    buf, sizeof(buf))) {
1072 			RADIUS_DEBUG("Failed to add WFA-HS20-T-C-Filtering");
1073 			radius_msg_free(msg);
1074 			return NULL;
1075 		}
1076 
1077 		if (!url) {
1078 			RADIUS_DEBUG("No t_c_server_url configured");
1079 			radius_msg_free(msg);
1080 			return NULL;
1081 		}
1082 
1083 		pos = os_strstr(url, "@1@");
1084 		if (!pos) {
1085 			RADIUS_DEBUG("No @1@ macro in t_c_server_url");
1086 			radius_msg_free(msg);
1087 			return NULL;
1088 		}
1089 
1090 		url_len = os_strlen(url) + ETH_ALEN * 3 - 1 - 3;
1091 		url2 = os_malloc(url_len + 1);
1092 		if (!url2) {
1093 			RADIUS_DEBUG("Failed to allocate room for T&C Server URL");
1094 			os_free(url2);
1095 			radius_msg_free(msg);
1096 			return NULL;
1097 		}
1098 		pos2 = url2;
1099 		end2 = url2 + url_len + 1;
1100 		os_memcpy(pos2, url, pos - url);
1101 		pos2 += pos - url;
1102 		os_snprintf(pos2, end2 - pos2, MACSTR, MAC2STR(sess->mac_addr));
1103 		pos2 += ETH_ALEN * 3 - 1;
1104 		os_memcpy(pos2, pos + 3, os_strlen(pos + 3));
1105 		if (!radius_msg_add_wfa(msg,
1106 					RADIUS_VENDOR_ATTR_WFA_HS20_T_C_URL,
1107 					(const u8 *) url2, url_len)) {
1108 			RADIUS_DEBUG("Failed to add WFA-HS20-T-C-URL");
1109 			os_free(url2);
1110 			radius_msg_free(msg);
1111 			return NULL;
1112 		}
1113 		os_free(url2);
1114 
1115 		radius_srv_hs20_t_c_pending(sess);
1116 	}
1117 #endif /* CONFIG_HS20 */
1118 
1119 	if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) {
1120 		RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
1121 		radius_msg_free(msg);
1122 		return NULL;
1123 	}
1124 
1125 	if (code == RADIUS_CODE_ACCESS_ACCEPT) {
1126 		struct hostapd_radius_attr *attr;
1127 		for (attr = sess->accept_attr; attr; attr = attr->next) {
1128 			if (!radius_msg_add_attr(msg, attr->type,
1129 						 wpabuf_head(attr->val),
1130 						 wpabuf_len(attr->val))) {
1131 				wpa_printf(MSG_ERROR, "Could not add RADIUS attribute");
1132 				radius_msg_free(msg);
1133 				return NULL;
1134 			}
1135 		}
1136 	}
1137 
1138 	if (code == RADIUS_CODE_ACCESS_REJECT) {
1139 		if (radius_msg_add_attr_int32(msg, RADIUS_ATTR_WLAN_REASON_CODE,
1140 					      reason) < 0) {
1141 			RADIUS_DEBUG("Failed to add WLAN-Reason-Code attribute");
1142 			radius_msg_free(msg);
1143 			return NULL;
1144 		}
1145 	}
1146 
1147 	if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
1148 				  client->shared_secret_len,
1149 				  hdr->authenticator) < 0) {
1150 		RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
1151 	}
1152 
1153 	if (code == RADIUS_CODE_ACCESS_ACCEPT)
1154 		radius_server_add_session(sess);
1155 
1156 	return msg;
1157 }
1158 
1159 
1160 static struct radius_msg *
radius_server_macacl(struct radius_server_data * data,struct radius_client * client,struct radius_session * sess,struct radius_msg * request)1161 radius_server_macacl(struct radius_server_data *data,
1162 		     struct radius_client *client,
1163 		     struct radius_session *sess,
1164 		     struct radius_msg *request)
1165 {
1166 	struct radius_msg *msg;
1167 	int code;
1168 	struct radius_hdr *hdr = radius_msg_get_hdr(request);
1169 	u8 *pw;
1170 	size_t pw_len;
1171 
1172 	code = RADIUS_CODE_ACCESS_ACCEPT;
1173 
1174 	if (radius_msg_get_attr_ptr(request, RADIUS_ATTR_USER_PASSWORD, &pw,
1175 				    &pw_len, NULL) < 0) {
1176 		RADIUS_DEBUG("Could not get User-Password");
1177 		code = RADIUS_CODE_ACCESS_REJECT;
1178 	} else {
1179 		int res;
1180 		struct eap_user tmp;
1181 
1182 		os_memset(&tmp, 0, sizeof(tmp));
1183 		res = data->get_eap_user(data->conf_ctx, (u8 *) sess->username,
1184 					 os_strlen(sess->username), 0, &tmp);
1185 		if (res || !tmp.macacl || tmp.password == NULL) {
1186 			RADIUS_DEBUG("No MAC ACL user entry");
1187 			bin_clear_free(tmp.password, tmp.password_len);
1188 			code = RADIUS_CODE_ACCESS_REJECT;
1189 		} else {
1190 			u8 buf[128];
1191 			res = radius_user_password_hide(
1192 				request, tmp.password, tmp.password_len,
1193 				(u8 *) client->shared_secret,
1194 				client->shared_secret_len,
1195 				buf, sizeof(buf));
1196 			bin_clear_free(tmp.password, tmp.password_len);
1197 
1198 			if (res < 0 || pw_len != (size_t) res ||
1199 			    os_memcmp_const(pw, buf, res) != 0) {
1200 				RADIUS_DEBUG("Incorrect User-Password");
1201 				code = RADIUS_CODE_ACCESS_REJECT;
1202 			}
1203 		}
1204 	}
1205 
1206 	msg = radius_msg_new(code, hdr->identifier);
1207 	if (msg == NULL) {
1208 		RADIUS_DEBUG("Failed to allocate reply message");
1209 		return NULL;
1210 	}
1211 
1212 	if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) {
1213 		RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
1214 		radius_msg_free(msg);
1215 		return NULL;
1216 	}
1217 
1218 	if (code == RADIUS_CODE_ACCESS_ACCEPT) {
1219 		struct hostapd_radius_attr *attr;
1220 		for (attr = sess->accept_attr; attr; attr = attr->next) {
1221 			if (!radius_msg_add_attr(msg, attr->type,
1222 						 wpabuf_head(attr->val),
1223 						 wpabuf_len(attr->val))) {
1224 				wpa_printf(MSG_ERROR, "Could not add RADIUS attribute");
1225 				radius_msg_free(msg);
1226 				return NULL;
1227 			}
1228 		}
1229 	}
1230 
1231 	if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
1232 				  client->shared_secret_len,
1233 				  hdr->authenticator) < 0) {
1234 		RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
1235 	}
1236 
1237 	return msg;
1238 }
1239 
1240 
radius_server_reject(struct radius_server_data * data,struct radius_client * client,struct radius_msg * request,struct sockaddr * from,socklen_t fromlen,const char * from_addr,int from_port)1241 static int radius_server_reject(struct radius_server_data *data,
1242 				struct radius_client *client,
1243 				struct radius_msg *request,
1244 				struct sockaddr *from, socklen_t fromlen,
1245 				const char *from_addr, int from_port)
1246 {
1247 	struct radius_msg *msg;
1248 	int ret = 0;
1249 	struct eap_hdr eapfail;
1250 	struct wpabuf *buf;
1251 	struct radius_hdr *hdr = radius_msg_get_hdr(request);
1252 
1253 	RADIUS_DEBUG("Reject invalid request from %s:%d",
1254 		     from_addr, from_port);
1255 
1256 	msg = radius_msg_new(RADIUS_CODE_ACCESS_REJECT, hdr->identifier);
1257 	if (msg == NULL) {
1258 		return -1;
1259 	}
1260 
1261 	os_memset(&eapfail, 0, sizeof(eapfail));
1262 	eapfail.code = EAP_CODE_FAILURE;
1263 	eapfail.identifier = 0;
1264 	eapfail.length = host_to_be16(sizeof(eapfail));
1265 
1266 	if (!radius_msg_add_eap(msg, (u8 *) &eapfail, sizeof(eapfail))) {
1267 		RADIUS_DEBUG("Failed to add EAP-Message attribute");
1268 	}
1269 
1270 	if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) {
1271 		RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
1272 		radius_msg_free(msg);
1273 		return -1;
1274 	}
1275 
1276 	if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
1277 				  client->shared_secret_len,
1278 				  hdr->authenticator) <
1279 	    0) {
1280 		RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
1281 	}
1282 
1283 	if (wpa_debug_level <= MSG_MSGDUMP) {
1284 		radius_msg_dump(msg);
1285 	}
1286 
1287 	data->counters.access_rejects++;
1288 	client->counters.access_rejects++;
1289 	buf = radius_msg_get_buf(msg);
1290 	if (sendto(data->auth_sock, wpabuf_head(buf), wpabuf_len(buf), 0,
1291 		   (struct sockaddr *) from, sizeof(*from)) < 0) {
1292 		wpa_printf(MSG_INFO, "sendto[RADIUS SRV]: %s", strerror(errno));
1293 		ret = -1;
1294 	}
1295 
1296 	radius_msg_free(msg);
1297 
1298 	return ret;
1299 }
1300 
1301 
radius_server_hs20_t_c_check(struct radius_session * sess,struct radius_msg * msg)1302 static void radius_server_hs20_t_c_check(struct radius_session *sess,
1303 					 struct radius_msg *msg)
1304 {
1305 #ifdef CONFIG_HS20
1306 	u8 *buf, *pos, *end, type, sublen, *timestamp = NULL;
1307 	size_t len;
1308 
1309 	buf = NULL;
1310 	for (;;) {
1311 		if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_VENDOR_SPECIFIC,
1312 					    &buf, &len, buf) < 0)
1313 			break;
1314 		if (len < 6)
1315 			continue;
1316 		pos = buf;
1317 		end = buf + len;
1318 		if (WPA_GET_BE32(pos) != RADIUS_VENDOR_ID_WFA)
1319 			continue;
1320 		pos += 4;
1321 
1322 		type = *pos++;
1323 		sublen = *pos++;
1324 		if (sublen < 2)
1325 			continue; /* invalid length */
1326 		sublen -= 2; /* skip header */
1327 		if (pos + sublen > end)
1328 			continue; /* invalid WFA VSA */
1329 
1330 		if (type == RADIUS_VENDOR_ATTR_WFA_HS20_TIMESTAMP && len >= 4) {
1331 			timestamp = pos;
1332 			break;
1333 		}
1334 	}
1335 
1336 	if (!timestamp)
1337 		return;
1338 	RADIUS_DEBUG("HS20-Timestamp: %u", WPA_GET_BE32(timestamp));
1339 	if (sess->t_c_timestamp != WPA_GET_BE32(timestamp)) {
1340 		RADIUS_DEBUG("Last read T&C timestamp does not match HS20-Timestamp --> require filtering");
1341 		sess->t_c_filtering = 1;
1342 	}
1343 #endif /* CONFIG_HS20 */
1344 }
1345 
1346 
radius_server_request(struct radius_server_data * data,struct radius_msg * msg,struct sockaddr * from,socklen_t fromlen,struct radius_client * client,const char * from_addr,int from_port,struct radius_session * force_sess)1347 static int radius_server_request(struct radius_server_data *data,
1348 				 struct radius_msg *msg,
1349 				 struct sockaddr *from, socklen_t fromlen,
1350 				 struct radius_client *client,
1351 				 const char *from_addr, int from_port,
1352 				 struct radius_session *force_sess)
1353 {
1354 	struct wpabuf *eap = NULL;
1355 	int res, state_included = 0;
1356 	u8 statebuf[4];
1357 	unsigned int state;
1358 	struct radius_session *sess;
1359 	struct radius_msg *reply;
1360 	int is_complete = 0;
1361 
1362 	if (force_sess)
1363 		sess = force_sess;
1364 	else {
1365 		res = radius_msg_get_attr(msg, RADIUS_ATTR_STATE, statebuf,
1366 					  sizeof(statebuf));
1367 		state_included = res >= 0;
1368 		if (res == sizeof(statebuf)) {
1369 			state = WPA_GET_BE32(statebuf);
1370 			sess = radius_server_get_session(client, state);
1371 		} else {
1372 			sess = NULL;
1373 		}
1374 	}
1375 
1376 	if (sess) {
1377 		RADIUS_DEBUG("Request for session 0x%x", sess->sess_id);
1378 	} else if (state_included) {
1379 		RADIUS_DEBUG("State attribute included but no session found");
1380 		radius_server_reject(data, client, msg, from, fromlen,
1381 				     from_addr, from_port);
1382 		return -1;
1383 	} else {
1384 		sess = radius_server_get_new_session(data, client, msg,
1385 						     from_addr);
1386 		if (sess == NULL) {
1387 			RADIUS_DEBUG("Could not create a new session");
1388 			radius_server_reject(data, client, msg, from, fromlen,
1389 					     from_addr, from_port);
1390 			return -1;
1391 		}
1392 	}
1393 
1394 	if (sess->last_from_port == from_port &&
1395 	    sess->last_identifier == radius_msg_get_hdr(msg)->identifier &&
1396 	    os_memcmp(sess->last_authenticator,
1397 		      radius_msg_get_hdr(msg)->authenticator, 16) == 0) {
1398 		RADIUS_DEBUG("Duplicate message from %s", from_addr);
1399 		data->counters.dup_access_requests++;
1400 		client->counters.dup_access_requests++;
1401 
1402 		if (sess->last_reply) {
1403 			struct wpabuf *buf;
1404 			buf = radius_msg_get_buf(sess->last_reply);
1405 			res = sendto(data->auth_sock, wpabuf_head(buf),
1406 				     wpabuf_len(buf), 0,
1407 				     (struct sockaddr *) from, fromlen);
1408 			if (res < 0) {
1409 				wpa_printf(MSG_INFO, "sendto[RADIUS SRV]: %s",
1410 					   strerror(errno));
1411 			}
1412 			return 0;
1413 		}
1414 
1415 		RADIUS_DEBUG("No previous reply available for duplicate "
1416 			     "message");
1417 		return -1;
1418 	}
1419 
1420 	eap = radius_msg_get_eap(msg);
1421 	if (eap == NULL && sess->macacl) {
1422 		reply = radius_server_macacl(data, client, sess, msg);
1423 		if (reply == NULL)
1424 			return -1;
1425 		goto send_reply;
1426 	}
1427 	if (eap == NULL) {
1428 		RADIUS_DEBUG("No EAP-Message in RADIUS packet from %s",
1429 			     from_addr);
1430 		data->counters.packets_dropped++;
1431 		client->counters.packets_dropped++;
1432 		return -1;
1433 	}
1434 
1435 	RADIUS_DUMP("Received EAP data", wpabuf_head(eap), wpabuf_len(eap));
1436 
1437 	/* FIX: if Code is Request, Success, or Failure, send Access-Reject;
1438 	 * RFC3579 Sect. 2.6.2.
1439 	 * Include EAP-Response/Nak with no preferred method if
1440 	 * code == request.
1441 	 * If code is not 1-4, discard the packet silently.
1442 	 * Or is this already done by the EAP state machine? */
1443 
1444 	wpabuf_free(sess->eap_if->eapRespData);
1445 	sess->eap_if->eapRespData = eap;
1446 	sess->eap_if->eapResp = true;
1447 	eap_server_sm_step(sess->eap);
1448 
1449 	if ((sess->eap_if->eapReq || sess->eap_if->eapSuccess ||
1450 	     sess->eap_if->eapFail) && sess->eap_if->eapReqData) {
1451 		RADIUS_DUMP("EAP data from the state machine",
1452 			    wpabuf_head(sess->eap_if->eapReqData),
1453 			    wpabuf_len(sess->eap_if->eapReqData));
1454 	} else if (sess->eap_if->eapFail) {
1455 		RADIUS_DEBUG("No EAP data from the state machine, but eapFail "
1456 			     "set");
1457 	} else if (eap_sm_method_pending(sess->eap)) {
1458 		radius_msg_free(sess->last_msg);
1459 		sess->last_msg = msg;
1460 		sess->last_from_port = from_port;
1461 		os_free(sess->last_from_addr);
1462 		sess->last_from_addr = os_strdup(from_addr);
1463 		sess->last_fromlen = fromlen;
1464 		os_memcpy(&sess->last_from, from, fromlen);
1465 		return -2;
1466 	} else {
1467 		RADIUS_DEBUG("No EAP data from the state machine - ignore this"
1468 			     " Access-Request silently (assuming it was a "
1469 			     "duplicate)");
1470 		data->counters.packets_dropped++;
1471 		client->counters.packets_dropped++;
1472 		return -1;
1473 	}
1474 
1475 	if (sess->eap_if->eapSuccess || sess->eap_if->eapFail)
1476 		is_complete = 1;
1477 	if (sess->eap_if->eapFail) {
1478 		srv_log(sess, "EAP authentication failed");
1479 		db_update_last_msk(sess, "FAIL");
1480 	} else if (sess->eap_if->eapSuccess) {
1481 		srv_log(sess, "EAP authentication succeeded");
1482 	}
1483 
1484 	if (sess->eap_if->eapSuccess)
1485 		radius_server_hs20_t_c_check(sess, msg);
1486 
1487 	reply = radius_server_encapsulate_eap(data, client, sess, msg);
1488 
1489 send_reply:
1490 	if (reply) {
1491 		struct wpabuf *buf;
1492 		struct radius_hdr *hdr;
1493 
1494 		RADIUS_DEBUG("Reply to %s:%d", from_addr, from_port);
1495 		if (wpa_debug_level <= MSG_MSGDUMP) {
1496 			radius_msg_dump(reply);
1497 		}
1498 
1499 		switch (radius_msg_get_hdr(reply)->code) {
1500 		case RADIUS_CODE_ACCESS_ACCEPT:
1501 			srv_log(sess, "Sending Access-Accept");
1502 			data->counters.access_accepts++;
1503 			client->counters.access_accepts++;
1504 			break;
1505 		case RADIUS_CODE_ACCESS_REJECT:
1506 			srv_log(sess, "Sending Access-Reject");
1507 			data->counters.access_rejects++;
1508 			client->counters.access_rejects++;
1509 			break;
1510 		case RADIUS_CODE_ACCESS_CHALLENGE:
1511 			data->counters.access_challenges++;
1512 			client->counters.access_challenges++;
1513 			break;
1514 		}
1515 		buf = radius_msg_get_buf(reply);
1516 		res = sendto(data->auth_sock, wpabuf_head(buf),
1517 			     wpabuf_len(buf), 0,
1518 			     (struct sockaddr *) from, fromlen);
1519 		if (res < 0) {
1520 			wpa_printf(MSG_INFO, "sendto[RADIUS SRV]: %s",
1521 				   strerror(errno));
1522 		}
1523 		radius_msg_free(sess->last_reply);
1524 		sess->last_reply = reply;
1525 		sess->last_from_port = from_port;
1526 		hdr = radius_msg_get_hdr(msg);
1527 		sess->last_identifier = hdr->identifier;
1528 		os_memcpy(sess->last_authenticator, hdr->authenticator, 16);
1529 	} else {
1530 		data->counters.packets_dropped++;
1531 		client->counters.packets_dropped++;
1532 	}
1533 
1534 	if (is_complete) {
1535 		RADIUS_DEBUG("Removing completed session 0x%x after timeout",
1536 			     sess->sess_id);
1537 		eloop_cancel_timeout(radius_server_session_remove_timeout,
1538 				     data, sess);
1539 		eloop_register_timeout(RADIUS_SESSION_MAINTAIN, 0,
1540 				       radius_server_session_remove_timeout,
1541 				       data, sess);
1542 	}
1543 
1544 	return 0;
1545 }
1546 
1547 
1548 static void
radius_server_receive_disconnect_resp(struct radius_server_data * data,struct radius_client * client,struct radius_msg * msg,int ack)1549 radius_server_receive_disconnect_resp(struct radius_server_data *data,
1550 				      struct radius_client *client,
1551 				      struct radius_msg *msg, int ack)
1552 {
1553 	struct radius_hdr *hdr;
1554 
1555 	if (!client->pending_dac_disconnect_req) {
1556 		RADIUS_DEBUG("Ignore unexpected Disconnect response");
1557 		radius_msg_free(msg);
1558 		return;
1559 	}
1560 
1561 	hdr = radius_msg_get_hdr(msg);
1562 	if (hdr->identifier != client->pending_dac_disconnect_id) {
1563 		RADIUS_DEBUG("Ignore unexpected Disconnect response with unexpected identifier %u (expected %u)",
1564 			     hdr->identifier,
1565 			     client->pending_dac_disconnect_id);
1566 		radius_msg_free(msg);
1567 		return;
1568 	}
1569 
1570 	if (radius_msg_verify(msg, (const u8 *) client->shared_secret,
1571 			      client->shared_secret_len,
1572 			      client->pending_dac_disconnect_req, 0)) {
1573 		RADIUS_DEBUG("Ignore Disconnect response with invalid authenticator");
1574 		radius_msg_free(msg);
1575 		return;
1576 	}
1577 
1578 	RADIUS_DEBUG("Disconnect-%s received for " MACSTR,
1579 		     ack ? "ACK" : "NAK",
1580 		     MAC2STR(client->pending_dac_disconnect_addr));
1581 
1582 	radius_msg_free(msg);
1583 	radius_msg_free(client->pending_dac_disconnect_req);
1584 	client->pending_dac_disconnect_req = NULL;
1585 }
1586 
1587 
radius_server_receive_coa_resp(struct radius_server_data * data,struct radius_client * client,struct radius_msg * msg,int ack)1588 static void radius_server_receive_coa_resp(struct radius_server_data *data,
1589 					   struct radius_client *client,
1590 					   struct radius_msg *msg, int ack)
1591 {
1592 	struct radius_hdr *hdr;
1593 #ifdef CONFIG_SQLITE
1594 	char addrtxt[3 * ETH_ALEN];
1595 	char *sql;
1596 	int res;
1597 #endif /* CONFIG_SQLITE */
1598 
1599 	if (!client->pending_dac_coa_req) {
1600 		RADIUS_DEBUG("Ignore unexpected CoA response");
1601 		radius_msg_free(msg);
1602 		return;
1603 	}
1604 
1605 	hdr = radius_msg_get_hdr(msg);
1606 	if (hdr->identifier != client->pending_dac_coa_id) {
1607 		RADIUS_DEBUG("Ignore unexpected CoA response with unexpected identifier %u (expected %u)",
1608 			     hdr->identifier,
1609 			     client->pending_dac_coa_id);
1610 		radius_msg_free(msg);
1611 		return;
1612 	}
1613 
1614 	if (radius_msg_verify(msg, (const u8 *) client->shared_secret,
1615 			      client->shared_secret_len,
1616 			      client->pending_dac_coa_req, 0)) {
1617 		RADIUS_DEBUG("Ignore CoA response with invalid authenticator");
1618 		radius_msg_free(msg);
1619 		return;
1620 	}
1621 
1622 	RADIUS_DEBUG("CoA-%s received for " MACSTR,
1623 		     ack ? "ACK" : "NAK",
1624 		     MAC2STR(client->pending_dac_coa_addr));
1625 
1626 	radius_msg_free(msg);
1627 	radius_msg_free(client->pending_dac_coa_req);
1628 	client->pending_dac_coa_req = NULL;
1629 
1630 #ifdef CONFIG_SQLITE
1631 	if (!data->db)
1632 		return;
1633 
1634 	os_snprintf(addrtxt, sizeof(addrtxt), MACSTR,
1635 		    MAC2STR(client->pending_dac_coa_addr));
1636 
1637 	if (ack) {
1638 		sql = sqlite3_mprintf("UPDATE current_sessions SET hs20_t_c_filtering=0, waiting_coa_ack=0, coa_ack_received=1 WHERE mac_addr=%Q",
1639 				      addrtxt);
1640 	} else {
1641 		sql = sqlite3_mprintf("UPDATE current_sessions SET waiting_coa_ack=0 WHERE mac_addr=%Q",
1642 				      addrtxt);
1643 	}
1644 	if (!sql)
1645 		return;
1646 
1647 	res = sqlite3_exec(data->db, sql, NULL, NULL, NULL);
1648 	sqlite3_free(sql);
1649 	if (res != SQLITE_OK) {
1650 		RADIUS_ERROR("Failed to update current_sessions entry: %s",
1651 			     sqlite3_errmsg(data->db));
1652 		return;
1653 	}
1654 #endif /* CONFIG_SQLITE */
1655 }
1656 
1657 
radius_server_receive_auth(int sock,void * eloop_ctx,void * sock_ctx)1658 static void radius_server_receive_auth(int sock, void *eloop_ctx,
1659 				       void *sock_ctx)
1660 {
1661 	struct radius_server_data *data = eloop_ctx;
1662 	u8 *buf = NULL;
1663 	union {
1664 		struct sockaddr_storage ss;
1665 		struct sockaddr_in sin;
1666 #ifdef CONFIG_IPV6
1667 		struct sockaddr_in6 sin6;
1668 #endif /* CONFIG_IPV6 */
1669 	} from;
1670 	socklen_t fromlen;
1671 	int len;
1672 	struct radius_client *client = NULL;
1673 	struct radius_msg *msg = NULL;
1674 	char abuf[50];
1675 	int from_port = 0;
1676 
1677 	buf = os_malloc(RADIUS_MAX_MSG_LEN);
1678 	if (buf == NULL) {
1679 		goto fail;
1680 	}
1681 
1682 	fromlen = sizeof(from);
1683 	len = recvfrom(sock, buf, RADIUS_MAX_MSG_LEN, 0,
1684 		       (struct sockaddr *) &from.ss, &fromlen);
1685 	if (len < 0) {
1686 		wpa_printf(MSG_INFO, "recvfrom[radius_server]: %s",
1687 			   strerror(errno));
1688 		goto fail;
1689 	}
1690 
1691 #ifdef CONFIG_IPV6
1692 	if (data->ipv6) {
1693 		if (inet_ntop(AF_INET6, &from.sin6.sin6_addr, abuf,
1694 			      sizeof(abuf)) == NULL)
1695 			abuf[0] = '\0';
1696 		from_port = ntohs(from.sin6.sin6_port);
1697 		RADIUS_DEBUG("Received %d bytes from %s:%d",
1698 			     len, abuf, from_port);
1699 
1700 		client = radius_server_get_client(data,
1701 						  (struct in_addr *)
1702 						  &from.sin6.sin6_addr, 1);
1703 	}
1704 #endif /* CONFIG_IPV6 */
1705 
1706 	if (!data->ipv6) {
1707 		os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf));
1708 		from_port = ntohs(from.sin.sin_port);
1709 		RADIUS_DEBUG("Received %d bytes from %s:%d",
1710 			     len, abuf, from_port);
1711 
1712 		client = radius_server_get_client(data, &from.sin.sin_addr, 0);
1713 	}
1714 
1715 	RADIUS_DUMP("Received data", buf, len);
1716 
1717 	if (client == NULL) {
1718 		RADIUS_DEBUG("Unknown client %s - packet ignored", abuf);
1719 		data->counters.invalid_requests++;
1720 		goto fail;
1721 	}
1722 
1723 	msg = radius_msg_parse(buf, len);
1724 	if (msg == NULL) {
1725 		RADIUS_DEBUG("Parsing incoming RADIUS frame failed");
1726 		data->counters.malformed_access_requests++;
1727 		client->counters.malformed_access_requests++;
1728 		goto fail;
1729 	}
1730 
1731 	os_free(buf);
1732 	buf = NULL;
1733 
1734 	if (wpa_debug_level <= MSG_MSGDUMP) {
1735 		radius_msg_dump(msg);
1736 	}
1737 
1738 	if (radius_msg_get_hdr(msg)->code == RADIUS_CODE_DISCONNECT_ACK) {
1739 		radius_server_receive_disconnect_resp(data, client, msg, 1);
1740 		return;
1741 	}
1742 
1743 	if (radius_msg_get_hdr(msg)->code == RADIUS_CODE_DISCONNECT_NAK) {
1744 		radius_server_receive_disconnect_resp(data, client, msg, 0);
1745 		return;
1746 	}
1747 
1748 	if (radius_msg_get_hdr(msg)->code == RADIUS_CODE_COA_ACK) {
1749 		radius_server_receive_coa_resp(data, client, msg, 1);
1750 		return;
1751 	}
1752 
1753 	if (radius_msg_get_hdr(msg)->code == RADIUS_CODE_COA_NAK) {
1754 		radius_server_receive_coa_resp(data, client, msg, 0);
1755 		return;
1756 	}
1757 
1758 	if (radius_msg_get_hdr(msg)->code != RADIUS_CODE_ACCESS_REQUEST) {
1759 		RADIUS_DEBUG("Unexpected RADIUS code %d",
1760 			     radius_msg_get_hdr(msg)->code);
1761 		data->counters.unknown_types++;
1762 		client->counters.unknown_types++;
1763 		goto fail;
1764 	}
1765 
1766 	data->counters.access_requests++;
1767 	client->counters.access_requests++;
1768 
1769 	if (radius_msg_verify_msg_auth(msg, (u8 *) client->shared_secret,
1770 				       client->shared_secret_len, NULL)) {
1771 		RADIUS_DEBUG("Invalid Message-Authenticator from %s", abuf);
1772 		data->counters.bad_authenticators++;
1773 		client->counters.bad_authenticators++;
1774 		goto fail;
1775 	}
1776 
1777 	if (radius_server_request(data, msg, (struct sockaddr *) &from,
1778 				  fromlen, client, abuf, from_port, NULL) ==
1779 	    -2)
1780 		return; /* msg was stored with the session */
1781 
1782 fail:
1783 	radius_msg_free(msg);
1784 	os_free(buf);
1785 }
1786 
1787 
radius_server_receive_acct(int sock,void * eloop_ctx,void * sock_ctx)1788 static void radius_server_receive_acct(int sock, void *eloop_ctx,
1789 				       void *sock_ctx)
1790 {
1791 	struct radius_server_data *data = eloop_ctx;
1792 	u8 *buf = NULL;
1793 	union {
1794 		struct sockaddr_storage ss;
1795 		struct sockaddr_in sin;
1796 #ifdef CONFIG_IPV6
1797 		struct sockaddr_in6 sin6;
1798 #endif /* CONFIG_IPV6 */
1799 	} from;
1800 	socklen_t fromlen;
1801 	int len, res;
1802 	struct radius_client *client = NULL;
1803 	struct radius_msg *msg = NULL, *resp = NULL;
1804 	char abuf[50];
1805 	int from_port = 0;
1806 	struct radius_hdr *hdr;
1807 	struct wpabuf *rbuf;
1808 
1809 	buf = os_malloc(RADIUS_MAX_MSG_LEN);
1810 	if (buf == NULL) {
1811 		goto fail;
1812 	}
1813 
1814 	fromlen = sizeof(from);
1815 	len = recvfrom(sock, buf, RADIUS_MAX_MSG_LEN, 0,
1816 		       (struct sockaddr *) &from.ss, &fromlen);
1817 	if (len < 0) {
1818 		wpa_printf(MSG_INFO, "recvfrom[radius_server]: %s",
1819 			   strerror(errno));
1820 		goto fail;
1821 	}
1822 
1823 #ifdef CONFIG_IPV6
1824 	if (data->ipv6) {
1825 		if (inet_ntop(AF_INET6, &from.sin6.sin6_addr, abuf,
1826 			      sizeof(abuf)) == NULL)
1827 			abuf[0] = '\0';
1828 		from_port = ntohs(from.sin6.sin6_port);
1829 		RADIUS_DEBUG("Received %d bytes from %s:%d",
1830 			     len, abuf, from_port);
1831 
1832 		client = radius_server_get_client(data,
1833 						  (struct in_addr *)
1834 						  &from.sin6.sin6_addr, 1);
1835 	}
1836 #endif /* CONFIG_IPV6 */
1837 
1838 	if (!data->ipv6) {
1839 		os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf));
1840 		from_port = ntohs(from.sin.sin_port);
1841 		RADIUS_DEBUG("Received %d bytes from %s:%d",
1842 			     len, abuf, from_port);
1843 
1844 		client = radius_server_get_client(data, &from.sin.sin_addr, 0);
1845 	}
1846 
1847 	RADIUS_DUMP("Received data", buf, len);
1848 
1849 	if (client == NULL) {
1850 		RADIUS_DEBUG("Unknown client %s - packet ignored", abuf);
1851 		data->counters.invalid_acct_requests++;
1852 		goto fail;
1853 	}
1854 
1855 	msg = radius_msg_parse(buf, len);
1856 	if (msg == NULL) {
1857 		RADIUS_DEBUG("Parsing incoming RADIUS frame failed");
1858 		data->counters.malformed_acct_requests++;
1859 		client->counters.malformed_acct_requests++;
1860 		goto fail;
1861 	}
1862 
1863 	os_free(buf);
1864 	buf = NULL;
1865 
1866 	if (wpa_debug_level <= MSG_MSGDUMP) {
1867 		radius_msg_dump(msg);
1868 	}
1869 
1870 	if (radius_msg_get_hdr(msg)->code != RADIUS_CODE_ACCOUNTING_REQUEST) {
1871 		RADIUS_DEBUG("Unexpected RADIUS code %d",
1872 			     radius_msg_get_hdr(msg)->code);
1873 		data->counters.unknown_acct_types++;
1874 		client->counters.unknown_acct_types++;
1875 		goto fail;
1876 	}
1877 
1878 	data->counters.acct_requests++;
1879 	client->counters.acct_requests++;
1880 
1881 	if (radius_msg_verify_acct_req(msg, (u8 *) client->shared_secret,
1882 				       client->shared_secret_len)) {
1883 		RADIUS_DEBUG("Invalid Authenticator from %s", abuf);
1884 		data->counters.acct_bad_authenticators++;
1885 		client->counters.acct_bad_authenticators++;
1886 		goto fail;
1887 	}
1888 
1889 	/* TODO: Write accounting information to a file or database */
1890 
1891 	hdr = radius_msg_get_hdr(msg);
1892 
1893 	resp = radius_msg_new(RADIUS_CODE_ACCOUNTING_RESPONSE, hdr->identifier);
1894 	if (resp == NULL)
1895 		goto fail;
1896 
1897 	radius_msg_finish_acct_resp(resp, (u8 *) client->shared_secret,
1898 				    client->shared_secret_len,
1899 				    hdr->authenticator);
1900 
1901 	RADIUS_DEBUG("Reply to %s:%d", abuf, from_port);
1902 	if (wpa_debug_level <= MSG_MSGDUMP) {
1903 		radius_msg_dump(resp);
1904 	}
1905 	rbuf = radius_msg_get_buf(resp);
1906 	data->counters.acct_responses++;
1907 	client->counters.acct_responses++;
1908 	res = sendto(data->acct_sock, wpabuf_head(rbuf), wpabuf_len(rbuf), 0,
1909 		     (struct sockaddr *) &from.ss, fromlen);
1910 	if (res < 0) {
1911 		wpa_printf(MSG_INFO, "sendto[RADIUS SRV]: %s",
1912 			   strerror(errno));
1913 	}
1914 
1915 fail:
1916 	radius_msg_free(resp);
1917 	radius_msg_free(msg);
1918 	os_free(buf);
1919 }
1920 
1921 
radius_server_disable_pmtu_discovery(int s)1922 static int radius_server_disable_pmtu_discovery(int s)
1923 {
1924 	int r = -1;
1925 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
1926 	/* Turn off Path MTU discovery on IPv4/UDP sockets. */
1927 	int action = IP_PMTUDISC_DONT;
1928 	r = setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &action,
1929 		       sizeof(action));
1930 	if (r == -1)
1931 		wpa_printf(MSG_ERROR, "Failed to set IP_MTU_DISCOVER: "
1932 			   "%s", strerror(errno));
1933 #endif
1934 	return r;
1935 }
1936 
1937 
radius_server_open_socket(int port)1938 static int radius_server_open_socket(int port)
1939 {
1940 	int s;
1941 	struct sockaddr_in addr;
1942 
1943 	s = socket(PF_INET, SOCK_DGRAM, 0);
1944 	if (s < 0) {
1945 		wpa_printf(MSG_INFO, "RADIUS: socket: %s", strerror(errno));
1946 		return -1;
1947 	}
1948 
1949 	radius_server_disable_pmtu_discovery(s);
1950 
1951 	os_memset(&addr, 0, sizeof(addr));
1952 	addr.sin_family = AF_INET;
1953 	addr.sin_port = htons(port);
1954 	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1955 		wpa_printf(MSG_INFO, "RADIUS: bind: %s", strerror(errno));
1956 		close(s);
1957 		return -1;
1958 	}
1959 
1960 	return s;
1961 }
1962 
1963 
1964 #ifdef CONFIG_IPV6
radius_server_open_socket6(int port)1965 static int radius_server_open_socket6(int port)
1966 {
1967 	int s;
1968 	struct sockaddr_in6 addr;
1969 
1970 	s = socket(PF_INET6, SOCK_DGRAM, 0);
1971 	if (s < 0) {
1972 		wpa_printf(MSG_INFO, "RADIUS: socket[IPv6]: %s",
1973 			   strerror(errno));
1974 		return -1;
1975 	}
1976 
1977 	os_memset(&addr, 0, sizeof(addr));
1978 	addr.sin6_family = AF_INET6;
1979 	os_memcpy(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any));
1980 	addr.sin6_port = htons(port);
1981 	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1982 		wpa_printf(MSG_INFO, "RADIUS: bind: %s", strerror(errno));
1983 		close(s);
1984 		return -1;
1985 	}
1986 
1987 	return s;
1988 }
1989 #endif /* CONFIG_IPV6 */
1990 
1991 
radius_server_free_sessions(struct radius_server_data * data,struct radius_session * sessions)1992 static void radius_server_free_sessions(struct radius_server_data *data,
1993 					struct radius_session *sessions)
1994 {
1995 	struct radius_session *session, *prev;
1996 
1997 	session = sessions;
1998 	while (session) {
1999 		prev = session;
2000 		session = session->next;
2001 		radius_server_session_free(data, prev);
2002 	}
2003 }
2004 
2005 
radius_server_free_clients(struct radius_server_data * data,struct radius_client * clients)2006 static void radius_server_free_clients(struct radius_server_data *data,
2007 				       struct radius_client *clients)
2008 {
2009 	struct radius_client *client, *prev;
2010 
2011 	client = clients;
2012 	while (client) {
2013 		prev = client;
2014 		client = client->next;
2015 
2016 		radius_server_free_sessions(data, prev->sessions);
2017 		os_free(prev->shared_secret);
2018 		radius_msg_free(prev->pending_dac_coa_req);
2019 		radius_msg_free(prev->pending_dac_disconnect_req);
2020 		os_free(prev);
2021 	}
2022 }
2023 
2024 
2025 static struct radius_client *
radius_server_read_clients(const char * client_file,int ipv6)2026 radius_server_read_clients(const char *client_file, int ipv6)
2027 {
2028 	FILE *f;
2029 	const int buf_size = 1024;
2030 	char *buf, *pos;
2031 	struct radius_client *clients, *tail, *entry;
2032 	int line = 0, mask, failed = 0, i;
2033 	struct in_addr addr;
2034 #ifdef CONFIG_IPV6
2035 	struct in6_addr addr6;
2036 #endif /* CONFIG_IPV6 */
2037 	unsigned int val;
2038 
2039 	f = fopen(client_file, "r");
2040 	if (f == NULL) {
2041 		RADIUS_ERROR("Could not open client file '%s'", client_file);
2042 		return NULL;
2043 	}
2044 
2045 	buf = os_malloc(buf_size);
2046 	if (buf == NULL) {
2047 		fclose(f);
2048 		return NULL;
2049 	}
2050 
2051 	clients = tail = NULL;
2052 	while (fgets(buf, buf_size, f)) {
2053 		/* Configuration file format:
2054 		 * 192.168.1.0/24 secret
2055 		 * 192.168.1.2 secret
2056 		 * fe80::211:22ff:fe33:4455/64 secretipv6
2057 		 */
2058 		line++;
2059 		buf[buf_size - 1] = '\0';
2060 		pos = buf;
2061 		while (*pos != '\0' && *pos != '\n')
2062 			pos++;
2063 		if (*pos == '\n')
2064 			*pos = '\0';
2065 		if (*buf == '\0' || *buf == '#')
2066 			continue;
2067 
2068 		pos = buf;
2069 		while ((*pos >= '0' && *pos <= '9') || *pos == '.' ||
2070 		       (*pos >= 'a' && *pos <= 'f') || *pos == ':' ||
2071 		       (*pos >= 'A' && *pos <= 'F')) {
2072 			pos++;
2073 		}
2074 
2075 		if (*pos == '\0') {
2076 			failed = 1;
2077 			break;
2078 		}
2079 
2080 		if (*pos == '/') {
2081 			char *end;
2082 			*pos++ = '\0';
2083 			mask = strtol(pos, &end, 10);
2084 			if ((pos == end) ||
2085 			    (mask < 0 || mask > (ipv6 ? 128 : 32))) {
2086 				failed = 1;
2087 				break;
2088 			}
2089 			pos = end;
2090 		} else {
2091 			mask = ipv6 ? 128 : 32;
2092 			*pos++ = '\0';
2093 		}
2094 
2095 		if (!ipv6 && inet_aton(buf, &addr) == 0) {
2096 			failed = 1;
2097 			break;
2098 		}
2099 #ifdef CONFIG_IPV6
2100 		if (ipv6 && inet_pton(AF_INET6, buf, &addr6) <= 0) {
2101 			if (inet_pton(AF_INET, buf, &addr) <= 0) {
2102 				failed = 1;
2103 				break;
2104 			}
2105 			/* Convert IPv4 address to IPv6 */
2106 			if (mask <= 32)
2107 				mask += (128 - 32);
2108 			os_memset(addr6.s6_addr, 0, 10);
2109 			addr6.s6_addr[10] = 0xff;
2110 			addr6.s6_addr[11] = 0xff;
2111 			os_memcpy(addr6.s6_addr + 12, (char *) &addr.s_addr,
2112 				  4);
2113 		}
2114 #endif /* CONFIG_IPV6 */
2115 
2116 		while (*pos == ' ' || *pos == '\t') {
2117 			pos++;
2118 		}
2119 
2120 		if (*pos == '\0') {
2121 			failed = 1;
2122 			break;
2123 		}
2124 
2125 		entry = os_zalloc(sizeof(*entry));
2126 		if (entry == NULL) {
2127 			failed = 1;
2128 			break;
2129 		}
2130 		entry->shared_secret = os_strdup(pos);
2131 		if (entry->shared_secret == NULL) {
2132 			failed = 1;
2133 			os_free(entry);
2134 			break;
2135 		}
2136 		entry->shared_secret_len = os_strlen(entry->shared_secret);
2137 		if (!ipv6) {
2138 			entry->addr.s_addr = addr.s_addr;
2139 			val = 0;
2140 			for (i = 0; i < mask; i++)
2141 				val |= 1U << (31 - i);
2142 			entry->mask.s_addr = htonl(val);
2143 		}
2144 #ifdef CONFIG_IPV6
2145 		if (ipv6) {
2146 			int offset = mask / 8;
2147 
2148 			os_memcpy(entry->addr6.s6_addr, addr6.s6_addr, 16);
2149 			os_memset(entry->mask6.s6_addr, 0xff, offset);
2150 			val = 0;
2151 			for (i = 0; i < (mask % 8); i++)
2152 				val |= 1 << (7 - i);
2153 			if (offset < 16)
2154 				entry->mask6.s6_addr[offset] = val;
2155 		}
2156 #endif /* CONFIG_IPV6 */
2157 
2158 		if (tail == NULL) {
2159 			clients = tail = entry;
2160 		} else {
2161 			tail->next = entry;
2162 			tail = entry;
2163 		}
2164 	}
2165 
2166 	if (failed) {
2167 		RADIUS_ERROR("Invalid line %d in '%s'", line, client_file);
2168 		radius_server_free_clients(NULL, clients);
2169 		clients = NULL;
2170 	}
2171 
2172 	os_free(buf);
2173 	fclose(f);
2174 
2175 	return clients;
2176 }
2177 
2178 
2179 /**
2180  * radius_server_init - Initialize RADIUS server
2181  * @conf: Configuration for the RADIUS server
2182  * Returns: Pointer to private RADIUS server context or %NULL on failure
2183  *
2184  * This initializes a RADIUS server instance and returns a context pointer that
2185  * will be used in other calls to the RADIUS server module. The server can be
2186  * deinitialize by calling radius_server_deinit().
2187  */
2188 struct radius_server_data *
radius_server_init(struct radius_server_conf * conf)2189 radius_server_init(struct radius_server_conf *conf)
2190 {
2191 	struct radius_server_data *data;
2192 
2193 #ifndef CONFIG_IPV6
2194 	if (conf->ipv6) {
2195 		wpa_printf(MSG_ERROR, "RADIUS server compiled without IPv6 support");
2196 		return NULL;
2197 	}
2198 #endif /* CONFIG_IPV6 */
2199 
2200 	data = os_zalloc(sizeof(*data));
2201 	if (data == NULL)
2202 		return NULL;
2203 
2204 	data->eap_cfg = conf->eap_cfg;
2205 	data->auth_sock = -1;
2206 	data->acct_sock = -1;
2207 	dl_list_init(&data->erp_keys);
2208 	os_get_reltime(&data->start_time);
2209 	data->conf_ctx = conf->conf_ctx;
2210 	conf->eap_cfg->backend_auth = true;
2211 	conf->eap_cfg->eap_server = 1;
2212 	data->ipv6 = conf->ipv6;
2213 	data->get_eap_user = conf->get_eap_user;
2214 	if (conf->eap_req_id_text) {
2215 		data->eap_req_id_text = os_malloc(conf->eap_req_id_text_len);
2216 		if (!data->eap_req_id_text)
2217 			goto fail;
2218 		os_memcpy(data->eap_req_id_text, conf->eap_req_id_text,
2219 			  conf->eap_req_id_text_len);
2220 		data->eap_req_id_text_len = conf->eap_req_id_text_len;
2221 	}
2222 	data->erp_domain = conf->erp_domain;
2223 
2224 	if (conf->subscr_remediation_url) {
2225 		data->subscr_remediation_url =
2226 			os_strdup(conf->subscr_remediation_url);
2227 		if (!data->subscr_remediation_url)
2228 			goto fail;
2229 	}
2230 	data->subscr_remediation_method = conf->subscr_remediation_method;
2231 	if (conf->hs20_sim_provisioning_url) {
2232 		data->hs20_sim_provisioning_url =
2233 			os_strdup(conf->hs20_sim_provisioning_url);
2234 		if (!data->hs20_sim_provisioning_url)
2235 			goto fail;
2236 	}
2237 
2238 	if (conf->t_c_server_url) {
2239 		data->t_c_server_url = os_strdup(conf->t_c_server_url);
2240 		if (!data->t_c_server_url)
2241 			goto fail;
2242 	}
2243 
2244 #ifdef CONFIG_SQLITE
2245 	if (conf->sqlite_file) {
2246 		if (sqlite3_open(conf->sqlite_file, &data->db)) {
2247 			RADIUS_ERROR("Could not open SQLite file '%s'",
2248 				     conf->sqlite_file);
2249 			goto fail;
2250 		}
2251 	}
2252 #endif /* CONFIG_SQLITE */
2253 
2254 #ifdef CONFIG_RADIUS_TEST
2255 	if (conf->dump_msk_file)
2256 		data->dump_msk_file = os_strdup(conf->dump_msk_file);
2257 #endif /* CONFIG_RADIUS_TEST */
2258 
2259 	data->clients = radius_server_read_clients(conf->client_file,
2260 						   conf->ipv6);
2261 	if (data->clients == NULL) {
2262 		wpa_printf(MSG_ERROR, "No RADIUS clients configured");
2263 		goto fail;
2264 	}
2265 
2266 #ifdef CONFIG_IPV6
2267 	if (conf->ipv6)
2268 		data->auth_sock = radius_server_open_socket6(conf->auth_port);
2269 	else
2270 #endif /* CONFIG_IPV6 */
2271 	data->auth_sock = radius_server_open_socket(conf->auth_port);
2272 	if (data->auth_sock < 0) {
2273 		wpa_printf(MSG_ERROR, "Failed to open UDP socket for RADIUS authentication server");
2274 		goto fail;
2275 	}
2276 	if (eloop_register_read_sock(data->auth_sock,
2277 				     radius_server_receive_auth,
2278 				     data, NULL)) {
2279 		goto fail;
2280 	}
2281 
2282 	if (conf->acct_port) {
2283 #ifdef CONFIG_IPV6
2284 		if (conf->ipv6)
2285 			data->acct_sock = radius_server_open_socket6(
2286 				conf->acct_port);
2287 		else
2288 #endif /* CONFIG_IPV6 */
2289 		data->acct_sock = radius_server_open_socket(conf->acct_port);
2290 		if (data->acct_sock < 0) {
2291 			wpa_printf(MSG_ERROR, "Failed to open UDP socket for RADIUS accounting server");
2292 			goto fail;
2293 		}
2294 		if (eloop_register_read_sock(data->acct_sock,
2295 					     radius_server_receive_acct,
2296 					     data, NULL))
2297 			goto fail;
2298 	} else {
2299 		data->acct_sock = -1;
2300 	}
2301 
2302 	return data;
2303 fail:
2304 	radius_server_deinit(data);
2305 	return NULL;
2306 }
2307 
2308 
2309 /**
2310  * radius_server_erp_flush - Flush all ERP keys
2311  * @data: RADIUS server context from radius_server_init()
2312  */
radius_server_erp_flush(struct radius_server_data * data)2313 void radius_server_erp_flush(struct radius_server_data *data)
2314 {
2315 	struct eap_server_erp_key *erp;
2316 
2317 	if (data == NULL)
2318 		return;
2319 	while ((erp = dl_list_first(&data->erp_keys, struct eap_server_erp_key,
2320 				    list)) != NULL) {
2321 		dl_list_del(&erp->list);
2322 		bin_clear_free(erp, sizeof(*erp));
2323 	}
2324 }
2325 
2326 
2327 /**
2328  * radius_server_deinit - Deinitialize RADIUS server
2329  * @data: RADIUS server context from radius_server_init()
2330  */
radius_server_deinit(struct radius_server_data * data)2331 void radius_server_deinit(struct radius_server_data *data)
2332 {
2333 	if (data == NULL)
2334 		return;
2335 
2336 	if (data->auth_sock >= 0) {
2337 		eloop_unregister_read_sock(data->auth_sock);
2338 		close(data->auth_sock);
2339 	}
2340 
2341 	if (data->acct_sock >= 0) {
2342 		eloop_unregister_read_sock(data->acct_sock);
2343 		close(data->acct_sock);
2344 	}
2345 
2346 	radius_server_free_clients(data, data->clients);
2347 
2348 	os_free(data->eap_req_id_text);
2349 #ifdef CONFIG_RADIUS_TEST
2350 	os_free(data->dump_msk_file);
2351 #endif /* CONFIG_RADIUS_TEST */
2352 	os_free(data->subscr_remediation_url);
2353 	os_free(data->hs20_sim_provisioning_url);
2354 	os_free(data->t_c_server_url);
2355 
2356 #ifdef CONFIG_SQLITE
2357 	if (data->db)
2358 		sqlite3_close(data->db);
2359 #endif /* CONFIG_SQLITE */
2360 
2361 	radius_server_erp_flush(data);
2362 
2363 	os_free(data);
2364 }
2365 
2366 
2367 /**
2368  * radius_server_get_mib - Get RADIUS server MIB information
2369  * @data: RADIUS server context from radius_server_init()
2370  * @buf: Buffer for returning the MIB data in text format
2371  * @buflen: buf length in octets
2372  * Returns: Number of octets written into buf
2373  */
radius_server_get_mib(struct radius_server_data * data,char * buf,size_t buflen)2374 int radius_server_get_mib(struct radius_server_data *data, char *buf,
2375 			  size_t buflen)
2376 {
2377 	int ret, uptime;
2378 	unsigned int idx;
2379 	char *end, *pos;
2380 	struct os_reltime now;
2381 	struct radius_client *cli;
2382 
2383 	/* RFC 2619 - RADIUS Authentication Server MIB */
2384 
2385 	if (data == NULL || buflen == 0)
2386 		return 0;
2387 
2388 	pos = buf;
2389 	end = buf + buflen;
2390 
2391 	os_get_reltime(&now);
2392 	uptime = (now.sec - data->start_time.sec) * 100 +
2393 		((now.usec - data->start_time.usec) / 10000) % 100;
2394 	ret = os_snprintf(pos, end - pos,
2395 			  "RADIUS-AUTH-SERVER-MIB\n"
2396 			  "radiusAuthServIdent=hostapd\n"
2397 			  "radiusAuthServUpTime=%d\n"
2398 			  "radiusAuthServResetTime=0\n"
2399 			  "radiusAuthServConfigReset=4\n",
2400 			  uptime);
2401 	if (os_snprintf_error(end - pos, ret)) {
2402 		*pos = '\0';
2403 		return pos - buf;
2404 	}
2405 	pos += ret;
2406 
2407 	ret = os_snprintf(pos, end - pos,
2408 			  "radiusAuthServTotalAccessRequests=%u\n"
2409 			  "radiusAuthServTotalInvalidRequests=%u\n"
2410 			  "radiusAuthServTotalDupAccessRequests=%u\n"
2411 			  "radiusAuthServTotalAccessAccepts=%u\n"
2412 			  "radiusAuthServTotalAccessRejects=%u\n"
2413 			  "radiusAuthServTotalAccessChallenges=%u\n"
2414 			  "radiusAuthServTotalMalformedAccessRequests=%u\n"
2415 			  "radiusAuthServTotalBadAuthenticators=%u\n"
2416 			  "radiusAuthServTotalPacketsDropped=%u\n"
2417 			  "radiusAuthServTotalUnknownTypes=%u\n"
2418 			  "radiusAccServTotalRequests=%u\n"
2419 			  "radiusAccServTotalInvalidRequests=%u\n"
2420 			  "radiusAccServTotalResponses=%u\n"
2421 			  "radiusAccServTotalMalformedRequests=%u\n"
2422 			  "radiusAccServTotalBadAuthenticators=%u\n"
2423 			  "radiusAccServTotalUnknownTypes=%u\n",
2424 			  data->counters.access_requests,
2425 			  data->counters.invalid_requests,
2426 			  data->counters.dup_access_requests,
2427 			  data->counters.access_accepts,
2428 			  data->counters.access_rejects,
2429 			  data->counters.access_challenges,
2430 			  data->counters.malformed_access_requests,
2431 			  data->counters.bad_authenticators,
2432 			  data->counters.packets_dropped,
2433 			  data->counters.unknown_types,
2434 			  data->counters.acct_requests,
2435 			  data->counters.invalid_acct_requests,
2436 			  data->counters.acct_responses,
2437 			  data->counters.malformed_acct_requests,
2438 			  data->counters.acct_bad_authenticators,
2439 			  data->counters.unknown_acct_types);
2440 	if (os_snprintf_error(end - pos, ret)) {
2441 		*pos = '\0';
2442 		return pos - buf;
2443 	}
2444 	pos += ret;
2445 
2446 	for (cli = data->clients, idx = 0; cli; cli = cli->next, idx++) {
2447 		char abuf[50], mbuf[50];
2448 #ifdef CONFIG_IPV6
2449 		if (data->ipv6) {
2450 			if (inet_ntop(AF_INET6, &cli->addr6, abuf,
2451 				      sizeof(abuf)) == NULL)
2452 				abuf[0] = '\0';
2453 			if (inet_ntop(AF_INET6, &cli->mask6, mbuf,
2454 				      sizeof(mbuf)) == NULL)
2455 				mbuf[0] = '\0';
2456 		}
2457 #endif /* CONFIG_IPV6 */
2458 		if (!data->ipv6) {
2459 			os_strlcpy(abuf, inet_ntoa(cli->addr), sizeof(abuf));
2460 			os_strlcpy(mbuf, inet_ntoa(cli->mask), sizeof(mbuf));
2461 		}
2462 
2463 		ret = os_snprintf(pos, end - pos,
2464 				  "radiusAuthClientIndex=%u\n"
2465 				  "radiusAuthClientAddress=%s/%s\n"
2466 				  "radiusAuthServAccessRequests=%u\n"
2467 				  "radiusAuthServDupAccessRequests=%u\n"
2468 				  "radiusAuthServAccessAccepts=%u\n"
2469 				  "radiusAuthServAccessRejects=%u\n"
2470 				  "radiusAuthServAccessChallenges=%u\n"
2471 				  "radiusAuthServMalformedAccessRequests=%u\n"
2472 				  "radiusAuthServBadAuthenticators=%u\n"
2473 				  "radiusAuthServPacketsDropped=%u\n"
2474 				  "radiusAuthServUnknownTypes=%u\n"
2475 				  "radiusAccServTotalRequests=%u\n"
2476 				  "radiusAccServTotalInvalidRequests=%u\n"
2477 				  "radiusAccServTotalResponses=%u\n"
2478 				  "radiusAccServTotalMalformedRequests=%u\n"
2479 				  "radiusAccServTotalBadAuthenticators=%u\n"
2480 				  "radiusAccServTotalUnknownTypes=%u\n",
2481 				  idx,
2482 				  abuf, mbuf,
2483 				  cli->counters.access_requests,
2484 				  cli->counters.dup_access_requests,
2485 				  cli->counters.access_accepts,
2486 				  cli->counters.access_rejects,
2487 				  cli->counters.access_challenges,
2488 				  cli->counters.malformed_access_requests,
2489 				  cli->counters.bad_authenticators,
2490 				  cli->counters.packets_dropped,
2491 				  cli->counters.unknown_types,
2492 				  cli->counters.acct_requests,
2493 				  cli->counters.invalid_acct_requests,
2494 				  cli->counters.acct_responses,
2495 				  cli->counters.malformed_acct_requests,
2496 				  cli->counters.acct_bad_authenticators,
2497 				  cli->counters.unknown_acct_types);
2498 		if (os_snprintf_error(end - pos, ret)) {
2499 			*pos = '\0';
2500 			return pos - buf;
2501 		}
2502 		pos += ret;
2503 	}
2504 
2505 	return pos - buf;
2506 }
2507 
2508 
radius_server_get_eap_user(void * ctx,const u8 * identity,size_t identity_len,int phase2,struct eap_user * user)2509 static int radius_server_get_eap_user(void *ctx, const u8 *identity,
2510 				      size_t identity_len, int phase2,
2511 				      struct eap_user *user)
2512 {
2513 	struct radius_session *sess = ctx;
2514 	struct radius_server_data *data = sess->server;
2515 	int ret;
2516 
2517 	ret = data->get_eap_user(data->conf_ctx, identity, identity_len,
2518 				 phase2, user);
2519 	if (ret == 0 && user) {
2520 		sess->accept_attr = user->accept_attr;
2521 		sess->remediation = user->remediation;
2522 		sess->macacl = user->macacl;
2523 		sess->t_c_timestamp = user->t_c_timestamp;
2524 	}
2525 
2526 	if (ret) {
2527 		RADIUS_DEBUG("%s: User-Name not found from user database",
2528 			     __func__);
2529 	}
2530 
2531 	return ret;
2532 }
2533 
2534 
radius_server_get_eap_req_id_text(void * ctx,size_t * len)2535 static const char * radius_server_get_eap_req_id_text(void *ctx, size_t *len)
2536 {
2537 	struct radius_session *sess = ctx;
2538 	struct radius_server_data *data = sess->server;
2539 	*len = data->eap_req_id_text_len;
2540 	return data->eap_req_id_text;
2541 }
2542 
2543 
radius_server_log_msg(void * ctx,const char * msg)2544 static void radius_server_log_msg(void *ctx, const char *msg)
2545 {
2546 	struct radius_session *sess = ctx;
2547 	srv_log(sess, "EAP: %s", msg);
2548 }
2549 
2550 
2551 #ifdef CONFIG_ERP
2552 
radius_server_get_erp_domain(void * ctx)2553 static const char * radius_server_get_erp_domain(void *ctx)
2554 {
2555 	struct radius_session *sess = ctx;
2556 	struct radius_server_data *data = sess->server;
2557 
2558 	return data->erp_domain;
2559 }
2560 
2561 
2562 static struct eap_server_erp_key *
radius_server_erp_get_key(void * ctx,const char * keyname)2563 radius_server_erp_get_key(void *ctx, const char *keyname)
2564 {
2565 	struct radius_session *sess = ctx;
2566 	struct radius_server_data *data = sess->server;
2567 
2568 	return radius_server_erp_find_key(data, keyname);
2569 }
2570 
2571 
radius_server_erp_add_key(void * ctx,struct eap_server_erp_key * erp)2572 static int radius_server_erp_add_key(void *ctx, struct eap_server_erp_key *erp)
2573 {
2574 	struct radius_session *sess = ctx;
2575 	struct radius_server_data *data = sess->server;
2576 
2577 	dl_list_add(&data->erp_keys, &erp->list);
2578 	return 0;
2579 }
2580 
2581 #endif /* CONFIG_ERP */
2582 
2583 
2584 static const struct eapol_callbacks radius_server_eapol_cb =
2585 {
2586 	.get_eap_user = radius_server_get_eap_user,
2587 	.get_eap_req_id_text = radius_server_get_eap_req_id_text,
2588 	.log_msg = radius_server_log_msg,
2589 #ifdef CONFIG_ERP
2590 	.get_erp_send_reauth_start = NULL,
2591 	.get_erp_domain = radius_server_get_erp_domain,
2592 	.erp_get_key = radius_server_erp_get_key,
2593 	.erp_add_key = radius_server_erp_add_key,
2594 #endif /* CONFIG_ERP */
2595 };
2596 
2597 
2598 /**
2599  * radius_server_eap_pending_cb - Pending EAP data notification
2600  * @data: RADIUS server context from radius_server_init()
2601  * @ctx: Pending EAP context pointer
2602  *
2603  * This function is used to notify EAP server module that a pending operation
2604  * has been completed and processing of the EAP session can proceed.
2605  */
radius_server_eap_pending_cb(struct radius_server_data * data,void * ctx)2606 void radius_server_eap_pending_cb(struct radius_server_data *data, void *ctx)
2607 {
2608 	struct radius_client *cli;
2609 	struct radius_session *s, *sess = NULL;
2610 	struct radius_msg *msg;
2611 
2612 	if (data == NULL)
2613 		return;
2614 
2615 	for (cli = data->clients; cli; cli = cli->next) {
2616 		for (s = cli->sessions; s; s = s->next) {
2617 			if (s->eap == ctx && s->last_msg) {
2618 				sess = s;
2619 				break;
2620 			}
2621 		}
2622 		if (sess)
2623 			break;
2624 	}
2625 
2626 	if (sess == NULL) {
2627 		RADIUS_DEBUG("No session matched callback ctx");
2628 		return;
2629 	}
2630 
2631 	msg = sess->last_msg;
2632 	sess->last_msg = NULL;
2633 	eap_sm_pending_cb(sess->eap);
2634 	if (radius_server_request(data, msg,
2635 				  (struct sockaddr *) &sess->last_from,
2636 				  sess->last_fromlen, cli,
2637 				  sess->last_from_addr,
2638 				  sess->last_from_port, sess) == -2)
2639 		return; /* msg was stored with the session */
2640 
2641 	radius_msg_free(msg);
2642 }
2643 
2644 
2645 #ifdef CONFIG_SQLITE
2646 
2647 struct db_session_fields {
2648 	char *identity;
2649 	char *nas;
2650 	int hs20_t_c_filtering;
2651 	int waiting_coa_ack;
2652 	int coa_ack_received;
2653 };
2654 
2655 
get_db_session_fields(void * ctx,int argc,char * argv[],char * col[])2656 static int get_db_session_fields(void *ctx, int argc, char *argv[], char *col[])
2657 {
2658 	struct db_session_fields *fields = ctx;
2659 	int i;
2660 
2661 	for (i = 0; i < argc; i++) {
2662 		if (!argv[i])
2663 			continue;
2664 
2665 		RADIUS_DEBUG("Session DB: %s=%s", col[i], argv[i]);
2666 
2667 		if (os_strcmp(col[i], "identity") == 0) {
2668 			os_free(fields->identity);
2669 			fields->identity = os_strdup(argv[i]);
2670 		} else if (os_strcmp(col[i], "nas") == 0) {
2671 			os_free(fields->nas);
2672 			fields->nas = os_strdup(argv[i]);
2673 		} else if (os_strcmp(col[i], "hs20_t_c_filtering") == 0) {
2674 			fields->hs20_t_c_filtering = atoi(argv[i]);
2675 		} else if (os_strcmp(col[i], "waiting_coa_ack") == 0) {
2676 			fields->waiting_coa_ack = atoi(argv[i]);
2677 		} else if (os_strcmp(col[i], "coa_ack_received") == 0) {
2678 			fields->coa_ack_received = atoi(argv[i]);
2679 		}
2680 	}
2681 
2682 	return 0;
2683 }
2684 
2685 
free_db_session_fields(struct db_session_fields * fields)2686 static void free_db_session_fields(struct db_session_fields *fields)
2687 {
2688 	os_free(fields->identity);
2689 	fields->identity = NULL;
2690 	os_free(fields->nas);
2691 	fields->nas = NULL;
2692 }
2693 
2694 #endif /* CONFIG_SQLITE */
2695 
2696 
radius_server_dac_request(struct radius_server_data * data,const char * req)2697 int radius_server_dac_request(struct radius_server_data *data, const char *req)
2698 {
2699 #ifdef CONFIG_SQLITE
2700 	char *sql;
2701 	int res;
2702 	int disconnect;
2703 	const char *pos = req;
2704 	u8 addr[ETH_ALEN];
2705 	char addrtxt[3 * ETH_ALEN];
2706 	int t_c_clear = 0;
2707 	struct db_session_fields fields;
2708 	struct sockaddr_in das;
2709 	struct radius_client *client;
2710 	struct radius_msg *msg;
2711 	struct wpabuf *buf;
2712 	u8 identifier;
2713 	struct os_time now;
2714 
2715 	if (!data)
2716 		return -1;
2717 
2718 	/* req: <disconnect|coa> <MAC Address> [t_c_clear] */
2719 
2720 	if (os_strncmp(pos, "disconnect ", 11) == 0) {
2721 		disconnect = 1;
2722 		pos += 11;
2723 	} else if (os_strncmp(req, "coa ", 4) == 0) {
2724 		disconnect = 0;
2725 		pos += 4;
2726 	} else {
2727 		return -1;
2728 	}
2729 
2730 	if (hwaddr_aton(pos, addr))
2731 		return -1;
2732 	pos = os_strchr(pos, ' ');
2733 	if (pos) {
2734 		if (os_strstr(pos, "t_c_clear"))
2735 			t_c_clear = 1;
2736 	}
2737 
2738 	if (!disconnect && !t_c_clear) {
2739 		RADIUS_ERROR("DAC request for CoA without any authorization change");
2740 		return -1;
2741 	}
2742 
2743 	if (!data->db) {
2744 		RADIUS_ERROR("SQLite database not in use");
2745 		return -1;
2746 	}
2747 
2748 	os_snprintf(addrtxt, sizeof(addrtxt), MACSTR, MAC2STR(addr));
2749 
2750 	sql = sqlite3_mprintf("SELECT * FROM current_sessions WHERE mac_addr=%Q",
2751 			      addrtxt);
2752 	if (!sql)
2753 		return -1;
2754 
2755 	os_memset(&fields, 0, sizeof(fields));
2756 	res = sqlite3_exec(data->db, sql, get_db_session_fields, &fields, NULL);
2757 	sqlite3_free(sql);
2758 	if (res != SQLITE_OK) {
2759 		RADIUS_ERROR("Failed to find matching current_sessions entry from sqlite database: %s",
2760 			     sqlite3_errmsg(data->db));
2761 		free_db_session_fields(&fields);
2762 		return -1;
2763 	}
2764 
2765 	if (!fields.nas) {
2766 		RADIUS_ERROR("No NAS information found from current_sessions");
2767 		free_db_session_fields(&fields);
2768 		return -1;
2769 	}
2770 
2771 	os_memset(&das, 0, sizeof(das));
2772 	das.sin_family = AF_INET;
2773 	das.sin_addr.s_addr = inet_addr(fields.nas);
2774 	das.sin_port = htons(3799);
2775 
2776 	free_db_session_fields(&fields);
2777 
2778 	client = radius_server_get_client(data, &das.sin_addr, 0);
2779 	if (!client) {
2780 		RADIUS_ERROR("No NAS information available to protect the packet");
2781 		return -1;
2782 	}
2783 
2784 	identifier = client->next_dac_identifier++;
2785 
2786 	msg = radius_msg_new(disconnect ? RADIUS_CODE_DISCONNECT_REQUEST :
2787 			     RADIUS_CODE_COA_REQUEST, identifier);
2788 	if (!msg)
2789 		return -1;
2790 
2791 	os_snprintf(addrtxt, sizeof(addrtxt), RADIUS_802_1X_ADDR_FORMAT,
2792 		    MAC2STR(addr));
2793 	if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID,
2794 				 (u8 *) addrtxt, os_strlen(addrtxt))) {
2795 		RADIUS_ERROR("Could not add Calling-Station-Id");
2796 		radius_msg_free(msg);
2797 		return -1;
2798 	}
2799 
2800 	if (!disconnect && t_c_clear) {
2801 		u8 val[4] = { 0x00, 0x00, 0x00, 0x00 }; /* E=0 */
2802 
2803 		if (!radius_msg_add_wfa(
2804 			    msg, RADIUS_VENDOR_ATTR_WFA_HS20_T_C_FILTERING,
2805 			    val, sizeof(val))) {
2806 			RADIUS_DEBUG("Failed to add WFA-HS20-T-C-Filtering");
2807 			radius_msg_free(msg);
2808 			return -1;
2809 		}
2810 	}
2811 
2812 	os_get_time(&now);
2813 	if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_EVENT_TIMESTAMP,
2814 				       now.sec)) {
2815 		RADIUS_ERROR("Failed to add Event-Timestamp attribute");
2816 		radius_msg_free(msg);
2817 		return -1;
2818 	}
2819 
2820 	radius_msg_finish_acct(msg, (u8 *) client->shared_secret,
2821 			       client->shared_secret_len);
2822 
2823 	if (wpa_debug_level <= MSG_MSGDUMP)
2824 		radius_msg_dump(msg);
2825 
2826 	buf = radius_msg_get_buf(msg);
2827 	if (sendto(data->auth_sock, wpabuf_head(buf), wpabuf_len(buf), 0,
2828 		   (struct sockaddr *) &das, sizeof(das)) < 0) {
2829 		RADIUS_ERROR("Failed to send packet - sendto: %s",
2830 			     strerror(errno));
2831 		radius_msg_free(msg);
2832 		return -1;
2833 	}
2834 
2835 	if (disconnect) {
2836 		radius_msg_free(client->pending_dac_disconnect_req);
2837 		client->pending_dac_disconnect_req = msg;
2838 		client->pending_dac_disconnect_id = identifier;
2839 		os_memcpy(client->pending_dac_disconnect_addr, addr, ETH_ALEN);
2840 	} else {
2841 		radius_msg_free(client->pending_dac_coa_req);
2842 		client->pending_dac_coa_req = msg;
2843 		client->pending_dac_coa_id = identifier;
2844 		os_memcpy(client->pending_dac_coa_addr, addr, ETH_ALEN);
2845 	}
2846 
2847 	return 0;
2848 #else /* CONFIG_SQLITE */
2849 	return -1;
2850 #endif /* CONFIG_SQLITE */
2851 }
2852