• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * RADIUS authentication server
3  * Copyright (c) 2005-2009, 2011-2014, 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_MAX_SESSION - Maximum number of active sessions
30  */
31 #define RADIUS_MAX_SESSION 100
32 
33 /**
34  * RADIUS_MAX_MSG_LEN - Maximum message length for incoming RADIUS messages
35  */
36 #define RADIUS_MAX_MSG_LEN 3000
37 
38 static 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 
79 	struct radius_msg *last_msg;
80 	char *last_from_addr;
81 	int last_from_port;
82 	struct sockaddr_storage last_from;
83 	socklen_t last_fromlen;
84 	u8 last_identifier;
85 	struct radius_msg *last_reply;
86 	u8 last_authenticator[16];
87 
88 	unsigned int remediation:1;
89 	unsigned int macacl:1;
90 
91 	struct hostapd_radius_attr *accept_attr;
92 };
93 
94 /**
95  * struct radius_client - Internal RADIUS server data for a client
96  */
97 struct radius_client {
98 	struct radius_client *next;
99 	struct in_addr addr;
100 	struct in_addr mask;
101 #ifdef CONFIG_IPV6
102 	struct in6_addr addr6;
103 	struct in6_addr mask6;
104 #endif /* CONFIG_IPV6 */
105 	char *shared_secret;
106 	int shared_secret_len;
107 	struct radius_session *sessions;
108 	struct radius_server_counters counters;
109 };
110 
111 /**
112  * struct radius_server_data - Internal RADIUS server data
113  */
114 struct radius_server_data {
115 	/**
116 	 * auth_sock - Socket for RADIUS authentication messages
117 	 */
118 	int auth_sock;
119 
120 	/**
121 	 * acct_sock - Socket for RADIUS accounting messages
122 	 */
123 	int acct_sock;
124 
125 	/**
126 	 * clients - List of authorized RADIUS clients
127 	 */
128 	struct radius_client *clients;
129 
130 	/**
131 	 * next_sess_id - Next session identifier
132 	 */
133 	unsigned int next_sess_id;
134 
135 	/**
136 	 * conf_ctx - Context pointer for callbacks
137 	 *
138 	 * This is used as the ctx argument in get_eap_user() calls.
139 	 */
140 	void *conf_ctx;
141 
142 	/**
143 	 * num_sess - Number of active sessions
144 	 */
145 	int num_sess;
146 
147 	/**
148 	 * eap_sim_db_priv - EAP-SIM/AKA database context
149 	 *
150 	 * This is passed to the EAP-SIM/AKA server implementation as a
151 	 * callback context.
152 	 */
153 	void *eap_sim_db_priv;
154 
155 	/**
156 	 * ssl_ctx - TLS context
157 	 *
158 	 * This is passed to the EAP server implementation as a callback
159 	 * context for TLS operations.
160 	 */
161 	void *ssl_ctx;
162 
163 	/**
164 	 * pac_opaque_encr_key - PAC-Opaque encryption key for EAP-FAST
165 	 *
166 	 * This parameter is used to set a key for EAP-FAST to encrypt the
167 	 * PAC-Opaque data. It can be set to %NULL if EAP-FAST is not used. If
168 	 * set, must point to a 16-octet key.
169 	 */
170 	u8 *pac_opaque_encr_key;
171 
172 	/**
173 	 * eap_fast_a_id - EAP-FAST authority identity (A-ID)
174 	 *
175 	 * If EAP-FAST is not used, this can be set to %NULL. In theory, this
176 	 * is a variable length field, but due to some existing implementations
177 	 * requiring A-ID to be 16 octets in length, it is recommended to use
178 	 * that length for the field to provide interoperability with deployed
179 	 * peer implementations.
180 	 */
181 	u8 *eap_fast_a_id;
182 
183 	/**
184 	 * eap_fast_a_id_len - Length of eap_fast_a_id buffer in octets
185 	 */
186 	size_t eap_fast_a_id_len;
187 
188 	/**
189 	 * eap_fast_a_id_info - EAP-FAST authority identifier information
190 	 *
191 	 * This A-ID-Info contains a user-friendly name for the A-ID. For
192 	 * example, this could be the enterprise and server names in
193 	 * human-readable format. This field is encoded as UTF-8. If EAP-FAST
194 	 * is not used, this can be set to %NULL.
195 	 */
196 	char *eap_fast_a_id_info;
197 
198 	/**
199 	 * eap_fast_prov - EAP-FAST provisioning modes
200 	 *
201 	 * 0 = provisioning disabled, 1 = only anonymous provisioning allowed,
202 	 * 2 = only authenticated provisioning allowed, 3 = both provisioning
203 	 * modes allowed.
204 	 */
205 	int eap_fast_prov;
206 
207 	/**
208 	 * pac_key_lifetime - EAP-FAST PAC-Key lifetime in seconds
209 	 *
210 	 * This is the hard limit on how long a provisioned PAC-Key can be
211 	 * used.
212 	 */
213 	int pac_key_lifetime;
214 
215 	/**
216 	 * pac_key_refresh_time - EAP-FAST PAC-Key refresh time in seconds
217 	 *
218 	 * This is a soft limit on the PAC-Key. The server will automatically
219 	 * generate a new PAC-Key when this number of seconds (or fewer) of the
220 	 * lifetime remains.
221 	 */
222 	int pac_key_refresh_time;
223 
224 	/**
225 	 * eap_sim_aka_result_ind - EAP-SIM/AKA protected success indication
226 	 *
227 	 * This controls whether the protected success/failure indication
228 	 * (AT_RESULT_IND) is used with EAP-SIM and EAP-AKA.
229 	 */
230 	int eap_sim_aka_result_ind;
231 
232 	/**
233 	 * tnc - Trusted Network Connect (TNC)
234 	 *
235 	 * This controls whether TNC is enabled and will be required before the
236 	 * peer is allowed to connect. Note: This is only used with EAP-TTLS
237 	 * and EAP-FAST. If any other EAP method is enabled, the peer will be
238 	 * allowed to connect without TNC.
239 	 */
240 	int tnc;
241 
242 	/**
243 	 * pwd_group - The D-H group assigned for EAP-pwd
244 	 *
245 	 * If EAP-pwd is not used it can be set to zero.
246 	 */
247 	u16 pwd_group;
248 
249 	/**
250 	 * server_id - Server identity
251 	 */
252 	const char *server_id;
253 
254 	/**
255 	 * wps - Wi-Fi Protected Setup context
256 	 *
257 	 * If WPS is used with an external RADIUS server (which is quite
258 	 * unlikely configuration), this is used to provide a pointer to WPS
259 	 * context data. Normally, this can be set to %NULL.
260 	 */
261 	struct wps_context *wps;
262 
263 	/**
264 	 * ipv6 - Whether to enable IPv6 support in the RADIUS server
265 	 */
266 	int ipv6;
267 
268 	/**
269 	 * start_time - Timestamp of server start
270 	 */
271 	struct os_reltime start_time;
272 
273 	/**
274 	 * counters - Statistics counters for server operations
275 	 *
276 	 * These counters are the sum over all clients.
277 	 */
278 	struct radius_server_counters counters;
279 
280 	/**
281 	 * get_eap_user - Callback for fetching EAP user information
282 	 * @ctx: Context data from conf_ctx
283 	 * @identity: User identity
284 	 * @identity_len: identity buffer length in octets
285 	 * @phase2: Whether this is for Phase 2 identity
286 	 * @user: Data structure for filling in the user information
287 	 * Returns: 0 on success, -1 on failure
288 	 *
289 	 * This is used to fetch information from user database. The callback
290 	 * will fill in information about allowed EAP methods and the user
291 	 * password. The password field will be an allocated copy of the
292 	 * password data and RADIUS server will free it after use.
293 	 */
294 	int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len,
295 			    int phase2, struct eap_user *user);
296 
297 	/**
298 	 * eap_req_id_text - Optional data for EAP-Request/Identity
299 	 *
300 	 * This can be used to configure an optional, displayable message that
301 	 * will be sent in EAP-Request/Identity. This string can contain an
302 	 * ASCII-0 character (nul) to separate network infromation per RFC
303 	 * 4284. The actual string length is explicit provided in
304 	 * eap_req_id_text_len since nul character will not be used as a string
305 	 * terminator.
306 	 */
307 	char *eap_req_id_text;
308 
309 	/**
310 	 * eap_req_id_text_len - Length of eap_req_id_text buffer in octets
311 	 */
312 	size_t eap_req_id_text_len;
313 
314 	/*
315 	 * msg_ctx - Context data for wpa_msg() calls
316 	 */
317 	void *msg_ctx;
318 
319 #ifdef CONFIG_RADIUS_TEST
320 	char *dump_msk_file;
321 #endif /* CONFIG_RADIUS_TEST */
322 
323 	char *subscr_remediation_url;
324 	u8 subscr_remediation_method;
325 
326 #ifdef CONFIG_SQLITE
327 	sqlite3 *db;
328 #endif /* CONFIG_SQLITE */
329 };
330 
331 
332 #define RADIUS_DEBUG(args...) \
333 wpa_printf(MSG_DEBUG, "RADIUS SRV: " args)
334 #define RADIUS_ERROR(args...) \
335 wpa_printf(MSG_ERROR, "RADIUS SRV: " args)
336 #define RADIUS_DUMP(args...) \
337 wpa_hexdump(MSG_MSGDUMP, "RADIUS SRV: " args)
338 #define RADIUS_DUMP_ASCII(args...) \
339 wpa_hexdump_ascii(MSG_MSGDUMP, "RADIUS SRV: " args)
340 
341 
342 static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx);
343 static void radius_server_session_remove_timeout(void *eloop_ctx,
344 						 void *timeout_ctx);
345 
346 void srv_log(struct radius_session *sess, const char *fmt, ...)
347 PRINTF_FORMAT(2, 3);
348 
srv_log(struct radius_session * sess,const char * fmt,...)349 void srv_log(struct radius_session *sess, const char *fmt, ...)
350 {
351 	va_list ap;
352 	char *buf;
353 	int buflen;
354 
355 	va_start(ap, fmt);
356 	buflen = vsnprintf(NULL, 0, fmt, ap) + 1;
357 	va_end(ap);
358 
359 	buf = os_malloc(buflen);
360 	if (buf == NULL)
361 		return;
362 	va_start(ap, fmt);
363 	vsnprintf(buf, buflen, fmt, ap);
364 	va_end(ap);
365 
366 	RADIUS_DEBUG("[0x%x %s] %s", sess->sess_id, sess->nas_ip, buf);
367 
368 #ifdef CONFIG_SQLITE
369 	if (sess->server->db) {
370 		char *sql;
371 		sql = sqlite3_mprintf("INSERT INTO authlog"
372 				      "(timestamp,session,nas_ip,username,note)"
373 				      " VALUES ("
374 				      "strftime('%%Y-%%m-%%d %%H:%%M:%%f',"
375 				      "'now'),%u,%Q,%Q,%Q)",
376 				      sess->sess_id, sess->nas_ip,
377 				      sess->username, buf);
378 		if (sql) {
379 			if (sqlite3_exec(sess->server->db, sql, NULL, NULL,
380 					 NULL) != SQLITE_OK) {
381 				RADIUS_ERROR("Failed to add authlog entry into sqlite database: %s",
382 					     sqlite3_errmsg(sess->server->db));
383 			}
384 			sqlite3_free(sql);
385 		}
386 	}
387 #endif /* CONFIG_SQLITE */
388 
389 	os_free(buf);
390 }
391 
392 
393 static struct radius_client *
radius_server_get_client(struct radius_server_data * data,struct in_addr * addr,int ipv6)394 radius_server_get_client(struct radius_server_data *data, struct in_addr *addr,
395 			 int ipv6)
396 {
397 	struct radius_client *client = data->clients;
398 
399 	while (client) {
400 #ifdef CONFIG_IPV6
401 		if (ipv6) {
402 			struct in6_addr *addr6;
403 			int i;
404 
405 			addr6 = (struct in6_addr *) addr;
406 			for (i = 0; i < 16; i++) {
407 				if ((addr6->s6_addr[i] &
408 				     client->mask6.s6_addr[i]) !=
409 				    (client->addr6.s6_addr[i] &
410 				     client->mask6.s6_addr[i])) {
411 					i = 17;
412 					break;
413 				}
414 			}
415 			if (i == 16) {
416 				break;
417 			}
418 		}
419 #endif /* CONFIG_IPV6 */
420 		if (!ipv6 && (client->addr.s_addr & client->mask.s_addr) ==
421 		    (addr->s_addr & client->mask.s_addr)) {
422 			break;
423 		}
424 
425 		client = client->next;
426 	}
427 
428 	return client;
429 }
430 
431 
432 static struct radius_session *
radius_server_get_session(struct radius_client * client,unsigned int sess_id)433 radius_server_get_session(struct radius_client *client, unsigned int sess_id)
434 {
435 	struct radius_session *sess = client->sessions;
436 
437 	while (sess) {
438 		if (sess->sess_id == sess_id) {
439 			break;
440 		}
441 		sess = sess->next;
442 	}
443 
444 	return sess;
445 }
446 
447 
radius_server_session_free(struct radius_server_data * data,struct radius_session * sess)448 static void radius_server_session_free(struct radius_server_data *data,
449 				       struct radius_session *sess)
450 {
451 	eloop_cancel_timeout(radius_server_session_timeout, data, sess);
452 	eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess);
453 	eap_server_sm_deinit(sess->eap);
454 	radius_msg_free(sess->last_msg);
455 	os_free(sess->last_from_addr);
456 	radius_msg_free(sess->last_reply);
457 	os_free(sess->username);
458 	os_free(sess->nas_ip);
459 	os_free(sess);
460 	data->num_sess--;
461 }
462 
463 
radius_server_session_remove(struct radius_server_data * data,struct radius_session * sess)464 static void radius_server_session_remove(struct radius_server_data *data,
465 					 struct radius_session *sess)
466 {
467 	struct radius_client *client = sess->client;
468 	struct radius_session *session, *prev;
469 
470 	eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess);
471 
472 	prev = NULL;
473 	session = client->sessions;
474 	while (session) {
475 		if (session == sess) {
476 			if (prev == NULL) {
477 				client->sessions = sess->next;
478 			} else {
479 				prev->next = sess->next;
480 			}
481 			radius_server_session_free(data, sess);
482 			break;
483 		}
484 		prev = session;
485 		session = session->next;
486 	}
487 }
488 
489 
radius_server_session_remove_timeout(void * eloop_ctx,void * timeout_ctx)490 static void radius_server_session_remove_timeout(void *eloop_ctx,
491 						 void *timeout_ctx)
492 {
493 	struct radius_server_data *data = eloop_ctx;
494 	struct radius_session *sess = timeout_ctx;
495 	RADIUS_DEBUG("Removing completed session 0x%x", sess->sess_id);
496 	radius_server_session_remove(data, sess);
497 }
498 
499 
radius_server_session_timeout(void * eloop_ctx,void * timeout_ctx)500 static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx)
501 {
502 	struct radius_server_data *data = eloop_ctx;
503 	struct radius_session *sess = timeout_ctx;
504 
505 	RADIUS_DEBUG("Timing out authentication session 0x%x", sess->sess_id);
506 	radius_server_session_remove(data, sess);
507 }
508 
509 
510 static struct radius_session *
radius_server_new_session(struct radius_server_data * data,struct radius_client * client)511 radius_server_new_session(struct radius_server_data *data,
512 			  struct radius_client *client)
513 {
514 	struct radius_session *sess;
515 
516 	if (data->num_sess >= RADIUS_MAX_SESSION) {
517 		RADIUS_DEBUG("Maximum number of existing session - no room "
518 			     "for a new session");
519 		return NULL;
520 	}
521 
522 	sess = os_zalloc(sizeof(*sess));
523 	if (sess == NULL)
524 		return NULL;
525 
526 	sess->server = data;
527 	sess->client = client;
528 	sess->sess_id = data->next_sess_id++;
529 	sess->next = client->sessions;
530 	client->sessions = sess;
531 	eloop_register_timeout(RADIUS_SESSION_TIMEOUT, 0,
532 			       radius_server_session_timeout, data, sess);
533 	data->num_sess++;
534 	return sess;
535 }
536 
537 
538 #ifdef CONFIG_TESTING_OPTIONS
radius_server_testing_options_tls(struct radius_session * sess,const char * tls,struct eap_config * eap_conf)539 static void radius_server_testing_options_tls(struct radius_session *sess,
540 					      const char *tls,
541 					      struct eap_config *eap_conf)
542 {
543 	int test = atoi(tls);
544 
545 	switch (test) {
546 	case 1:
547 		srv_log(sess, "TLS test - break VerifyData");
548 		eap_conf->tls_test_flags = TLS_BREAK_VERIFY_DATA;
549 		break;
550 	case 2:
551 		srv_log(sess, "TLS test - break ServerKeyExchange ServerParams hash");
552 		eap_conf->tls_test_flags = TLS_BREAK_SRV_KEY_X_HASH;
553 		break;
554 	case 3:
555 		srv_log(sess, "TLS test - break ServerKeyExchange ServerParams Signature");
556 		eap_conf->tls_test_flags = TLS_BREAK_SRV_KEY_X_SIGNATURE;
557 		break;
558 	case 4:
559 		srv_log(sess, "TLS test - RSA-DHE using a short 511-bit prime");
560 		eap_conf->tls_test_flags = TLS_DHE_PRIME_511B;
561 		break;
562 	case 5:
563 		srv_log(sess, "TLS test - RSA-DHE using a short 767-bit prime");
564 		eap_conf->tls_test_flags = TLS_DHE_PRIME_767B;
565 		break;
566 	case 6:
567 		srv_log(sess, "TLS test - RSA-DHE using a bogus 15 \"prime\"");
568 		eap_conf->tls_test_flags = TLS_DHE_PRIME_15;
569 		break;
570 	case 7:
571 		srv_log(sess, "TLS test - RSA-DHE using a short 58-bit prime in long container");
572 		eap_conf->tls_test_flags = TLS_DHE_PRIME_58B;
573 		break;
574 	case 8:
575 		srv_log(sess, "TLS test - RSA-DHE using a non-prime");
576 		eap_conf->tls_test_flags = TLS_DHE_NON_PRIME;
577 		break;
578 	default:
579 		srv_log(sess, "Unrecognized TLS test");
580 		break;
581 	}
582 }
583 #endif /* CONFIG_TESTING_OPTIONS */
584 
radius_server_testing_options(struct radius_session * sess,struct eap_config * eap_conf)585 static void radius_server_testing_options(struct radius_session *sess,
586 					  struct eap_config *eap_conf)
587 {
588 #ifdef CONFIG_TESTING_OPTIONS
589 	const char *pos;
590 
591 	pos = os_strstr(sess->username, "@test-");
592 	if (pos == NULL)
593 		return;
594 	pos += 6;
595 	if (os_strncmp(pos, "tls-", 4) == 0)
596 		radius_server_testing_options_tls(sess, pos + 4, eap_conf);
597 	else
598 		srv_log(sess, "Unrecognized test: %s", pos);
599 #endif /* CONFIG_TESTING_OPTIONS */
600 }
601 
602 
603 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)604 radius_server_get_new_session(struct radius_server_data *data,
605 			      struct radius_client *client,
606 			      struct radius_msg *msg, const char *from_addr)
607 {
608 	u8 *user;
609 	size_t user_len;
610 	int res;
611 	struct radius_session *sess;
612 	struct eap_config eap_conf;
613 	struct eap_user tmp;
614 
615 	RADIUS_DEBUG("Creating a new session");
616 
617 	if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME, &user,
618 				    &user_len, NULL) < 0) {
619 		RADIUS_DEBUG("Could not get User-Name");
620 		return NULL;
621 	}
622 	RADIUS_DUMP_ASCII("User-Name", user, user_len);
623 
624 	os_memset(&tmp, 0, sizeof(tmp));
625 	res = data->get_eap_user(data->conf_ctx, user, user_len, 0, &tmp);
626 	bin_clear_free(tmp.password, tmp.password_len);
627 
628 	if (res != 0) {
629 		RADIUS_DEBUG("User-Name not found from user database");
630 		return NULL;
631 	}
632 
633 	RADIUS_DEBUG("Matching user entry found");
634 	sess = radius_server_new_session(data, client);
635 	if (sess == NULL) {
636 		RADIUS_DEBUG("Failed to create a new session");
637 		return NULL;
638 	}
639 	sess->accept_attr = tmp.accept_attr;
640 	sess->macacl = tmp.macacl;
641 
642 	sess->username = os_malloc(user_len * 4 + 1);
643 	if (sess->username == NULL) {
644 		radius_server_session_free(data, sess);
645 		return NULL;
646 	}
647 	printf_encode(sess->username, user_len * 4 + 1, user, user_len);
648 
649 	sess->nas_ip = os_strdup(from_addr);
650 	if (sess->nas_ip == NULL) {
651 		radius_server_session_free(data, sess);
652 		return NULL;
653 	}
654 
655 	srv_log(sess, "New session created");
656 
657 	os_memset(&eap_conf, 0, sizeof(eap_conf));
658 	eap_conf.ssl_ctx = data->ssl_ctx;
659 	eap_conf.msg_ctx = data->msg_ctx;
660 	eap_conf.eap_sim_db_priv = data->eap_sim_db_priv;
661 	eap_conf.backend_auth = TRUE;
662 	eap_conf.eap_server = 1;
663 	eap_conf.pac_opaque_encr_key = data->pac_opaque_encr_key;
664 	eap_conf.eap_fast_a_id = data->eap_fast_a_id;
665 	eap_conf.eap_fast_a_id_len = data->eap_fast_a_id_len;
666 	eap_conf.eap_fast_a_id_info = data->eap_fast_a_id_info;
667 	eap_conf.eap_fast_prov = data->eap_fast_prov;
668 	eap_conf.pac_key_lifetime = data->pac_key_lifetime;
669 	eap_conf.pac_key_refresh_time = data->pac_key_refresh_time;
670 	eap_conf.eap_sim_aka_result_ind = data->eap_sim_aka_result_ind;
671 	eap_conf.tnc = data->tnc;
672 	eap_conf.wps = data->wps;
673 	eap_conf.pwd_group = data->pwd_group;
674 	eap_conf.server_id = (const u8 *) data->server_id;
675 	eap_conf.server_id_len = os_strlen(data->server_id);
676 	radius_server_testing_options(sess, &eap_conf);
677 	sess->eap = eap_server_sm_init(sess, &radius_server_eapol_cb,
678 				       &eap_conf);
679 	if (sess->eap == NULL) {
680 		RADIUS_DEBUG("Failed to initialize EAP state machine for the "
681 			     "new session");
682 		radius_server_session_free(data, sess);
683 		return NULL;
684 	}
685 	sess->eap_if = eap_get_interface(sess->eap);
686 	sess->eap_if->eapRestart = TRUE;
687 	sess->eap_if->portEnabled = TRUE;
688 
689 	RADIUS_DEBUG("New session 0x%x initialized", sess->sess_id);
690 
691 	return sess;
692 }
693 
694 
695 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)696 radius_server_encapsulate_eap(struct radius_server_data *data,
697 			      struct radius_client *client,
698 			      struct radius_session *sess,
699 			      struct radius_msg *request)
700 {
701 	struct radius_msg *msg;
702 	int code;
703 	unsigned int sess_id;
704 	struct radius_hdr *hdr = radius_msg_get_hdr(request);
705 
706 	if (sess->eap_if->eapFail) {
707 		sess->eap_if->eapFail = FALSE;
708 		code = RADIUS_CODE_ACCESS_REJECT;
709 	} else if (sess->eap_if->eapSuccess) {
710 		sess->eap_if->eapSuccess = FALSE;
711 		code = RADIUS_CODE_ACCESS_ACCEPT;
712 	} else {
713 		sess->eap_if->eapReq = FALSE;
714 		code = RADIUS_CODE_ACCESS_CHALLENGE;
715 	}
716 
717 	msg = radius_msg_new(code, hdr->identifier);
718 	if (msg == NULL) {
719 		RADIUS_DEBUG("Failed to allocate reply message");
720 		return NULL;
721 	}
722 
723 	sess_id = htonl(sess->sess_id);
724 	if (code == RADIUS_CODE_ACCESS_CHALLENGE &&
725 	    !radius_msg_add_attr(msg, RADIUS_ATTR_STATE,
726 				 (u8 *) &sess_id, sizeof(sess_id))) {
727 		RADIUS_DEBUG("Failed to add State attribute");
728 	}
729 
730 	if (sess->eap_if->eapReqData &&
731 	    !radius_msg_add_eap(msg, wpabuf_head(sess->eap_if->eapReqData),
732 				wpabuf_len(sess->eap_if->eapReqData))) {
733 		RADIUS_DEBUG("Failed to add EAP-Message attribute");
734 	}
735 
736 	if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->eap_if->eapKeyData) {
737 		int len;
738 #ifdef CONFIG_RADIUS_TEST
739 		if (data->dump_msk_file) {
740 			FILE *f;
741 			char buf[2 * 64 + 1];
742 			f = fopen(data->dump_msk_file, "a");
743 			if (f) {
744 				len = sess->eap_if->eapKeyDataLen;
745 				if (len > 64)
746 					len = 64;
747 				len = wpa_snprintf_hex(
748 					buf, sizeof(buf),
749 					sess->eap_if->eapKeyData, len);
750 				buf[len] = '\0';
751 				fprintf(f, "%s\n", buf);
752 				fclose(f);
753 			}
754 		}
755 #endif /* CONFIG_RADIUS_TEST */
756 		if (sess->eap_if->eapKeyDataLen > 64) {
757 			len = 32;
758 		} else {
759 			len = sess->eap_if->eapKeyDataLen / 2;
760 		}
761 		if (!radius_msg_add_mppe_keys(msg, hdr->authenticator,
762 					      (u8 *) client->shared_secret,
763 					      client->shared_secret_len,
764 					      sess->eap_if->eapKeyData + len,
765 					      len, sess->eap_if->eapKeyData,
766 					      len)) {
767 			RADIUS_DEBUG("Failed to add MPPE key attributes");
768 		}
769 	}
770 
771 #ifdef CONFIG_HS20
772 	if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->remediation &&
773 	    data->subscr_remediation_url) {
774 		u8 *buf;
775 		size_t url_len = os_strlen(data->subscr_remediation_url);
776 		buf = os_malloc(1 + url_len);
777 		if (buf == NULL) {
778 			radius_msg_free(msg);
779 			return NULL;
780 		}
781 		buf[0] = data->subscr_remediation_method;
782 		os_memcpy(&buf[1], data->subscr_remediation_url, url_len);
783 		if (!radius_msg_add_wfa(
784 			    msg, RADIUS_VENDOR_ATTR_WFA_HS20_SUBSCR_REMEDIATION,
785 			    buf, 1 + url_len)) {
786 			RADIUS_DEBUG("Failed to add WFA-HS20-SubscrRem");
787 		}
788 		os_free(buf);
789 	} else if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->remediation) {
790 		u8 buf[1];
791 		if (!radius_msg_add_wfa(
792 			    msg, RADIUS_VENDOR_ATTR_WFA_HS20_SUBSCR_REMEDIATION,
793 			    buf, 0)) {
794 			RADIUS_DEBUG("Failed to add WFA-HS20-SubscrRem");
795 		}
796 	}
797 #endif /* CONFIG_HS20 */
798 
799 	if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) {
800 		RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
801 		radius_msg_free(msg);
802 		return NULL;
803 	}
804 
805 	if (code == RADIUS_CODE_ACCESS_ACCEPT) {
806 		struct hostapd_radius_attr *attr;
807 		for (attr = sess->accept_attr; attr; attr = attr->next) {
808 			if (!radius_msg_add_attr(msg, attr->type,
809 						 wpabuf_head(attr->val),
810 						 wpabuf_len(attr->val))) {
811 				wpa_printf(MSG_ERROR, "Could not add RADIUS attribute");
812 				radius_msg_free(msg);
813 				return NULL;
814 			}
815 		}
816 	}
817 
818 	if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
819 				  client->shared_secret_len,
820 				  hdr->authenticator) < 0) {
821 		RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
822 	}
823 
824 	return msg;
825 }
826 
827 
828 static struct radius_msg *
radius_server_macacl(struct radius_server_data * data,struct radius_client * client,struct radius_session * sess,struct radius_msg * request)829 radius_server_macacl(struct radius_server_data *data,
830 		     struct radius_client *client,
831 		     struct radius_session *sess,
832 		     struct radius_msg *request)
833 {
834 	struct radius_msg *msg;
835 	int code;
836 	struct radius_hdr *hdr = radius_msg_get_hdr(request);
837 	u8 *pw;
838 	size_t pw_len;
839 
840 	code = RADIUS_CODE_ACCESS_ACCEPT;
841 
842 	if (radius_msg_get_attr_ptr(request, RADIUS_ATTR_USER_PASSWORD, &pw,
843 				    &pw_len, NULL) < 0) {
844 		RADIUS_DEBUG("Could not get User-Password");
845 		code = RADIUS_CODE_ACCESS_REJECT;
846 	} else {
847 		int res;
848 		struct eap_user tmp;
849 
850 		os_memset(&tmp, 0, sizeof(tmp));
851 		res = data->get_eap_user(data->conf_ctx, (u8 *) sess->username,
852 					 os_strlen(sess->username), 0, &tmp);
853 		if (res || !tmp.macacl || tmp.password == NULL) {
854 			RADIUS_DEBUG("No MAC ACL user entry");
855 			bin_clear_free(tmp.password, tmp.password_len);
856 			code = RADIUS_CODE_ACCESS_REJECT;
857 		} else {
858 			u8 buf[128];
859 			res = radius_user_password_hide(
860 				request, tmp.password, tmp.password_len,
861 				(u8 *) client->shared_secret,
862 				client->shared_secret_len,
863 				buf, sizeof(buf));
864 			bin_clear_free(tmp.password, tmp.password_len);
865 
866 			if (res < 0 || pw_len != (size_t) res ||
867 			    os_memcmp_const(pw, buf, res) != 0) {
868 				RADIUS_DEBUG("Incorrect User-Password");
869 				code = RADIUS_CODE_ACCESS_REJECT;
870 			}
871 		}
872 	}
873 
874 	msg = radius_msg_new(code, hdr->identifier);
875 	if (msg == NULL) {
876 		RADIUS_DEBUG("Failed to allocate reply message");
877 		return NULL;
878 	}
879 
880 	if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) {
881 		RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
882 		radius_msg_free(msg);
883 		return NULL;
884 	}
885 
886 	if (code == RADIUS_CODE_ACCESS_ACCEPT) {
887 		struct hostapd_radius_attr *attr;
888 		for (attr = sess->accept_attr; attr; attr = attr->next) {
889 			if (!radius_msg_add_attr(msg, attr->type,
890 						 wpabuf_head(attr->val),
891 						 wpabuf_len(attr->val))) {
892 				wpa_printf(MSG_ERROR, "Could not add RADIUS attribute");
893 				radius_msg_free(msg);
894 				return NULL;
895 			}
896 		}
897 	}
898 
899 	if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
900 				  client->shared_secret_len,
901 				  hdr->authenticator) < 0) {
902 		RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
903 	}
904 
905 	return msg;
906 }
907 
908 
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)909 static int radius_server_reject(struct radius_server_data *data,
910 				struct radius_client *client,
911 				struct radius_msg *request,
912 				struct sockaddr *from, socklen_t fromlen,
913 				const char *from_addr, int from_port)
914 {
915 	struct radius_msg *msg;
916 	int ret = 0;
917 	struct eap_hdr eapfail;
918 	struct wpabuf *buf;
919 	struct radius_hdr *hdr = radius_msg_get_hdr(request);
920 
921 	RADIUS_DEBUG("Reject invalid request from %s:%d",
922 		     from_addr, from_port);
923 
924 	msg = radius_msg_new(RADIUS_CODE_ACCESS_REJECT, hdr->identifier);
925 	if (msg == NULL) {
926 		return -1;
927 	}
928 
929 	os_memset(&eapfail, 0, sizeof(eapfail));
930 	eapfail.code = EAP_CODE_FAILURE;
931 	eapfail.identifier = 0;
932 	eapfail.length = host_to_be16(sizeof(eapfail));
933 
934 	if (!radius_msg_add_eap(msg, (u8 *) &eapfail, sizeof(eapfail))) {
935 		RADIUS_DEBUG("Failed to add EAP-Message attribute");
936 	}
937 
938 	if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) {
939 		RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
940 		radius_msg_free(msg);
941 		return -1;
942 	}
943 
944 	if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
945 				  client->shared_secret_len,
946 				  hdr->authenticator) <
947 	    0) {
948 		RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
949 	}
950 
951 	if (wpa_debug_level <= MSG_MSGDUMP) {
952 		radius_msg_dump(msg);
953 	}
954 
955 	data->counters.access_rejects++;
956 	client->counters.access_rejects++;
957 	buf = radius_msg_get_buf(msg);
958 	if (sendto(data->auth_sock, wpabuf_head(buf), wpabuf_len(buf), 0,
959 		   (struct sockaddr *) from, sizeof(*from)) < 0) {
960 		wpa_printf(MSG_INFO, "sendto[RADIUS SRV]: %s", strerror(errno));
961 		ret = -1;
962 	}
963 
964 	radius_msg_free(msg);
965 
966 	return ret;
967 }
968 
969 
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)970 static int radius_server_request(struct radius_server_data *data,
971 				 struct radius_msg *msg,
972 				 struct sockaddr *from, socklen_t fromlen,
973 				 struct radius_client *client,
974 				 const char *from_addr, int from_port,
975 				 struct radius_session *force_sess)
976 {
977 	struct wpabuf *eap = NULL;
978 	int res, state_included = 0;
979 	u8 statebuf[4];
980 	unsigned int state;
981 	struct radius_session *sess;
982 	struct radius_msg *reply;
983 	int is_complete = 0;
984 
985 	if (force_sess)
986 		sess = force_sess;
987 	else {
988 		res = radius_msg_get_attr(msg, RADIUS_ATTR_STATE, statebuf,
989 					  sizeof(statebuf));
990 		state_included = res >= 0;
991 		if (res == sizeof(statebuf)) {
992 			state = WPA_GET_BE32(statebuf);
993 			sess = radius_server_get_session(client, state);
994 		} else {
995 			sess = NULL;
996 		}
997 	}
998 
999 	if (sess) {
1000 		RADIUS_DEBUG("Request for session 0x%x", sess->sess_id);
1001 	} else if (state_included) {
1002 		RADIUS_DEBUG("State attribute included but no session found");
1003 		radius_server_reject(data, client, msg, from, fromlen,
1004 				     from_addr, from_port);
1005 		return -1;
1006 	} else {
1007 		sess = radius_server_get_new_session(data, client, msg,
1008 						     from_addr);
1009 		if (sess == NULL) {
1010 			RADIUS_DEBUG("Could not create a new session");
1011 			radius_server_reject(data, client, msg, from, fromlen,
1012 					     from_addr, from_port);
1013 			return -1;
1014 		}
1015 	}
1016 
1017 	if (sess->last_from_port == from_port &&
1018 	    sess->last_identifier == radius_msg_get_hdr(msg)->identifier &&
1019 	    os_memcmp(sess->last_authenticator,
1020 		      radius_msg_get_hdr(msg)->authenticator, 16) == 0) {
1021 		RADIUS_DEBUG("Duplicate message from %s", from_addr);
1022 		data->counters.dup_access_requests++;
1023 		client->counters.dup_access_requests++;
1024 
1025 		if (sess->last_reply) {
1026 			struct wpabuf *buf;
1027 			buf = radius_msg_get_buf(sess->last_reply);
1028 			res = sendto(data->auth_sock, wpabuf_head(buf),
1029 				     wpabuf_len(buf), 0,
1030 				     (struct sockaddr *) from, fromlen);
1031 			if (res < 0) {
1032 				wpa_printf(MSG_INFO, "sendto[RADIUS SRV]: %s",
1033 					   strerror(errno));
1034 			}
1035 			return 0;
1036 		}
1037 
1038 		RADIUS_DEBUG("No previous reply available for duplicate "
1039 			     "message");
1040 		return -1;
1041 	}
1042 
1043 	eap = radius_msg_get_eap(msg);
1044 	if (eap == NULL && sess->macacl) {
1045 		reply = radius_server_macacl(data, client, sess, msg);
1046 		if (reply == NULL)
1047 			return -1;
1048 		goto send_reply;
1049 	}
1050 	if (eap == NULL) {
1051 		RADIUS_DEBUG("No EAP-Message in RADIUS packet from %s",
1052 			     from_addr);
1053 		data->counters.packets_dropped++;
1054 		client->counters.packets_dropped++;
1055 		return -1;
1056 	}
1057 
1058 	RADIUS_DUMP("Received EAP data", wpabuf_head(eap), wpabuf_len(eap));
1059 
1060 	/* FIX: if Code is Request, Success, or Failure, send Access-Reject;
1061 	 * RFC3579 Sect. 2.6.2.
1062 	 * Include EAP-Response/Nak with no preferred method if
1063 	 * code == request.
1064 	 * If code is not 1-4, discard the packet silently.
1065 	 * Or is this already done by the EAP state machine? */
1066 
1067 	wpabuf_free(sess->eap_if->eapRespData);
1068 	sess->eap_if->eapRespData = eap;
1069 	sess->eap_if->eapResp = TRUE;
1070 	eap_server_sm_step(sess->eap);
1071 
1072 	if ((sess->eap_if->eapReq || sess->eap_if->eapSuccess ||
1073 	     sess->eap_if->eapFail) && sess->eap_if->eapReqData) {
1074 		RADIUS_DUMP("EAP data from the state machine",
1075 			    wpabuf_head(sess->eap_if->eapReqData),
1076 			    wpabuf_len(sess->eap_if->eapReqData));
1077 	} else if (sess->eap_if->eapFail) {
1078 		RADIUS_DEBUG("No EAP data from the state machine, but eapFail "
1079 			     "set");
1080 	} else if (eap_sm_method_pending(sess->eap)) {
1081 		radius_msg_free(sess->last_msg);
1082 		sess->last_msg = msg;
1083 		sess->last_from_port = from_port;
1084 		os_free(sess->last_from_addr);
1085 		sess->last_from_addr = os_strdup(from_addr);
1086 		sess->last_fromlen = fromlen;
1087 		os_memcpy(&sess->last_from, from, fromlen);
1088 		return -2;
1089 	} else {
1090 		RADIUS_DEBUG("No EAP data from the state machine - ignore this"
1091 			     " Access-Request silently (assuming it was a "
1092 			     "duplicate)");
1093 		data->counters.packets_dropped++;
1094 		client->counters.packets_dropped++;
1095 		return -1;
1096 	}
1097 
1098 	if (sess->eap_if->eapSuccess || sess->eap_if->eapFail)
1099 		is_complete = 1;
1100 	if (sess->eap_if->eapFail)
1101 		srv_log(sess, "EAP authentication failed");
1102 	else if (sess->eap_if->eapSuccess)
1103 		srv_log(sess, "EAP authentication succeeded");
1104 
1105 	reply = radius_server_encapsulate_eap(data, client, sess, msg);
1106 
1107 send_reply:
1108 	if (reply) {
1109 		struct wpabuf *buf;
1110 		struct radius_hdr *hdr;
1111 
1112 		RADIUS_DEBUG("Reply to %s:%d", from_addr, from_port);
1113 		if (wpa_debug_level <= MSG_MSGDUMP) {
1114 			radius_msg_dump(reply);
1115 		}
1116 
1117 		switch (radius_msg_get_hdr(reply)->code) {
1118 		case RADIUS_CODE_ACCESS_ACCEPT:
1119 			srv_log(sess, "Sending Access-Accept");
1120 			data->counters.access_accepts++;
1121 			client->counters.access_accepts++;
1122 			break;
1123 		case RADIUS_CODE_ACCESS_REJECT:
1124 			srv_log(sess, "Sending Access-Reject");
1125 			data->counters.access_rejects++;
1126 			client->counters.access_rejects++;
1127 			break;
1128 		case RADIUS_CODE_ACCESS_CHALLENGE:
1129 			data->counters.access_challenges++;
1130 			client->counters.access_challenges++;
1131 			break;
1132 		}
1133 		buf = radius_msg_get_buf(reply);
1134 		res = sendto(data->auth_sock, wpabuf_head(buf),
1135 			     wpabuf_len(buf), 0,
1136 			     (struct sockaddr *) from, fromlen);
1137 		if (res < 0) {
1138 			wpa_printf(MSG_INFO, "sendto[RADIUS SRV]: %s",
1139 				   strerror(errno));
1140 		}
1141 		radius_msg_free(sess->last_reply);
1142 		sess->last_reply = reply;
1143 		sess->last_from_port = from_port;
1144 		hdr = radius_msg_get_hdr(msg);
1145 		sess->last_identifier = hdr->identifier;
1146 		os_memcpy(sess->last_authenticator, hdr->authenticator, 16);
1147 	} else {
1148 		data->counters.packets_dropped++;
1149 		client->counters.packets_dropped++;
1150 	}
1151 
1152 	if (is_complete) {
1153 		RADIUS_DEBUG("Removing completed session 0x%x after timeout",
1154 			     sess->sess_id);
1155 		eloop_cancel_timeout(radius_server_session_remove_timeout,
1156 				     data, sess);
1157 		eloop_register_timeout(10, 0,
1158 				       radius_server_session_remove_timeout,
1159 				       data, sess);
1160 	}
1161 
1162 	return 0;
1163 }
1164 
1165 
radius_server_receive_auth(int sock,void * eloop_ctx,void * sock_ctx)1166 static void radius_server_receive_auth(int sock, void *eloop_ctx,
1167 				       void *sock_ctx)
1168 {
1169 	struct radius_server_data *data = eloop_ctx;
1170 	u8 *buf = NULL;
1171 	union {
1172 		struct sockaddr_storage ss;
1173 		struct sockaddr_in sin;
1174 #ifdef CONFIG_IPV6
1175 		struct sockaddr_in6 sin6;
1176 #endif /* CONFIG_IPV6 */
1177 	} from;
1178 	socklen_t fromlen;
1179 	int len;
1180 	struct radius_client *client = NULL;
1181 	struct radius_msg *msg = NULL;
1182 	char abuf[50];
1183 	int from_port = 0;
1184 
1185 	buf = os_malloc(RADIUS_MAX_MSG_LEN);
1186 	if (buf == NULL) {
1187 		goto fail;
1188 	}
1189 
1190 	fromlen = sizeof(from);
1191 	len = recvfrom(sock, buf, RADIUS_MAX_MSG_LEN, 0,
1192 		       (struct sockaddr *) &from.ss, &fromlen);
1193 	if (len < 0) {
1194 		wpa_printf(MSG_INFO, "recvfrom[radius_server]: %s",
1195 			   strerror(errno));
1196 		goto fail;
1197 	}
1198 
1199 #ifdef CONFIG_IPV6
1200 	if (data->ipv6) {
1201 		if (inet_ntop(AF_INET6, &from.sin6.sin6_addr, abuf,
1202 			      sizeof(abuf)) == NULL)
1203 			abuf[0] = '\0';
1204 		from_port = ntohs(from.sin6.sin6_port);
1205 		RADIUS_DEBUG("Received %d bytes from %s:%d",
1206 			     len, abuf, from_port);
1207 
1208 		client = radius_server_get_client(data,
1209 						  (struct in_addr *)
1210 						  &from.sin6.sin6_addr, 1);
1211 	}
1212 #endif /* CONFIG_IPV6 */
1213 
1214 	if (!data->ipv6) {
1215 		os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf));
1216 		from_port = ntohs(from.sin.sin_port);
1217 		RADIUS_DEBUG("Received %d bytes from %s:%d",
1218 			     len, abuf, from_port);
1219 
1220 		client = radius_server_get_client(data, &from.sin.sin_addr, 0);
1221 	}
1222 
1223 	RADIUS_DUMP("Received data", buf, len);
1224 
1225 	if (client == NULL) {
1226 		RADIUS_DEBUG("Unknown client %s - packet ignored", abuf);
1227 		data->counters.invalid_requests++;
1228 		goto fail;
1229 	}
1230 
1231 	msg = radius_msg_parse(buf, len);
1232 	if (msg == NULL) {
1233 		RADIUS_DEBUG("Parsing incoming RADIUS frame failed");
1234 		data->counters.malformed_access_requests++;
1235 		client->counters.malformed_access_requests++;
1236 		goto fail;
1237 	}
1238 
1239 	os_free(buf);
1240 	buf = NULL;
1241 
1242 	if (wpa_debug_level <= MSG_MSGDUMP) {
1243 		radius_msg_dump(msg);
1244 	}
1245 
1246 	if (radius_msg_get_hdr(msg)->code != RADIUS_CODE_ACCESS_REQUEST) {
1247 		RADIUS_DEBUG("Unexpected RADIUS code %d",
1248 			     radius_msg_get_hdr(msg)->code);
1249 		data->counters.unknown_types++;
1250 		client->counters.unknown_types++;
1251 		goto fail;
1252 	}
1253 
1254 	data->counters.access_requests++;
1255 	client->counters.access_requests++;
1256 
1257 	if (radius_msg_verify_msg_auth(msg, (u8 *) client->shared_secret,
1258 				       client->shared_secret_len, NULL)) {
1259 		RADIUS_DEBUG("Invalid Message-Authenticator from %s", abuf);
1260 		data->counters.bad_authenticators++;
1261 		client->counters.bad_authenticators++;
1262 		goto fail;
1263 	}
1264 
1265 	if (radius_server_request(data, msg, (struct sockaddr *) &from,
1266 				  fromlen, client, abuf, from_port, NULL) ==
1267 	    -2)
1268 		return; /* msg was stored with the session */
1269 
1270 fail:
1271 	radius_msg_free(msg);
1272 	os_free(buf);
1273 }
1274 
1275 
radius_server_receive_acct(int sock,void * eloop_ctx,void * sock_ctx)1276 static void radius_server_receive_acct(int sock, void *eloop_ctx,
1277 				       void *sock_ctx)
1278 {
1279 	struct radius_server_data *data = eloop_ctx;
1280 	u8 *buf = NULL;
1281 	union {
1282 		struct sockaddr_storage ss;
1283 		struct sockaddr_in sin;
1284 #ifdef CONFIG_IPV6
1285 		struct sockaddr_in6 sin6;
1286 #endif /* CONFIG_IPV6 */
1287 	} from;
1288 	socklen_t fromlen;
1289 	int len, res;
1290 	struct radius_client *client = NULL;
1291 	struct radius_msg *msg = NULL, *resp = NULL;
1292 	char abuf[50];
1293 	int from_port = 0;
1294 	struct radius_hdr *hdr;
1295 	struct wpabuf *rbuf;
1296 
1297 	buf = os_malloc(RADIUS_MAX_MSG_LEN);
1298 	if (buf == NULL) {
1299 		goto fail;
1300 	}
1301 
1302 	fromlen = sizeof(from);
1303 	len = recvfrom(sock, buf, RADIUS_MAX_MSG_LEN, 0,
1304 		       (struct sockaddr *) &from.ss, &fromlen);
1305 	if (len < 0) {
1306 		wpa_printf(MSG_INFO, "recvfrom[radius_server]: %s",
1307 			   strerror(errno));
1308 		goto fail;
1309 	}
1310 
1311 #ifdef CONFIG_IPV6
1312 	if (data->ipv6) {
1313 		if (inet_ntop(AF_INET6, &from.sin6.sin6_addr, abuf,
1314 			      sizeof(abuf)) == NULL)
1315 			abuf[0] = '\0';
1316 		from_port = ntohs(from.sin6.sin6_port);
1317 		RADIUS_DEBUG("Received %d bytes from %s:%d",
1318 			     len, abuf, from_port);
1319 
1320 		client = radius_server_get_client(data,
1321 						  (struct in_addr *)
1322 						  &from.sin6.sin6_addr, 1);
1323 	}
1324 #endif /* CONFIG_IPV6 */
1325 
1326 	if (!data->ipv6) {
1327 		os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf));
1328 		from_port = ntohs(from.sin.sin_port);
1329 		RADIUS_DEBUG("Received %d bytes from %s:%d",
1330 			     len, abuf, from_port);
1331 
1332 		client = radius_server_get_client(data, &from.sin.sin_addr, 0);
1333 	}
1334 
1335 	RADIUS_DUMP("Received data", buf, len);
1336 
1337 	if (client == NULL) {
1338 		RADIUS_DEBUG("Unknown client %s - packet ignored", abuf);
1339 		data->counters.invalid_acct_requests++;
1340 		goto fail;
1341 	}
1342 
1343 	msg = radius_msg_parse(buf, len);
1344 	if (msg == NULL) {
1345 		RADIUS_DEBUG("Parsing incoming RADIUS frame failed");
1346 		data->counters.malformed_acct_requests++;
1347 		client->counters.malformed_acct_requests++;
1348 		goto fail;
1349 	}
1350 
1351 	os_free(buf);
1352 	buf = NULL;
1353 
1354 	if (wpa_debug_level <= MSG_MSGDUMP) {
1355 		radius_msg_dump(msg);
1356 	}
1357 
1358 	if (radius_msg_get_hdr(msg)->code != RADIUS_CODE_ACCOUNTING_REQUEST) {
1359 		RADIUS_DEBUG("Unexpected RADIUS code %d",
1360 			     radius_msg_get_hdr(msg)->code);
1361 		data->counters.unknown_acct_types++;
1362 		client->counters.unknown_acct_types++;
1363 		goto fail;
1364 	}
1365 
1366 	data->counters.acct_requests++;
1367 	client->counters.acct_requests++;
1368 
1369 	if (radius_msg_verify_acct_req(msg, (u8 *) client->shared_secret,
1370 				       client->shared_secret_len)) {
1371 		RADIUS_DEBUG("Invalid Authenticator from %s", abuf);
1372 		data->counters.acct_bad_authenticators++;
1373 		client->counters.acct_bad_authenticators++;
1374 		goto fail;
1375 	}
1376 
1377 	/* TODO: Write accounting information to a file or database */
1378 
1379 	hdr = radius_msg_get_hdr(msg);
1380 
1381 	resp = radius_msg_new(RADIUS_CODE_ACCOUNTING_RESPONSE, hdr->identifier);
1382 	if (resp == NULL)
1383 		goto fail;
1384 
1385 	radius_msg_finish_acct_resp(resp, (u8 *) client->shared_secret,
1386 				    client->shared_secret_len,
1387 				    hdr->authenticator);
1388 
1389 	RADIUS_DEBUG("Reply to %s:%d", abuf, from_port);
1390 	if (wpa_debug_level <= MSG_MSGDUMP) {
1391 		radius_msg_dump(resp);
1392 	}
1393 	rbuf = radius_msg_get_buf(resp);
1394 	data->counters.acct_responses++;
1395 	client->counters.acct_responses++;
1396 	res = sendto(data->acct_sock, wpabuf_head(rbuf), wpabuf_len(rbuf), 0,
1397 		     (struct sockaddr *) &from.ss, fromlen);
1398 	if (res < 0) {
1399 		wpa_printf(MSG_INFO, "sendto[RADIUS SRV]: %s",
1400 			   strerror(errno));
1401 	}
1402 
1403 fail:
1404 	radius_msg_free(resp);
1405 	radius_msg_free(msg);
1406 	os_free(buf);
1407 }
1408 
1409 
radius_server_disable_pmtu_discovery(int s)1410 static int radius_server_disable_pmtu_discovery(int s)
1411 {
1412 	int r = -1;
1413 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
1414 	/* Turn off Path MTU discovery on IPv4/UDP sockets. */
1415 	int action = IP_PMTUDISC_DONT;
1416 	r = setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &action,
1417 		       sizeof(action));
1418 	if (r == -1)
1419 		wpa_printf(MSG_ERROR, "Failed to set IP_MTU_DISCOVER: "
1420 			   "%s", strerror(errno));
1421 #endif
1422 	return r;
1423 }
1424 
1425 
radius_server_open_socket(int port)1426 static int radius_server_open_socket(int port)
1427 {
1428 	int s;
1429 	struct sockaddr_in addr;
1430 
1431 	s = socket(PF_INET, SOCK_DGRAM, 0);
1432 	if (s < 0) {
1433 		wpa_printf(MSG_INFO, "RADIUS: socket: %s", strerror(errno));
1434 		return -1;
1435 	}
1436 
1437 	radius_server_disable_pmtu_discovery(s);
1438 
1439 	os_memset(&addr, 0, sizeof(addr));
1440 	addr.sin_family = AF_INET;
1441 	addr.sin_port = htons(port);
1442 	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1443 		wpa_printf(MSG_INFO, "RADIUS: bind: %s", strerror(errno));
1444 		close(s);
1445 		return -1;
1446 	}
1447 
1448 	return s;
1449 }
1450 
1451 
1452 #ifdef CONFIG_IPV6
radius_server_open_socket6(int port)1453 static int radius_server_open_socket6(int port)
1454 {
1455 	int s;
1456 	struct sockaddr_in6 addr;
1457 
1458 	s = socket(PF_INET6, SOCK_DGRAM, 0);
1459 	if (s < 0) {
1460 		wpa_printf(MSG_INFO, "RADIUS: socket[IPv6]: %s",
1461 			   strerror(errno));
1462 		return -1;
1463 	}
1464 
1465 	os_memset(&addr, 0, sizeof(addr));
1466 	addr.sin6_family = AF_INET6;
1467 	os_memcpy(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any));
1468 	addr.sin6_port = htons(port);
1469 	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1470 		wpa_printf(MSG_INFO, "RADIUS: bind: %s", strerror(errno));
1471 		close(s);
1472 		return -1;
1473 	}
1474 
1475 	return s;
1476 }
1477 #endif /* CONFIG_IPV6 */
1478 
1479 
radius_server_free_sessions(struct radius_server_data * data,struct radius_session * sessions)1480 static void radius_server_free_sessions(struct radius_server_data *data,
1481 					struct radius_session *sessions)
1482 {
1483 	struct radius_session *session, *prev;
1484 
1485 	session = sessions;
1486 	while (session) {
1487 		prev = session;
1488 		session = session->next;
1489 		radius_server_session_free(data, prev);
1490 	}
1491 }
1492 
1493 
radius_server_free_clients(struct radius_server_data * data,struct radius_client * clients)1494 static void radius_server_free_clients(struct radius_server_data *data,
1495 				       struct radius_client *clients)
1496 {
1497 	struct radius_client *client, *prev;
1498 
1499 	client = clients;
1500 	while (client) {
1501 		prev = client;
1502 		client = client->next;
1503 
1504 		radius_server_free_sessions(data, prev->sessions);
1505 		os_free(prev->shared_secret);
1506 		os_free(prev);
1507 	}
1508 }
1509 
1510 
1511 static struct radius_client *
radius_server_read_clients(const char * client_file,int ipv6)1512 radius_server_read_clients(const char *client_file, int ipv6)
1513 {
1514 	FILE *f;
1515 	const int buf_size = 1024;
1516 	char *buf, *pos;
1517 	struct radius_client *clients, *tail, *entry;
1518 	int line = 0, mask, failed = 0, i;
1519 	struct in_addr addr;
1520 #ifdef CONFIG_IPV6
1521 	struct in6_addr addr6;
1522 #endif /* CONFIG_IPV6 */
1523 	unsigned int val;
1524 
1525 	f = fopen(client_file, "r");
1526 	if (f == NULL) {
1527 		RADIUS_ERROR("Could not open client file '%s'", client_file);
1528 		return NULL;
1529 	}
1530 
1531 	buf = os_malloc(buf_size);
1532 	if (buf == NULL) {
1533 		fclose(f);
1534 		return NULL;
1535 	}
1536 
1537 	clients = tail = NULL;
1538 	while (fgets(buf, buf_size, f)) {
1539 		/* Configuration file format:
1540 		 * 192.168.1.0/24 secret
1541 		 * 192.168.1.2 secret
1542 		 * fe80::211:22ff:fe33:4455/64 secretipv6
1543 		 */
1544 		line++;
1545 		buf[buf_size - 1] = '\0';
1546 		pos = buf;
1547 		while (*pos != '\0' && *pos != '\n')
1548 			pos++;
1549 		if (*pos == '\n')
1550 			*pos = '\0';
1551 		if (*buf == '\0' || *buf == '#')
1552 			continue;
1553 
1554 		pos = buf;
1555 		while ((*pos >= '0' && *pos <= '9') || *pos == '.' ||
1556 		       (*pos >= 'a' && *pos <= 'f') || *pos == ':' ||
1557 		       (*pos >= 'A' && *pos <= 'F')) {
1558 			pos++;
1559 		}
1560 
1561 		if (*pos == '\0') {
1562 			failed = 1;
1563 			break;
1564 		}
1565 
1566 		if (*pos == '/') {
1567 			char *end;
1568 			*pos++ = '\0';
1569 			mask = strtol(pos, &end, 10);
1570 			if ((pos == end) ||
1571 			    (mask < 0 || mask > (ipv6 ? 128 : 32))) {
1572 				failed = 1;
1573 				break;
1574 			}
1575 			pos = end;
1576 		} else {
1577 			mask = ipv6 ? 128 : 32;
1578 			*pos++ = '\0';
1579 		}
1580 
1581 		if (!ipv6 && inet_aton(buf, &addr) == 0) {
1582 			failed = 1;
1583 			break;
1584 		}
1585 #ifdef CONFIG_IPV6
1586 		if (ipv6 && inet_pton(AF_INET6, buf, &addr6) <= 0) {
1587 			if (inet_pton(AF_INET, buf, &addr) <= 0) {
1588 				failed = 1;
1589 				break;
1590 			}
1591 			/* Convert IPv4 address to IPv6 */
1592 			if (mask <= 32)
1593 				mask += (128 - 32);
1594 			os_memset(addr6.s6_addr, 0, 10);
1595 			addr6.s6_addr[10] = 0xff;
1596 			addr6.s6_addr[11] = 0xff;
1597 			os_memcpy(addr6.s6_addr + 12, (char *) &addr.s_addr,
1598 				  4);
1599 		}
1600 #endif /* CONFIG_IPV6 */
1601 
1602 		while (*pos == ' ' || *pos == '\t') {
1603 			pos++;
1604 		}
1605 
1606 		if (*pos == '\0') {
1607 			failed = 1;
1608 			break;
1609 		}
1610 
1611 		entry = os_zalloc(sizeof(*entry));
1612 		if (entry == NULL) {
1613 			failed = 1;
1614 			break;
1615 		}
1616 		entry->shared_secret = os_strdup(pos);
1617 		if (entry->shared_secret == NULL) {
1618 			failed = 1;
1619 			os_free(entry);
1620 			break;
1621 		}
1622 		entry->shared_secret_len = os_strlen(entry->shared_secret);
1623 		if (!ipv6) {
1624 			entry->addr.s_addr = addr.s_addr;
1625 			val = 0;
1626 			for (i = 0; i < mask; i++)
1627 				val |= 1 << (31 - i);
1628 			entry->mask.s_addr = htonl(val);
1629 		}
1630 #ifdef CONFIG_IPV6
1631 		if (ipv6) {
1632 			int offset = mask / 8;
1633 
1634 			os_memcpy(entry->addr6.s6_addr, addr6.s6_addr, 16);
1635 			os_memset(entry->mask6.s6_addr, 0xff, offset);
1636 			val = 0;
1637 			for (i = 0; i < (mask % 8); i++)
1638 				val |= 1 << (7 - i);
1639 			if (offset < 16)
1640 				entry->mask6.s6_addr[offset] = val;
1641 		}
1642 #endif /* CONFIG_IPV6 */
1643 
1644 		if (tail == NULL) {
1645 			clients = tail = entry;
1646 		} else {
1647 			tail->next = entry;
1648 			tail = entry;
1649 		}
1650 	}
1651 
1652 	if (failed) {
1653 		RADIUS_ERROR("Invalid line %d in '%s'", line, client_file);
1654 		radius_server_free_clients(NULL, clients);
1655 		clients = NULL;
1656 	}
1657 
1658 	os_free(buf);
1659 	fclose(f);
1660 
1661 	return clients;
1662 }
1663 
1664 
1665 /**
1666  * radius_server_init - Initialize RADIUS server
1667  * @conf: Configuration for the RADIUS server
1668  * Returns: Pointer to private RADIUS server context or %NULL on failure
1669  *
1670  * This initializes a RADIUS server instance and returns a context pointer that
1671  * will be used in other calls to the RADIUS server module. The server can be
1672  * deinitialize by calling radius_server_deinit().
1673  */
1674 struct radius_server_data *
radius_server_init(struct radius_server_conf * conf)1675 radius_server_init(struct radius_server_conf *conf)
1676 {
1677 	struct radius_server_data *data;
1678 
1679 #ifndef CONFIG_IPV6
1680 	if (conf->ipv6) {
1681 		wpa_printf(MSG_ERROR, "RADIUS server compiled without IPv6 support");
1682 		return NULL;
1683 	}
1684 #endif /* CONFIG_IPV6 */
1685 
1686 	data = os_zalloc(sizeof(*data));
1687 	if (data == NULL)
1688 		return NULL;
1689 
1690 	os_get_reltime(&data->start_time);
1691 	data->conf_ctx = conf->conf_ctx;
1692 	data->eap_sim_db_priv = conf->eap_sim_db_priv;
1693 	data->ssl_ctx = conf->ssl_ctx;
1694 	data->msg_ctx = conf->msg_ctx;
1695 	data->ipv6 = conf->ipv6;
1696 	if (conf->pac_opaque_encr_key) {
1697 		data->pac_opaque_encr_key = os_malloc(16);
1698 		os_memcpy(data->pac_opaque_encr_key, conf->pac_opaque_encr_key,
1699 			  16);
1700 	}
1701 	if (conf->eap_fast_a_id) {
1702 		data->eap_fast_a_id = os_malloc(conf->eap_fast_a_id_len);
1703 		if (data->eap_fast_a_id) {
1704 			os_memcpy(data->eap_fast_a_id, conf->eap_fast_a_id,
1705 				  conf->eap_fast_a_id_len);
1706 			data->eap_fast_a_id_len = conf->eap_fast_a_id_len;
1707 		}
1708 	}
1709 	if (conf->eap_fast_a_id_info)
1710 		data->eap_fast_a_id_info = os_strdup(conf->eap_fast_a_id_info);
1711 	data->eap_fast_prov = conf->eap_fast_prov;
1712 	data->pac_key_lifetime = conf->pac_key_lifetime;
1713 	data->pac_key_refresh_time = conf->pac_key_refresh_time;
1714 	data->get_eap_user = conf->get_eap_user;
1715 	data->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;
1716 	data->tnc = conf->tnc;
1717 	data->wps = conf->wps;
1718 	data->pwd_group = conf->pwd_group;
1719 	data->server_id = conf->server_id;
1720 	if (conf->eap_req_id_text) {
1721 		data->eap_req_id_text = os_malloc(conf->eap_req_id_text_len);
1722 		if (data->eap_req_id_text) {
1723 			os_memcpy(data->eap_req_id_text, conf->eap_req_id_text,
1724 				  conf->eap_req_id_text_len);
1725 			data->eap_req_id_text_len = conf->eap_req_id_text_len;
1726 		}
1727 	}
1728 
1729 	if (conf->subscr_remediation_url) {
1730 		data->subscr_remediation_url =
1731 			os_strdup(conf->subscr_remediation_url);
1732 	}
1733 	data->subscr_remediation_method = conf->subscr_remediation_method;
1734 
1735 #ifdef CONFIG_SQLITE
1736 	if (conf->sqlite_file) {
1737 		if (sqlite3_open(conf->sqlite_file, &data->db)) {
1738 			RADIUS_ERROR("Could not open SQLite file '%s'",
1739 				     conf->sqlite_file);
1740 			radius_server_deinit(data);
1741 			return NULL;
1742 		}
1743 	}
1744 #endif /* CONFIG_SQLITE */
1745 
1746 #ifdef CONFIG_RADIUS_TEST
1747 	if (conf->dump_msk_file)
1748 		data->dump_msk_file = os_strdup(conf->dump_msk_file);
1749 #endif /* CONFIG_RADIUS_TEST */
1750 
1751 	data->clients = radius_server_read_clients(conf->client_file,
1752 						   conf->ipv6);
1753 	if (data->clients == NULL) {
1754 		wpa_printf(MSG_ERROR, "No RADIUS clients configured");
1755 		radius_server_deinit(data);
1756 		return NULL;
1757 	}
1758 
1759 #ifdef CONFIG_IPV6
1760 	if (conf->ipv6)
1761 		data->auth_sock = radius_server_open_socket6(conf->auth_port);
1762 	else
1763 #endif /* CONFIG_IPV6 */
1764 	data->auth_sock = radius_server_open_socket(conf->auth_port);
1765 	if (data->auth_sock < 0) {
1766 		wpa_printf(MSG_ERROR, "Failed to open UDP socket for RADIUS authentication server");
1767 		radius_server_deinit(data);
1768 		return NULL;
1769 	}
1770 	if (eloop_register_read_sock(data->auth_sock,
1771 				     radius_server_receive_auth,
1772 				     data, NULL)) {
1773 		radius_server_deinit(data);
1774 		return NULL;
1775 	}
1776 
1777 	if (conf->acct_port) {
1778 #ifdef CONFIG_IPV6
1779 		if (conf->ipv6)
1780 			data->acct_sock = radius_server_open_socket6(
1781 				conf->acct_port);
1782 		else
1783 #endif /* CONFIG_IPV6 */
1784 		data->acct_sock = radius_server_open_socket(conf->acct_port);
1785 		if (data->acct_sock < 0) {
1786 			wpa_printf(MSG_ERROR, "Failed to open UDP socket for RADIUS accounting server");
1787 			radius_server_deinit(data);
1788 			return NULL;
1789 		}
1790 		if (eloop_register_read_sock(data->acct_sock,
1791 					     radius_server_receive_acct,
1792 					     data, NULL)) {
1793 			radius_server_deinit(data);
1794 			return NULL;
1795 		}
1796 	} else {
1797 		data->acct_sock = -1;
1798 	}
1799 
1800 	return data;
1801 }
1802 
1803 
1804 /**
1805  * radius_server_deinit - Deinitialize RADIUS server
1806  * @data: RADIUS server context from radius_server_init()
1807  */
radius_server_deinit(struct radius_server_data * data)1808 void radius_server_deinit(struct radius_server_data *data)
1809 {
1810 	if (data == NULL)
1811 		return;
1812 
1813 	if (data->auth_sock >= 0) {
1814 		eloop_unregister_read_sock(data->auth_sock);
1815 		close(data->auth_sock);
1816 	}
1817 
1818 	if (data->acct_sock >= 0) {
1819 		eloop_unregister_read_sock(data->acct_sock);
1820 		close(data->acct_sock);
1821 	}
1822 
1823 	radius_server_free_clients(data, data->clients);
1824 
1825 	os_free(data->pac_opaque_encr_key);
1826 	os_free(data->eap_fast_a_id);
1827 	os_free(data->eap_fast_a_id_info);
1828 	os_free(data->eap_req_id_text);
1829 #ifdef CONFIG_RADIUS_TEST
1830 	os_free(data->dump_msk_file);
1831 #endif /* CONFIG_RADIUS_TEST */
1832 	os_free(data->subscr_remediation_url);
1833 
1834 #ifdef CONFIG_SQLITE
1835 	if (data->db)
1836 		sqlite3_close(data->db);
1837 #endif /* CONFIG_SQLITE */
1838 
1839 	os_free(data);
1840 }
1841 
1842 
1843 /**
1844  * radius_server_get_mib - Get RADIUS server MIB information
1845  * @data: RADIUS server context from radius_server_init()
1846  * @buf: Buffer for returning the MIB data in text format
1847  * @buflen: buf length in octets
1848  * Returns: Number of octets written into buf
1849  */
radius_server_get_mib(struct radius_server_data * data,char * buf,size_t buflen)1850 int radius_server_get_mib(struct radius_server_data *data, char *buf,
1851 			  size_t buflen)
1852 {
1853 	int ret, uptime;
1854 	unsigned int idx;
1855 	char *end, *pos;
1856 	struct os_reltime now;
1857 	struct radius_client *cli;
1858 
1859 	/* RFC 2619 - RADIUS Authentication Server MIB */
1860 
1861 	if (data == NULL || buflen == 0)
1862 		return 0;
1863 
1864 	pos = buf;
1865 	end = buf + buflen;
1866 
1867 	os_get_reltime(&now);
1868 	uptime = (now.sec - data->start_time.sec) * 100 +
1869 		((now.usec - data->start_time.usec) / 10000) % 100;
1870 	ret = os_snprintf(pos, end - pos,
1871 			  "RADIUS-AUTH-SERVER-MIB\n"
1872 			  "radiusAuthServIdent=hostapd\n"
1873 			  "radiusAuthServUpTime=%d\n"
1874 			  "radiusAuthServResetTime=0\n"
1875 			  "radiusAuthServConfigReset=4\n",
1876 			  uptime);
1877 	if (ret < 0 || ret >= end - pos) {
1878 		*pos = '\0';
1879 		return pos - buf;
1880 	}
1881 	pos += ret;
1882 
1883 	ret = os_snprintf(pos, end - pos,
1884 			  "radiusAuthServTotalAccessRequests=%u\n"
1885 			  "radiusAuthServTotalInvalidRequests=%u\n"
1886 			  "radiusAuthServTotalDupAccessRequests=%u\n"
1887 			  "radiusAuthServTotalAccessAccepts=%u\n"
1888 			  "radiusAuthServTotalAccessRejects=%u\n"
1889 			  "radiusAuthServTotalAccessChallenges=%u\n"
1890 			  "radiusAuthServTotalMalformedAccessRequests=%u\n"
1891 			  "radiusAuthServTotalBadAuthenticators=%u\n"
1892 			  "radiusAuthServTotalPacketsDropped=%u\n"
1893 			  "radiusAuthServTotalUnknownTypes=%u\n"
1894 			  "radiusAccServTotalRequests=%u\n"
1895 			  "radiusAccServTotalInvalidRequests=%u\n"
1896 			  "radiusAccServTotalResponses=%u\n"
1897 			  "radiusAccServTotalMalformedRequests=%u\n"
1898 			  "radiusAccServTotalBadAuthenticators=%u\n"
1899 			  "radiusAccServTotalUnknownTypes=%u\n",
1900 			  data->counters.access_requests,
1901 			  data->counters.invalid_requests,
1902 			  data->counters.dup_access_requests,
1903 			  data->counters.access_accepts,
1904 			  data->counters.access_rejects,
1905 			  data->counters.access_challenges,
1906 			  data->counters.malformed_access_requests,
1907 			  data->counters.bad_authenticators,
1908 			  data->counters.packets_dropped,
1909 			  data->counters.unknown_types,
1910 			  data->counters.acct_requests,
1911 			  data->counters.invalid_acct_requests,
1912 			  data->counters.acct_responses,
1913 			  data->counters.malformed_acct_requests,
1914 			  data->counters.acct_bad_authenticators,
1915 			  data->counters.unknown_acct_types);
1916 	if (ret < 0 || ret >= end - pos) {
1917 		*pos = '\0';
1918 		return pos - buf;
1919 	}
1920 	pos += ret;
1921 
1922 	for (cli = data->clients, idx = 0; cli; cli = cli->next, idx++) {
1923 		char abuf[50], mbuf[50];
1924 #ifdef CONFIG_IPV6
1925 		if (data->ipv6) {
1926 			if (inet_ntop(AF_INET6, &cli->addr6, abuf,
1927 				      sizeof(abuf)) == NULL)
1928 				abuf[0] = '\0';
1929 			if (inet_ntop(AF_INET6, &cli->mask6, mbuf,
1930 				      sizeof(mbuf)) == NULL)
1931 				mbuf[0] = '\0';
1932 		}
1933 #endif /* CONFIG_IPV6 */
1934 		if (!data->ipv6) {
1935 			os_strlcpy(abuf, inet_ntoa(cli->addr), sizeof(abuf));
1936 			os_strlcpy(mbuf, inet_ntoa(cli->mask), sizeof(mbuf));
1937 		}
1938 
1939 		ret = os_snprintf(pos, end - pos,
1940 				  "radiusAuthClientIndex=%u\n"
1941 				  "radiusAuthClientAddress=%s/%s\n"
1942 				  "radiusAuthServAccessRequests=%u\n"
1943 				  "radiusAuthServDupAccessRequests=%u\n"
1944 				  "radiusAuthServAccessAccepts=%u\n"
1945 				  "radiusAuthServAccessRejects=%u\n"
1946 				  "radiusAuthServAccessChallenges=%u\n"
1947 				  "radiusAuthServMalformedAccessRequests=%u\n"
1948 				  "radiusAuthServBadAuthenticators=%u\n"
1949 				  "radiusAuthServPacketsDropped=%u\n"
1950 				  "radiusAuthServUnknownTypes=%u\n"
1951 				  "radiusAccServTotalRequests=%u\n"
1952 				  "radiusAccServTotalInvalidRequests=%u\n"
1953 				  "radiusAccServTotalResponses=%u\n"
1954 				  "radiusAccServTotalMalformedRequests=%u\n"
1955 				  "radiusAccServTotalBadAuthenticators=%u\n"
1956 				  "radiusAccServTotalUnknownTypes=%u\n",
1957 				  idx,
1958 				  abuf, mbuf,
1959 				  cli->counters.access_requests,
1960 				  cli->counters.dup_access_requests,
1961 				  cli->counters.access_accepts,
1962 				  cli->counters.access_rejects,
1963 				  cli->counters.access_challenges,
1964 				  cli->counters.malformed_access_requests,
1965 				  cli->counters.bad_authenticators,
1966 				  cli->counters.packets_dropped,
1967 				  cli->counters.unknown_types,
1968 				  cli->counters.acct_requests,
1969 				  cli->counters.invalid_acct_requests,
1970 				  cli->counters.acct_responses,
1971 				  cli->counters.malformed_acct_requests,
1972 				  cli->counters.acct_bad_authenticators,
1973 				  cli->counters.unknown_acct_types);
1974 		if (ret < 0 || ret >= end - pos) {
1975 			*pos = '\0';
1976 			return pos - buf;
1977 		}
1978 		pos += ret;
1979 	}
1980 
1981 	return pos - buf;
1982 }
1983 
1984 
radius_server_get_eap_user(void * ctx,const u8 * identity,size_t identity_len,int phase2,struct eap_user * user)1985 static int radius_server_get_eap_user(void *ctx, const u8 *identity,
1986 				      size_t identity_len, int phase2,
1987 				      struct eap_user *user)
1988 {
1989 	struct radius_session *sess = ctx;
1990 	struct radius_server_data *data = sess->server;
1991 	int ret;
1992 
1993 	ret = data->get_eap_user(data->conf_ctx, identity, identity_len,
1994 				 phase2, user);
1995 	if (ret == 0 && user) {
1996 		sess->accept_attr = user->accept_attr;
1997 		sess->remediation = user->remediation;
1998 		sess->macacl = user->macacl;
1999 	}
2000 	return ret;
2001 }
2002 
2003 
radius_server_get_eap_req_id_text(void * ctx,size_t * len)2004 static const char * radius_server_get_eap_req_id_text(void *ctx, size_t *len)
2005 {
2006 	struct radius_session *sess = ctx;
2007 	struct radius_server_data *data = sess->server;
2008 	*len = data->eap_req_id_text_len;
2009 	return data->eap_req_id_text;
2010 }
2011 
2012 
radius_server_log_msg(void * ctx,const char * msg)2013 static void radius_server_log_msg(void *ctx, const char *msg)
2014 {
2015 	struct radius_session *sess = ctx;
2016 	srv_log(sess, "EAP: %s", msg);
2017 }
2018 
2019 
2020 static struct eapol_callbacks radius_server_eapol_cb =
2021 {
2022 	.get_eap_user = radius_server_get_eap_user,
2023 	.get_eap_req_id_text = radius_server_get_eap_req_id_text,
2024 	.log_msg = radius_server_log_msg,
2025 };
2026 
2027 
2028 /**
2029  * radius_server_eap_pending_cb - Pending EAP data notification
2030  * @data: RADIUS server context from radius_server_init()
2031  * @ctx: Pending EAP context pointer
2032  *
2033  * This function is used to notify EAP server module that a pending operation
2034  * has been completed and processing of the EAP session can proceed.
2035  */
radius_server_eap_pending_cb(struct radius_server_data * data,void * ctx)2036 void radius_server_eap_pending_cb(struct radius_server_data *data, void *ctx)
2037 {
2038 	struct radius_client *cli;
2039 	struct radius_session *s, *sess = NULL;
2040 	struct radius_msg *msg;
2041 
2042 	if (data == NULL)
2043 		return;
2044 
2045 	for (cli = data->clients; cli; cli = cli->next) {
2046 		for (s = cli->sessions; s; s = s->next) {
2047 			if (s->eap == ctx && s->last_msg) {
2048 				sess = s;
2049 				break;
2050 			}
2051 		}
2052 		if (sess)
2053 			break;
2054 	}
2055 
2056 	if (sess == NULL) {
2057 		RADIUS_DEBUG("No session matched callback ctx");
2058 		return;
2059 	}
2060 
2061 	msg = sess->last_msg;
2062 	sess->last_msg = NULL;
2063 	eap_sm_pending_cb(sess->eap);
2064 	if (radius_server_request(data, msg,
2065 				  (struct sockaddr *) &sess->last_from,
2066 				  sess->last_fromlen, cli,
2067 				  sess->last_from_addr,
2068 				  sess->last_from_port, sess) == -2)
2069 		return; /* msg was stored with the session */
2070 
2071 	radius_msg_free(msg);
2072 }
2073