1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* 2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * hostapd / RADIUS authentication server 3526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright (c) 2005-2008, Jouni Malinen <j@w1.fi> 4526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 5526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This program is free software; you can redistribute it and/or modify 6526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * it under the terms of the GNU General Public License version 2 as 7526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * published by the Free Software Foundation. 8526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 9526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 10526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * license. 11526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 12526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * See README and COPYING for more details. 13526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 14526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 15526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "includes.h" 16526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <net/if.h> 17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 18526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "common.h" 19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "radius.h" 20526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eloop.h" 21526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "defs.h" 22526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eap_server/eap.h" 23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "radius_server.h" 24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define RADIUS_SESSION_TIMEOUT 60 26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define RADIUS_MAX_SESSION 100 27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define RADIUS_MAX_MSG_LEN 3000 28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct eapol_callbacks radius_server_eapol_cb; 30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct radius_client; 32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct radius_server_data; 33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct radius_server_counters { 35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u32 access_requests; 36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u32 invalid_requests; 37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u32 dup_access_requests; 38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u32 access_accepts; 39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u32 access_rejects; 40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u32 access_challenges; 41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u32 malformed_access_requests; 42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u32 bad_authenticators; 43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u32 packets_dropped; 44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u32 unknown_types; 45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}; 46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct radius_session { 48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_session *next; 49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_client *client; 50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_server_data *server; 51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt unsigned int sess_id; 52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_sm *eap; 53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_eapol_interface *eap_if; 54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg *last_msg; 56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char *last_from_addr; 57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int last_from_port; 58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct sockaddr_storage last_from; 59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt socklen_t last_fromlen; 60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 last_identifier; 61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg *last_reply; 62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 last_authenticator[16]; 63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}; 64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct radius_client { 66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_client *next; 67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct in_addr addr; 68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct in_addr mask; 69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IPV6 70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct in6_addr addr6; 71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct in6_addr mask6; 72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IPV6 */ 73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char *shared_secret; 74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int shared_secret_len; 75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_session *sessions; 76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_server_counters counters; 77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}; 78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct radius_server_data { 80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int auth_sock; 81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_client *clients; 82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt unsigned int next_sess_id; 83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt void *conf_ctx; 84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int num_sess; 85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt void *eap_sim_db_priv; 86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt void *ssl_ctx; 87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *pac_opaque_encr_key; 88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *eap_fast_a_id; 89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t eap_fast_a_id_len; 90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char *eap_fast_a_id_info; 91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int eap_fast_prov; 92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int pac_key_lifetime; 93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int pac_key_refresh_time; 94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int eap_sim_aka_result_ind; 95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int tnc; 96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wps_context *wps; 97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int ipv6; 98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct os_time start_time; 99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_server_counters counters; 100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len, 101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int phase2, struct eap_user *user); 102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char *eap_req_id_text; 103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t eap_req_id_text_len; 104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}; 105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtextern int wpa_debug_level; 108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define RADIUS_DEBUG(args...) \ 110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtwpa_printf(MSG_DEBUG, "RADIUS SRV: " args) 111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define RADIUS_ERROR(args...) \ 112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtwpa_printf(MSG_ERROR, "RADIUS SRV: " args) 113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define RADIUS_DUMP(args...) \ 114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtwpa_hexdump(MSG_MSGDUMP, "RADIUS SRV: " args) 115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define RADIUS_DUMP_ASCII(args...) \ 116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtwpa_hexdump_ascii(MSG_MSGDUMP, "RADIUS SRV: " args) 117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx); 120dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidtstatic void radius_server_session_remove_timeout(void *eloop_ctx, 121dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt void *timeout_ctx); 122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct radius_client * 125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtradius_server_get_client(struct radius_server_data *data, struct in_addr *addr, 126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int ipv6) 127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_client *client = data->clients; 129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (client) { 131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IPV6 132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ipv6) { 133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct in6_addr *addr6; 134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int i; 135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr6 = (struct in6_addr *) addr; 137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (i = 0; i < 16; i++) { 138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if ((addr6->s6_addr[i] & 139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt client->mask6.s6_addr[i]) != 140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (client->addr6.s6_addr[i] & 141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt client->mask6.s6_addr[i])) { 142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt i = 17; 143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (i == 16) { 147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IPV6 */ 151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!ipv6 && (client->addr.s_addr & client->mask.s_addr) == 152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (addr->s_addr & client->mask.s_addr)) { 153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt client = client->next; 157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return client; 160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct radius_session * 164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtradius_server_get_session(struct radius_client *client, unsigned int sess_id) 165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_session *sess = client->sessions; 167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (sess) { 169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sess->sess_id == sess_id) { 170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess = sess->next; 173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return sess; 176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void radius_server_session_free(struct radius_server_data *data, 180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_session *sess) 181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_cancel_timeout(radius_server_session_timeout, data, sess); 183dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess); 184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_server_sm_deinit(sess->eap); 185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sess->last_msg) { 186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_msg_free(sess->last_msg); 187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(sess->last_msg); 188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(sess->last_from_addr); 190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sess->last_reply) { 191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_msg_free(sess->last_reply); 192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(sess->last_reply); 193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(sess); 195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->num_sess--; 196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void radius_server_session_remove(struct radius_server_data *data, 200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_session *sess) 201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_client *client = sess->client; 203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_session *session, *prev; 204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess); 206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prev = NULL; 208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt session = client->sessions; 209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (session) { 210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (session == sess) { 211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (prev == NULL) { 212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt client->sessions = sess->next; 213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prev->next = sess->next; 215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_server_session_free(data, sess); 217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prev = session; 220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt session = session->next; 221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void radius_server_session_remove_timeout(void *eloop_ctx, 226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt void *timeout_ctx) 227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_server_data *data = eloop_ctx; 229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_session *sess = timeout_ctx; 230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("Removing completed session 0x%x", sess->sess_id); 231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_server_session_remove(data, sess); 232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx) 236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_server_data *data = eloop_ctx; 238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_session *sess = timeout_ctx; 239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("Timing out authentication session 0x%x", sess->sess_id); 241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_server_session_remove(data, sess); 242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct radius_session * 246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtradius_server_new_session(struct radius_server_data *data, 247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_client *client) 248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_session *sess; 250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->num_sess >= RADIUS_MAX_SESSION) { 252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("Maximum number of existing session - no room " 253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "for a new session"); 254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess = os_zalloc(sizeof(*sess)); 258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sess == NULL) 259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess->server = data; 262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess->client = client; 263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess->sess_id = data->next_sess_id++; 264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess->next = client->sessions; 265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt client->sessions = sess; 266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_register_timeout(RADIUS_SESSION_TIMEOUT, 0, 267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_server_session_timeout, data, sess); 268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->num_sess++; 269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return sess; 270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct radius_session * 274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtradius_server_get_new_session(struct radius_server_data *data, 275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_client *client, 276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg *msg) 277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *user; 279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t user_len; 280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int res; 281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_session *sess; 282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_config eap_conf; 283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("Creating a new session"); 285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt user = os_malloc(256); 287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (user == NULL) { 288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 289526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 290526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt res = radius_msg_get_attr(msg, RADIUS_ATTR_USER_NAME, user, 256); 291526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (res < 0 || res > 256) { 292526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("Could not get User-Name"); 293526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(user); 294526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 295526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt user_len = res; 297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DUMP_ASCII("User-Name", user, user_len); 298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt res = data->get_eap_user(data->conf_ctx, user, user_len, 0, NULL); 300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(user); 301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 302526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (res == 0) { 303526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("Matching user entry found"); 304526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess = radius_server_new_session(data, client); 305526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sess == NULL) { 306526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("Failed to create a new session"); 307526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 308526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 309526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 310526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("User-Name not found from user database"); 311526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 312526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 313526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 314526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(&eap_conf, 0, sizeof(eap_conf)); 315526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_conf.ssl_ctx = data->ssl_ctx; 316526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_conf.eap_sim_db_priv = data->eap_sim_db_priv; 317526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_conf.backend_auth = TRUE; 318526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_conf.eap_server = 1; 319526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_conf.pac_opaque_encr_key = data->pac_opaque_encr_key; 320526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_conf.eap_fast_a_id = data->eap_fast_a_id; 321526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_conf.eap_fast_a_id_len = data->eap_fast_a_id_len; 322526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_conf.eap_fast_a_id_info = data->eap_fast_a_id_info; 323526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_conf.eap_fast_prov = data->eap_fast_prov; 324526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_conf.pac_key_lifetime = data->pac_key_lifetime; 325526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_conf.pac_key_refresh_time = data->pac_key_refresh_time; 326526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_conf.eap_sim_aka_result_ind = data->eap_sim_aka_result_ind; 327526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_conf.tnc = data->tnc; 328526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_conf.wps = data->wps; 329526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess->eap = eap_server_sm_init(sess, &radius_server_eapol_cb, 330526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt &eap_conf); 331526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sess->eap == NULL) { 332526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("Failed to initialize EAP state machine for the " 333526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "new session"); 334526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_server_session_free(data, sess); 335526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 336526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 337526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess->eap_if = eap_get_interface(sess->eap); 338526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess->eap_if->eapRestart = TRUE; 339526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess->eap_if->portEnabled = TRUE; 340526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 341526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("New session 0x%x initialized", sess->sess_id); 342526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 343526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return sess; 344526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 345526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 346526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 347526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct radius_msg * 348526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtradius_server_encapsulate_eap(struct radius_server_data *data, 349526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_client *client, 350526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_session *sess, 351526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg *request) 352526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 353526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg *msg; 354526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int code; 355526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt unsigned int sess_id; 356526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 357526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sess->eap_if->eapFail) { 358526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess->eap_if->eapFail = FALSE; 359526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt code = RADIUS_CODE_ACCESS_REJECT; 360526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else if (sess->eap_if->eapSuccess) { 361526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess->eap_if->eapSuccess = FALSE; 362526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt code = RADIUS_CODE_ACCESS_ACCEPT; 363526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 364526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess->eap_if->eapReq = FALSE; 365526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt code = RADIUS_CODE_ACCESS_CHALLENGE; 366526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 367526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 368526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt msg = radius_msg_new(code, request->hdr->identifier); 369526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (msg == NULL) { 370526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("Failed to allocate reply message"); 371526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 372526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 373526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 374526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess_id = htonl(sess->sess_id); 375526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (code == RADIUS_CODE_ACCESS_CHALLENGE && 376526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt !radius_msg_add_attr(msg, RADIUS_ATTR_STATE, 377526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (u8 *) &sess_id, sizeof(sess_id))) { 378526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("Failed to add State attribute"); 379526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 380526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 381526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sess->eap_if->eapReqData && 382526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt !radius_msg_add_eap(msg, wpabuf_head(sess->eap_if->eapReqData), 383526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_len(sess->eap_if->eapReqData))) { 384526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("Failed to add EAP-Message attribute"); 385526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 386526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 387526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->eap_if->eapKeyData) { 388526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int len; 389526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sess->eap_if->eapKeyDataLen > 64) { 390526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len = 32; 391526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 392526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len = sess->eap_if->eapKeyDataLen / 2; 393526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 394526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!radius_msg_add_mppe_keys(msg, request->hdr->authenticator, 395526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (u8 *) client->shared_secret, 396526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt client->shared_secret_len, 397526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess->eap_if->eapKeyData + len, 398526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len, sess->eap_if->eapKeyData, 399526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len)) { 400526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("Failed to add MPPE key attributes"); 401526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 402526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 403526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 404526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) { 405526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)"); 406526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_msg_free(msg); 407526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(msg); 408526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 409526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 410526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 411526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret, 412526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt client->shared_secret_len, 413526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt request->hdr->authenticator) < 0) { 414526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("Failed to add Message-Authenticator attribute"); 415526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 416526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 417526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return msg; 418526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 419526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 420526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 421526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int radius_server_reject(struct radius_server_data *data, 422526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_client *client, 423526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg *request, 424526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct sockaddr *from, socklen_t fromlen, 425526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const char *from_addr, int from_port) 426526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 427526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg *msg; 428526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int ret = 0; 429526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_hdr eapfail; 430526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 431526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("Reject invalid request from %s:%d", 432526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt from_addr, from_port); 433526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 434526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt msg = radius_msg_new(RADIUS_CODE_ACCESS_REJECT, 435526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt request->hdr->identifier); 436526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (msg == NULL) { 437526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 438526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 439526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 440526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(&eapfail, 0, sizeof(eapfail)); 441526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eapfail.code = EAP_CODE_FAILURE; 442526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eapfail.identifier = 0; 443526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eapfail.length = host_to_be16(sizeof(eapfail)); 444526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 445526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!radius_msg_add_eap(msg, (u8 *) &eapfail, sizeof(eapfail))) { 446526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("Failed to add EAP-Message attribute"); 447526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 448526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 449526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) { 450526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)"); 451526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_msg_free(msg); 452526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(msg); 453526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 454526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 455526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 456526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret, 457526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt client->shared_secret_len, 458526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt request->hdr->authenticator) < 0) { 459526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("Failed to add Message-Authenticator attribute"); 460526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 461526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 462526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpa_debug_level <= MSG_MSGDUMP) { 463526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_msg_dump(msg); 464526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 465526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 466526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->counters.access_rejects++; 467526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt client->counters.access_rejects++; 468526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sendto(data->auth_sock, msg->buf, msg->buf_used, 0, 469526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (struct sockaddr *) from, sizeof(*from)) < 0) { 470526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("sendto[RADIUS SRV]"); 471526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = -1; 472526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 473526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 474526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_msg_free(msg); 475526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(msg); 476526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 477526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return ret; 478526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 479526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 480526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 481526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int radius_server_request(struct radius_server_data *data, 482526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg *msg, 483526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct sockaddr *from, socklen_t fromlen, 484526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_client *client, 485526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const char *from_addr, int from_port, 486526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_session *force_sess) 487526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 488526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *eap = NULL; 489526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t eap_len; 490526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int res, state_included = 0; 491526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 statebuf[4]; 492526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt unsigned int state; 493526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_session *sess; 494526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg *reply; 495dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt int is_complete = 0; 496526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 497526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (force_sess) 498526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess = force_sess; 499526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else { 500526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt res = radius_msg_get_attr(msg, RADIUS_ATTR_STATE, statebuf, 501526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(statebuf)); 502526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt state_included = res >= 0; 503526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (res == sizeof(statebuf)) { 504526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt state = WPA_GET_BE32(statebuf); 505526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess = radius_server_get_session(client, state); 506526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 507526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess = NULL; 508526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 509526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 510526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 511526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sess) { 512526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("Request for session 0x%x", sess->sess_id); 513526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else if (state_included) { 514526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("State attribute included but no session found"); 515526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_server_reject(data, client, msg, from, fromlen, 516526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt from_addr, from_port); 517526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 518526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 519526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess = radius_server_get_new_session(data, client, msg); 520526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sess == NULL) { 521526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("Could not create a new session"); 522526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_server_reject(data, client, msg, from, fromlen, 523526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt from_addr, from_port); 524526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 525526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 526526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 527526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 528526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sess->last_from_port == from_port && 529526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess->last_identifier == msg->hdr->identifier && 530526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcmp(sess->last_authenticator, msg->hdr->authenticator, 16) == 531526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 0) { 532526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("Duplicate message from %s", from_addr); 533526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->counters.dup_access_requests++; 534526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt client->counters.dup_access_requests++; 535526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 536526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sess->last_reply) { 537526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt res = sendto(data->auth_sock, sess->last_reply->buf, 538526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess->last_reply->buf_used, 0, 539526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (struct sockaddr *) from, fromlen); 540526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (res < 0) { 541526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("sendto[RADIUS SRV]"); 542526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 543526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 544526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 545526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 546526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("No previous reply available for duplicate " 547526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "message"); 548526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 549526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 550526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 551526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap = radius_msg_get_eap(msg, &eap_len); 552526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap == NULL) { 553526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("No EAP-Message in RADIUS packet from %s", 554526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt from_addr); 555526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->counters.packets_dropped++; 556526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt client->counters.packets_dropped++; 557526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 558526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 559526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 560526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DUMP("Received EAP data", eap, eap_len); 561526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 562526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* FIX: if Code is Request, Success, or Failure, send Access-Reject; 563526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * RFC3579 Sect. 2.6.2. 564526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Include EAP-Response/Nak with no preferred method if 565526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * code == request. 566526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * If code is not 1-4, discard the packet silently. 567526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Or is this already done by the EAP state machine? */ 568526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 569526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(sess->eap_if->eapRespData); 570526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess->eap_if->eapRespData = wpabuf_alloc_ext_data(eap, eap_len); 571526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sess->eap_if->eapRespData == NULL) 572526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(eap); 573526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap = NULL; 574526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess->eap_if->eapResp = TRUE; 575526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_server_sm_step(sess->eap); 576526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 577526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if ((sess->eap_if->eapReq || sess->eap_if->eapSuccess || 578526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess->eap_if->eapFail) && sess->eap_if->eapReqData) { 579526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DUMP("EAP data from the state machine", 580526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_head(sess->eap_if->eapReqData), 581526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_len(sess->eap_if->eapReqData)); 582526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else if (sess->eap_if->eapFail) { 583526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("No EAP data from the state machine, but eapFail " 584526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "set"); 585526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else if (eap_sm_method_pending(sess->eap)) { 586526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sess->last_msg) { 587526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_msg_free(sess->last_msg); 588526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(sess->last_msg); 589526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 590526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess->last_msg = msg; 591526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess->last_from_port = from_port; 592526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(sess->last_from_addr); 593526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess->last_from_addr = os_strdup(from_addr); 594526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess->last_fromlen = fromlen; 595526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(&sess->last_from, from, fromlen); 596526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -2; 597526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 598526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("No EAP data from the state machine - ignore this" 599526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt " Access-Request silently (assuming it was a " 600526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "duplicate)"); 601526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->counters.packets_dropped++; 602526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt client->counters.packets_dropped++; 603526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 604526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 605526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 606dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt if (sess->eap_if->eapSuccess || sess->eap_if->eapFail) 607dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt is_complete = 1; 608dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt 609526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt reply = radius_server_encapsulate_eap(data, client, sess, msg); 610526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 611526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (reply) { 612526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("Reply to %s:%d", from_addr, from_port); 613526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpa_debug_level <= MSG_MSGDUMP) { 614526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_msg_dump(reply); 615526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 616526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 617526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (reply->hdr->code) { 618526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case RADIUS_CODE_ACCESS_ACCEPT: 619526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->counters.access_accepts++; 620526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt client->counters.access_accepts++; 621526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 622526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case RADIUS_CODE_ACCESS_REJECT: 623526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->counters.access_rejects++; 624526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt client->counters.access_rejects++; 625526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 626526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case RADIUS_CODE_ACCESS_CHALLENGE: 627526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->counters.access_challenges++; 628526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt client->counters.access_challenges++; 629526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 630526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 631526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt res = sendto(data->auth_sock, reply->buf, reply->buf_used, 0, 632526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (struct sockaddr *) from, fromlen); 633526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (res < 0) { 634526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("sendto[RADIUS SRV]"); 635526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 636526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sess->last_reply) { 637526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_msg_free(sess->last_reply); 638526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(sess->last_reply); 639526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 640526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess->last_reply = reply; 641526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess->last_from_port = from_port; 642526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess->last_identifier = msg->hdr->identifier; 643526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(sess->last_authenticator, msg->hdr->authenticator, 644526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 16); 645526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 646526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->counters.packets_dropped++; 647526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt client->counters.packets_dropped++; 648526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 649526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 650dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt if (is_complete) { 651526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("Removing completed session 0x%x after timeout", 652526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess->sess_id); 653526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_cancel_timeout(radius_server_session_remove_timeout, 654526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data, sess); 655526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_register_timeout(10, 0, 656526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_server_session_remove_timeout, 657526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data, sess); 658526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 659526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 660526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 661526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 662526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 663526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 664526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void radius_server_receive_auth(int sock, void *eloop_ctx, 665526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt void *sock_ctx) 666526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 667526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_server_data *data = eloop_ctx; 668526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *buf = NULL; 669dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt union { 670dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt struct sockaddr_storage ss; 671dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt struct sockaddr_in sin; 672dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt#ifdef CONFIG_IPV6 673dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt struct sockaddr_in6 sin6; 674dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt#endif /* CONFIG_IPV6 */ 675dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt } from; 676526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt socklen_t fromlen; 677526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int len; 678526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_client *client = NULL; 679526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg *msg = NULL; 680526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char abuf[50]; 681526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int from_port = 0; 682526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 683526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf = os_malloc(RADIUS_MAX_MSG_LEN); 684526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (buf == NULL) { 685526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt goto fail; 686526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 687526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 688526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt fromlen = sizeof(from); 689526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len = recvfrom(sock, buf, RADIUS_MAX_MSG_LEN, 0, 690dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt (struct sockaddr *) &from.ss, &fromlen); 691526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (len < 0) { 692526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("recvfrom[radius_server]"); 693526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt goto fail; 694526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 695526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 696526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IPV6 697526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->ipv6) { 698dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt if (inet_ntop(AF_INET6, &from.sin6.sin6_addr, abuf, 699dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt sizeof(abuf)) == NULL) 700526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt abuf[0] = '\0'; 701dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt from_port = ntohs(from.sin6.sin6_port); 702526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("Received %d bytes from %s:%d", 703526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len, abuf, from_port); 704526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 705526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt client = radius_server_get_client(data, 706526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (struct in_addr *) 707dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt &from.sin6.sin6_addr, 1); 708526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 709526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IPV6 */ 710526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 711526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!data->ipv6) { 712dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf)); 713dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt from_port = ntohs(from.sin.sin_port); 714526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("Received %d bytes from %s:%d", 715526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len, abuf, from_port); 716526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 717dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt client = radius_server_get_client(data, &from.sin.sin_addr, 0); 718526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 719526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 720526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DUMP("Received data", buf, len); 721526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 722526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (client == NULL) { 723526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("Unknown client %s - packet ignored", abuf); 724526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->counters.invalid_requests++; 725526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt goto fail; 726526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 727526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 728526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt msg = radius_msg_parse(buf, len); 729526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (msg == NULL) { 730526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("Parsing incoming RADIUS frame failed"); 731526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->counters.malformed_access_requests++; 732526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt client->counters.malformed_access_requests++; 733526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt goto fail; 734526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 735526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 736526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(buf); 737526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf = NULL; 738526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 739526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpa_debug_level <= MSG_MSGDUMP) { 740526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_msg_dump(msg); 741526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 742526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 743526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (msg->hdr->code != RADIUS_CODE_ACCESS_REQUEST) { 744526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("Unexpected RADIUS code %d", msg->hdr->code); 745526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->counters.unknown_types++; 746526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt client->counters.unknown_types++; 747526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt goto fail; 748526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 749526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 750526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->counters.access_requests++; 751526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt client->counters.access_requests++; 752526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 753526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (radius_msg_verify_msg_auth(msg, (u8 *) client->shared_secret, 754526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt client->shared_secret_len, NULL)) { 755526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("Invalid Message-Authenticator from %s", abuf); 756526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->counters.bad_authenticators++; 757526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt client->counters.bad_authenticators++; 758526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt goto fail; 759526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 760526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 761526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (radius_server_request(data, msg, (struct sockaddr *) &from, 762526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt fromlen, client, abuf, from_port, NULL) == 763526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt -2) 764526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; /* msg was stored with the session */ 765526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 766526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtfail: 767526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (msg) { 768526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_msg_free(msg); 769526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(msg); 770526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 771526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(buf); 772526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 773526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 774526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 775dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidtstatic int radius_server_disable_pmtu_discovery(int s) 776dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt{ 777dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt int r = -1; 778dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) 779dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt /* Turn off Path MTU discovery on IPv4/UDP sockets. */ 780dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt int action = IP_PMTUDISC_DONT; 781dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt r = setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &action, 782dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt sizeof(action)); 783dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt if (r == -1) 784dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt wpa_printf(MSG_ERROR, "Failed to set IP_MTU_DISCOVER: " 785dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt "%s", strerror(errno)); 786dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt#endif 787dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt return r; 788dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt} 789dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt 790dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt 791526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int radius_server_open_socket(int port) 792526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 793526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int s; 794526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct sockaddr_in addr; 795526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 796526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt s = socket(PF_INET, SOCK_DGRAM, 0); 797526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (s < 0) { 798526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("socket"); 799526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 800526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 801526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 802dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt radius_server_disable_pmtu_discovery(s); 803dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt 804526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(&addr, 0, sizeof(addr)); 805526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr.sin_family = AF_INET; 806526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr.sin_port = htons(port); 807526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 808526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("bind"); 809526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt close(s); 810526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 811526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 812526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 813526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return s; 814526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 815526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 816526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 817526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IPV6 818526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int radius_server_open_socket6(int port) 819526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 820526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int s; 821526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct sockaddr_in6 addr; 822526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 823526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt s = socket(PF_INET6, SOCK_DGRAM, 0); 824526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (s < 0) { 825526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("socket[IPv6]"); 826526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 827526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 828526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 829526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(&addr, 0, sizeof(addr)); 830526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr.sin6_family = AF_INET6; 831526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any)); 832526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr.sin6_port = htons(port); 833526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 834526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("bind"); 835526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt close(s); 836526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 837526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 838526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 839526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return s; 840526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 841526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IPV6 */ 842526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 843526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 844526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void radius_server_free_sessions(struct radius_server_data *data, 845526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_session *sessions) 846526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 847526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_session *session, *prev; 848526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 849526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt session = sessions; 850526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (session) { 851526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prev = session; 852526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt session = session->next; 853526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_server_session_free(data, prev); 854526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 855526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 856526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 857526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 858526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void radius_server_free_clients(struct radius_server_data *data, 859526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_client *clients) 860526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 861526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_client *client, *prev; 862526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 863526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt client = clients; 864526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (client) { 865526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prev = client; 866526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt client = client->next; 867526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 868526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_server_free_sessions(data, prev->sessions); 869526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(prev->shared_secret); 870526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(prev); 871526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 872526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 873526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 874526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 875526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct radius_client * 876526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtradius_server_read_clients(const char *client_file, int ipv6) 877526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 878526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt FILE *f; 879526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const int buf_size = 1024; 880526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char *buf, *pos; 881526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_client *clients, *tail, *entry; 882526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int line = 0, mask, failed = 0, i; 883526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct in_addr addr; 884526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IPV6 885526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct in6_addr addr6; 886526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IPV6 */ 887526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt unsigned int val; 888526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 889526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt f = fopen(client_file, "r"); 890526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (f == NULL) { 891526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_ERROR("Could not open client file '%s'", client_file); 892526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 893526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 894526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 895526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf = os_malloc(buf_size); 896526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (buf == NULL) { 897526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt fclose(f); 898526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 899526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 900526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 901526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt clients = tail = NULL; 902526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (fgets(buf, buf_size, f)) { 903526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Configuration file format: 904526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 192.168.1.0/24 secret 905526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 192.168.1.2 secret 906526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * fe80::211:22ff:fe33:4455/64 secretipv6 907526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 908526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt line++; 909526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf[buf_size - 1] = '\0'; 910526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = buf; 911526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (*pos != '\0' && *pos != '\n') 912526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos++; 913526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (*pos == '\n') 914526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *pos = '\0'; 915526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (*buf == '\0' || *buf == '#') 916526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt continue; 917526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 918526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = buf; 919526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while ((*pos >= '0' && *pos <= '9') || *pos == '.' || 920526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (*pos >= 'a' && *pos <= 'f') || *pos == ':' || 921526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (*pos >= 'A' && *pos <= 'F')) { 922526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos++; 923526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 924526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 925526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (*pos == '\0') { 926526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt failed = 1; 927526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 928526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 929526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 930526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (*pos == '/') { 931526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char *end; 932526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *pos++ = '\0'; 933526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt mask = strtol(pos, &end, 10); 934526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if ((pos == end) || 935526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (mask < 0 || mask > (ipv6 ? 128 : 32))) { 936526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt failed = 1; 937526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 938526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 939526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = end; 940526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 941526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt mask = ipv6 ? 128 : 32; 942526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *pos++ = '\0'; 943526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 944526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 945526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!ipv6 && inet_aton(buf, &addr) == 0) { 946526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt failed = 1; 947526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 948526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 949526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IPV6 950526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ipv6 && inet_pton(AF_INET6, buf, &addr6) <= 0) { 951526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (inet_pton(AF_INET, buf, &addr) <= 0) { 952526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt failed = 1; 953526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 954526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 955526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Convert IPv4 address to IPv6 */ 956526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (mask <= 32) 957526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt mask += (128 - 32); 958526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(addr6.s6_addr, 0, 10); 959526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr6.s6_addr[10] = 0xff; 960526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr6.s6_addr[11] = 0xff; 961526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(addr6.s6_addr + 12, (char *) &addr.s_addr, 962526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 4); 963526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 964526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IPV6 */ 965526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 966526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (*pos == ' ' || *pos == '\t') { 967526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos++; 968526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 969526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 970526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (*pos == '\0') { 971526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt failed = 1; 972526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 973526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 974526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 975526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry = os_zalloc(sizeof(*entry)); 976526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (entry == NULL) { 977526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt failed = 1; 978526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 979526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 980526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry->shared_secret = os_strdup(pos); 981526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (entry->shared_secret == NULL) { 982526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt failed = 1; 983526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(entry); 984526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 985526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 986526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry->shared_secret_len = os_strlen(entry->shared_secret); 987526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry->addr.s_addr = addr.s_addr; 988526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!ipv6) { 989526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt val = 0; 990526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (i = 0; i < mask; i++) 991526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt val |= 1 << (31 - i); 992526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry->mask.s_addr = htonl(val); 993526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 994526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IPV6 995526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ipv6) { 996526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int offset = mask / 8; 997526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 998526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(entry->addr6.s6_addr, addr6.s6_addr, 16); 999526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(entry->mask6.s6_addr, 0xff, offset); 1000526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt val = 0; 1001526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (i = 0; i < (mask % 8); i++) 1002526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt val |= 1 << (7 - i); 1003526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (offset < 16) 1004526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry->mask6.s6_addr[offset] = val; 1005526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1006526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IPV6 */ 1007526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1008526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (tail == NULL) { 1009526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt clients = tail = entry; 1010526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 1011526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt tail->next = entry; 1012526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt tail = entry; 1013526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1014526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1015526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1016526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (failed) { 1017526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_ERROR("Invalid line %d in '%s'", line, client_file); 1018526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_server_free_clients(NULL, clients); 1019526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt clients = NULL; 1020526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1021526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1022526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(buf); 1023526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt fclose(f); 1024526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1025526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return clients; 1026526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1027526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1028526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1029526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct radius_server_data * 1030526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtradius_server_init(struct radius_server_conf *conf) 1031526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1032526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_server_data *data; 1033526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1034526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifndef CONFIG_IPV6 1035526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (conf->ipv6) { 1036526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt fprintf(stderr, "RADIUS server compiled without IPv6 " 1037526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "support.\n"); 1038526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 1039526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1040526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IPV6 */ 1041526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1042526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data = os_zalloc(sizeof(*data)); 1043526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data == NULL) 1044526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 1045526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1046526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_get_time(&data->start_time); 1047526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->conf_ctx = conf->conf_ctx; 1048526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->eap_sim_db_priv = conf->eap_sim_db_priv; 1049526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->ssl_ctx = conf->ssl_ctx; 1050526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->ipv6 = conf->ipv6; 1051526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (conf->pac_opaque_encr_key) { 1052526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->pac_opaque_encr_key = os_malloc(16); 1053526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(data->pac_opaque_encr_key, conf->pac_opaque_encr_key, 1054526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 16); 1055526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1056526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (conf->eap_fast_a_id) { 1057526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->eap_fast_a_id = os_malloc(conf->eap_fast_a_id_len); 1058526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->eap_fast_a_id) { 1059526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(data->eap_fast_a_id, conf->eap_fast_a_id, 1060526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt conf->eap_fast_a_id_len); 1061526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->eap_fast_a_id_len = conf->eap_fast_a_id_len; 1062526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1063526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1064526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (conf->eap_fast_a_id_info) 1065526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->eap_fast_a_id_info = os_strdup(conf->eap_fast_a_id_info); 1066526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->eap_fast_prov = conf->eap_fast_prov; 1067526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->pac_key_lifetime = conf->pac_key_lifetime; 1068526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->pac_key_refresh_time = conf->pac_key_refresh_time; 1069526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->get_eap_user = conf->get_eap_user; 1070526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind; 1071526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->tnc = conf->tnc; 1072526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->wps = conf->wps; 1073526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (conf->eap_req_id_text) { 1074526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->eap_req_id_text = os_malloc(conf->eap_req_id_text_len); 1075526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->eap_req_id_text) { 1076526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(data->eap_req_id_text, conf->eap_req_id_text, 1077526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt conf->eap_req_id_text_len); 1078526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->eap_req_id_text_len = conf->eap_req_id_text_len; 1079526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1080526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1081526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1082526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->clients = radius_server_read_clients(conf->client_file, 1083526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt conf->ipv6); 1084526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->clients == NULL) { 1085526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt printf("No RADIUS clients configured.\n"); 1086526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_server_deinit(data); 1087526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 1088526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1089526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1090526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IPV6 1091526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (conf->ipv6) 1092526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->auth_sock = radius_server_open_socket6(conf->auth_port); 1093526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else 1094526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IPV6 */ 1095526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->auth_sock = radius_server_open_socket(conf->auth_port); 1096526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->auth_sock < 0) { 1097526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt printf("Failed to open UDP socket for RADIUS authentication " 1098526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "server\n"); 1099526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_server_deinit(data); 1100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 1101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eloop_register_read_sock(data->auth_sock, 1103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_server_receive_auth, 1104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data, NULL)) { 1105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_server_deinit(data); 1106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 1107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return data; 1110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid radius_server_deinit(struct radius_server_data *data) 1114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data == NULL) 1116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 1117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->auth_sock >= 0) { 1119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_unregister_read_sock(data->auth_sock); 1120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt close(data->auth_sock); 1121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_server_free_clients(data, data->clients); 1124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data->pac_opaque_encr_key); 1126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data->eap_fast_a_id); 1127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data->eap_fast_a_id_info); 1128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data->eap_req_id_text); 1129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data); 1130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint radius_server_get_mib(struct radius_server_data *data, char *buf, 1134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t buflen) 1135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int ret, uptime; 1137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt unsigned int idx; 1138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char *end, *pos; 1139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct os_time now; 1140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_client *cli; 1141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* RFC 2619 - RADIUS Authentication Server MIB */ 1143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data == NULL || buflen == 0) 1145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 1146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = buf; 1148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt end = buf + buflen; 1149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_get_time(&now); 1151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt uptime = (now.sec - data->start_time.sec) * 100 + 1152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ((now.usec - data->start_time.usec) / 10000) % 100; 1153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = os_snprintf(pos, end - pos, 1154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "RADIUS-AUTH-SERVER-MIB\n" 1155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthServIdent=hostapd\n" 1156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthServUpTime=%d\n" 1157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthServResetTime=0\n" 1158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthServConfigReset=4\n", 1159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt uptime); 1160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ret < 0 || ret >= end - pos) { 1161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *pos = '\0'; 1162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return pos - buf; 1163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += ret; 1165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = os_snprintf(pos, end - pos, 1167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthServTotalAccessRequests=%u\n" 1168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthServTotalInvalidRequests=%u\n" 1169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthServTotalDupAccessRequests=%u\n" 1170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthServTotalAccessAccepts=%u\n" 1171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthServTotalAccessRejects=%u\n" 1172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthServTotalAccessChallenges=%u\n" 1173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthServTotalMalformedAccessRequests=%u\n" 1174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthServTotalBadAuthenticators=%u\n" 1175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthServTotalPacketsDropped=%u\n" 1176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthServTotalUnknownTypes=%u\n", 1177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->counters.access_requests, 1178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->counters.invalid_requests, 1179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->counters.dup_access_requests, 1180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->counters.access_accepts, 1181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->counters.access_rejects, 1182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->counters.access_challenges, 1183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->counters.malformed_access_requests, 1184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->counters.bad_authenticators, 1185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->counters.packets_dropped, 1186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->counters.unknown_types); 1187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ret < 0 || ret >= end - pos) { 1188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *pos = '\0'; 1189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return pos - buf; 1190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += ret; 1192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (cli = data->clients, idx = 0; cli; cli = cli->next, idx++) { 1194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char abuf[50], mbuf[50]; 1195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IPV6 1196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->ipv6) { 1197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (inet_ntop(AF_INET6, &cli->addr6, abuf, 1198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(abuf)) == NULL) 1199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt abuf[0] = '\0'; 1200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (inet_ntop(AF_INET6, &cli->mask6, abuf, 1201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(mbuf)) == NULL) 1202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt mbuf[0] = '\0'; 1203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IPV6 */ 1205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!data->ipv6) { 1206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_strlcpy(abuf, inet_ntoa(cli->addr), sizeof(abuf)); 1207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_strlcpy(mbuf, inet_ntoa(cli->mask), sizeof(mbuf)); 1208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = os_snprintf(pos, end - pos, 1211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthClientIndex=%u\n" 1212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthClientAddress=%s/%s\n" 1213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthServAccessRequests=%u\n" 1214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthServDupAccessRequests=%u\n" 1215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthServAccessAccepts=%u\n" 1216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthServAccessRejects=%u\n" 1217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthServAccessChallenges=%u\n" 1218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthServMalformedAccessRequests=%u\n" 1219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthServBadAuthenticators=%u\n" 1220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthServPacketsDropped=%u\n" 1221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthServUnknownTypes=%u\n", 1222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt idx, 1223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt abuf, mbuf, 1224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cli->counters.access_requests, 1225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cli->counters.dup_access_requests, 1226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cli->counters.access_accepts, 1227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cli->counters.access_rejects, 1228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cli->counters.access_challenges, 1229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cli->counters.malformed_access_requests, 1230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cli->counters.bad_authenticators, 1231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cli->counters.packets_dropped, 1232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cli->counters.unknown_types); 1233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ret < 0 || ret >= end - pos) { 1234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *pos = '\0'; 1235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return pos - buf; 1236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += ret; 1238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return pos - buf; 1241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int radius_server_get_eap_user(void *ctx, const u8 *identity, 1245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t identity_len, int phase2, 1246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_user *user) 1247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_session *sess = ctx; 1249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_server_data *data = sess->server; 1250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return data->get_eap_user(data->conf_ctx, identity, identity_len, 1252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt phase2, user); 1253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic const char * radius_server_get_eap_req_id_text(void *ctx, size_t *len) 1257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_session *sess = ctx; 1259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_server_data *data = sess->server; 1260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *len = data->eap_req_id_text_len; 1261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return data->eap_req_id_text; 1262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct eapol_callbacks radius_server_eapol_cb = 1266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt .get_eap_user = radius_server_get_eap_user, 1268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt .get_eap_req_id_text = radius_server_get_eap_req_id_text, 1269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}; 1270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid radius_server_eap_pending_cb(struct radius_server_data *data, void *ctx) 1273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_client *cli; 1275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_session *s, *sess = NULL; 1276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg *msg; 1277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data == NULL) 1279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 1280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (cli = data->clients; cli; cli = cli->next) { 1282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (s = cli->sessions; s; s = s->next) { 1283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (s->eap == ctx && s->last_msg) { 1284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess = s; 1285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 1286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sess) 1288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 1289526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1290526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sess) 1291526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 1292526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1293526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1294526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sess == NULL) { 1295526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RADIUS_DEBUG("No session matched callback ctx"); 1296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 1297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt msg = sess->last_msg; 1300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess->last_msg = NULL; 1301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_sm_pending_cb(sess->eap); 1302526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (radius_server_request(data, msg, 1303526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (struct sockaddr *) &sess->last_from, 1304526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess->last_fromlen, cli, 1305526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess->last_from_addr, 1306526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sess->last_from_port, sess) == -2) 1307526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; /* msg was stored with the session */ 1308526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1309526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_msg_free(msg); 1310526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(msg); 1311526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1312