Home | History | Annotate | Download | only in radius
      1 /*
      2  * RADIUS authentication server
      3  * Copyright (c) 2005-2009, Jouni Malinen <j (at) 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 "eap_server/eap.h"
     22 #include "radius_server.h"
     23 
     24 /**
     25  * RADIUS_SESSION_TIMEOUT - Session timeout in seconds
     26  */
     27 #define RADIUS_SESSION_TIMEOUT 60
     28 
     29 /**
     30  * RADIUS_MAX_SESSION - Maximum number of active sessions
     31  */
     32 #define RADIUS_MAX_SESSION 100
     33 
     34 /**
     35  * RADIUS_MAX_MSG_LEN - Maximum message length for incoming RADIUS messages
     36  */
     37 #define RADIUS_MAX_MSG_LEN 3000
     38 
     39 static struct eapol_callbacks radius_server_eapol_cb;
     40 
     41 struct radius_client;
     42 struct radius_server_data;
     43 
     44 /**
     45  * struct radius_server_counters - RADIUS server statistics counters
     46  */
     47 struct radius_server_counters {
     48 	u32 access_requests;
     49 	u32 invalid_requests;
     50 	u32 dup_access_requests;
     51 	u32 access_accepts;
     52 	u32 access_rejects;
     53 	u32 access_challenges;
     54 	u32 malformed_access_requests;
     55 	u32 bad_authenticators;
     56 	u32 packets_dropped;
     57 	u32 unknown_types;
     58 };
     59 
     60 /**
     61  * struct radius_session - Internal RADIUS server data for a session
     62  */
     63 struct radius_session {
     64 	struct radius_session *next;
     65 	struct radius_client *client;
     66 	struct radius_server_data *server;
     67 	unsigned int sess_id;
     68 	struct eap_sm *eap;
     69 	struct eap_eapol_interface *eap_if;
     70 
     71 	struct radius_msg *last_msg;
     72 	char *last_from_addr;
     73 	int last_from_port;
     74 	struct sockaddr_storage last_from;
     75 	socklen_t last_fromlen;
     76 	u8 last_identifier;
     77 	struct radius_msg *last_reply;
     78 	u8 last_authenticator[16];
     79 };
     80 
     81 /**
     82  * struct radius_client - Internal RADIUS server data for a client
     83  */
     84 struct radius_client {
     85 	struct radius_client *next;
     86 	struct in_addr addr;
     87 	struct in_addr mask;
     88 #ifdef CONFIG_IPV6
     89 	struct in6_addr addr6;
     90 	struct in6_addr mask6;
     91 #endif /* CONFIG_IPV6 */
     92 	char *shared_secret;
     93 	int shared_secret_len;
     94 	struct radius_session *sessions;
     95 	struct radius_server_counters counters;
     96 };
     97 
     98 /**
     99  * struct radius_server_data - Internal RADIUS server data
    100  */
    101 struct radius_server_data {
    102 	/**
    103 	 * auth_sock - Socket for RADIUS authentication messages
    104 	 */
    105 	int auth_sock;
    106 
    107 	/**
    108 	 * clients - List of authorized RADIUS clients
    109 	 */
    110 	struct radius_client *clients;
    111 
    112 	/**
    113 	 * next_sess_id - Next session identifier
    114 	 */
    115 	unsigned int next_sess_id;
    116 
    117 	/**
    118 	 * conf_ctx - Context pointer for callbacks
    119 	 *
    120 	 * This is used as the ctx argument in get_eap_user() calls.
    121 	 */
    122 	void *conf_ctx;
    123 
    124 	/**
    125 	 * num_sess - Number of active sessions
    126 	 */
    127 	int num_sess;
    128 
    129 	/**
    130 	 * eap_sim_db_priv - EAP-SIM/AKA database context
    131 	 *
    132 	 * This is passed to the EAP-SIM/AKA server implementation as a
    133 	 * callback context.
    134 	 */
    135 	void *eap_sim_db_priv;
    136 
    137 	/**
    138 	 * ssl_ctx - TLS context
    139 	 *
    140 	 * This is passed to the EAP server implementation as a callback
    141 	 * context for TLS operations.
    142 	 */
    143 	void *ssl_ctx;
    144 
    145 	/**
    146 	 * pac_opaque_encr_key - PAC-Opaque encryption key for EAP-FAST
    147 	 *
    148 	 * This parameter is used to set a key for EAP-FAST to encrypt the
    149 	 * PAC-Opaque data. It can be set to %NULL if EAP-FAST is not used. If
    150 	 * set, must point to a 16-octet key.
    151 	 */
    152 	u8 *pac_opaque_encr_key;
    153 
    154 	/**
    155 	 * eap_fast_a_id - EAP-FAST authority identity (A-ID)
    156 	 *
    157 	 * If EAP-FAST is not used, this can be set to %NULL. In theory, this
    158 	 * is a variable length field, but due to some existing implementations
    159 	 * requiring A-ID to be 16 octets in length, it is recommended to use
    160 	 * that length for the field to provide interoperability with deployed
    161 	 * peer implementations.
    162 	 */
    163 	u8 *eap_fast_a_id;
    164 
    165 	/**
    166 	 * eap_fast_a_id_len - Length of eap_fast_a_id buffer in octets
    167 	 */
    168 	size_t eap_fast_a_id_len;
    169 
    170 	/**
    171 	 * eap_fast_a_id_info - EAP-FAST authority identifier information
    172 	 *
    173 	 * This A-ID-Info contains a user-friendly name for the A-ID. For
    174 	 * example, this could be the enterprise and server names in
    175 	 * human-readable format. This field is encoded as UTF-8. If EAP-FAST
    176 	 * is not used, this can be set to %NULL.
    177 	 */
    178 	char *eap_fast_a_id_info;
    179 
    180 	/**
    181 	 * eap_fast_prov - EAP-FAST provisioning modes
    182 	 *
    183 	 * 0 = provisioning disabled, 1 = only anonymous provisioning allowed,
    184 	 * 2 = only authenticated provisioning allowed, 3 = both provisioning
    185 	 * modes allowed.
    186 	 */
    187 	int eap_fast_prov;
    188 
    189 	/**
    190 	 * pac_key_lifetime - EAP-FAST PAC-Key lifetime in seconds
    191 	 *
    192 	 * This is the hard limit on how long a provisioned PAC-Key can be
    193 	 * used.
    194 	 */
    195 	int pac_key_lifetime;
    196 
    197 	/**
    198 	 * pac_key_refresh_time - EAP-FAST PAC-Key refresh time in seconds
    199 	 *
    200 	 * This is a soft limit on the PAC-Key. The server will automatically
    201 	 * generate a new PAC-Key when this number of seconds (or fewer) of the
    202 	 * lifetime remains.
    203 	 */
    204 	int pac_key_refresh_time;
    205 
    206 	/**
    207 	 * eap_sim_aka_result_ind - EAP-SIM/AKA protected success indication
    208 	 *
    209 	 * This controls whether the protected success/failure indication
    210 	 * (AT_RESULT_IND) is used with EAP-SIM and EAP-AKA.
    211 	 */
    212 	int eap_sim_aka_result_ind;
    213 
    214 	/**
    215 	 * tnc - Trusted Network Connect (TNC)
    216 	 *
    217 	 * This controls whether TNC is enabled and will be required before the
    218 	 * peer is allowed to connect. Note: This is only used with EAP-TTLS
    219 	 * and EAP-FAST. If any other EAP method is enabled, the peer will be
    220 	 * allowed to connect without TNC.
    221 	 */
    222 	int tnc;
    223 
    224 	/**
    225 	 * pwd_group - The D-H group assigned for EAP-pwd
    226 	 *
    227 	 * If EAP-pwd is not used it can be set to zero.
    228 	 */
    229 	u16 pwd_group;
    230 
    231 	/**
    232 	 * wps - Wi-Fi Protected Setup context
    233 	 *
    234 	 * If WPS is used with an external RADIUS server (which is quite
    235 	 * unlikely configuration), this is used to provide a pointer to WPS
    236 	 * context data. Normally, this can be set to %NULL.
    237 	 */
    238 	struct wps_context *wps;
    239 
    240 	/**
    241 	 * ipv6 - Whether to enable IPv6 support in the RADIUS server
    242 	 */
    243 	int ipv6;
    244 
    245 	/**
    246 	 * start_time - Timestamp of server start
    247 	 */
    248 	struct os_time start_time;
    249 
    250 	/**
    251 	 * counters - Statistics counters for server operations
    252 	 *
    253 	 * These counters are the sum over all clients.
    254 	 */
    255 	struct radius_server_counters counters;
    256 
    257 	/**
    258 	 * get_eap_user - Callback for fetching EAP user information
    259 	 * @ctx: Context data from conf_ctx
    260 	 * @identity: User identity
    261 	 * @identity_len: identity buffer length in octets
    262 	 * @phase2: Whether this is for Phase 2 identity
    263 	 * @user: Data structure for filling in the user information
    264 	 * Returns: 0 on success, -1 on failure
    265 	 *
    266 	 * This is used to fetch information from user database. The callback
    267 	 * will fill in information about allowed EAP methods and the user
    268 	 * password. The password field will be an allocated copy of the
    269 	 * password data and RADIUS server will free it after use.
    270 	 */
    271 	int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len,
    272 			    int phase2, struct eap_user *user);
    273 
    274 	/**
    275 	 * eap_req_id_text - Optional data for EAP-Request/Identity
    276 	 *
    277 	 * This can be used to configure an optional, displayable message that
    278 	 * will be sent in EAP-Request/Identity. This string can contain an
    279 	 * ASCII-0 character (nul) to separate network infromation per RFC
    280 	 * 4284. The actual string length is explicit provided in
    281 	 * eap_req_id_text_len since nul character will not be used as a string
    282 	 * terminator.
    283 	 */
    284 	char *eap_req_id_text;
    285 
    286 	/**
    287 	 * eap_req_id_text_len - Length of eap_req_id_text buffer in octets
    288 	 */
    289 	size_t eap_req_id_text_len;
    290 
    291 	/*
    292 	 * msg_ctx - Context data for wpa_msg() calls
    293 	 */
    294 	void *msg_ctx;
    295 };
    296 
    297 
    298 extern int wpa_debug_level;
    299 
    300 #define RADIUS_DEBUG(args...) \
    301 wpa_printf(MSG_DEBUG, "RADIUS SRV: " args)
    302 #define RADIUS_ERROR(args...) \
    303 wpa_printf(MSG_ERROR, "RADIUS SRV: " args)
    304 #define RADIUS_DUMP(args...) \
    305 wpa_hexdump(MSG_MSGDUMP, "RADIUS SRV: " args)
    306 #define RADIUS_DUMP_ASCII(args...) \
    307 wpa_hexdump_ascii(MSG_MSGDUMP, "RADIUS SRV: " args)
    308 
    309 
    310 static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx);
    311 static void radius_server_session_remove_timeout(void *eloop_ctx,
    312 						 void *timeout_ctx);
    313 
    314 
    315 static struct radius_client *
    316 radius_server_get_client(struct radius_server_data *data, struct in_addr *addr,
    317 			 int ipv6)
    318 {
    319 	struct radius_client *client = data->clients;
    320 
    321 	while (client) {
    322 #ifdef CONFIG_IPV6
    323 		if (ipv6) {
    324 			struct in6_addr *addr6;
    325 			int i;
    326 
    327 			addr6 = (struct in6_addr *) addr;
    328 			for (i = 0; i < 16; i++) {
    329 				if ((addr6->s6_addr[i] &
    330 				     client->mask6.s6_addr[i]) !=
    331 				    (client->addr6.s6_addr[i] &
    332 				     client->mask6.s6_addr[i])) {
    333 					i = 17;
    334 					break;
    335 				}
    336 			}
    337 			if (i == 16) {
    338 				break;
    339 			}
    340 		}
    341 #endif /* CONFIG_IPV6 */
    342 		if (!ipv6 && (client->addr.s_addr & client->mask.s_addr) ==
    343 		    (addr->s_addr & client->mask.s_addr)) {
    344 			break;
    345 		}
    346 
    347 		client = client->next;
    348 	}
    349 
    350 	return client;
    351 }
    352 
    353 
    354 static struct radius_session *
    355 radius_server_get_session(struct radius_client *client, unsigned int sess_id)
    356 {
    357 	struct radius_session *sess = client->sessions;
    358 
    359 	while (sess) {
    360 		if (sess->sess_id == sess_id) {
    361 			break;
    362 		}
    363 		sess = sess->next;
    364 	}
    365 
    366 	return sess;
    367 }
    368 
    369 
    370 static void radius_server_session_free(struct radius_server_data *data,
    371 				       struct radius_session *sess)
    372 {
    373 	eloop_cancel_timeout(radius_server_session_timeout, data, sess);
    374 	eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess);
    375 	eap_server_sm_deinit(sess->eap);
    376 	radius_msg_free(sess->last_msg);
    377 	os_free(sess->last_from_addr);
    378 	radius_msg_free(sess->last_reply);
    379 	os_free(sess);
    380 	data->num_sess--;
    381 }
    382 
    383 
    384 static void radius_server_session_remove(struct radius_server_data *data,
    385 					 struct radius_session *sess)
    386 {
    387 	struct radius_client *client = sess->client;
    388 	struct radius_session *session, *prev;
    389 
    390 	eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess);
    391 
    392 	prev = NULL;
    393 	session = client->sessions;
    394 	while (session) {
    395 		if (session == sess) {
    396 			if (prev == NULL) {
    397 				client->sessions = sess->next;
    398 			} else {
    399 				prev->next = sess->next;
    400 			}
    401 			radius_server_session_free(data, sess);
    402 			break;
    403 		}
    404 		prev = session;
    405 		session = session->next;
    406 	}
    407 }
    408 
    409 
    410 static void radius_server_session_remove_timeout(void *eloop_ctx,
    411 						 void *timeout_ctx)
    412 {
    413 	struct radius_server_data *data = eloop_ctx;
    414 	struct radius_session *sess = timeout_ctx;
    415 	RADIUS_DEBUG("Removing completed session 0x%x", sess->sess_id);
    416 	radius_server_session_remove(data, sess);
    417 }
    418 
    419 
    420 static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx)
    421 {
    422 	struct radius_server_data *data = eloop_ctx;
    423 	struct radius_session *sess = timeout_ctx;
    424 
    425 	RADIUS_DEBUG("Timing out authentication session 0x%x", sess->sess_id);
    426 	radius_server_session_remove(data, sess);
    427 }
    428 
    429 
    430 static struct radius_session *
    431 radius_server_new_session(struct radius_server_data *data,
    432 			  struct radius_client *client)
    433 {
    434 	struct radius_session *sess;
    435 
    436 	if (data->num_sess >= RADIUS_MAX_SESSION) {
    437 		RADIUS_DEBUG("Maximum number of existing session - no room "
    438 			     "for a new session");
    439 		return NULL;
    440 	}
    441 
    442 	sess = os_zalloc(sizeof(*sess));
    443 	if (sess == NULL)
    444 		return NULL;
    445 
    446 	sess->server = data;
    447 	sess->client = client;
    448 	sess->sess_id = data->next_sess_id++;
    449 	sess->next = client->sessions;
    450 	client->sessions = sess;
    451 	eloop_register_timeout(RADIUS_SESSION_TIMEOUT, 0,
    452 			       radius_server_session_timeout, data, sess);
    453 	data->num_sess++;
    454 	return sess;
    455 }
    456 
    457 
    458 static struct radius_session *
    459 radius_server_get_new_session(struct radius_server_data *data,
    460 			      struct radius_client *client,
    461 			      struct radius_msg *msg)
    462 {
    463 	u8 *user;
    464 	size_t user_len;
    465 	int res;
    466 	struct radius_session *sess;
    467 	struct eap_config eap_conf;
    468 
    469 	RADIUS_DEBUG("Creating a new session");
    470 
    471 	user = os_malloc(256);
    472 	if (user == NULL) {
    473 		return NULL;
    474 	}
    475 	res = radius_msg_get_attr(msg, RADIUS_ATTR_USER_NAME, user, 256);
    476 	if (res < 0 || res > 256) {
    477 		RADIUS_DEBUG("Could not get User-Name");
    478 		os_free(user);
    479 		return NULL;
    480 	}
    481 	user_len = res;
    482 	RADIUS_DUMP_ASCII("User-Name", user, user_len);
    483 
    484 	res = data->get_eap_user(data->conf_ctx, user, user_len, 0, NULL);
    485 	os_free(user);
    486 
    487 	if (res == 0) {
    488 		RADIUS_DEBUG("Matching user entry found");
    489 		sess = radius_server_new_session(data, client);
    490 		if (sess == NULL) {
    491 			RADIUS_DEBUG("Failed to create a new session");
    492 			return NULL;
    493 		}
    494 	} else {
    495 		RADIUS_DEBUG("User-Name not found from user database");
    496 		return NULL;
    497 	}
    498 
    499 	os_memset(&eap_conf, 0, sizeof(eap_conf));
    500 	eap_conf.ssl_ctx = data->ssl_ctx;
    501 	eap_conf.msg_ctx = data->msg_ctx;
    502 	eap_conf.eap_sim_db_priv = data->eap_sim_db_priv;
    503 	eap_conf.backend_auth = TRUE;
    504 	eap_conf.eap_server = 1;
    505 	eap_conf.pac_opaque_encr_key = data->pac_opaque_encr_key;
    506 	eap_conf.eap_fast_a_id = data->eap_fast_a_id;
    507 	eap_conf.eap_fast_a_id_len = data->eap_fast_a_id_len;
    508 	eap_conf.eap_fast_a_id_info = data->eap_fast_a_id_info;
    509 	eap_conf.eap_fast_prov = data->eap_fast_prov;
    510 	eap_conf.pac_key_lifetime = data->pac_key_lifetime;
    511 	eap_conf.pac_key_refresh_time = data->pac_key_refresh_time;
    512 	eap_conf.eap_sim_aka_result_ind = data->eap_sim_aka_result_ind;
    513 	eap_conf.tnc = data->tnc;
    514 	eap_conf.wps = data->wps;
    515 	eap_conf.pwd_group = data->pwd_group;
    516 	sess->eap = eap_server_sm_init(sess, &radius_server_eapol_cb,
    517 				       &eap_conf);
    518 	if (sess->eap == NULL) {
    519 		RADIUS_DEBUG("Failed to initialize EAP state machine for the "
    520 			     "new session");
    521 		radius_server_session_free(data, sess);
    522 		return NULL;
    523 	}
    524 	sess->eap_if = eap_get_interface(sess->eap);
    525 	sess->eap_if->eapRestart = TRUE;
    526 	sess->eap_if->portEnabled = TRUE;
    527 
    528 	RADIUS_DEBUG("New session 0x%x initialized", sess->sess_id);
    529 
    530 	return sess;
    531 }
    532 
    533 
    534 static struct radius_msg *
    535 radius_server_encapsulate_eap(struct radius_server_data *data,
    536 			      struct radius_client *client,
    537 			      struct radius_session *sess,
    538 			      struct radius_msg *request)
    539 {
    540 	struct radius_msg *msg;
    541 	int code;
    542 	unsigned int sess_id;
    543 	struct radius_hdr *hdr = radius_msg_get_hdr(request);
    544 
    545 	if (sess->eap_if->eapFail) {
    546 		sess->eap_if->eapFail = FALSE;
    547 		code = RADIUS_CODE_ACCESS_REJECT;
    548 	} else if (sess->eap_if->eapSuccess) {
    549 		sess->eap_if->eapSuccess = FALSE;
    550 		code = RADIUS_CODE_ACCESS_ACCEPT;
    551 	} else {
    552 		sess->eap_if->eapReq = FALSE;
    553 		code = RADIUS_CODE_ACCESS_CHALLENGE;
    554 	}
    555 
    556 	msg = radius_msg_new(code, hdr->identifier);
    557 	if (msg == NULL) {
    558 		RADIUS_DEBUG("Failed to allocate reply message");
    559 		return NULL;
    560 	}
    561 
    562 	sess_id = htonl(sess->sess_id);
    563 	if (code == RADIUS_CODE_ACCESS_CHALLENGE &&
    564 	    !radius_msg_add_attr(msg, RADIUS_ATTR_STATE,
    565 				 (u8 *) &sess_id, sizeof(sess_id))) {
    566 		RADIUS_DEBUG("Failed to add State attribute");
    567 	}
    568 
    569 	if (sess->eap_if->eapReqData &&
    570 	    !radius_msg_add_eap(msg, wpabuf_head(sess->eap_if->eapReqData),
    571 				wpabuf_len(sess->eap_if->eapReqData))) {
    572 		RADIUS_DEBUG("Failed to add EAP-Message attribute");
    573 	}
    574 
    575 	if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->eap_if->eapKeyData) {
    576 		int len;
    577 		if (sess->eap_if->eapKeyDataLen > 64) {
    578 			len = 32;
    579 		} else {
    580 			len = sess->eap_if->eapKeyDataLen / 2;
    581 		}
    582 		if (!radius_msg_add_mppe_keys(msg, hdr->authenticator,
    583 					      (u8 *) client->shared_secret,
    584 					      client->shared_secret_len,
    585 					      sess->eap_if->eapKeyData + len,
    586 					      len, sess->eap_if->eapKeyData,
    587 					      len)) {
    588 			RADIUS_DEBUG("Failed to add MPPE key attributes");
    589 		}
    590 	}
    591 
    592 	if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) {
    593 		RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
    594 		radius_msg_free(msg);
    595 		return NULL;
    596 	}
    597 
    598 	if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
    599 				  client->shared_secret_len,
    600 				  hdr->authenticator) < 0) {
    601 		RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
    602 	}
    603 
    604 	return msg;
    605 }
    606 
    607 
    608 static int radius_server_reject(struct radius_server_data *data,
    609 				struct radius_client *client,
    610 				struct radius_msg *request,
    611 				struct sockaddr *from, socklen_t fromlen,
    612 				const char *from_addr, int from_port)
    613 {
    614 	struct radius_msg *msg;
    615 	int ret = 0;
    616 	struct eap_hdr eapfail;
    617 	struct wpabuf *buf;
    618 	struct radius_hdr *hdr = radius_msg_get_hdr(request);
    619 
    620 	RADIUS_DEBUG("Reject invalid request from %s:%d",
    621 		     from_addr, from_port);
    622 
    623 	msg = radius_msg_new(RADIUS_CODE_ACCESS_REJECT, hdr->identifier);
    624 	if (msg == NULL) {
    625 		return -1;
    626 	}
    627 
    628 	os_memset(&eapfail, 0, sizeof(eapfail));
    629 	eapfail.code = EAP_CODE_FAILURE;
    630 	eapfail.identifier = 0;
    631 	eapfail.length = host_to_be16(sizeof(eapfail));
    632 
    633 	if (!radius_msg_add_eap(msg, (u8 *) &eapfail, sizeof(eapfail))) {
    634 		RADIUS_DEBUG("Failed to add EAP-Message attribute");
    635 	}
    636 
    637 	if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) {
    638 		RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
    639 		radius_msg_free(msg);
    640 		return -1;
    641 	}
    642 
    643 	if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
    644 				  client->shared_secret_len,
    645 				  hdr->authenticator) <
    646 	    0) {
    647 		RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
    648 	}
    649 
    650 	if (wpa_debug_level <= MSG_MSGDUMP) {
    651 		radius_msg_dump(msg);
    652 	}
    653 
    654 	data->counters.access_rejects++;
    655 	client->counters.access_rejects++;
    656 	buf = radius_msg_get_buf(msg);
    657 	if (sendto(data->auth_sock, wpabuf_head(buf), wpabuf_len(buf), 0,
    658 		   (struct sockaddr *) from, sizeof(*from)) < 0) {
    659 		perror("sendto[RADIUS SRV]");
    660 		ret = -1;
    661 	}
    662 
    663 	radius_msg_free(msg);
    664 
    665 	return ret;
    666 }
    667 
    668 
    669 static int radius_server_request(struct radius_server_data *data,
    670 				 struct radius_msg *msg,
    671 				 struct sockaddr *from, socklen_t fromlen,
    672 				 struct radius_client *client,
    673 				 const char *from_addr, int from_port,
    674 				 struct radius_session *force_sess)
    675 {
    676 	u8 *eap = NULL;
    677 	size_t eap_len;
    678 	int res, state_included = 0;
    679 	u8 statebuf[4];
    680 	unsigned int state;
    681 	struct radius_session *sess;
    682 	struct radius_msg *reply;
    683 	int is_complete = 0;
    684 
    685 	if (force_sess)
    686 		sess = force_sess;
    687 	else {
    688 		res = radius_msg_get_attr(msg, RADIUS_ATTR_STATE, statebuf,
    689 					  sizeof(statebuf));
    690 		state_included = res >= 0;
    691 		if (res == sizeof(statebuf)) {
    692 			state = WPA_GET_BE32(statebuf);
    693 			sess = radius_server_get_session(client, state);
    694 		} else {
    695 			sess = NULL;
    696 		}
    697 	}
    698 
    699 	if (sess) {
    700 		RADIUS_DEBUG("Request for session 0x%x", sess->sess_id);
    701 	} else if (state_included) {
    702 		RADIUS_DEBUG("State attribute included but no session found");
    703 		radius_server_reject(data, client, msg, from, fromlen,
    704 				     from_addr, from_port);
    705 		return -1;
    706 	} else {
    707 		sess = radius_server_get_new_session(data, client, msg);
    708 		if (sess == NULL) {
    709 			RADIUS_DEBUG("Could not create a new session");
    710 			radius_server_reject(data, client, msg, from, fromlen,
    711 					     from_addr, from_port);
    712 			return -1;
    713 		}
    714 	}
    715 
    716 	if (sess->last_from_port == from_port &&
    717 	    sess->last_identifier == radius_msg_get_hdr(msg)->identifier &&
    718 	    os_memcmp(sess->last_authenticator,
    719 		      radius_msg_get_hdr(msg)->authenticator, 16) == 0) {
    720 		RADIUS_DEBUG("Duplicate message from %s", from_addr);
    721 		data->counters.dup_access_requests++;
    722 		client->counters.dup_access_requests++;
    723 
    724 		if (sess->last_reply) {
    725 			struct wpabuf *buf;
    726 			buf = radius_msg_get_buf(sess->last_reply);
    727 			res = sendto(data->auth_sock, wpabuf_head(buf),
    728 				     wpabuf_len(buf), 0,
    729 				     (struct sockaddr *) from, fromlen);
    730 			if (res < 0) {
    731 				perror("sendto[RADIUS SRV]");
    732 			}
    733 			return 0;
    734 		}
    735 
    736 		RADIUS_DEBUG("No previous reply available for duplicate "
    737 			     "message");
    738 		return -1;
    739 	}
    740 
    741 	eap = radius_msg_get_eap(msg, &eap_len);
    742 	if (eap == NULL) {
    743 		RADIUS_DEBUG("No EAP-Message in RADIUS packet from %s",
    744 			     from_addr);
    745 		data->counters.packets_dropped++;
    746 		client->counters.packets_dropped++;
    747 		return -1;
    748 	}
    749 
    750 	RADIUS_DUMP("Received EAP data", eap, eap_len);
    751 
    752 	/* FIX: if Code is Request, Success, or Failure, send Access-Reject;
    753 	 * RFC3579 Sect. 2.6.2.
    754 	 * Include EAP-Response/Nak with no preferred method if
    755 	 * code == request.
    756 	 * If code is not 1-4, discard the packet silently.
    757 	 * Or is this already done by the EAP state machine? */
    758 
    759 	wpabuf_free(sess->eap_if->eapRespData);
    760 	sess->eap_if->eapRespData = wpabuf_alloc_ext_data(eap, eap_len);
    761 	if (sess->eap_if->eapRespData == NULL)
    762 		os_free(eap);
    763 	eap = NULL;
    764 	sess->eap_if->eapResp = TRUE;
    765 	eap_server_sm_step(sess->eap);
    766 
    767 	if ((sess->eap_if->eapReq || sess->eap_if->eapSuccess ||
    768 	     sess->eap_if->eapFail) && sess->eap_if->eapReqData) {
    769 		RADIUS_DUMP("EAP data from the state machine",
    770 			    wpabuf_head(sess->eap_if->eapReqData),
    771 			    wpabuf_len(sess->eap_if->eapReqData));
    772 	} else if (sess->eap_if->eapFail) {
    773 		RADIUS_DEBUG("No EAP data from the state machine, but eapFail "
    774 			     "set");
    775 	} else if (eap_sm_method_pending(sess->eap)) {
    776 		radius_msg_free(sess->last_msg);
    777 		sess->last_msg = msg;
    778 		sess->last_from_port = from_port;
    779 		os_free(sess->last_from_addr);
    780 		sess->last_from_addr = os_strdup(from_addr);
    781 		sess->last_fromlen = fromlen;
    782 		os_memcpy(&sess->last_from, from, fromlen);
    783 		return -2;
    784 	} else {
    785 		RADIUS_DEBUG("No EAP data from the state machine - ignore this"
    786 			     " Access-Request silently (assuming it was a "
    787 			     "duplicate)");
    788 		data->counters.packets_dropped++;
    789 		client->counters.packets_dropped++;
    790 		return -1;
    791 	}
    792 
    793 	if (sess->eap_if->eapSuccess || sess->eap_if->eapFail)
    794 		is_complete = 1;
    795 
    796 	reply = radius_server_encapsulate_eap(data, client, sess, msg);
    797 
    798 	if (reply) {
    799 		struct wpabuf *buf;
    800 		struct radius_hdr *hdr;
    801 
    802 		RADIUS_DEBUG("Reply to %s:%d", from_addr, from_port);
    803 		if (wpa_debug_level <= MSG_MSGDUMP) {
    804 			radius_msg_dump(reply);
    805 		}
    806 
    807 		switch (radius_msg_get_hdr(reply)->code) {
    808 		case RADIUS_CODE_ACCESS_ACCEPT:
    809 			data->counters.access_accepts++;
    810 			client->counters.access_accepts++;
    811 			break;
    812 		case RADIUS_CODE_ACCESS_REJECT:
    813 			data->counters.access_rejects++;
    814 			client->counters.access_rejects++;
    815 			break;
    816 		case RADIUS_CODE_ACCESS_CHALLENGE:
    817 			data->counters.access_challenges++;
    818 			client->counters.access_challenges++;
    819 			break;
    820 		}
    821 		buf = radius_msg_get_buf(reply);
    822 		res = sendto(data->auth_sock, wpabuf_head(buf),
    823 			     wpabuf_len(buf), 0,
    824 			     (struct sockaddr *) from, fromlen);
    825 		if (res < 0) {
    826 			perror("sendto[RADIUS SRV]");
    827 		}
    828 		radius_msg_free(sess->last_reply);
    829 		sess->last_reply = reply;
    830 		sess->last_from_port = from_port;
    831 		hdr = radius_msg_get_hdr(msg);
    832 		sess->last_identifier = hdr->identifier;
    833 		os_memcpy(sess->last_authenticator, hdr->authenticator, 16);
    834 	} else {
    835 		data->counters.packets_dropped++;
    836 		client->counters.packets_dropped++;
    837 	}
    838 
    839 	if (is_complete) {
    840 		RADIUS_DEBUG("Removing completed session 0x%x after timeout",
    841 			     sess->sess_id);
    842 		eloop_cancel_timeout(radius_server_session_remove_timeout,
    843 				     data, sess);
    844 		eloop_register_timeout(10, 0,
    845 				       radius_server_session_remove_timeout,
    846 				       data, sess);
    847 	}
    848 
    849 	return 0;
    850 }
    851 
    852 
    853 static void radius_server_receive_auth(int sock, void *eloop_ctx,
    854 				       void *sock_ctx)
    855 {
    856 	struct radius_server_data *data = eloop_ctx;
    857 	u8 *buf = NULL;
    858 	union {
    859 		struct sockaddr_storage ss;
    860 		struct sockaddr_in sin;
    861 #ifdef CONFIG_IPV6
    862 		struct sockaddr_in6 sin6;
    863 #endif /* CONFIG_IPV6 */
    864 	} from;
    865 	socklen_t fromlen;
    866 	int len;
    867 	struct radius_client *client = NULL;
    868 	struct radius_msg *msg = NULL;
    869 	char abuf[50];
    870 	int from_port = 0;
    871 
    872 	buf = os_malloc(RADIUS_MAX_MSG_LEN);
    873 	if (buf == NULL) {
    874 		goto fail;
    875 	}
    876 
    877 	fromlen = sizeof(from);
    878 	len = recvfrom(sock, buf, RADIUS_MAX_MSG_LEN, 0,
    879 		       (struct sockaddr *) &from.ss, &fromlen);
    880 	if (len < 0) {
    881 		perror("recvfrom[radius_server]");
    882 		goto fail;
    883 	}
    884 
    885 #ifdef CONFIG_IPV6
    886 	if (data->ipv6) {
    887 		if (inet_ntop(AF_INET6, &from.sin6.sin6_addr, abuf,
    888 			      sizeof(abuf)) == NULL)
    889 			abuf[0] = '\0';
    890 		from_port = ntohs(from.sin6.sin6_port);
    891 		RADIUS_DEBUG("Received %d bytes from %s:%d",
    892 			     len, abuf, from_port);
    893 
    894 		client = radius_server_get_client(data,
    895 						  (struct in_addr *)
    896 						  &from.sin6.sin6_addr, 1);
    897 	}
    898 #endif /* CONFIG_IPV6 */
    899 
    900 	if (!data->ipv6) {
    901 		os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf));
    902 		from_port = ntohs(from.sin.sin_port);
    903 		RADIUS_DEBUG("Received %d bytes from %s:%d",
    904 			     len, abuf, from_port);
    905 
    906 		client = radius_server_get_client(data, &from.sin.sin_addr, 0);
    907 	}
    908 
    909 	RADIUS_DUMP("Received data", buf, len);
    910 
    911 	if (client == NULL) {
    912 		RADIUS_DEBUG("Unknown client %s - packet ignored", abuf);
    913 		data->counters.invalid_requests++;
    914 		goto fail;
    915 	}
    916 
    917 	msg = radius_msg_parse(buf, len);
    918 	if (msg == NULL) {
    919 		RADIUS_DEBUG("Parsing incoming RADIUS frame failed");
    920 		data->counters.malformed_access_requests++;
    921 		client->counters.malformed_access_requests++;
    922 		goto fail;
    923 	}
    924 
    925 	os_free(buf);
    926 	buf = NULL;
    927 
    928 	if (wpa_debug_level <= MSG_MSGDUMP) {
    929 		radius_msg_dump(msg);
    930 	}
    931 
    932 	if (radius_msg_get_hdr(msg)->code != RADIUS_CODE_ACCESS_REQUEST) {
    933 		RADIUS_DEBUG("Unexpected RADIUS code %d",
    934 			     radius_msg_get_hdr(msg)->code);
    935 		data->counters.unknown_types++;
    936 		client->counters.unknown_types++;
    937 		goto fail;
    938 	}
    939 
    940 	data->counters.access_requests++;
    941 	client->counters.access_requests++;
    942 
    943 	if (radius_msg_verify_msg_auth(msg, (u8 *) client->shared_secret,
    944 				       client->shared_secret_len, NULL)) {
    945 		RADIUS_DEBUG("Invalid Message-Authenticator from %s", abuf);
    946 		data->counters.bad_authenticators++;
    947 		client->counters.bad_authenticators++;
    948 		goto fail;
    949 	}
    950 
    951 	if (radius_server_request(data, msg, (struct sockaddr *) &from,
    952 				  fromlen, client, abuf, from_port, NULL) ==
    953 	    -2)
    954 		return; /* msg was stored with the session */
    955 
    956 fail:
    957 	radius_msg_free(msg);
    958 	os_free(buf);
    959 }
    960 
    961 
    962 static int radius_server_disable_pmtu_discovery(int s)
    963 {
    964 	int r = -1;
    965 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
    966 	/* Turn off Path MTU discovery on IPv4/UDP sockets. */
    967 	int action = IP_PMTUDISC_DONT;
    968 	r = setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &action,
    969 		       sizeof(action));
    970 	if (r == -1)
    971 		wpa_printf(MSG_ERROR, "Failed to set IP_MTU_DISCOVER: "
    972 			   "%s", strerror(errno));
    973 #endif
    974 	return r;
    975 }
    976 
    977 
    978 static int radius_server_open_socket(int port)
    979 {
    980 	int s;
    981 	struct sockaddr_in addr;
    982 
    983 	s = socket(PF_INET, SOCK_DGRAM, 0);
    984 	if (s < 0) {
    985 		perror("socket");
    986 		return -1;
    987 	}
    988 
    989 	radius_server_disable_pmtu_discovery(s);
    990 
    991 	os_memset(&addr, 0, sizeof(addr));
    992 	addr.sin_family = AF_INET;
    993 	addr.sin_port = htons(port);
    994 	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
    995 		perror("bind");
    996 		close(s);
    997 		return -1;
    998 	}
    999 
   1000 	return s;
   1001 }
   1002 
   1003 
   1004 #ifdef CONFIG_IPV6
   1005 static int radius_server_open_socket6(int port)
   1006 {
   1007 	int s;
   1008 	struct sockaddr_in6 addr;
   1009 
   1010 	s = socket(PF_INET6, SOCK_DGRAM, 0);
   1011 	if (s < 0) {
   1012 		perror("socket[IPv6]");
   1013 		return -1;
   1014 	}
   1015 
   1016 	os_memset(&addr, 0, sizeof(addr));
   1017 	addr.sin6_family = AF_INET6;
   1018 	os_memcpy(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any));
   1019 	addr.sin6_port = htons(port);
   1020 	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
   1021 		perror("bind");
   1022 		close(s);
   1023 		return -1;
   1024 	}
   1025 
   1026 	return s;
   1027 }
   1028 #endif /* CONFIG_IPV6 */
   1029 
   1030 
   1031 static void radius_server_free_sessions(struct radius_server_data *data,
   1032 					struct radius_session *sessions)
   1033 {
   1034 	struct radius_session *session, *prev;
   1035 
   1036 	session = sessions;
   1037 	while (session) {
   1038 		prev = session;
   1039 		session = session->next;
   1040 		radius_server_session_free(data, prev);
   1041 	}
   1042 }
   1043 
   1044 
   1045 static void radius_server_free_clients(struct radius_server_data *data,
   1046 				       struct radius_client *clients)
   1047 {
   1048 	struct radius_client *client, *prev;
   1049 
   1050 	client = clients;
   1051 	while (client) {
   1052 		prev = client;
   1053 		client = client->next;
   1054 
   1055 		radius_server_free_sessions(data, prev->sessions);
   1056 		os_free(prev->shared_secret);
   1057 		os_free(prev);
   1058 	}
   1059 }
   1060 
   1061 
   1062 static struct radius_client *
   1063 radius_server_read_clients(const char *client_file, int ipv6)
   1064 {
   1065 	FILE *f;
   1066 	const int buf_size = 1024;
   1067 	char *buf, *pos;
   1068 	struct radius_client *clients, *tail, *entry;
   1069 	int line = 0, mask, failed = 0, i;
   1070 	struct in_addr addr;
   1071 #ifdef CONFIG_IPV6
   1072 	struct in6_addr addr6;
   1073 #endif /* CONFIG_IPV6 */
   1074 	unsigned int val;
   1075 
   1076 	f = fopen(client_file, "r");
   1077 	if (f == NULL) {
   1078 		RADIUS_ERROR("Could not open client file '%s'", client_file);
   1079 		return NULL;
   1080 	}
   1081 
   1082 	buf = os_malloc(buf_size);
   1083 	if (buf == NULL) {
   1084 		fclose(f);
   1085 		return NULL;
   1086 	}
   1087 
   1088 	clients = tail = NULL;
   1089 	while (fgets(buf, buf_size, f)) {
   1090 		/* Configuration file format:
   1091 		 * 192.168.1.0/24 secret
   1092 		 * 192.168.1.2 secret
   1093 		 * fe80::211:22ff:fe33:4455/64 secretipv6
   1094 		 */
   1095 		line++;
   1096 		buf[buf_size - 1] = '\0';
   1097 		pos = buf;
   1098 		while (*pos != '\0' && *pos != '\n')
   1099 			pos++;
   1100 		if (*pos == '\n')
   1101 			*pos = '\0';
   1102 		if (*buf == '\0' || *buf == '#')
   1103 			continue;
   1104 
   1105 		pos = buf;
   1106 		while ((*pos >= '0' && *pos <= '9') || *pos == '.' ||
   1107 		       (*pos >= 'a' && *pos <= 'f') || *pos == ':' ||
   1108 		       (*pos >= 'A' && *pos <= 'F')) {
   1109 			pos++;
   1110 		}
   1111 
   1112 		if (*pos == '\0') {
   1113 			failed = 1;
   1114 			break;
   1115 		}
   1116 
   1117 		if (*pos == '/') {
   1118 			char *end;
   1119 			*pos++ = '\0';
   1120 			mask = strtol(pos, &end, 10);
   1121 			if ((pos == end) ||
   1122 			    (mask < 0 || mask > (ipv6 ? 128 : 32))) {
   1123 				failed = 1;
   1124 				break;
   1125 			}
   1126 			pos = end;
   1127 		} else {
   1128 			mask = ipv6 ? 128 : 32;
   1129 			*pos++ = '\0';
   1130 		}
   1131 
   1132 		if (!ipv6 && inet_aton(buf, &addr) == 0) {
   1133 			failed = 1;
   1134 			break;
   1135 		}
   1136 #ifdef CONFIG_IPV6
   1137 		if (ipv6 && inet_pton(AF_INET6, buf, &addr6) <= 0) {
   1138 			if (inet_pton(AF_INET, buf, &addr) <= 0) {
   1139 				failed = 1;
   1140 				break;
   1141 			}
   1142 			/* Convert IPv4 address to IPv6 */
   1143 			if (mask <= 32)
   1144 				mask += (128 - 32);
   1145 			os_memset(addr6.s6_addr, 0, 10);
   1146 			addr6.s6_addr[10] = 0xff;
   1147 			addr6.s6_addr[11] = 0xff;
   1148 			os_memcpy(addr6.s6_addr + 12, (char *) &addr.s_addr,
   1149 				  4);
   1150 		}
   1151 #endif /* CONFIG_IPV6 */
   1152 
   1153 		while (*pos == ' ' || *pos == '\t') {
   1154 			pos++;
   1155 		}
   1156 
   1157 		if (*pos == '\0') {
   1158 			failed = 1;
   1159 			break;
   1160 		}
   1161 
   1162 		entry = os_zalloc(sizeof(*entry));
   1163 		if (entry == NULL) {
   1164 			failed = 1;
   1165 			break;
   1166 		}
   1167 		entry->shared_secret = os_strdup(pos);
   1168 		if (entry->shared_secret == NULL) {
   1169 			failed = 1;
   1170 			os_free(entry);
   1171 			break;
   1172 		}
   1173 		entry->shared_secret_len = os_strlen(entry->shared_secret);
   1174 		entry->addr.s_addr = addr.s_addr;
   1175 		if (!ipv6) {
   1176 			val = 0;
   1177 			for (i = 0; i < mask; i++)
   1178 				val |= 1 << (31 - i);
   1179 			entry->mask.s_addr = htonl(val);
   1180 		}
   1181 #ifdef CONFIG_IPV6
   1182 		if (ipv6) {
   1183 			int offset = mask / 8;
   1184 
   1185 			os_memcpy(entry->addr6.s6_addr, addr6.s6_addr, 16);
   1186 			os_memset(entry->mask6.s6_addr, 0xff, offset);
   1187 			val = 0;
   1188 			for (i = 0; i < (mask % 8); i++)
   1189 				val |= 1 << (7 - i);
   1190 			if (offset < 16)
   1191 				entry->mask6.s6_addr[offset] = val;
   1192 		}
   1193 #endif /* CONFIG_IPV6 */
   1194 
   1195 		if (tail == NULL) {
   1196 			clients = tail = entry;
   1197 		} else {
   1198 			tail->next = entry;
   1199 			tail = entry;
   1200 		}
   1201 	}
   1202 
   1203 	if (failed) {
   1204 		RADIUS_ERROR("Invalid line %d in '%s'", line, client_file);
   1205 		radius_server_free_clients(NULL, clients);
   1206 		clients = NULL;
   1207 	}
   1208 
   1209 	os_free(buf);
   1210 	fclose(f);
   1211 
   1212 	return clients;
   1213 }
   1214 
   1215 
   1216 /**
   1217  * radius_server_init - Initialize RADIUS server
   1218  * @conf: Configuration for the RADIUS server
   1219  * Returns: Pointer to private RADIUS server context or %NULL on failure
   1220  *
   1221  * This initializes a RADIUS server instance and returns a context pointer that
   1222  * will be used in other calls to the RADIUS server module. The server can be
   1223  * deinitialize by calling radius_server_deinit().
   1224  */
   1225 struct radius_server_data *
   1226 radius_server_init(struct radius_server_conf *conf)
   1227 {
   1228 	struct radius_server_data *data;
   1229 
   1230 #ifndef CONFIG_IPV6
   1231 	if (conf->ipv6) {
   1232 		fprintf(stderr, "RADIUS server compiled without IPv6 "
   1233 			"support.\n");
   1234 		return NULL;
   1235 	}
   1236 #endif /* CONFIG_IPV6 */
   1237 
   1238 	data = os_zalloc(sizeof(*data));
   1239 	if (data == NULL)
   1240 		return NULL;
   1241 
   1242 	os_get_time(&data->start_time);
   1243 	data->conf_ctx = conf->conf_ctx;
   1244 	data->eap_sim_db_priv = conf->eap_sim_db_priv;
   1245 	data->ssl_ctx = conf->ssl_ctx;
   1246 	data->msg_ctx = conf->msg_ctx;
   1247 	data->ipv6 = conf->ipv6;
   1248 	if (conf->pac_opaque_encr_key) {
   1249 		data->pac_opaque_encr_key = os_malloc(16);
   1250 		os_memcpy(data->pac_opaque_encr_key, conf->pac_opaque_encr_key,
   1251 			  16);
   1252 	}
   1253 	if (conf->eap_fast_a_id) {
   1254 		data->eap_fast_a_id = os_malloc(conf->eap_fast_a_id_len);
   1255 		if (data->eap_fast_a_id) {
   1256 			os_memcpy(data->eap_fast_a_id, conf->eap_fast_a_id,
   1257 				  conf->eap_fast_a_id_len);
   1258 			data->eap_fast_a_id_len = conf->eap_fast_a_id_len;
   1259 		}
   1260 	}
   1261 	if (conf->eap_fast_a_id_info)
   1262 		data->eap_fast_a_id_info = os_strdup(conf->eap_fast_a_id_info);
   1263 	data->eap_fast_prov = conf->eap_fast_prov;
   1264 	data->pac_key_lifetime = conf->pac_key_lifetime;
   1265 	data->pac_key_refresh_time = conf->pac_key_refresh_time;
   1266 	data->get_eap_user = conf->get_eap_user;
   1267 	data->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;
   1268 	data->tnc = conf->tnc;
   1269 	data->wps = conf->wps;
   1270 	data->pwd_group = conf->pwd_group;
   1271 	if (conf->eap_req_id_text) {
   1272 		data->eap_req_id_text = os_malloc(conf->eap_req_id_text_len);
   1273 		if (data->eap_req_id_text) {
   1274 			os_memcpy(data->eap_req_id_text, conf->eap_req_id_text,
   1275 				  conf->eap_req_id_text_len);
   1276 			data->eap_req_id_text_len = conf->eap_req_id_text_len;
   1277 		}
   1278 	}
   1279 
   1280 	data->clients = radius_server_read_clients(conf->client_file,
   1281 						   conf->ipv6);
   1282 	if (data->clients == NULL) {
   1283 		printf("No RADIUS clients configured.\n");
   1284 		radius_server_deinit(data);
   1285 		return NULL;
   1286 	}
   1287 
   1288 #ifdef CONFIG_IPV6
   1289 	if (conf->ipv6)
   1290 		data->auth_sock = radius_server_open_socket6(conf->auth_port);
   1291 	else
   1292 #endif /* CONFIG_IPV6 */
   1293 	data->auth_sock = radius_server_open_socket(conf->auth_port);
   1294 	if (data->auth_sock < 0) {
   1295 		printf("Failed to open UDP socket for RADIUS authentication "
   1296 		       "server\n");
   1297 		radius_server_deinit(data);
   1298 		return NULL;
   1299 	}
   1300 	if (eloop_register_read_sock(data->auth_sock,
   1301 				     radius_server_receive_auth,
   1302 				     data, NULL)) {
   1303 		radius_server_deinit(data);
   1304 		return NULL;
   1305 	}
   1306 
   1307 	return data;
   1308 }
   1309 
   1310 
   1311 /**
   1312  * radius_server_deinit - Deinitialize RADIUS server
   1313  * @data: RADIUS server context from radius_server_init()
   1314  */
   1315 void radius_server_deinit(struct radius_server_data *data)
   1316 {
   1317 	if (data == NULL)
   1318 		return;
   1319 
   1320 	if (data->auth_sock >= 0) {
   1321 		eloop_unregister_read_sock(data->auth_sock);
   1322 		close(data->auth_sock);
   1323 	}
   1324 
   1325 	radius_server_free_clients(data, data->clients);
   1326 
   1327 	os_free(data->pac_opaque_encr_key);
   1328 	os_free(data->eap_fast_a_id);
   1329 	os_free(data->eap_fast_a_id_info);
   1330 	os_free(data->eap_req_id_text);
   1331 	os_free(data);
   1332 }
   1333 
   1334 
   1335 /**
   1336  * radius_server_get_mib - Get RADIUS server MIB information
   1337  * @data: RADIUS server context from radius_server_init()
   1338  * @buf: Buffer for returning the MIB data in text format
   1339  * @buflen: buf length in octets
   1340  * Returns: Number of octets written into buf
   1341  */
   1342 int radius_server_get_mib(struct radius_server_data *data, char *buf,
   1343 			  size_t buflen)
   1344 {
   1345 	int ret, uptime;
   1346 	unsigned int idx;
   1347 	char *end, *pos;
   1348 	struct os_time now;
   1349 	struct radius_client *cli;
   1350 
   1351 	/* RFC 2619 - RADIUS Authentication Server MIB */
   1352 
   1353 	if (data == NULL || buflen == 0)
   1354 		return 0;
   1355 
   1356 	pos = buf;
   1357 	end = buf + buflen;
   1358 
   1359 	os_get_time(&now);
   1360 	uptime = (now.sec - data->start_time.sec) * 100 +
   1361 		((now.usec - data->start_time.usec) / 10000) % 100;
   1362 	ret = os_snprintf(pos, end - pos,
   1363 			  "RADIUS-AUTH-SERVER-MIB\n"
   1364 			  "radiusAuthServIdent=hostapd\n"
   1365 			  "radiusAuthServUpTime=%d\n"
   1366 			  "radiusAuthServResetTime=0\n"
   1367 			  "radiusAuthServConfigReset=4\n",
   1368 			  uptime);
   1369 	if (ret < 0 || ret >= end - pos) {
   1370 		*pos = '\0';
   1371 		return pos - buf;
   1372 	}
   1373 	pos += ret;
   1374 
   1375 	ret = os_snprintf(pos, end - pos,
   1376 			  "radiusAuthServTotalAccessRequests=%u\n"
   1377 			  "radiusAuthServTotalInvalidRequests=%u\n"
   1378 			  "radiusAuthServTotalDupAccessRequests=%u\n"
   1379 			  "radiusAuthServTotalAccessAccepts=%u\n"
   1380 			  "radiusAuthServTotalAccessRejects=%u\n"
   1381 			  "radiusAuthServTotalAccessChallenges=%u\n"
   1382 			  "radiusAuthServTotalMalformedAccessRequests=%u\n"
   1383 			  "radiusAuthServTotalBadAuthenticators=%u\n"
   1384 			  "radiusAuthServTotalPacketsDropped=%u\n"
   1385 			  "radiusAuthServTotalUnknownTypes=%u\n",
   1386 			  data->counters.access_requests,
   1387 			  data->counters.invalid_requests,
   1388 			  data->counters.dup_access_requests,
   1389 			  data->counters.access_accepts,
   1390 			  data->counters.access_rejects,
   1391 			  data->counters.access_challenges,
   1392 			  data->counters.malformed_access_requests,
   1393 			  data->counters.bad_authenticators,
   1394 			  data->counters.packets_dropped,
   1395 			  data->counters.unknown_types);
   1396 	if (ret < 0 || ret >= end - pos) {
   1397 		*pos = '\0';
   1398 		return pos - buf;
   1399 	}
   1400 	pos += ret;
   1401 
   1402 	for (cli = data->clients, idx = 0; cli; cli = cli->next, idx++) {
   1403 		char abuf[50], mbuf[50];
   1404 #ifdef CONFIG_IPV6
   1405 		if (data->ipv6) {
   1406 			if (inet_ntop(AF_INET6, &cli->addr6, abuf,
   1407 				      sizeof(abuf)) == NULL)
   1408 				abuf[0] = '\0';
   1409 			if (inet_ntop(AF_INET6, &cli->mask6, abuf,
   1410 				      sizeof(mbuf)) == NULL)
   1411 				mbuf[0] = '\0';
   1412 		}
   1413 #endif /* CONFIG_IPV6 */
   1414 		if (!data->ipv6) {
   1415 			os_strlcpy(abuf, inet_ntoa(cli->addr), sizeof(abuf));
   1416 			os_strlcpy(mbuf, inet_ntoa(cli->mask), sizeof(mbuf));
   1417 		}
   1418 
   1419 		ret = os_snprintf(pos, end - pos,
   1420 				  "radiusAuthClientIndex=%u\n"
   1421 				  "radiusAuthClientAddress=%s/%s\n"
   1422 				  "radiusAuthServAccessRequests=%u\n"
   1423 				  "radiusAuthServDupAccessRequests=%u\n"
   1424 				  "radiusAuthServAccessAccepts=%u\n"
   1425 				  "radiusAuthServAccessRejects=%u\n"
   1426 				  "radiusAuthServAccessChallenges=%u\n"
   1427 				  "radiusAuthServMalformedAccessRequests=%u\n"
   1428 				  "radiusAuthServBadAuthenticators=%u\n"
   1429 				  "radiusAuthServPacketsDropped=%u\n"
   1430 				  "radiusAuthServUnknownTypes=%u\n",
   1431 				  idx,
   1432 				  abuf, mbuf,
   1433 				  cli->counters.access_requests,
   1434 				  cli->counters.dup_access_requests,
   1435 				  cli->counters.access_accepts,
   1436 				  cli->counters.access_rejects,
   1437 				  cli->counters.access_challenges,
   1438 				  cli->counters.malformed_access_requests,
   1439 				  cli->counters.bad_authenticators,
   1440 				  cli->counters.packets_dropped,
   1441 				  cli->counters.unknown_types);
   1442 		if (ret < 0 || ret >= end - pos) {
   1443 			*pos = '\0';
   1444 			return pos - buf;
   1445 		}
   1446 		pos += ret;
   1447 	}
   1448 
   1449 	return pos - buf;
   1450 }
   1451 
   1452 
   1453 static int radius_server_get_eap_user(void *ctx, const u8 *identity,
   1454 				      size_t identity_len, int phase2,
   1455 				      struct eap_user *user)
   1456 {
   1457 	struct radius_session *sess = ctx;
   1458 	struct radius_server_data *data = sess->server;
   1459 
   1460 	return data->get_eap_user(data->conf_ctx, identity, identity_len,
   1461 				  phase2, user);
   1462 }
   1463 
   1464 
   1465 static const char * radius_server_get_eap_req_id_text(void *ctx, size_t *len)
   1466 {
   1467 	struct radius_session *sess = ctx;
   1468 	struct radius_server_data *data = sess->server;
   1469 	*len = data->eap_req_id_text_len;
   1470 	return data->eap_req_id_text;
   1471 }
   1472 
   1473 
   1474 static struct eapol_callbacks radius_server_eapol_cb =
   1475 {
   1476 	.get_eap_user = radius_server_get_eap_user,
   1477 	.get_eap_req_id_text = radius_server_get_eap_req_id_text,
   1478 };
   1479 
   1480 
   1481 /**
   1482  * radius_server_eap_pending_cb - Pending EAP data notification
   1483  * @data: RADIUS server context from radius_server_init()
   1484  * @ctx: Pending EAP context pointer
   1485  *
   1486  * This function is used to notify EAP server module that a pending operation
   1487  * has been completed and processing of the EAP session can proceed.
   1488  */
   1489 void radius_server_eap_pending_cb(struct radius_server_data *data, void *ctx)
   1490 {
   1491 	struct radius_client *cli;
   1492 	struct radius_session *s, *sess = NULL;
   1493 	struct radius_msg *msg;
   1494 
   1495 	if (data == NULL)
   1496 		return;
   1497 
   1498 	for (cli = data->clients; cli; cli = cli->next) {
   1499 		for (s = cli->sessions; s; s = s->next) {
   1500 			if (s->eap == ctx && s->last_msg) {
   1501 				sess = s;
   1502 				break;
   1503 			}
   1504 			if (sess)
   1505 				break;
   1506 		}
   1507 		if (sess)
   1508 			break;
   1509 	}
   1510 
   1511 	if (sess == NULL) {
   1512 		RADIUS_DEBUG("No session matched callback ctx");
   1513 		return;
   1514 	}
   1515 
   1516 	msg = sess->last_msg;
   1517 	sess->last_msg = NULL;
   1518 	eap_sm_pending_cb(sess->eap);
   1519 	if (radius_server_request(data, msg,
   1520 				  (struct sockaddr *) &sess->last_from,
   1521 				  sess->last_fromlen, cli,
   1522 				  sess->last_from_addr,
   1523 				  sess->last_from_port, sess) == -2)
   1524 		return; /* msg was stored with the session */
   1525 
   1526 	radius_msg_free(msg);
   1527 }
   1528