18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RADIUS authentication server 31f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Copyright (c) 2005-2009, 2011, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <net/if.h> 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "radius.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_server/eap.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "radius_server.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RADIUS_SESSION_TIMEOUT - Session timeout in seconds 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RADIUS_SESSION_TIMEOUT 60 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RADIUS_MAX_SESSION - Maximum number of active sessions 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RADIUS_MAX_SESSION 100 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RADIUS_MAX_MSG_LEN - Maximum message length for incoming RADIUS messages 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RADIUS_MAX_MSG_LEN 3000 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct eapol_callbacks radius_server_eapol_cb; 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct radius_client; 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct radius_server_data; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * struct radius_server_counters - RADIUS server statistics counters 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct radius_server_counters { 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 access_requests; 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 invalid_requests; 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 dup_access_requests; 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 access_accepts; 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 access_rejects; 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 access_challenges; 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 malformed_access_requests; 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 bad_authenticators; 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 packets_dropped; 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 unknown_types; 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * struct radius_session - Internal RADIUS server data for a session 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct radius_session { 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_session *next; 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_client *client; 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_server_data *server; 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int sess_id; 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sm *eap; 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_eapol_interface *eap_if; 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg *last_msg; 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *last_from_addr; 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int last_from_port; 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_storage last_from; 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt socklen_t last_fromlen; 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 last_identifier; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg *last_reply; 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 last_authenticator[16]; 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * struct radius_client - Internal RADIUS server data for a client 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct radius_client { 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_client *next; 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct in_addr addr; 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct in_addr mask; 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IPV6 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct in6_addr addr6; 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct in6_addr mask6; 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IPV6 */ 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *shared_secret; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int shared_secret_len; 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_session *sessions; 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_server_counters counters; 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * struct radius_server_data - Internal RADIUS server data 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct radius_server_data { 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * auth_sock - Socket for RADIUS authentication messages 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int auth_sock; 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * clients - List of authorized RADIUS clients 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_client *clients; 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * next_sess_id - Next session identifier 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int next_sess_id; 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * conf_ctx - Context pointer for callbacks 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This is used as the ctx argument in get_eap_user() calls. 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *conf_ctx; 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * num_sess - Number of active sessions 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int num_sess; 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_priv - EAP-SIM/AKA database context 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This is passed to the EAP-SIM/AKA server implementation as a 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * callback context. 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *eap_sim_db_priv; 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ssl_ctx - TLS context 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This is passed to the EAP server implementation as a callback 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * context for TLS operations. 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *ssl_ctx; 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * pac_opaque_encr_key - PAC-Opaque encryption key for EAP-FAST 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This parameter is used to set a key for EAP-FAST to encrypt the 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PAC-Opaque data. It can be set to %NULL if EAP-FAST is not used. If 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * set, must point to a 16-octet key. 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pac_opaque_encr_key; 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_fast_a_id - EAP-FAST authority identity (A-ID) 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * If EAP-FAST is not used, this can be set to %NULL. In theory, this 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * is a variable length field, but due to some existing implementations 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * requiring A-ID to be 16 octets in length, it is recommended to use 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * that length for the field to provide interoperability with deployed 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * peer implementations. 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *eap_fast_a_id; 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_fast_a_id_len - Length of eap_fast_a_id buffer in octets 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t eap_fast_a_id_len; 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_fast_a_id_info - EAP-FAST authority identifier information 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This A-ID-Info contains a user-friendly name for the A-ID. For 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * example, this could be the enterprise and server names in 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * human-readable format. This field is encoded as UTF-8. If EAP-FAST 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * is not used, this can be set to %NULL. 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *eap_fast_a_id_info; 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_fast_prov - EAP-FAST provisioning modes 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 0 = provisioning disabled, 1 = only anonymous provisioning allowed, 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2 = only authenticated provisioning allowed, 3 = both provisioning 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * modes allowed. 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int eap_fast_prov; 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * pac_key_lifetime - EAP-FAST PAC-Key lifetime in seconds 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This is the hard limit on how long a provisioned PAC-Key can be 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * used. 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int pac_key_lifetime; 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * pac_key_refresh_time - EAP-FAST PAC-Key refresh time in seconds 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This is a soft limit on the PAC-Key. The server will automatically 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * generate a new PAC-Key when this number of seconds (or fewer) of the 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * lifetime remains. 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int pac_key_refresh_time; 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_aka_result_ind - EAP-SIM/AKA protected success indication 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This controls whether the protected success/failure indication 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * (AT_RESULT_IND) is used with EAP-SIM and EAP-AKA. 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int eap_sim_aka_result_ind; 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tnc - Trusted Network Connect (TNC) 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This controls whether TNC is enabled and will be required before the 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * peer is allowed to connect. Note: This is only used with EAP-TTLS 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * and EAP-FAST. If any other EAP method is enabled, the peer will be 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * allowed to connect without TNC. 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tnc; 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * pwd_group - The D-H group assigned for EAP-pwd 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * If EAP-pwd is not used it can be set to zero. 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 pwd_group; 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 22634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * server_id - Server identity 22734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt */ 22834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const char *server_id; 22934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 23034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt /** 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wps - Wi-Fi Protected Setup context 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * If WPS is used with an external RADIUS server (which is quite 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * unlikely configuration), this is used to provide a pointer to WPS 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * context data. Normally, this can be set to %NULL. 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_context *wps; 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ipv6 - Whether to enable IPv6 support in the RADIUS server 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ipv6; 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * start_time - Timestamp of server start 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct os_time start_time; 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * counters - Statistics counters for server operations 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * These counters are the sum over all clients. 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_server_counters counters; 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * get_eap_user - Callback for fetching EAP user information 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ctx: Context data from conf_ctx 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @identity: User identity 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @identity_len: identity buffer length in octets 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @phase2: Whether this is for Phase 2 identity 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @user: Data structure for filling in the user information 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This is used to fetch information from user database. The callback 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * will fill in information about allowed EAP methods and the user 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * password. The password field will be an allocated copy of the 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * password data and RADIUS server will free it after use. 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len, 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int phase2, struct eap_user *user); 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_req_id_text - Optional data for EAP-Request/Identity 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This can be used to configure an optional, displayable message that 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * will be sent in EAP-Request/Identity. This string can contain an 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ASCII-0 character (nul) to separate network infromation per RFC 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 4284. The actual string length is explicit provided in 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_req_id_text_len since nul character will not be used as a string 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * terminator. 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *eap_req_id_text; 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_req_id_text_len - Length of eap_req_id_text buffer in octets 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t eap_req_id_text_len; 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * msg_ctx - Context data for wpa_msg() calls 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *msg_ctx; 2941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_RADIUS_TEST 2961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt char *dump_msk_file; 2971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_RADIUS_TEST */ 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtextern int wpa_debug_level; 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RADIUS_DEBUG(args...) \ 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_printf(MSG_DEBUG, "RADIUS SRV: " args) 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RADIUS_ERROR(args...) \ 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_printf(MSG_ERROR, "RADIUS SRV: " args) 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RADIUS_DUMP(args...) \ 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_hexdump(MSG_MSGDUMP, "RADIUS SRV: " args) 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RADIUS_DUMP_ASCII(args...) \ 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_hexdump_ascii(MSG_MSGDUMP, "RADIUS SRV: " args) 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx); 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void radius_server_session_remove_timeout(void *eloop_ctx, 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *timeout_ctx); 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct radius_client * 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtradius_server_get_client(struct radius_server_data *data, struct in_addr *addr, 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ipv6) 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_client *client = data->clients; 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (client) { 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IPV6 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ipv6) { 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct in6_addr *addr6; 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr6 = (struct in6_addr *) addr; 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < 16; i++) { 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((addr6->s6_addr[i] & 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt client->mask6.s6_addr[i]) != 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (client->addr6.s6_addr[i] & 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt client->mask6.s6_addr[i])) { 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i = 17; 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (i == 16) { 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IPV6 */ 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ipv6 && (client->addr.s_addr & client->mask.s_addr) == 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (addr->s_addr & client->mask.s_addr)) { 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt client = client->next; 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return client; 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct radius_session * 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtradius_server_get_session(struct radius_client *client, unsigned int sess_id) 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_session *sess = client->sessions; 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (sess) { 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sess->sess_id == sess_id) { 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess = sess->next; 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sess; 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void radius_server_session_free(struct radius_server_data *data, 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_session *sess) 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(radius_server_session_timeout, data, sess); 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess); 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_server_sm_deinit(sess->eap); 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_free(sess->last_msg); 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sess->last_from_addr); 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_free(sess->last_reply); 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sess); 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_sess--; 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void radius_server_session_remove(struct radius_server_data *data, 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_session *sess) 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_client *client = sess->client; 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_session *session, *prev; 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess); 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = NULL; 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt session = client->sessions; 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (session) { 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (session == sess) { 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (prev == NULL) { 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt client->sessions = sess->next; 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev->next = sess->next; 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_server_session_free(data, sess); 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = session; 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt session = session->next; 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void radius_server_session_remove_timeout(void *eloop_ctx, 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *timeout_ctx) 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_server_data *data = eloop_ctx; 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_session *sess = timeout_ctx; 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("Removing completed session 0x%x", sess->sess_id); 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_server_session_remove(data, sess); 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx) 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_server_data *data = eloop_ctx; 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_session *sess = timeout_ctx; 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("Timing out authentication session 0x%x", sess->sess_id); 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_server_session_remove(data, sess); 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct radius_session * 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtradius_server_new_session(struct radius_server_data *data, 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_client *client) 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_session *sess; 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->num_sess >= RADIUS_MAX_SESSION) { 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("Maximum number of existing session - no room " 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for a new session"); 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess = os_zalloc(sizeof(*sess)); 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sess == NULL) 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess->server = data; 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess->client = client; 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess->sess_id = data->next_sess_id++; 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess->next = client->sessions; 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt client->sessions = sess; 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(RADIUS_SESSION_TIMEOUT, 0, 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_server_session_timeout, data, sess); 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_sess++; 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sess; 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct radius_session * 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtradius_server_get_new_session(struct radius_server_data *data, 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_client *client, 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg *msg) 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *user; 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t user_len; 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_session *sess; 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_config eap_conf; 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("Creating a new session"); 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt user = os_malloc(256); 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (user == NULL) { 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = radius_msg_get_attr(msg, RADIUS_ATTR_USER_NAME, user, 256); 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0 || res > 256) { 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("Could not get User-Name"); 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(user); 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt user_len = res; 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DUMP_ASCII("User-Name", user, user_len); 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = data->get_eap_user(data->conf_ctx, user, user_len, 0, NULL); 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(user); 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == 0) { 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("Matching user entry found"); 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess = radius_server_new_session(data, client); 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sess == NULL) { 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("Failed to create a new session"); 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("User-Name not found from user database"); 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&eap_conf, 0, sizeof(eap_conf)); 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_conf.ssl_ctx = data->ssl_ctx; 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_conf.msg_ctx = data->msg_ctx; 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_conf.eap_sim_db_priv = data->eap_sim_db_priv; 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_conf.backend_auth = TRUE; 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_conf.eap_server = 1; 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_conf.pac_opaque_encr_key = data->pac_opaque_encr_key; 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_conf.eap_fast_a_id = data->eap_fast_a_id; 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_conf.eap_fast_a_id_len = data->eap_fast_a_id_len; 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_conf.eap_fast_a_id_info = data->eap_fast_a_id_info; 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_conf.eap_fast_prov = data->eap_fast_prov; 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_conf.pac_key_lifetime = data->pac_key_lifetime; 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_conf.pac_key_refresh_time = data->pac_key_refresh_time; 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_conf.eap_sim_aka_result_ind = data->eap_sim_aka_result_ind; 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_conf.tnc = data->tnc; 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_conf.wps = data->wps; 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_conf.pwd_group = data->pwd_group; 51934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_conf.server_id = (const u8 *) data->server_id; 52034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_conf.server_id_len = os_strlen(data->server_id); 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess->eap = eap_server_sm_init(sess, &radius_server_eapol_cb, 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &eap_conf); 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sess->eap == NULL) { 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("Failed to initialize EAP state machine for the " 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "new session"); 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_server_session_free(data, sess); 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess->eap_if = eap_get_interface(sess->eap); 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess->eap_if->eapRestart = TRUE; 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess->eap_if->portEnabled = TRUE; 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("New session 0x%x initialized", sess->sess_id); 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sess; 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct radius_msg * 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtradius_server_encapsulate_eap(struct radius_server_data *data, 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_client *client, 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_session *sess, 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg *request) 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg *msg; 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int code; 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int sess_id; 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_hdr *hdr = radius_msg_get_hdr(request); 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sess->eap_if->eapFail) { 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess->eap_if->eapFail = FALSE; 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt code = RADIUS_CODE_ACCESS_REJECT; 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (sess->eap_if->eapSuccess) { 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess->eap_if->eapSuccess = FALSE; 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt code = RADIUS_CODE_ACCESS_ACCEPT; 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess->eap_if->eapReq = FALSE; 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt code = RADIUS_CODE_ACCESS_CHALLENGE; 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = radius_msg_new(code, hdr->identifier); 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) { 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("Failed to allocate reply message"); 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess_id = htonl(sess->sess_id); 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (code == RADIUS_CODE_ACCESS_CHALLENGE && 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !radius_msg_add_attr(msg, RADIUS_ATTR_STATE, 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) &sess_id, sizeof(sess_id))) { 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("Failed to add State attribute"); 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sess->eap_if->eapReqData && 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !radius_msg_add_eap(msg, wpabuf_head(sess->eap_if->eapReqData), 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(sess->eap_if->eapReqData))) { 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("Failed to add EAP-Message attribute"); 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->eap_if->eapKeyData) { 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int len; 5821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_RADIUS_TEST 5831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (data->dump_msk_file) { 5841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt FILE *f; 5851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt char buf[2 * 64 + 1]; 5861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt f = fopen(data->dump_msk_file, "a"); 5871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (f) { 5881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len = sess->eap_if->eapKeyDataLen; 5891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (len > 64) 5901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len = 64; 5911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len = wpa_snprintf_hex( 5921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt buf, sizeof(buf), 5931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt sess->eap_if->eapKeyData, len); 5941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt buf[len] = '\0'; 5951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt fprintf(f, "%s\n", buf); 5961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt fclose(f); 5971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 5981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 5991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_RADIUS_TEST */ 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sess->eap_if->eapKeyDataLen > 64) { 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = 32; 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = sess->eap_if->eapKeyDataLen / 2; 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!radius_msg_add_mppe_keys(msg, hdr->authenticator, 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) client->shared_secret, 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt client->shared_secret_len, 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess->eap_if->eapKeyData + len, 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len, sess->eap_if->eapKeyData, 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len)) { 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("Failed to add MPPE key attributes"); 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) { 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)"); 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_free(msg); 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret, 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt client->shared_secret_len, 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->authenticator) < 0) { 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("Failed to add Message-Authenticator attribute"); 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return msg; 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int radius_server_reject(struct radius_server_data *data, 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_client *client, 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg *request, 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr *from, socklen_t fromlen, 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *from_addr, int from_port) 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg *msg; 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_hdr eapfail; 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_hdr *hdr = radius_msg_get_hdr(request); 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("Reject invalid request from %s:%d", 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt from_addr, from_port); 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = radius_msg_new(RADIUS_CODE_ACCESS_REJECT, hdr->identifier); 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) { 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&eapfail, 0, sizeof(eapfail)); 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapfail.code = EAP_CODE_FAILURE; 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapfail.identifier = 0; 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapfail.length = host_to_be16(sizeof(eapfail)); 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!radius_msg_add_eap(msg, (u8 *) &eapfail, sizeof(eapfail))) { 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("Failed to add EAP-Message attribute"); 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) { 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)"); 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_free(msg); 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret, 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt client->shared_secret_len, 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->authenticator) < 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) { 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("Failed to add Message-Authenticator attribute"); 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_debug_level <= MSG_MSGDUMP) { 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_dump(msg); 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counters.access_rejects++; 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt client->counters.access_rejects++; 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = radius_msg_get_buf(msg); 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sendto(data->auth_sock, wpabuf_head(buf), wpabuf_len(buf), 0, 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (struct sockaddr *) from, sizeof(*from)) < 0) { 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("sendto[RADIUS SRV]"); 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_free(msg); 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int radius_server_request(struct radius_server_data *data, 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg *msg, 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr *from, socklen_t fromlen, 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_client *client, 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *from_addr, int from_port, 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_session *force_sess) 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 69961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpabuf *eap = NULL; 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res, state_included = 0; 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 statebuf[4]; 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int state; 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_session *sess; 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg *reply; 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int is_complete = 0; 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (force_sess) 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess = force_sess; 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else { 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = radius_msg_get_attr(msg, RADIUS_ATTR_STATE, statebuf, 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(statebuf)); 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt state_included = res >= 0; 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == sizeof(statebuf)) { 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt state = WPA_GET_BE32(statebuf); 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess = radius_server_get_session(client, state); 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess = NULL; 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sess) { 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("Request for session 0x%x", sess->sess_id); 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (state_included) { 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("State attribute included but no session found"); 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_server_reject(data, client, msg, from, fromlen, 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt from_addr, from_port); 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess = radius_server_get_new_session(data, client, msg); 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sess == NULL) { 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("Could not create a new session"); 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_server_reject(data, client, msg, from, fromlen, 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt from_addr, from_port); 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sess->last_from_port == from_port && 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess->last_identifier == radius_msg_get_hdr(msg)->identifier && 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(sess->last_authenticator, 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_get_hdr(msg)->authenticator, 16) == 0) { 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("Duplicate message from %s", from_addr); 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counters.dup_access_requests++; 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt client->counters.dup_access_requests++; 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sess->last_reply) { 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = radius_msg_get_buf(sess->last_reply); 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = sendto(data->auth_sock, wpabuf_head(buf), 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(buf), 0, 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (struct sockaddr *) from, fromlen); 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("sendto[RADIUS SRV]"); 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("No previous reply available for duplicate " 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "message"); 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 76361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt eap = radius_msg_get_eap(msg); 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) { 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("No EAP-Message in RADIUS packet from %s", 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt from_addr); 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counters.packets_dropped++; 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt client->counters.packets_dropped++; 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 77261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt RADIUS_DUMP("Received EAP data", wpabuf_head(eap), wpabuf_len(eap)); 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: if Code is Request, Success, or Failure, send Access-Reject; 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RFC3579 Sect. 2.6.2. 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Include EAP-Response/Nak with no preferred method if 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * code == request. 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * If code is not 1-4, discard the packet silently. 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Or is this already done by the EAP state machine? */ 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(sess->eap_if->eapRespData); 78261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sess->eap_if->eapRespData = eap; 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess->eap_if->eapResp = TRUE; 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_server_sm_step(sess->eap); 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((sess->eap_if->eapReq || sess->eap_if->eapSuccess || 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess->eap_if->eapFail) && sess->eap_if->eapReqData) { 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DUMP("EAP data from the state machine", 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_head(sess->eap_if->eapReqData), 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(sess->eap_if->eapReqData)); 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (sess->eap_if->eapFail) { 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("No EAP data from the state machine, but eapFail " 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "set"); 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (eap_sm_method_pending(sess->eap)) { 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_free(sess->last_msg); 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess->last_msg = msg; 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess->last_from_port = from_port; 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sess->last_from_addr); 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess->last_from_addr = os_strdup(from_addr); 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess->last_fromlen = fromlen; 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&sess->last_from, from, fromlen); 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -2; 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("No EAP data from the state machine - ignore this" 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " Access-Request silently (assuming it was a " 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "duplicate)"); 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counters.packets_dropped++; 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt client->counters.packets_dropped++; 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sess->eap_if->eapSuccess || sess->eap_if->eapFail) 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt is_complete = 1; 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply = radius_server_encapsulate_eap(data, client, sess, msg); 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (reply) { 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_hdr *hdr; 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("Reply to %s:%d", from_addr, from_port); 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_debug_level <= MSG_MSGDUMP) { 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_dump(reply); 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (radius_msg_get_hdr(reply)->code) { 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case RADIUS_CODE_ACCESS_ACCEPT: 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counters.access_accepts++; 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt client->counters.access_accepts++; 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case RADIUS_CODE_ACCESS_REJECT: 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counters.access_rejects++; 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt client->counters.access_rejects++; 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case RADIUS_CODE_ACCESS_CHALLENGE: 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counters.access_challenges++; 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt client->counters.access_challenges++; 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = radius_msg_get_buf(reply); 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = sendto(data->auth_sock, wpabuf_head(buf), 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(buf), 0, 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (struct sockaddr *) from, fromlen); 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("sendto[RADIUS SRV]"); 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_free(sess->last_reply); 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess->last_reply = reply; 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess->last_from_port = from_port; 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = radius_msg_get_hdr(msg); 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess->last_identifier = hdr->identifier; 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sess->last_authenticator, hdr->authenticator, 16); 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counters.packets_dropped++; 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt client->counters.packets_dropped++; 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (is_complete) { 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("Removing completed session 0x%x after timeout", 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess->sess_id); 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(radius_server_session_remove_timeout, 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data, sess); 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(10, 0, 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_server_session_remove_timeout, 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data, sess); 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void radius_server_receive_auth(int sock, void *eloop_ctx, 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *sock_ctx) 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_server_data *data = eloop_ctx; 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf = NULL; 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union { 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_storage ss; 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in sin; 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IPV6 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in6 sin6; 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IPV6 */ 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } from; 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt socklen_t fromlen; 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int len; 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_client *client = NULL; 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg *msg = NULL; 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char abuf[50]; 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int from_port = 0; 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_malloc(RADIUS_MAX_MSG_LEN); 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fromlen = sizeof(from); 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = recvfrom(sock, buf, RADIUS_MAX_MSG_LEN, 0, 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (struct sockaddr *) &from.ss, &fromlen); 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < 0) { 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("recvfrom[radius_server]"); 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IPV6 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->ipv6) { 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (inet_ntop(AF_INET6, &from.sin6.sin6_addr, abuf, 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(abuf)) == NULL) 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt abuf[0] = '\0'; 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt from_port = ntohs(from.sin6.sin6_port); 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("Received %d bytes from %s:%d", 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len, abuf, from_port); 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt client = radius_server_get_client(data, 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (struct in_addr *) 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &from.sin6.sin6_addr, 1); 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IPV6 */ 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!data->ipv6) { 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf)); 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt from_port = ntohs(from.sin.sin_port); 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("Received %d bytes from %s:%d", 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len, abuf, from_port); 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt client = radius_server_get_client(data, &from.sin.sin_addr, 0); 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DUMP("Received data", buf, len); 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (client == NULL) { 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("Unknown client %s - packet ignored", abuf); 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counters.invalid_requests++; 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = radius_msg_parse(buf, len); 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) { 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("Parsing incoming RADIUS frame failed"); 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counters.malformed_access_requests++; 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt client->counters.malformed_access_requests++; 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = NULL; 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_debug_level <= MSG_MSGDUMP) { 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_dump(msg); 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius_msg_get_hdr(msg)->code != RADIUS_CODE_ACCESS_REQUEST) { 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("Unexpected RADIUS code %d", 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_get_hdr(msg)->code); 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counters.unknown_types++; 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt client->counters.unknown_types++; 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counters.access_requests++; 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt client->counters.access_requests++; 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius_msg_verify_msg_auth(msg, (u8 *) client->shared_secret, 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt client->shared_secret_len, NULL)) { 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("Invalid Message-Authenticator from %s", abuf); 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counters.bad_authenticators++; 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt client->counters.bad_authenticators++; 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius_server_request(data, msg, (struct sockaddr *) &from, 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fromlen, client, abuf, from_port, NULL) == 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt -2) 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; /* msg was stored with the session */ 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail: 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_free(msg); 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int radius_server_disable_pmtu_discovery(int s) 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int r = -1; 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Turn off Path MTU discovery on IPv4/UDP sockets. */ 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int action = IP_PMTUDISC_DONT; 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r = setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &action, 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(action)); 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (r == -1) 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Failed to set IP_MTU_DISCOVER: " 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%s", strerror(errno)); 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return r; 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int radius_server_open_socket(int port) 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int s; 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in addr; 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = socket(PF_INET, SOCK_DGRAM, 0); 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (s < 0) { 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("socket"); 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_server_disable_pmtu_discovery(s); 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&addr, 0, sizeof(addr)); 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr.sin_family = AF_INET; 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr.sin_port = htons(port); 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("bind"); 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(s); 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return s; 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IPV6 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int radius_server_open_socket6(int port) 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int s; 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in6 addr; 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = socket(PF_INET6, SOCK_DGRAM, 0); 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (s < 0) { 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("socket[IPv6]"); 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&addr, 0, sizeof(addr)); 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr.sin6_family = AF_INET6; 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any)); 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr.sin6_port = htons(port); 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("bind"); 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(s); 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return s; 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IPV6 */ 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void radius_server_free_sessions(struct radius_server_data *data, 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_session *sessions) 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_session *session, *prev; 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt session = sessions; 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (session) { 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = session; 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt session = session->next; 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_server_session_free(data, prev); 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void radius_server_free_clients(struct radius_server_data *data, 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_client *clients) 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_client *client, *prev; 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt client = clients; 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (client) { 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = client; 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt client = client->next; 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_server_free_sessions(data, prev->sessions); 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(prev->shared_secret); 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(prev); 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct radius_client * 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtradius_server_read_clients(const char *client_file, int ipv6) 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt FILE *f; 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const int buf_size = 1024; 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *buf, *pos; 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_client *clients, *tail, *entry; 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int line = 0, mask, failed = 0, i; 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct in_addr addr; 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IPV6 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct in6_addr addr6; 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IPV6 */ 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int val; 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt f = fopen(client_file, "r"); 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (f == NULL) { 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_ERROR("Could not open client file '%s'", client_file); 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_malloc(buf_size); 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fclose(f); 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt clients = tail = NULL; 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (fgets(buf, buf_size, f)) { 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Configuration file format: 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 192.168.1.0/24 secret 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 192.168.1.2 secret 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * fe80::211:22ff:fe33:4455/64 secretipv6 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt line++; 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[buf_size - 1] = '\0'; 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*pos != '\0' && *pos != '\n') 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos++; 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*pos == '\n') 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos = '\0'; 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*buf == '\0' || *buf == '#') 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while ((*pos >= '0' && *pos <= '9') || *pos == '.' || 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (*pos >= 'a' && *pos <= 'f') || *pos == ':' || 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (*pos >= 'A' && *pos <= 'F')) { 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos++; 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*pos == '\0') { 11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt failed = 1; 11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*pos == '/') { 11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *end; 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = '\0'; 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mask = strtol(pos, &end, 10); 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((pos == end) || 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (mask < 0 || mask > (ipv6 ? 128 : 32))) { 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt failed = 1; 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = end; 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mask = ipv6 ? 128 : 32; 11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = '\0'; 11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ipv6 && inet_aton(buf, &addr) == 0) { 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt failed = 1; 11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IPV6 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ipv6 && inet_pton(AF_INET6, buf, &addr6) <= 0) { 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (inet_pton(AF_INET, buf, &addr) <= 0) { 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt failed = 1; 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Convert IPv4 address to IPv6 */ 11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mask <= 32) 11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mask += (128 - 32); 11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(addr6.s6_addr, 0, 10); 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr6.s6_addr[10] = 0xff; 11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr6.s6_addr[11] = 0xff; 11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(addr6.s6_addr + 12, (char *) &addr.s_addr, 11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4); 11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IPV6 */ 11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*pos == ' ' || *pos == '\t') { 11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos++; 11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*pos == '\0') { 11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt failed = 1; 11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = os_zalloc(sizeof(*entry)); 11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (entry == NULL) { 11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt failed = 1; 11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->shared_secret = os_strdup(pos); 11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (entry->shared_secret == NULL) { 11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt failed = 1; 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(entry); 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->shared_secret_len = os_strlen(entry->shared_secret); 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->addr.s_addr = addr.s_addr; 11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ipv6) { 11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt val = 0; 11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < mask; i++) 11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt val |= 1 << (31 - i); 11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->mask.s_addr = htonl(val); 11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IPV6 12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ipv6) { 12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int offset = mask / 8; 12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(entry->addr6.s6_addr, addr6.s6_addr, 16); 12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(entry->mask6.s6_addr, 0xff, offset); 12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt val = 0; 12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < (mask % 8); i++) 12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt val |= 1 << (7 - i); 12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (offset < 16) 12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->mask6.s6_addr[offset] = val; 12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IPV6 */ 12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tail == NULL) { 12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt clients = tail = entry; 12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tail->next = entry; 12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tail = entry; 12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (failed) { 12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_ERROR("Invalid line %d in '%s'", line, client_file); 12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_server_free_clients(NULL, clients); 12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt clients = NULL; 12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fclose(f); 12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return clients; 12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * radius_server_init - Initialize RADIUS server 12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @conf: Configuration for the RADIUS server 12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to private RADIUS server context or %NULL on failure 12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This initializes a RADIUS server instance and returns a context pointer that 12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * will be used in other calls to the RADIUS server module. The server can be 12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * deinitialize by calling radius_server_deinit(). 12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct radius_server_data * 12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtradius_server_init(struct radius_server_conf *conf) 12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_server_data *data; 12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_IPV6 12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->ipv6) { 12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fprintf(stderr, "RADIUS server compiled without IPv6 " 12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "support.\n"); 12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IPV6 */ 12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = os_zalloc(sizeof(*data)); 12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_get_time(&data->start_time); 12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->conf_ctx = conf->conf_ctx; 12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->eap_sim_db_priv = conf->eap_sim_db_priv; 12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ssl_ctx = conf->ssl_ctx; 12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->msg_ctx = conf->msg_ctx; 12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ipv6 = conf->ipv6; 12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->pac_opaque_encr_key) { 12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pac_opaque_encr_key = os_malloc(16); 12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->pac_opaque_encr_key, conf->pac_opaque_encr_key, 12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16); 12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->eap_fast_a_id) { 12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->eap_fast_a_id = os_malloc(conf->eap_fast_a_id_len); 12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_fast_a_id) { 12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->eap_fast_a_id, conf->eap_fast_a_id, 12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf->eap_fast_a_id_len); 12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->eap_fast_a_id_len = conf->eap_fast_a_id_len; 12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->eap_fast_a_id_info) 12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->eap_fast_a_id_info = os_strdup(conf->eap_fast_a_id_info); 12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->eap_fast_prov = conf->eap_fast_prov; 12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pac_key_lifetime = conf->pac_key_lifetime; 12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pac_key_refresh_time = conf->pac_key_refresh_time; 12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->get_eap_user = conf->get_eap_user; 12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind; 12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tnc = conf->tnc; 12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->wps = conf->wps; 12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pwd_group = conf->pwd_group; 129034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->server_id = conf->server_id; 12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->eap_req_id_text) { 12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->eap_req_id_text = os_malloc(conf->eap_req_id_text_len); 12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_req_id_text) { 12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->eap_req_id_text, conf->eap_req_id_text, 12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf->eap_req_id_text_len); 12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->eap_req_id_text_len = conf->eap_req_id_text_len; 12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_RADIUS_TEST 13011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (conf->dump_msk_file) 13021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt data->dump_msk_file = os_strdup(conf->dump_msk_file); 13031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_RADIUS_TEST */ 13041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->clients = radius_server_read_clients(conf->client_file, 13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf->ipv6); 13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->clients == NULL) { 13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("No RADIUS clients configured.\n"); 13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_server_deinit(data); 13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IPV6 13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->ipv6) 13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->auth_sock = radius_server_open_socket6(conf->auth_port); 13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IPV6 */ 13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->auth_sock = radius_server_open_socket(conf->auth_port); 13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->auth_sock < 0) { 13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Failed to open UDP socket for RADIUS authentication " 13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "server\n"); 13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_server_deinit(data); 13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eloop_register_read_sock(data->auth_sock, 13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_server_receive_auth, 13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data, NULL)) { 13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_server_deinit(data); 13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data; 13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * radius_server_deinit - Deinitialize RADIUS server 13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: RADIUS server context from radius_server_init() 13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid radius_server_deinit(struct radius_server_data *data) 13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->auth_sock >= 0) { 13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_unregister_read_sock(data->auth_sock); 13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(data->auth_sock); 13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_server_free_clients(data, data->clients); 13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->pac_opaque_encr_key); 13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->eap_fast_a_id); 13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->eap_fast_a_id_info); 13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->eap_req_id_text); 13561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_RADIUS_TEST 13571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(data->dump_msk_file); 13581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_RADIUS_TEST */ 13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * radius_server_get_mib - Get RADIUS server MIB information 13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: RADIUS server context from radius_server_init() 13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Buffer for returning the MIB data in text format 13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buflen: buf length in octets 13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Number of octets written into buf 13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint radius_server_get_mib(struct radius_server_data *data, char *buf, 13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buflen) 13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret, uptime; 13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int idx; 13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *end, *pos; 13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct os_time now; 13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_client *cli; 13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RFC 2619 - RADIUS Authentication Server MIB */ 13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL || buflen == 0) 13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = buf + buflen; 13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_get_time(&now); 13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uptime = (now.sec - data->start_time.sec) * 100 + 13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ((now.usec - data->start_time.usec) / 10000) % 100; 13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(pos, end - pos, 13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RADIUS-AUTH-SERVER-MIB\n" 13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthServIdent=hostapd\n" 13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthServUpTime=%d\n" 13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthServResetTime=0\n" 13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthServConfigReset=4\n", 13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uptime); 13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || ret >= end - pos) { 13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos = '\0'; 13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos - buf; 14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ret; 14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(pos, end - pos, 14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthServTotalAccessRequests=%u\n" 14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthServTotalInvalidRequests=%u\n" 14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthServTotalDupAccessRequests=%u\n" 14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthServTotalAccessAccepts=%u\n" 14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthServTotalAccessRejects=%u\n" 14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthServTotalAccessChallenges=%u\n" 14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthServTotalMalformedAccessRequests=%u\n" 14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthServTotalBadAuthenticators=%u\n" 14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthServTotalPacketsDropped=%u\n" 14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthServTotalUnknownTypes=%u\n", 14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counters.access_requests, 14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counters.invalid_requests, 14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counters.dup_access_requests, 14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counters.access_accepts, 14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counters.access_rejects, 14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counters.access_challenges, 14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counters.malformed_access_requests, 14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counters.bad_authenticators, 14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counters.packets_dropped, 14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counters.unknown_types); 14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || ret >= end - pos) { 14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos = '\0'; 14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos - buf; 14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ret; 14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (cli = data->clients, idx = 0; cli; cli = cli->next, idx++) { 14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char abuf[50], mbuf[50]; 14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IPV6 14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->ipv6) { 14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (inet_ntop(AF_INET6, &cli->addr6, abuf, 14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(abuf)) == NULL) 14368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt abuf[0] = '\0'; 14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (inet_ntop(AF_INET6, &cli->mask6, abuf, 14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(mbuf)) == NULL) 14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mbuf[0] = '\0'; 14408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IPV6 */ 14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!data->ipv6) { 14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(abuf, inet_ntoa(cli->addr), sizeof(abuf)); 14448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(mbuf, inet_ntoa(cli->mask), sizeof(mbuf)); 14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(pos, end - pos, 14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthClientIndex=%u\n" 14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthClientAddress=%s/%s\n" 14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthServAccessRequests=%u\n" 14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthServDupAccessRequests=%u\n" 14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthServAccessAccepts=%u\n" 14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthServAccessRejects=%u\n" 14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthServAccessChallenges=%u\n" 14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthServMalformedAccessRequests=%u\n" 14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthServBadAuthenticators=%u\n" 14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthServPacketsDropped=%u\n" 14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthServUnknownTypes=%u\n", 14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt idx, 14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt abuf, mbuf, 14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cli->counters.access_requests, 14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cli->counters.dup_access_requests, 14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cli->counters.access_accepts, 14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cli->counters.access_rejects, 14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cli->counters.access_challenges, 14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cli->counters.malformed_access_requests, 14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cli->counters.bad_authenticators, 14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cli->counters.packets_dropped, 14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cli->counters.unknown_types); 14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || ret >= end - pos) { 14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos = '\0'; 14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos - buf; 14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ret; 14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos - buf; 14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int radius_server_get_eap_user(void *ctx, const u8 *identity, 14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t identity_len, int phase2, 14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_user *user) 14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_session *sess = ctx; 14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_server_data *data = sess->server; 14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->get_eap_user(data->conf_ctx, identity, identity_len, 14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phase2, user); 14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * radius_server_get_eap_req_id_text(void *ctx, size_t *len) 14948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_session *sess = ctx; 14968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_server_data *data = sess->server; 14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = data->eap_req_id_text_len; 14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->eap_req_id_text; 14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct eapol_callbacks radius_server_eapol_cb = 15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .get_eap_user = radius_server_get_eap_user, 15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .get_eap_req_id_text = radius_server_get_eap_req_id_text, 15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * radius_server_eap_pending_cb - Pending EAP data notification 15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: RADIUS server context from radius_server_init() 15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ctx: Pending EAP context pointer 15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to notify EAP server module that a pending operation 15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * has been completed and processing of the EAP session can proceed. 15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid radius_server_eap_pending_cb(struct radius_server_data *data, void *ctx) 15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_client *cli; 15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_session *s, *sess = NULL; 15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg *msg; 15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 15248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (cli = data->clients; cli; cli = cli->next) { 15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (s = cli->sessions; s; s = s->next) { 15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (s->eap == ctx && s->last_msg) { 15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess = s; 15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sess) 15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sess) 15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sess == NULL) { 15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_DEBUG("No session matched callback ctx"); 15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = sess->last_msg; 15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess->last_msg = NULL; 15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sm_pending_cb(sess->eap); 15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius_server_request(data, msg, 15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (struct sockaddr *) &sess->last_from, 15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess->last_fromlen, cli, 15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess->last_from_addr, 15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sess->last_from_port, sess) == -2) 15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; /* msg was stored with the session */ 15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_free(msg); 15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1556