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