13ff40c12SJohn Marino /*
23ff40c12SJohn Marino * Authentication server setup
33ff40c12SJohn Marino * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
43ff40c12SJohn Marino *
53ff40c12SJohn Marino * This software may be distributed under the terms of the BSD license.
63ff40c12SJohn Marino * See README for more details.
73ff40c12SJohn Marino */
83ff40c12SJohn Marino
93ff40c12SJohn Marino #include "utils/includes.h"
103ff40c12SJohn Marino
113ff40c12SJohn Marino #include "utils/common.h"
123ff40c12SJohn Marino #include "crypto/tls.h"
133ff40c12SJohn Marino #include "eap_server/eap.h"
143ff40c12SJohn Marino #include "eap_server/eap_sim_db.h"
153ff40c12SJohn Marino #include "eapol_auth/eapol_auth_sm.h"
163ff40c12SJohn Marino #include "radius/radius_server.h"
173ff40c12SJohn Marino #include "hostapd.h"
183ff40c12SJohn Marino #include "ap_config.h"
193ff40c12SJohn Marino #include "sta_info.h"
203ff40c12SJohn Marino #include "authsrv.h"
213ff40c12SJohn Marino
223ff40c12SJohn Marino
233ff40c12SJohn Marino #if defined(EAP_SERVER_SIM) || defined(EAP_SERVER_AKA)
243ff40c12SJohn Marino #define EAP_SIM_DB
253ff40c12SJohn Marino #endif /* EAP_SERVER_SIM || EAP_SERVER_AKA */
263ff40c12SJohn Marino
273ff40c12SJohn Marino
283ff40c12SJohn Marino #ifdef EAP_SIM_DB
hostapd_sim_db_cb_sta(struct hostapd_data * hapd,struct sta_info * sta,void * ctx)293ff40c12SJohn Marino static int hostapd_sim_db_cb_sta(struct hostapd_data *hapd,
303ff40c12SJohn Marino struct sta_info *sta, void *ctx)
313ff40c12SJohn Marino {
323ff40c12SJohn Marino if (eapol_auth_eap_pending_cb(sta->eapol_sm, ctx) == 0)
333ff40c12SJohn Marino return 1;
343ff40c12SJohn Marino return 0;
353ff40c12SJohn Marino }
363ff40c12SJohn Marino
373ff40c12SJohn Marino
hostapd_sim_db_cb(void * ctx,void * session_ctx)383ff40c12SJohn Marino static void hostapd_sim_db_cb(void *ctx, void *session_ctx)
393ff40c12SJohn Marino {
403ff40c12SJohn Marino struct hostapd_data *hapd = ctx;
413ff40c12SJohn Marino if (ap_for_each_sta(hapd, hostapd_sim_db_cb_sta, session_ctx) == 0) {
423ff40c12SJohn Marino #ifdef RADIUS_SERVER
433ff40c12SJohn Marino radius_server_eap_pending_cb(hapd->radius_srv, session_ctx);
443ff40c12SJohn Marino #endif /* RADIUS_SERVER */
453ff40c12SJohn Marino }
463ff40c12SJohn Marino }
473ff40c12SJohn Marino #endif /* EAP_SIM_DB */
483ff40c12SJohn Marino
493ff40c12SJohn Marino
503ff40c12SJohn Marino #ifdef RADIUS_SERVER
513ff40c12SJohn Marino
hostapd_radius_get_eap_user(void * ctx,const u8 * identity,size_t identity_len,int phase2,struct eap_user * user)523ff40c12SJohn Marino static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity,
533ff40c12SJohn Marino size_t identity_len, int phase2,
543ff40c12SJohn Marino struct eap_user *user)
553ff40c12SJohn Marino {
563ff40c12SJohn Marino const struct hostapd_eap_user *eap_user;
573ff40c12SJohn Marino int i;
58*a1157835SDaniel Fojt int rv = -1;
593ff40c12SJohn Marino
603ff40c12SJohn Marino eap_user = hostapd_get_eap_user(ctx, identity, identity_len, phase2);
613ff40c12SJohn Marino if (eap_user == NULL)
62*a1157835SDaniel Fojt goto out;
633ff40c12SJohn Marino
643ff40c12SJohn Marino if (user == NULL)
653ff40c12SJohn Marino return 0;
663ff40c12SJohn Marino
673ff40c12SJohn Marino os_memset(user, 0, sizeof(*user));
683ff40c12SJohn Marino for (i = 0; i < EAP_MAX_METHODS; i++) {
693ff40c12SJohn Marino user->methods[i].vendor = eap_user->methods[i].vendor;
703ff40c12SJohn Marino user->methods[i].method = eap_user->methods[i].method;
713ff40c12SJohn Marino }
723ff40c12SJohn Marino
733ff40c12SJohn Marino if (eap_user->password) {
74*a1157835SDaniel Fojt user->password = os_memdup(eap_user->password,
753ff40c12SJohn Marino eap_user->password_len);
76*a1157835SDaniel Fojt if (user->password == NULL)
77*a1157835SDaniel Fojt goto out;
783ff40c12SJohn Marino user->password_len = eap_user->password_len;
793ff40c12SJohn Marino user->password_hash = eap_user->password_hash;
80*a1157835SDaniel Fojt if (eap_user->salt && eap_user->salt_len) {
81*a1157835SDaniel Fojt user->salt = os_memdup(eap_user->salt,
82*a1157835SDaniel Fojt eap_user->salt_len);
83*a1157835SDaniel Fojt if (!user->salt)
84*a1157835SDaniel Fojt goto out;
85*a1157835SDaniel Fojt user->salt_len = eap_user->salt_len;
86*a1157835SDaniel Fojt }
873ff40c12SJohn Marino }
883ff40c12SJohn Marino user->force_version = eap_user->force_version;
89*a1157835SDaniel Fojt user->macacl = eap_user->macacl;
903ff40c12SJohn Marino user->ttls_auth = eap_user->ttls_auth;
91*a1157835SDaniel Fojt user->remediation = eap_user->remediation;
92*a1157835SDaniel Fojt user->accept_attr = eap_user->accept_attr;
93*a1157835SDaniel Fojt user->t_c_timestamp = eap_user->t_c_timestamp;
94*a1157835SDaniel Fojt rv = 0;
953ff40c12SJohn Marino
96*a1157835SDaniel Fojt out:
97*a1157835SDaniel Fojt if (rv)
98*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "%s: Failed to find user", __func__);
99*a1157835SDaniel Fojt
100*a1157835SDaniel Fojt return rv;
1013ff40c12SJohn Marino }
1023ff40c12SJohn Marino
1033ff40c12SJohn Marino
hostapd_setup_radius_srv(struct hostapd_data * hapd)1043ff40c12SJohn Marino static int hostapd_setup_radius_srv(struct hostapd_data *hapd)
1053ff40c12SJohn Marino {
1063ff40c12SJohn Marino struct radius_server_conf srv;
1073ff40c12SJohn Marino struct hostapd_bss_config *conf = hapd->conf;
1083ff40c12SJohn Marino os_memset(&srv, 0, sizeof(srv));
1093ff40c12SJohn Marino srv.client_file = conf->radius_server_clients;
1103ff40c12SJohn Marino srv.auth_port = conf->radius_server_auth_port;
111*a1157835SDaniel Fojt srv.acct_port = conf->radius_server_acct_port;
1123ff40c12SJohn Marino srv.conf_ctx = hapd;
1133ff40c12SJohn Marino srv.eap_sim_db_priv = hapd->eap_sim_db_priv;
1143ff40c12SJohn Marino srv.ssl_ctx = hapd->ssl_ctx;
1153ff40c12SJohn Marino srv.msg_ctx = hapd->msg_ctx;
1163ff40c12SJohn Marino srv.pac_opaque_encr_key = conf->pac_opaque_encr_key;
1173ff40c12SJohn Marino srv.eap_fast_a_id = conf->eap_fast_a_id;
1183ff40c12SJohn Marino srv.eap_fast_a_id_len = conf->eap_fast_a_id_len;
1193ff40c12SJohn Marino srv.eap_fast_a_id_info = conf->eap_fast_a_id_info;
1203ff40c12SJohn Marino srv.eap_fast_prov = conf->eap_fast_prov;
1213ff40c12SJohn Marino srv.pac_key_lifetime = conf->pac_key_lifetime;
1223ff40c12SJohn Marino srv.pac_key_refresh_time = conf->pac_key_refresh_time;
123*a1157835SDaniel Fojt srv.eap_teap_auth = conf->eap_teap_auth;
124*a1157835SDaniel Fojt srv.eap_teap_pac_no_inner = conf->eap_teap_pac_no_inner;
1253ff40c12SJohn Marino srv.eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;
126*a1157835SDaniel Fojt srv.eap_sim_id = conf->eap_sim_id;
1273ff40c12SJohn Marino srv.tnc = conf->tnc;
1283ff40c12SJohn Marino srv.wps = hapd->wps;
1293ff40c12SJohn Marino srv.ipv6 = conf->radius_server_ipv6;
1303ff40c12SJohn Marino srv.get_eap_user = hostapd_radius_get_eap_user;
1313ff40c12SJohn Marino srv.eap_req_id_text = conf->eap_req_id_text;
1323ff40c12SJohn Marino srv.eap_req_id_text_len = conf->eap_req_id_text_len;
1333ff40c12SJohn Marino srv.pwd_group = conf->pwd_group;
1343ff40c12SJohn Marino srv.server_id = conf->server_id ? conf->server_id : "hostapd";
135*a1157835SDaniel Fojt srv.sqlite_file = conf->eap_user_sqlite;
1363ff40c12SJohn Marino #ifdef CONFIG_RADIUS_TEST
1373ff40c12SJohn Marino srv.dump_msk_file = conf->dump_msk_file;
1383ff40c12SJohn Marino #endif /* CONFIG_RADIUS_TEST */
139*a1157835SDaniel Fojt #ifdef CONFIG_HS20
140*a1157835SDaniel Fojt srv.subscr_remediation_url = conf->subscr_remediation_url;
141*a1157835SDaniel Fojt srv.subscr_remediation_method = conf->subscr_remediation_method;
142*a1157835SDaniel Fojt srv.hs20_sim_provisioning_url = conf->hs20_sim_provisioning_url;
143*a1157835SDaniel Fojt srv.t_c_server_url = conf->t_c_server_url;
144*a1157835SDaniel Fojt #endif /* CONFIG_HS20 */
145*a1157835SDaniel Fojt srv.erp = conf->eap_server_erp;
146*a1157835SDaniel Fojt srv.erp_domain = conf->erp_domain;
147*a1157835SDaniel Fojt srv.tls_session_lifetime = conf->tls_session_lifetime;
148*a1157835SDaniel Fojt srv.tls_flags = conf->tls_flags;
1493ff40c12SJohn Marino
1503ff40c12SJohn Marino hapd->radius_srv = radius_server_init(&srv);
1513ff40c12SJohn Marino if (hapd->radius_srv == NULL) {
1523ff40c12SJohn Marino wpa_printf(MSG_ERROR, "RADIUS server initialization failed.");
1533ff40c12SJohn Marino return -1;
1543ff40c12SJohn Marino }
1553ff40c12SJohn Marino
1563ff40c12SJohn Marino return 0;
1573ff40c12SJohn Marino }
1583ff40c12SJohn Marino
1593ff40c12SJohn Marino #endif /* RADIUS_SERVER */
1603ff40c12SJohn Marino
1613ff40c12SJohn Marino
162*a1157835SDaniel Fojt #ifdef EAP_TLS_FUNCS
authsrv_tls_event(void * ctx,enum tls_event ev,union tls_event_data * data)163*a1157835SDaniel Fojt static void authsrv_tls_event(void *ctx, enum tls_event ev,
164*a1157835SDaniel Fojt union tls_event_data *data)
165*a1157835SDaniel Fojt {
166*a1157835SDaniel Fojt switch (ev) {
167*a1157835SDaniel Fojt case TLS_CERT_CHAIN_SUCCESS:
168*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "authsrv: remote certificate verification success");
169*a1157835SDaniel Fojt break;
170*a1157835SDaniel Fojt case TLS_CERT_CHAIN_FAILURE:
171*a1157835SDaniel Fojt wpa_printf(MSG_INFO, "authsrv: certificate chain failure: reason=%d depth=%d subject='%s' err='%s'",
172*a1157835SDaniel Fojt data->cert_fail.reason,
173*a1157835SDaniel Fojt data->cert_fail.depth,
174*a1157835SDaniel Fojt data->cert_fail.subject,
175*a1157835SDaniel Fojt data->cert_fail.reason_txt);
176*a1157835SDaniel Fojt break;
177*a1157835SDaniel Fojt case TLS_PEER_CERTIFICATE:
178*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "authsrv: peer certificate: depth=%d serial_num=%s subject=%s",
179*a1157835SDaniel Fojt data->peer_cert.depth,
180*a1157835SDaniel Fojt data->peer_cert.serial_num ? data->peer_cert.serial_num : "N/A",
181*a1157835SDaniel Fojt data->peer_cert.subject);
182*a1157835SDaniel Fojt break;
183*a1157835SDaniel Fojt case TLS_ALERT:
184*a1157835SDaniel Fojt if (data->alert.is_local)
185*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "authsrv: local TLS alert: %s",
186*a1157835SDaniel Fojt data->alert.description);
187*a1157835SDaniel Fojt else
188*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "authsrv: remote TLS alert: %s",
189*a1157835SDaniel Fojt data->alert.description);
190*a1157835SDaniel Fojt break;
191*a1157835SDaniel Fojt }
192*a1157835SDaniel Fojt }
193*a1157835SDaniel Fojt #endif /* EAP_TLS_FUNCS */
194*a1157835SDaniel Fojt
195*a1157835SDaniel Fojt
authsrv_init(struct hostapd_data * hapd)1963ff40c12SJohn Marino int authsrv_init(struct hostapd_data *hapd)
1973ff40c12SJohn Marino {
1983ff40c12SJohn Marino #ifdef EAP_TLS_FUNCS
1993ff40c12SJohn Marino if (hapd->conf->eap_server &&
2003ff40c12SJohn Marino (hapd->conf->ca_cert || hapd->conf->server_cert ||
201*a1157835SDaniel Fojt hapd->conf->private_key || hapd->conf->dh_file ||
202*a1157835SDaniel Fojt hapd->conf->server_cert2 || hapd->conf->private_key2)) {
203*a1157835SDaniel Fojt struct tls_config conf;
2043ff40c12SJohn Marino struct tls_connection_params params;
2053ff40c12SJohn Marino
206*a1157835SDaniel Fojt os_memset(&conf, 0, sizeof(conf));
207*a1157835SDaniel Fojt conf.tls_session_lifetime = hapd->conf->tls_session_lifetime;
208*a1157835SDaniel Fojt if (hapd->conf->crl_reload_interval > 0 &&
209*a1157835SDaniel Fojt hapd->conf->check_crl <= 0) {
210*a1157835SDaniel Fojt wpa_printf(MSG_INFO,
211*a1157835SDaniel Fojt "Cannot enable CRL reload functionality - it depends on check_crl being set");
212*a1157835SDaniel Fojt } else if (hapd->conf->crl_reload_interval > 0) {
213*a1157835SDaniel Fojt conf.crl_reload_interval =
214*a1157835SDaniel Fojt hapd->conf->crl_reload_interval;
215*a1157835SDaniel Fojt wpa_printf(MSG_INFO,
216*a1157835SDaniel Fojt "Enabled CRL reload functionality");
217*a1157835SDaniel Fojt }
218*a1157835SDaniel Fojt conf.tls_flags = hapd->conf->tls_flags;
219*a1157835SDaniel Fojt conf.event_cb = authsrv_tls_event;
220*a1157835SDaniel Fojt conf.cb_ctx = hapd;
221*a1157835SDaniel Fojt hapd->ssl_ctx = tls_init(&conf);
2223ff40c12SJohn Marino if (hapd->ssl_ctx == NULL) {
2233ff40c12SJohn Marino wpa_printf(MSG_ERROR, "Failed to initialize TLS");
2243ff40c12SJohn Marino authsrv_deinit(hapd);
2253ff40c12SJohn Marino return -1;
2263ff40c12SJohn Marino }
2273ff40c12SJohn Marino
2283ff40c12SJohn Marino os_memset(¶ms, 0, sizeof(params));
2293ff40c12SJohn Marino params.ca_cert = hapd->conf->ca_cert;
2303ff40c12SJohn Marino params.client_cert = hapd->conf->server_cert;
231*a1157835SDaniel Fojt params.client_cert2 = hapd->conf->server_cert2;
2323ff40c12SJohn Marino params.private_key = hapd->conf->private_key;
233*a1157835SDaniel Fojt params.private_key2 = hapd->conf->private_key2;
2343ff40c12SJohn Marino params.private_key_passwd = hapd->conf->private_key_passwd;
235*a1157835SDaniel Fojt params.private_key_passwd2 = hapd->conf->private_key_passwd2;
2363ff40c12SJohn Marino params.dh_file = hapd->conf->dh_file;
237*a1157835SDaniel Fojt params.openssl_ciphers = hapd->conf->openssl_ciphers;
238*a1157835SDaniel Fojt params.openssl_ecdh_curves = hapd->conf->openssl_ecdh_curves;
2393ff40c12SJohn Marino params.ocsp_stapling_response =
2403ff40c12SJohn Marino hapd->conf->ocsp_stapling_response;
241*a1157835SDaniel Fojt params.ocsp_stapling_response_multi =
242*a1157835SDaniel Fojt hapd->conf->ocsp_stapling_response_multi;
243*a1157835SDaniel Fojt params.check_cert_subject = hapd->conf->check_cert_subject;
2443ff40c12SJohn Marino
2453ff40c12SJohn Marino if (tls_global_set_params(hapd->ssl_ctx, ¶ms)) {
2463ff40c12SJohn Marino wpa_printf(MSG_ERROR, "Failed to set TLS parameters");
2473ff40c12SJohn Marino authsrv_deinit(hapd);
2483ff40c12SJohn Marino return -1;
2493ff40c12SJohn Marino }
2503ff40c12SJohn Marino
2513ff40c12SJohn Marino if (tls_global_set_verify(hapd->ssl_ctx,
252*a1157835SDaniel Fojt hapd->conf->check_crl,
253*a1157835SDaniel Fojt hapd->conf->check_crl_strict)) {
2543ff40c12SJohn Marino wpa_printf(MSG_ERROR, "Failed to enable check_crl");
2553ff40c12SJohn Marino authsrv_deinit(hapd);
2563ff40c12SJohn Marino return -1;
2573ff40c12SJohn Marino }
2583ff40c12SJohn Marino }
2593ff40c12SJohn Marino #endif /* EAP_TLS_FUNCS */
2603ff40c12SJohn Marino
2613ff40c12SJohn Marino #ifdef EAP_SIM_DB
2623ff40c12SJohn Marino if (hapd->conf->eap_sim_db) {
2633ff40c12SJohn Marino hapd->eap_sim_db_priv =
2643ff40c12SJohn Marino eap_sim_db_init(hapd->conf->eap_sim_db,
265*a1157835SDaniel Fojt hapd->conf->eap_sim_db_timeout,
2663ff40c12SJohn Marino hostapd_sim_db_cb, hapd);
2673ff40c12SJohn Marino if (hapd->eap_sim_db_priv == NULL) {
2683ff40c12SJohn Marino wpa_printf(MSG_ERROR, "Failed to initialize EAP-SIM "
2693ff40c12SJohn Marino "database interface");
2703ff40c12SJohn Marino authsrv_deinit(hapd);
2713ff40c12SJohn Marino return -1;
2723ff40c12SJohn Marino }
2733ff40c12SJohn Marino }
2743ff40c12SJohn Marino #endif /* EAP_SIM_DB */
2753ff40c12SJohn Marino
2763ff40c12SJohn Marino #ifdef RADIUS_SERVER
2773ff40c12SJohn Marino if (hapd->conf->radius_server_clients &&
2783ff40c12SJohn Marino hostapd_setup_radius_srv(hapd))
2793ff40c12SJohn Marino return -1;
2803ff40c12SJohn Marino #endif /* RADIUS_SERVER */
2813ff40c12SJohn Marino
2823ff40c12SJohn Marino return 0;
2833ff40c12SJohn Marino }
2843ff40c12SJohn Marino
2853ff40c12SJohn Marino
authsrv_deinit(struct hostapd_data * hapd)2863ff40c12SJohn Marino void authsrv_deinit(struct hostapd_data *hapd)
2873ff40c12SJohn Marino {
2883ff40c12SJohn Marino #ifdef RADIUS_SERVER
2893ff40c12SJohn Marino radius_server_deinit(hapd->radius_srv);
2903ff40c12SJohn Marino hapd->radius_srv = NULL;
2913ff40c12SJohn Marino #endif /* RADIUS_SERVER */
2923ff40c12SJohn Marino
2933ff40c12SJohn Marino #ifdef EAP_TLS_FUNCS
2943ff40c12SJohn Marino if (hapd->ssl_ctx) {
2953ff40c12SJohn Marino tls_deinit(hapd->ssl_ctx);
2963ff40c12SJohn Marino hapd->ssl_ctx = NULL;
2973ff40c12SJohn Marino }
2983ff40c12SJohn Marino #endif /* EAP_TLS_FUNCS */
2993ff40c12SJohn Marino
3003ff40c12SJohn Marino #ifdef EAP_SIM_DB
3013ff40c12SJohn Marino if (hapd->eap_sim_db_priv) {
3023ff40c12SJohn Marino eap_sim_db_deinit(hapd->eap_sim_db_priv);
3033ff40c12SJohn Marino hapd->eap_sim_db_priv = NULL;
3043ff40c12SJohn Marino }
3053ff40c12SJohn Marino #endif /* EAP_SIM_DB */
3063ff40c12SJohn Marino }
307