1/*
2 * hostapd / RADIUS authentication server
3 * Copyright (c) 2005-2008, Jouni Malinen <j@w1.fi>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
11 *
12 * See README and COPYING for more details.
13 */
14
15#include "includes.h"
16#include <net/if.h>
17
18#include "common.h"
19#include "radius.h"
20#include "eloop.h"
21#include "defs.h"
22#include "eap_server/eap.h"
23#include "radius_server.h"
24
25#define RADIUS_SESSION_TIMEOUT 60
26#define RADIUS_MAX_SESSION 100
27#define RADIUS_MAX_MSG_LEN 3000
28
29static struct eapol_callbacks radius_server_eapol_cb;
30
31struct radius_client;
32struct radius_server_data;
33
34struct radius_server_counters {
35	u32 access_requests;
36	u32 invalid_requests;
37	u32 dup_access_requests;
38	u32 access_accepts;
39	u32 access_rejects;
40	u32 access_challenges;
41	u32 malformed_access_requests;
42	u32 bad_authenticators;
43	u32 packets_dropped;
44	u32 unknown_types;
45};
46
47struct radius_session {
48	struct radius_session *next;
49	struct radius_client *client;
50	struct radius_server_data *server;
51	unsigned int sess_id;
52	struct eap_sm *eap;
53	struct eap_eapol_interface *eap_if;
54
55	struct radius_msg *last_msg;
56	char *last_from_addr;
57	int last_from_port;
58	struct sockaddr_storage last_from;
59	socklen_t last_fromlen;
60	u8 last_identifier;
61	struct radius_msg *last_reply;
62	u8 last_authenticator[16];
63};
64
65struct radius_client {
66	struct radius_client *next;
67	struct in_addr addr;
68	struct in_addr mask;
69#ifdef CONFIG_IPV6
70	struct in6_addr addr6;
71	struct in6_addr mask6;
72#endif /* CONFIG_IPV6 */
73	char *shared_secret;
74	int shared_secret_len;
75	struct radius_session *sessions;
76	struct radius_server_counters counters;
77};
78
79struct radius_server_data {
80	int auth_sock;
81	struct radius_client *clients;
82	unsigned int next_sess_id;
83	void *conf_ctx;
84	int num_sess;
85	void *eap_sim_db_priv;
86	void *ssl_ctx;
87	u8 *pac_opaque_encr_key;
88	u8 *eap_fast_a_id;
89	size_t eap_fast_a_id_len;
90	char *eap_fast_a_id_info;
91	int eap_fast_prov;
92	int pac_key_lifetime;
93	int pac_key_refresh_time;
94	int eap_sim_aka_result_ind;
95	int tnc;
96	struct wps_context *wps;
97	int ipv6;
98	struct os_time start_time;
99	struct radius_server_counters counters;
100	int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len,
101			    int phase2, struct eap_user *user);
102	char *eap_req_id_text;
103	size_t eap_req_id_text_len;
104};
105
106
107extern int wpa_debug_level;
108
109#define RADIUS_DEBUG(args...) \
110wpa_printf(MSG_DEBUG, "RADIUS SRV: " args)
111#define RADIUS_ERROR(args...) \
112wpa_printf(MSG_ERROR, "RADIUS SRV: " args)
113#define RADIUS_DUMP(args...) \
114wpa_hexdump(MSG_MSGDUMP, "RADIUS SRV: " args)
115#define RADIUS_DUMP_ASCII(args...) \
116wpa_hexdump_ascii(MSG_MSGDUMP, "RADIUS SRV: " args)
117
118
119static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx);
120static void radius_server_session_remove_timeout(void *eloop_ctx,
121						 void *timeout_ctx);
122
123
124static struct radius_client *
125radius_server_get_client(struct radius_server_data *data, struct in_addr *addr,
126			 int ipv6)
127{
128	struct radius_client *client = data->clients;
129
130	while (client) {
131#ifdef CONFIG_IPV6
132		if (ipv6) {
133			struct in6_addr *addr6;
134			int i;
135
136			addr6 = (struct in6_addr *) addr;
137			for (i = 0; i < 16; i++) {
138				if ((addr6->s6_addr[i] &
139				     client->mask6.s6_addr[i]) !=
140				    (client->addr6.s6_addr[i] &
141				     client->mask6.s6_addr[i])) {
142					i = 17;
143					break;
144				}
145			}
146			if (i == 16) {
147				break;
148			}
149		}
150#endif /* CONFIG_IPV6 */
151		if (!ipv6 && (client->addr.s_addr & client->mask.s_addr) ==
152		    (addr->s_addr & client->mask.s_addr)) {
153			break;
154		}
155
156		client = client->next;
157	}
158
159	return client;
160}
161
162
163static struct radius_session *
164radius_server_get_session(struct radius_client *client, unsigned int sess_id)
165{
166	struct radius_session *sess = client->sessions;
167
168	while (sess) {
169		if (sess->sess_id == sess_id) {
170			break;
171		}
172		sess = sess->next;
173	}
174
175	return sess;
176}
177
178
179static void radius_server_session_free(struct radius_server_data *data,
180				       struct radius_session *sess)
181{
182	eloop_cancel_timeout(radius_server_session_timeout, data, sess);
183	eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess);
184	eap_server_sm_deinit(sess->eap);
185	if (sess->last_msg) {
186		radius_msg_free(sess->last_msg);
187		os_free(sess->last_msg);
188	}
189	os_free(sess->last_from_addr);
190	if (sess->last_reply) {
191		radius_msg_free(sess->last_reply);
192		os_free(sess->last_reply);
193	}
194	os_free(sess);
195	data->num_sess--;
196}
197
198
199static void radius_server_session_remove(struct radius_server_data *data,
200					 struct radius_session *sess)
201{
202	struct radius_client *client = sess->client;
203	struct radius_session *session, *prev;
204
205	eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess);
206
207	prev = NULL;
208	session = client->sessions;
209	while (session) {
210		if (session == sess) {
211			if (prev == NULL) {
212				client->sessions = sess->next;
213			} else {
214				prev->next = sess->next;
215			}
216			radius_server_session_free(data, sess);
217			break;
218		}
219		prev = session;
220		session = session->next;
221	}
222}
223
224
225static void radius_server_session_remove_timeout(void *eloop_ctx,
226						 void *timeout_ctx)
227{
228	struct radius_server_data *data = eloop_ctx;
229	struct radius_session *sess = timeout_ctx;
230	RADIUS_DEBUG("Removing completed session 0x%x", sess->sess_id);
231	radius_server_session_remove(data, sess);
232}
233
234
235static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx)
236{
237	struct radius_server_data *data = eloop_ctx;
238	struct radius_session *sess = timeout_ctx;
239
240	RADIUS_DEBUG("Timing out authentication session 0x%x", sess->sess_id);
241	radius_server_session_remove(data, sess);
242}
243
244
245static struct radius_session *
246radius_server_new_session(struct radius_server_data *data,
247			  struct radius_client *client)
248{
249	struct radius_session *sess;
250
251	if (data->num_sess >= RADIUS_MAX_SESSION) {
252		RADIUS_DEBUG("Maximum number of existing session - no room "
253			     "for a new session");
254		return NULL;
255	}
256
257	sess = os_zalloc(sizeof(*sess));
258	if (sess == NULL)
259		return NULL;
260
261	sess->server = data;
262	sess->client = client;
263	sess->sess_id = data->next_sess_id++;
264	sess->next = client->sessions;
265	client->sessions = sess;
266	eloop_register_timeout(RADIUS_SESSION_TIMEOUT, 0,
267			       radius_server_session_timeout, data, sess);
268	data->num_sess++;
269	return sess;
270}
271
272
273static struct radius_session *
274radius_server_get_new_session(struct radius_server_data *data,
275			      struct radius_client *client,
276			      struct radius_msg *msg)
277{
278	u8 *user;
279	size_t user_len;
280	int res;
281	struct radius_session *sess;
282	struct eap_config eap_conf;
283
284	RADIUS_DEBUG("Creating a new session");
285
286	user = os_malloc(256);
287	if (user == NULL) {
288		return NULL;
289	}
290	res = radius_msg_get_attr(msg, RADIUS_ATTR_USER_NAME, user, 256);
291	if (res < 0 || res > 256) {
292		RADIUS_DEBUG("Could not get User-Name");
293		os_free(user);
294		return NULL;
295	}
296	user_len = res;
297	RADIUS_DUMP_ASCII("User-Name", user, user_len);
298
299	res = data->get_eap_user(data->conf_ctx, user, user_len, 0, NULL);
300	os_free(user);
301
302	if (res == 0) {
303		RADIUS_DEBUG("Matching user entry found");
304		sess = radius_server_new_session(data, client);
305		if (sess == NULL) {
306			RADIUS_DEBUG("Failed to create a new session");
307			return NULL;
308		}
309	} else {
310		RADIUS_DEBUG("User-Name not found from user database");
311		return NULL;
312	}
313
314	os_memset(&eap_conf, 0, sizeof(eap_conf));
315	eap_conf.ssl_ctx = data->ssl_ctx;
316	eap_conf.eap_sim_db_priv = data->eap_sim_db_priv;
317	eap_conf.backend_auth = TRUE;
318	eap_conf.eap_server = 1;
319	eap_conf.pac_opaque_encr_key = data->pac_opaque_encr_key;
320	eap_conf.eap_fast_a_id = data->eap_fast_a_id;
321	eap_conf.eap_fast_a_id_len = data->eap_fast_a_id_len;
322	eap_conf.eap_fast_a_id_info = data->eap_fast_a_id_info;
323	eap_conf.eap_fast_prov = data->eap_fast_prov;
324	eap_conf.pac_key_lifetime = data->pac_key_lifetime;
325	eap_conf.pac_key_refresh_time = data->pac_key_refresh_time;
326	eap_conf.eap_sim_aka_result_ind = data->eap_sim_aka_result_ind;
327	eap_conf.tnc = data->tnc;
328	eap_conf.wps = data->wps;
329	sess->eap = eap_server_sm_init(sess, &radius_server_eapol_cb,
330				       &eap_conf);
331	if (sess->eap == NULL) {
332		RADIUS_DEBUG("Failed to initialize EAP state machine for the "
333			     "new session");
334		radius_server_session_free(data, sess);
335		return NULL;
336	}
337	sess->eap_if = eap_get_interface(sess->eap);
338	sess->eap_if->eapRestart = TRUE;
339	sess->eap_if->portEnabled = TRUE;
340
341	RADIUS_DEBUG("New session 0x%x initialized", sess->sess_id);
342
343	return sess;
344}
345
346
347static struct radius_msg *
348radius_server_encapsulate_eap(struct radius_server_data *data,
349			      struct radius_client *client,
350			      struct radius_session *sess,
351			      struct radius_msg *request)
352{
353	struct radius_msg *msg;
354	int code;
355	unsigned int sess_id;
356
357	if (sess->eap_if->eapFail) {
358		sess->eap_if->eapFail = FALSE;
359		code = RADIUS_CODE_ACCESS_REJECT;
360	} else if (sess->eap_if->eapSuccess) {
361		sess->eap_if->eapSuccess = FALSE;
362		code = RADIUS_CODE_ACCESS_ACCEPT;
363	} else {
364		sess->eap_if->eapReq = FALSE;
365		code = RADIUS_CODE_ACCESS_CHALLENGE;
366	}
367
368	msg = radius_msg_new(code, request->hdr->identifier);
369	if (msg == NULL) {
370		RADIUS_DEBUG("Failed to allocate reply message");
371		return NULL;
372	}
373
374	sess_id = htonl(sess->sess_id);
375	if (code == RADIUS_CODE_ACCESS_CHALLENGE &&
376	    !radius_msg_add_attr(msg, RADIUS_ATTR_STATE,
377				 (u8 *) &sess_id, sizeof(sess_id))) {
378		RADIUS_DEBUG("Failed to add State attribute");
379	}
380
381	if (sess->eap_if->eapReqData &&
382	    !radius_msg_add_eap(msg, wpabuf_head(sess->eap_if->eapReqData),
383				wpabuf_len(sess->eap_if->eapReqData))) {
384		RADIUS_DEBUG("Failed to add EAP-Message attribute");
385	}
386
387	if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->eap_if->eapKeyData) {
388		int len;
389		if (sess->eap_if->eapKeyDataLen > 64) {
390			len = 32;
391		} else {
392			len = sess->eap_if->eapKeyDataLen / 2;
393		}
394		if (!radius_msg_add_mppe_keys(msg, request->hdr->authenticator,
395					      (u8 *) client->shared_secret,
396					      client->shared_secret_len,
397					      sess->eap_if->eapKeyData + len,
398					      len, sess->eap_if->eapKeyData,
399					      len)) {
400			RADIUS_DEBUG("Failed to add MPPE key attributes");
401		}
402	}
403
404	if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) {
405		RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
406		radius_msg_free(msg);
407		os_free(msg);
408		return NULL;
409	}
410
411	if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
412				  client->shared_secret_len,
413				  request->hdr->authenticator) < 0) {
414		RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
415	}
416
417	return msg;
418}
419
420
421static int radius_server_reject(struct radius_server_data *data,
422				struct radius_client *client,
423				struct radius_msg *request,
424				struct sockaddr *from, socklen_t fromlen,
425				const char *from_addr, int from_port)
426{
427	struct radius_msg *msg;
428	int ret = 0;
429	struct eap_hdr eapfail;
430
431	RADIUS_DEBUG("Reject invalid request from %s:%d",
432		     from_addr, from_port);
433
434	msg = radius_msg_new(RADIUS_CODE_ACCESS_REJECT,
435			     request->hdr->identifier);
436	if (msg == NULL) {
437		return -1;
438	}
439
440	os_memset(&eapfail, 0, sizeof(eapfail));
441	eapfail.code = EAP_CODE_FAILURE;
442	eapfail.identifier = 0;
443	eapfail.length = host_to_be16(sizeof(eapfail));
444
445	if (!radius_msg_add_eap(msg, (u8 *) &eapfail, sizeof(eapfail))) {
446		RADIUS_DEBUG("Failed to add EAP-Message attribute");
447	}
448
449	if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) {
450		RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
451		radius_msg_free(msg);
452		os_free(msg);
453		return -1;
454	}
455
456	if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
457				  client->shared_secret_len,
458				  request->hdr->authenticator) < 0) {
459		RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
460	}
461
462	if (wpa_debug_level <= MSG_MSGDUMP) {
463		radius_msg_dump(msg);
464	}
465
466	data->counters.access_rejects++;
467	client->counters.access_rejects++;
468	if (sendto(data->auth_sock, msg->buf, msg->buf_used, 0,
469		   (struct sockaddr *) from, sizeof(*from)) < 0) {
470		perror("sendto[RADIUS SRV]");
471		ret = -1;
472	}
473
474	radius_msg_free(msg);
475	os_free(msg);
476
477	return ret;
478}
479
480
481static int radius_server_request(struct radius_server_data *data,
482				 struct radius_msg *msg,
483				 struct sockaddr *from, socklen_t fromlen,
484				 struct radius_client *client,
485				 const char *from_addr, int from_port,
486				 struct radius_session *force_sess)
487{
488	u8 *eap = NULL;
489	size_t eap_len;
490	int res, state_included = 0;
491	u8 statebuf[4];
492	unsigned int state;
493	struct radius_session *sess;
494	struct radius_msg *reply;
495	int is_complete = 0;
496
497	if (force_sess)
498		sess = force_sess;
499	else {
500		res = radius_msg_get_attr(msg, RADIUS_ATTR_STATE, statebuf,
501					  sizeof(statebuf));
502		state_included = res >= 0;
503		if (res == sizeof(statebuf)) {
504			state = WPA_GET_BE32(statebuf);
505			sess = radius_server_get_session(client, state);
506		} else {
507			sess = NULL;
508		}
509	}
510
511	if (sess) {
512		RADIUS_DEBUG("Request for session 0x%x", sess->sess_id);
513	} else if (state_included) {
514		RADIUS_DEBUG("State attribute included but no session found");
515		radius_server_reject(data, client, msg, from, fromlen,
516				     from_addr, from_port);
517		return -1;
518	} else {
519		sess = radius_server_get_new_session(data, client, msg);
520		if (sess == NULL) {
521			RADIUS_DEBUG("Could not create a new session");
522			radius_server_reject(data, client, msg, from, fromlen,
523					     from_addr, from_port);
524			return -1;
525		}
526	}
527
528	if (sess->last_from_port == from_port &&
529	    sess->last_identifier == msg->hdr->identifier &&
530	    os_memcmp(sess->last_authenticator, msg->hdr->authenticator, 16) ==
531	    0) {
532		RADIUS_DEBUG("Duplicate message from %s", from_addr);
533		data->counters.dup_access_requests++;
534		client->counters.dup_access_requests++;
535
536		if (sess->last_reply) {
537			res = sendto(data->auth_sock, sess->last_reply->buf,
538				     sess->last_reply->buf_used, 0,
539				     (struct sockaddr *) from, fromlen);
540			if (res < 0) {
541				perror("sendto[RADIUS SRV]");
542			}
543			return 0;
544		}
545
546		RADIUS_DEBUG("No previous reply available for duplicate "
547			     "message");
548		return -1;
549	}
550
551	eap = radius_msg_get_eap(msg, &eap_len);
552	if (eap == NULL) {
553		RADIUS_DEBUG("No EAP-Message in RADIUS packet from %s",
554			     from_addr);
555		data->counters.packets_dropped++;
556		client->counters.packets_dropped++;
557		return -1;
558	}
559
560	RADIUS_DUMP("Received EAP data", eap, eap_len);
561
562	/* FIX: if Code is Request, Success, or Failure, send Access-Reject;
563	 * RFC3579 Sect. 2.6.2.
564	 * Include EAP-Response/Nak with no preferred method if
565	 * code == request.
566	 * If code is not 1-4, discard the packet silently.
567	 * Or is this already done by the EAP state machine? */
568
569	wpabuf_free(sess->eap_if->eapRespData);
570	sess->eap_if->eapRespData = wpabuf_alloc_ext_data(eap, eap_len);
571	if (sess->eap_if->eapRespData == NULL)
572		os_free(eap);
573	eap = NULL;
574	sess->eap_if->eapResp = TRUE;
575	eap_server_sm_step(sess->eap);
576
577	if ((sess->eap_if->eapReq || sess->eap_if->eapSuccess ||
578	     sess->eap_if->eapFail) && sess->eap_if->eapReqData) {
579		RADIUS_DUMP("EAP data from the state machine",
580			    wpabuf_head(sess->eap_if->eapReqData),
581			    wpabuf_len(sess->eap_if->eapReqData));
582	} else if (sess->eap_if->eapFail) {
583		RADIUS_DEBUG("No EAP data from the state machine, but eapFail "
584			     "set");
585	} else if (eap_sm_method_pending(sess->eap)) {
586		if (sess->last_msg) {
587			radius_msg_free(sess->last_msg);
588			os_free(sess->last_msg);
589		}
590		sess->last_msg = msg;
591		sess->last_from_port = from_port;
592		os_free(sess->last_from_addr);
593		sess->last_from_addr = os_strdup(from_addr);
594		sess->last_fromlen = fromlen;
595		os_memcpy(&sess->last_from, from, fromlen);
596		return -2;
597	} else {
598		RADIUS_DEBUG("No EAP data from the state machine - ignore this"
599			     " Access-Request silently (assuming it was a "
600			     "duplicate)");
601		data->counters.packets_dropped++;
602		client->counters.packets_dropped++;
603		return -1;
604	}
605
606	if (sess->eap_if->eapSuccess || sess->eap_if->eapFail)
607		is_complete = 1;
608
609	reply = radius_server_encapsulate_eap(data, client, sess, msg);
610
611	if (reply) {
612		RADIUS_DEBUG("Reply to %s:%d", from_addr, from_port);
613		if (wpa_debug_level <= MSG_MSGDUMP) {
614			radius_msg_dump(reply);
615		}
616
617		switch (reply->hdr->code) {
618		case RADIUS_CODE_ACCESS_ACCEPT:
619			data->counters.access_accepts++;
620			client->counters.access_accepts++;
621			break;
622		case RADIUS_CODE_ACCESS_REJECT:
623			data->counters.access_rejects++;
624			client->counters.access_rejects++;
625			break;
626		case RADIUS_CODE_ACCESS_CHALLENGE:
627			data->counters.access_challenges++;
628			client->counters.access_challenges++;
629			break;
630		}
631		res = sendto(data->auth_sock, reply->buf, reply->buf_used, 0,
632			     (struct sockaddr *) from, fromlen);
633		if (res < 0) {
634			perror("sendto[RADIUS SRV]");
635		}
636		if (sess->last_reply) {
637			radius_msg_free(sess->last_reply);
638			os_free(sess->last_reply);
639		}
640		sess->last_reply = reply;
641		sess->last_from_port = from_port;
642		sess->last_identifier = msg->hdr->identifier;
643		os_memcpy(sess->last_authenticator, msg->hdr->authenticator,
644			  16);
645	} else {
646		data->counters.packets_dropped++;
647		client->counters.packets_dropped++;
648	}
649
650	if (is_complete) {
651		RADIUS_DEBUG("Removing completed session 0x%x after timeout",
652			     sess->sess_id);
653		eloop_cancel_timeout(radius_server_session_remove_timeout,
654				     data, sess);
655		eloop_register_timeout(10, 0,
656				       radius_server_session_remove_timeout,
657				       data, sess);
658	}
659
660	return 0;
661}
662
663
664static void radius_server_receive_auth(int sock, void *eloop_ctx,
665				       void *sock_ctx)
666{
667	struct radius_server_data *data = eloop_ctx;
668	u8 *buf = NULL;
669	union {
670		struct sockaddr_storage ss;
671		struct sockaddr_in sin;
672#ifdef CONFIG_IPV6
673		struct sockaddr_in6 sin6;
674#endif /* CONFIG_IPV6 */
675	} from;
676	socklen_t fromlen;
677	int len;
678	struct radius_client *client = NULL;
679	struct radius_msg *msg = NULL;
680	char abuf[50];
681	int from_port = 0;
682
683	buf = os_malloc(RADIUS_MAX_MSG_LEN);
684	if (buf == NULL) {
685		goto fail;
686	}
687
688	fromlen = sizeof(from);
689	len = recvfrom(sock, buf, RADIUS_MAX_MSG_LEN, 0,
690		       (struct sockaddr *) &from.ss, &fromlen);
691	if (len < 0) {
692		perror("recvfrom[radius_server]");
693		goto fail;
694	}
695
696#ifdef CONFIG_IPV6
697	if (data->ipv6) {
698		if (inet_ntop(AF_INET6, &from.sin6.sin6_addr, abuf,
699			      sizeof(abuf)) == NULL)
700			abuf[0] = '\0';
701		from_port = ntohs(from.sin6.sin6_port);
702		RADIUS_DEBUG("Received %d bytes from %s:%d",
703			     len, abuf, from_port);
704
705		client = radius_server_get_client(data,
706						  (struct in_addr *)
707						  &from.sin6.sin6_addr, 1);
708	}
709#endif /* CONFIG_IPV6 */
710
711	if (!data->ipv6) {
712		os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf));
713		from_port = ntohs(from.sin.sin_port);
714		RADIUS_DEBUG("Received %d bytes from %s:%d",
715			     len, abuf, from_port);
716
717		client = radius_server_get_client(data, &from.sin.sin_addr, 0);
718	}
719
720	RADIUS_DUMP("Received data", buf, len);
721
722	if (client == NULL) {
723		RADIUS_DEBUG("Unknown client %s - packet ignored", abuf);
724		data->counters.invalid_requests++;
725		goto fail;
726	}
727
728	msg = radius_msg_parse(buf, len);
729	if (msg == NULL) {
730		RADIUS_DEBUG("Parsing incoming RADIUS frame failed");
731		data->counters.malformed_access_requests++;
732		client->counters.malformed_access_requests++;
733		goto fail;
734	}
735
736	os_free(buf);
737	buf = NULL;
738
739	if (wpa_debug_level <= MSG_MSGDUMP) {
740		radius_msg_dump(msg);
741	}
742
743	if (msg->hdr->code != RADIUS_CODE_ACCESS_REQUEST) {
744		RADIUS_DEBUG("Unexpected RADIUS code %d", msg->hdr->code);
745		data->counters.unknown_types++;
746		client->counters.unknown_types++;
747		goto fail;
748	}
749
750	data->counters.access_requests++;
751	client->counters.access_requests++;
752
753	if (radius_msg_verify_msg_auth(msg, (u8 *) client->shared_secret,
754				       client->shared_secret_len, NULL)) {
755		RADIUS_DEBUG("Invalid Message-Authenticator from %s", abuf);
756		data->counters.bad_authenticators++;
757		client->counters.bad_authenticators++;
758		goto fail;
759	}
760
761	if (radius_server_request(data, msg, (struct sockaddr *) &from,
762				  fromlen, client, abuf, from_port, NULL) ==
763	    -2)
764		return; /* msg was stored with the session */
765
766fail:
767	if (msg) {
768		radius_msg_free(msg);
769		os_free(msg);
770	}
771	os_free(buf);
772}
773
774
775static int radius_server_disable_pmtu_discovery(int s)
776{
777	int r = -1;
778#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
779	/* Turn off Path MTU discovery on IPv4/UDP sockets. */
780	int action = IP_PMTUDISC_DONT;
781	r = setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &action,
782		       sizeof(action));
783	if (r == -1)
784		wpa_printf(MSG_ERROR, "Failed to set IP_MTU_DISCOVER: "
785			   "%s", strerror(errno));
786#endif
787	return r;
788}
789
790
791static int radius_server_open_socket(int port)
792{
793	int s;
794	struct sockaddr_in addr;
795
796	s = socket(PF_INET, SOCK_DGRAM, 0);
797	if (s < 0) {
798		perror("socket");
799		return -1;
800	}
801
802	radius_server_disable_pmtu_discovery(s);
803
804	os_memset(&addr, 0, sizeof(addr));
805	addr.sin_family = AF_INET;
806	addr.sin_port = htons(port);
807	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
808		perror("bind");
809		close(s);
810		return -1;
811	}
812
813	return s;
814}
815
816
817#ifdef CONFIG_IPV6
818static int radius_server_open_socket6(int port)
819{
820	int s;
821	struct sockaddr_in6 addr;
822
823	s = socket(PF_INET6, SOCK_DGRAM, 0);
824	if (s < 0) {
825		perror("socket[IPv6]");
826		return -1;
827	}
828
829	os_memset(&addr, 0, sizeof(addr));
830	addr.sin6_family = AF_INET6;
831	os_memcpy(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any));
832	addr.sin6_port = htons(port);
833	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
834		perror("bind");
835		close(s);
836		return -1;
837	}
838
839	return s;
840}
841#endif /* CONFIG_IPV6 */
842
843
844static void radius_server_free_sessions(struct radius_server_data *data,
845					struct radius_session *sessions)
846{
847	struct radius_session *session, *prev;
848
849	session = sessions;
850	while (session) {
851		prev = session;
852		session = session->next;
853		radius_server_session_free(data, prev);
854	}
855}
856
857
858static void radius_server_free_clients(struct radius_server_data *data,
859				       struct radius_client *clients)
860{
861	struct radius_client *client, *prev;
862
863	client = clients;
864	while (client) {
865		prev = client;
866		client = client->next;
867
868		radius_server_free_sessions(data, prev->sessions);
869		os_free(prev->shared_secret);
870		os_free(prev);
871	}
872}
873
874
875static struct radius_client *
876radius_server_read_clients(const char *client_file, int ipv6)
877{
878	FILE *f;
879	const int buf_size = 1024;
880	char *buf, *pos;
881	struct radius_client *clients, *tail, *entry;
882	int line = 0, mask, failed = 0, i;
883	struct in_addr addr;
884#ifdef CONFIG_IPV6
885	struct in6_addr addr6;
886#endif /* CONFIG_IPV6 */
887	unsigned int val;
888
889	f = fopen(client_file, "r");
890	if (f == NULL) {
891		RADIUS_ERROR("Could not open client file '%s'", client_file);
892		return NULL;
893	}
894
895	buf = os_malloc(buf_size);
896	if (buf == NULL) {
897		fclose(f);
898		return NULL;
899	}
900
901	clients = tail = NULL;
902	while (fgets(buf, buf_size, f)) {
903		/* Configuration file format:
904		 * 192.168.1.0/24 secret
905		 * 192.168.1.2 secret
906		 * fe80::211:22ff:fe33:4455/64 secretipv6
907		 */
908		line++;
909		buf[buf_size - 1] = '\0';
910		pos = buf;
911		while (*pos != '\0' && *pos != '\n')
912			pos++;
913		if (*pos == '\n')
914			*pos = '\0';
915		if (*buf == '\0' || *buf == '#')
916			continue;
917
918		pos = buf;
919		while ((*pos >= '0' && *pos <= '9') || *pos == '.' ||
920		       (*pos >= 'a' && *pos <= 'f') || *pos == ':' ||
921		       (*pos >= 'A' && *pos <= 'F')) {
922			pos++;
923		}
924
925		if (*pos == '\0') {
926			failed = 1;
927			break;
928		}
929
930		if (*pos == '/') {
931			char *end;
932			*pos++ = '\0';
933			mask = strtol(pos, &end, 10);
934			if ((pos == end) ||
935			    (mask < 0 || mask > (ipv6 ? 128 : 32))) {
936				failed = 1;
937				break;
938			}
939			pos = end;
940		} else {
941			mask = ipv6 ? 128 : 32;
942			*pos++ = '\0';
943		}
944
945		if (!ipv6 && inet_aton(buf, &addr) == 0) {
946			failed = 1;
947			break;
948		}
949#ifdef CONFIG_IPV6
950		if (ipv6 && inet_pton(AF_INET6, buf, &addr6) <= 0) {
951			if (inet_pton(AF_INET, buf, &addr) <= 0) {
952				failed = 1;
953				break;
954			}
955			/* Convert IPv4 address to IPv6 */
956			if (mask <= 32)
957				mask += (128 - 32);
958			os_memset(addr6.s6_addr, 0, 10);
959			addr6.s6_addr[10] = 0xff;
960			addr6.s6_addr[11] = 0xff;
961			os_memcpy(addr6.s6_addr + 12, (char *) &addr.s_addr,
962				  4);
963		}
964#endif /* CONFIG_IPV6 */
965
966		while (*pos == ' ' || *pos == '\t') {
967			pos++;
968		}
969
970		if (*pos == '\0') {
971			failed = 1;
972			break;
973		}
974
975		entry = os_zalloc(sizeof(*entry));
976		if (entry == NULL) {
977			failed = 1;
978			break;
979		}
980		entry->shared_secret = os_strdup(pos);
981		if (entry->shared_secret == NULL) {
982			failed = 1;
983			os_free(entry);
984			break;
985		}
986		entry->shared_secret_len = os_strlen(entry->shared_secret);
987		entry->addr.s_addr = addr.s_addr;
988		if (!ipv6) {
989			val = 0;
990			for (i = 0; i < mask; i++)
991				val |= 1 << (31 - i);
992			entry->mask.s_addr = htonl(val);
993		}
994#ifdef CONFIG_IPV6
995		if (ipv6) {
996			int offset = mask / 8;
997
998			os_memcpy(entry->addr6.s6_addr, addr6.s6_addr, 16);
999			os_memset(entry->mask6.s6_addr, 0xff, offset);
1000			val = 0;
1001			for (i = 0; i < (mask % 8); i++)
1002				val |= 1 << (7 - i);
1003			if (offset < 16)
1004				entry->mask6.s6_addr[offset] = val;
1005		}
1006#endif /* CONFIG_IPV6 */
1007
1008		if (tail == NULL) {
1009			clients = tail = entry;
1010		} else {
1011			tail->next = entry;
1012			tail = entry;
1013		}
1014	}
1015
1016	if (failed) {
1017		RADIUS_ERROR("Invalid line %d in '%s'", line, client_file);
1018		radius_server_free_clients(NULL, clients);
1019		clients = NULL;
1020	}
1021
1022	os_free(buf);
1023	fclose(f);
1024
1025	return clients;
1026}
1027
1028
1029struct radius_server_data *
1030radius_server_init(struct radius_server_conf *conf)
1031{
1032	struct radius_server_data *data;
1033
1034#ifndef CONFIG_IPV6
1035	if (conf->ipv6) {
1036		fprintf(stderr, "RADIUS server compiled without IPv6 "
1037			"support.\n");
1038		return NULL;
1039	}
1040#endif /* CONFIG_IPV6 */
1041
1042	data = os_zalloc(sizeof(*data));
1043	if (data == NULL)
1044		return NULL;
1045
1046	os_get_time(&data->start_time);
1047	data->conf_ctx = conf->conf_ctx;
1048	data->eap_sim_db_priv = conf->eap_sim_db_priv;
1049	data->ssl_ctx = conf->ssl_ctx;
1050	data->ipv6 = conf->ipv6;
1051	if (conf->pac_opaque_encr_key) {
1052		data->pac_opaque_encr_key = os_malloc(16);
1053		os_memcpy(data->pac_opaque_encr_key, conf->pac_opaque_encr_key,
1054			  16);
1055	}
1056	if (conf->eap_fast_a_id) {
1057		data->eap_fast_a_id = os_malloc(conf->eap_fast_a_id_len);
1058		if (data->eap_fast_a_id) {
1059			os_memcpy(data->eap_fast_a_id, conf->eap_fast_a_id,
1060				  conf->eap_fast_a_id_len);
1061			data->eap_fast_a_id_len = conf->eap_fast_a_id_len;
1062		}
1063	}
1064	if (conf->eap_fast_a_id_info)
1065		data->eap_fast_a_id_info = os_strdup(conf->eap_fast_a_id_info);
1066	data->eap_fast_prov = conf->eap_fast_prov;
1067	data->pac_key_lifetime = conf->pac_key_lifetime;
1068	data->pac_key_refresh_time = conf->pac_key_refresh_time;
1069	data->get_eap_user = conf->get_eap_user;
1070	data->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;
1071	data->tnc = conf->tnc;
1072	data->wps = conf->wps;
1073	if (conf->eap_req_id_text) {
1074		data->eap_req_id_text = os_malloc(conf->eap_req_id_text_len);
1075		if (data->eap_req_id_text) {
1076			os_memcpy(data->eap_req_id_text, conf->eap_req_id_text,
1077				  conf->eap_req_id_text_len);
1078			data->eap_req_id_text_len = conf->eap_req_id_text_len;
1079		}
1080	}
1081
1082	data->clients = radius_server_read_clients(conf->client_file,
1083						   conf->ipv6);
1084	if (data->clients == NULL) {
1085		printf("No RADIUS clients configured.\n");
1086		radius_server_deinit(data);
1087		return NULL;
1088	}
1089
1090#ifdef CONFIG_IPV6
1091	if (conf->ipv6)
1092		data->auth_sock = radius_server_open_socket6(conf->auth_port);
1093	else
1094#endif /* CONFIG_IPV6 */
1095	data->auth_sock = radius_server_open_socket(conf->auth_port);
1096	if (data->auth_sock < 0) {
1097		printf("Failed to open UDP socket for RADIUS authentication "
1098		       "server\n");
1099		radius_server_deinit(data);
1100		return NULL;
1101	}
1102	if (eloop_register_read_sock(data->auth_sock,
1103				     radius_server_receive_auth,
1104				     data, NULL)) {
1105		radius_server_deinit(data);
1106		return NULL;
1107	}
1108
1109	return data;
1110}
1111
1112
1113void radius_server_deinit(struct radius_server_data *data)
1114{
1115	if (data == NULL)
1116		return;
1117
1118	if (data->auth_sock >= 0) {
1119		eloop_unregister_read_sock(data->auth_sock);
1120		close(data->auth_sock);
1121	}
1122
1123	radius_server_free_clients(data, data->clients);
1124
1125	os_free(data->pac_opaque_encr_key);
1126	os_free(data->eap_fast_a_id);
1127	os_free(data->eap_fast_a_id_info);
1128	os_free(data->eap_req_id_text);
1129	os_free(data);
1130}
1131
1132
1133int radius_server_get_mib(struct radius_server_data *data, char *buf,
1134			  size_t buflen)
1135{
1136	int ret, uptime;
1137	unsigned int idx;
1138	char *end, *pos;
1139	struct os_time now;
1140	struct radius_client *cli;
1141
1142	/* RFC 2619 - RADIUS Authentication Server MIB */
1143
1144	if (data == NULL || buflen == 0)
1145		return 0;
1146
1147	pos = buf;
1148	end = buf + buflen;
1149
1150	os_get_time(&now);
1151	uptime = (now.sec - data->start_time.sec) * 100 +
1152		((now.usec - data->start_time.usec) / 10000) % 100;
1153	ret = os_snprintf(pos, end - pos,
1154			  "RADIUS-AUTH-SERVER-MIB\n"
1155			  "radiusAuthServIdent=hostapd\n"
1156			  "radiusAuthServUpTime=%d\n"
1157			  "radiusAuthServResetTime=0\n"
1158			  "radiusAuthServConfigReset=4\n",
1159			  uptime);
1160	if (ret < 0 || ret >= end - pos) {
1161		*pos = '\0';
1162		return pos - buf;
1163	}
1164	pos += ret;
1165
1166	ret = os_snprintf(pos, end - pos,
1167			  "radiusAuthServTotalAccessRequests=%u\n"
1168			  "radiusAuthServTotalInvalidRequests=%u\n"
1169			  "radiusAuthServTotalDupAccessRequests=%u\n"
1170			  "radiusAuthServTotalAccessAccepts=%u\n"
1171			  "radiusAuthServTotalAccessRejects=%u\n"
1172			  "radiusAuthServTotalAccessChallenges=%u\n"
1173			  "radiusAuthServTotalMalformedAccessRequests=%u\n"
1174			  "radiusAuthServTotalBadAuthenticators=%u\n"
1175			  "radiusAuthServTotalPacketsDropped=%u\n"
1176			  "radiusAuthServTotalUnknownTypes=%u\n",
1177			  data->counters.access_requests,
1178			  data->counters.invalid_requests,
1179			  data->counters.dup_access_requests,
1180			  data->counters.access_accepts,
1181			  data->counters.access_rejects,
1182			  data->counters.access_challenges,
1183			  data->counters.malformed_access_requests,
1184			  data->counters.bad_authenticators,
1185			  data->counters.packets_dropped,
1186			  data->counters.unknown_types);
1187	if (ret < 0 || ret >= end - pos) {
1188		*pos = '\0';
1189		return pos - buf;
1190	}
1191	pos += ret;
1192
1193	for (cli = data->clients, idx = 0; cli; cli = cli->next, idx++) {
1194		char abuf[50], mbuf[50];
1195#ifdef CONFIG_IPV6
1196		if (data->ipv6) {
1197			if (inet_ntop(AF_INET6, &cli->addr6, abuf,
1198				      sizeof(abuf)) == NULL)
1199				abuf[0] = '\0';
1200			if (inet_ntop(AF_INET6, &cli->mask6, abuf,
1201				      sizeof(mbuf)) == NULL)
1202				mbuf[0] = '\0';
1203		}
1204#endif /* CONFIG_IPV6 */
1205		if (!data->ipv6) {
1206			os_strlcpy(abuf, inet_ntoa(cli->addr), sizeof(abuf));
1207			os_strlcpy(mbuf, inet_ntoa(cli->mask), sizeof(mbuf));
1208		}
1209
1210		ret = os_snprintf(pos, end - pos,
1211				  "radiusAuthClientIndex=%u\n"
1212				  "radiusAuthClientAddress=%s/%s\n"
1213				  "radiusAuthServAccessRequests=%u\n"
1214				  "radiusAuthServDupAccessRequests=%u\n"
1215				  "radiusAuthServAccessAccepts=%u\n"
1216				  "radiusAuthServAccessRejects=%u\n"
1217				  "radiusAuthServAccessChallenges=%u\n"
1218				  "radiusAuthServMalformedAccessRequests=%u\n"
1219				  "radiusAuthServBadAuthenticators=%u\n"
1220				  "radiusAuthServPacketsDropped=%u\n"
1221				  "radiusAuthServUnknownTypes=%u\n",
1222				  idx,
1223				  abuf, mbuf,
1224				  cli->counters.access_requests,
1225				  cli->counters.dup_access_requests,
1226				  cli->counters.access_accepts,
1227				  cli->counters.access_rejects,
1228				  cli->counters.access_challenges,
1229				  cli->counters.malformed_access_requests,
1230				  cli->counters.bad_authenticators,
1231				  cli->counters.packets_dropped,
1232				  cli->counters.unknown_types);
1233		if (ret < 0 || ret >= end - pos) {
1234			*pos = '\0';
1235			return pos - buf;
1236		}
1237		pos += ret;
1238	}
1239
1240	return pos - buf;
1241}
1242
1243
1244static int radius_server_get_eap_user(void *ctx, const u8 *identity,
1245				      size_t identity_len, int phase2,
1246				      struct eap_user *user)
1247{
1248	struct radius_session *sess = ctx;
1249	struct radius_server_data *data = sess->server;
1250
1251	return data->get_eap_user(data->conf_ctx, identity, identity_len,
1252				  phase2, user);
1253}
1254
1255
1256static const char * radius_server_get_eap_req_id_text(void *ctx, size_t *len)
1257{
1258	struct radius_session *sess = ctx;
1259	struct radius_server_data *data = sess->server;
1260	*len = data->eap_req_id_text_len;
1261	return data->eap_req_id_text;
1262}
1263
1264
1265static struct eapol_callbacks radius_server_eapol_cb =
1266{
1267	.get_eap_user = radius_server_get_eap_user,
1268	.get_eap_req_id_text = radius_server_get_eap_req_id_text,
1269};
1270
1271
1272void radius_server_eap_pending_cb(struct radius_server_data *data, void *ctx)
1273{
1274	struct radius_client *cli;
1275	struct radius_session *s, *sess = NULL;
1276	struct radius_msg *msg;
1277
1278	if (data == NULL)
1279		return;
1280
1281	for (cli = data->clients; cli; cli = cli->next) {
1282		for (s = cli->sessions; s; s = s->next) {
1283			if (s->eap == ctx && s->last_msg) {
1284				sess = s;
1285				break;
1286			}
1287			if (sess)
1288				break;
1289		}
1290		if (sess)
1291			break;
1292	}
1293
1294	if (sess == NULL) {
1295		RADIUS_DEBUG("No session matched callback ctx");
1296		return;
1297	}
1298
1299	msg = sess->last_msg;
1300	sess->last_msg = NULL;
1301	eap_sm_pending_cb(sess->eap);
1302	if (radius_server_request(data, msg,
1303				  (struct sockaddr *) &sess->last_from,
1304				  sess->last_fromlen, cli,
1305				  sess->last_from_addr,
1306				  sess->last_from_port, sess) == -2)
1307		return; /* msg was stored with the session */
1308
1309	radius_msg_free(msg);
1310	os_free(msg);
1311}
1312