• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
29 static struct eapol_callbacks radius_server_eapol_cb;
30 
31 struct radius_client;
32 struct radius_server_data;
33 
34 struct 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 
47 struct 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 
65 struct 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 
79 struct 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 
107 extern int wpa_debug_level;
108 
109 #define RADIUS_DEBUG(args...) \
110 wpa_printf(MSG_DEBUG, "RADIUS SRV: " args)
111 #define RADIUS_ERROR(args...) \
112 wpa_printf(MSG_ERROR, "RADIUS SRV: " args)
113 #define RADIUS_DUMP(args...) \
114 wpa_hexdump(MSG_MSGDUMP, "RADIUS SRV: " args)
115 #define RADIUS_DUMP_ASCII(args...) \
116 wpa_hexdump_ascii(MSG_MSGDUMP, "RADIUS SRV: " args)
117 
118 
119 static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx);
120 static void radius_server_session_remove_timeout(void *eloop_ctx,
121 						 void *timeout_ctx);
122 
123 
124 static struct radius_client *
radius_server_get_client(struct radius_server_data * data,struct in_addr * addr,int ipv6)125 radius_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 
163 static struct radius_session *
radius_server_get_session(struct radius_client * client,unsigned int sess_id)164 radius_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 
radius_server_session_free(struct radius_server_data * data,struct radius_session * sess)179 static 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 
radius_server_session_remove(struct radius_server_data * data,struct radius_session * sess)199 static 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 
radius_server_session_remove_timeout(void * eloop_ctx,void * timeout_ctx)225 static 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 
radius_server_session_timeout(void * eloop_ctx,void * timeout_ctx)235 static 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 
245 static struct radius_session *
radius_server_new_session(struct radius_server_data * data,struct radius_client * client)246 radius_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 
273 static struct radius_session *
radius_server_get_new_session(struct radius_server_data * data,struct radius_client * client,struct radius_msg * msg)274 radius_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 
347 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)348 radius_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 
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)421 static 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 
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)481 static 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 
radius_server_receive_auth(int sock,void * eloop_ctx,void * sock_ctx)664 static 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 
766 fail:
767 	if (msg) {
768 		radius_msg_free(msg);
769 		os_free(msg);
770 	}
771 	os_free(buf);
772 }
773 
774 
radius_server_disable_pmtu_discovery(int s)775 static 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 
radius_server_open_socket(int port)791 static 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
radius_server_open_socket6(int port)818 static 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 
radius_server_free_sessions(struct radius_server_data * data,struct radius_session * sessions)844 static 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 
radius_server_free_clients(struct radius_server_data * data,struct radius_client * clients)858 static 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 
875 static struct radius_client *
radius_server_read_clients(const char * client_file,int ipv6)876 radius_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 
1029 struct radius_server_data *
radius_server_init(struct radius_server_conf * conf)1030 radius_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 
radius_server_deinit(struct radius_server_data * data)1113 void 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 
radius_server_get_mib(struct radius_server_data * data,char * buf,size_t buflen)1133 int 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 
radius_server_get_eap_user(void * ctx,const u8 * identity,size_t identity_len,int phase2,struct eap_user * user)1244 static 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 
radius_server_get_eap_req_id_text(void * ctx,size_t * len)1256 static 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 
1265 static 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 
radius_server_eap_pending_cb(struct radius_server_data * data,void * ctx)1272 void 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