$search
00001 /* 00002 * hostapd / WPA authenticator glue code 00003 * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "utils/includes.h" 00016 00017 #include "utils/common.h" 00018 #include "common/ieee802_11_defs.h" 00019 #include "eapol_auth/eapol_auth_sm.h" 00020 #include "eapol_auth/eapol_auth_sm_i.h" 00021 #include "eap_server/eap.h" 00022 #include "l2_packet/l2_packet.h" 00023 #include "drivers/driver.h" 00024 #include "hostapd.h" 00025 #include "ieee802_1x.h" 00026 #include "preauth_auth.h" 00027 #include "sta_info.h" 00028 #include "tkip_countermeasures.h" 00029 #include "ap_drv_ops.h" 00030 #include "ap_config.h" 00031 #include "wpa_auth.h" 00032 00033 00034 static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, 00035 struct wpa_auth_config *wconf) 00036 { 00037 wconf->wpa = conf->wpa; 00038 wconf->wpa_key_mgmt = conf->wpa_key_mgmt; 00039 wconf->wpa_pairwise = conf->wpa_pairwise; 00040 wconf->wpa_group = conf->wpa_group; 00041 wconf->wpa_group_rekey = conf->wpa_group_rekey; 00042 wconf->wpa_strict_rekey = conf->wpa_strict_rekey; 00043 wconf->wpa_gmk_rekey = conf->wpa_gmk_rekey; 00044 wconf->wpa_ptk_rekey = conf->wpa_ptk_rekey; 00045 wconf->rsn_pairwise = conf->rsn_pairwise; 00046 wconf->rsn_preauth = conf->rsn_preauth; 00047 wconf->eapol_version = conf->eapol_version; 00048 wconf->peerkey = conf->peerkey; 00049 wconf->wmm_enabled = conf->wmm_enabled; 00050 wconf->wmm_uapsd = conf->wmm_uapsd; 00051 wconf->okc = conf->okc; 00052 #ifdef CONFIG_IEEE80211W 00053 wconf->ieee80211w = conf->ieee80211w; 00054 #endif /* CONFIG_IEEE80211W */ 00055 #ifdef CONFIG_IEEE80211R 00056 wconf->ssid_len = conf->ssid.ssid_len; 00057 if (wconf->ssid_len > SSID_LEN) 00058 wconf->ssid_len = SSID_LEN; 00059 os_memcpy(wconf->ssid, conf->ssid.ssid, wconf->ssid_len); 00060 os_memcpy(wconf->mobility_domain, conf->mobility_domain, 00061 MOBILITY_DOMAIN_ID_LEN); 00062 if (conf->nas_identifier && 00063 os_strlen(conf->nas_identifier) <= FT_R0KH_ID_MAX_LEN) { 00064 wconf->r0_key_holder_len = os_strlen(conf->nas_identifier); 00065 os_memcpy(wconf->r0_key_holder, conf->nas_identifier, 00066 wconf->r0_key_holder_len); 00067 } 00068 os_memcpy(wconf->r1_key_holder, conf->r1_key_holder, FT_R1KH_ID_LEN); 00069 wconf->r0_key_lifetime = conf->r0_key_lifetime; 00070 wconf->reassociation_deadline = conf->reassociation_deadline; 00071 wconf->r0kh_list = conf->r0kh_list; 00072 wconf->r1kh_list = conf->r1kh_list; 00073 wconf->pmk_r1_push = conf->pmk_r1_push; 00074 #endif /* CONFIG_IEEE80211R */ 00075 } 00076 00077 00078 static void hostapd_wpa_auth_logger(void *ctx, const u8 *addr, 00079 logger_level level, const char *txt) 00080 { 00081 #ifndef CONFIG_NO_HOSTAPD_LOGGER 00082 struct hostapd_data *hapd = ctx; 00083 int hlevel; 00084 00085 switch (level) { 00086 case LOGGER_WARNING: 00087 hlevel = HOSTAPD_LEVEL_WARNING; 00088 break; 00089 case LOGGER_INFO: 00090 hlevel = HOSTAPD_LEVEL_INFO; 00091 break; 00092 case LOGGER_DEBUG: 00093 default: 00094 hlevel = HOSTAPD_LEVEL_DEBUG; 00095 break; 00096 } 00097 00098 hostapd_logger(hapd, addr, HOSTAPD_MODULE_WPA, hlevel, "%s", txt); 00099 #endif /* CONFIG_NO_HOSTAPD_LOGGER */ 00100 } 00101 00102 00103 static void hostapd_wpa_auth_disconnect(void *ctx, const u8 *addr, 00104 u16 reason) 00105 { 00106 struct hostapd_data *hapd = ctx; 00107 wpa_printf(MSG_DEBUG, "%s: WPA authenticator requests disconnect: " 00108 "STA " MACSTR " reason %d", 00109 __func__, MAC2STR(addr), reason); 00110 ap_sta_disconnect(hapd, NULL, addr, reason); 00111 } 00112 00113 00114 static void hostapd_wpa_auth_mic_failure_report(void *ctx, const u8 *addr) 00115 { 00116 struct hostapd_data *hapd = ctx; 00117 michael_mic_failure(hapd, addr, 0); 00118 } 00119 00120 00121 static void hostapd_wpa_auth_set_eapol(void *ctx, const u8 *addr, 00122 wpa_eapol_variable var, int value) 00123 { 00124 struct hostapd_data *hapd = ctx; 00125 struct sta_info *sta = ap_get_sta(hapd, addr); 00126 if (sta == NULL) 00127 return; 00128 switch (var) { 00129 case WPA_EAPOL_portEnabled: 00130 ieee802_1x_notify_port_enabled(sta->eapol_sm, value); 00131 break; 00132 case WPA_EAPOL_portValid: 00133 ieee802_1x_notify_port_valid(sta->eapol_sm, value); 00134 break; 00135 case WPA_EAPOL_authorized: 00136 ieee802_1x_set_sta_authorized(hapd, sta, value); 00137 break; 00138 case WPA_EAPOL_portControl_Auto: 00139 if (sta->eapol_sm) 00140 sta->eapol_sm->portControl = Auto; 00141 break; 00142 case WPA_EAPOL_keyRun: 00143 if (sta->eapol_sm) 00144 sta->eapol_sm->keyRun = value ? TRUE : FALSE; 00145 break; 00146 case WPA_EAPOL_keyAvailable: 00147 if (sta->eapol_sm) 00148 sta->eapol_sm->eap_if->eapKeyAvailable = 00149 value ? TRUE : FALSE; 00150 break; 00151 case WPA_EAPOL_keyDone: 00152 if (sta->eapol_sm) 00153 sta->eapol_sm->keyDone = value ? TRUE : FALSE; 00154 break; 00155 case WPA_EAPOL_inc_EapolFramesTx: 00156 if (sta->eapol_sm) 00157 sta->eapol_sm->dot1xAuthEapolFramesTx++; 00158 break; 00159 } 00160 } 00161 00162 00163 static int hostapd_wpa_auth_get_eapol(void *ctx, const u8 *addr, 00164 wpa_eapol_variable var) 00165 { 00166 struct hostapd_data *hapd = ctx; 00167 struct sta_info *sta = ap_get_sta(hapd, addr); 00168 if (sta == NULL || sta->eapol_sm == NULL) 00169 return -1; 00170 switch (var) { 00171 case WPA_EAPOL_keyRun: 00172 return sta->eapol_sm->keyRun; 00173 case WPA_EAPOL_keyAvailable: 00174 return sta->eapol_sm->eap_if->eapKeyAvailable; 00175 default: 00176 return -1; 00177 } 00178 } 00179 00180 00181 static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr, 00182 const u8 *prev_psk) 00183 { 00184 struct hostapd_data *hapd = ctx; 00185 return hostapd_get_psk(hapd->conf, addr, prev_psk); 00186 } 00187 00188 00189 static int hostapd_wpa_auth_get_msk(void *ctx, const u8 *addr, u8 *msk, 00190 size_t *len) 00191 { 00192 struct hostapd_data *hapd = ctx; 00193 const u8 *key; 00194 size_t keylen; 00195 struct sta_info *sta; 00196 00197 sta = ap_get_sta(hapd, addr); 00198 if (sta == NULL) 00199 return -1; 00200 00201 key = ieee802_1x_get_key(sta->eapol_sm, &keylen); 00202 if (key == NULL) 00203 return -1; 00204 00205 if (keylen > *len) 00206 keylen = *len; 00207 os_memcpy(msk, key, keylen); 00208 *len = keylen; 00209 00210 return 0; 00211 } 00212 00213 00214 static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg, 00215 const u8 *addr, int idx, u8 *key, 00216 size_t key_len) 00217 { 00218 struct hostapd_data *hapd = ctx; 00219 const char *ifname = hapd->conf->iface; 00220 00221 if (vlan_id > 0) { 00222 ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan, vlan_id); 00223 if (ifname == NULL) 00224 return -1; 00225 } 00226 00227 return hapd->drv.set_key(ifname, hapd, alg, addr, idx, 1, NULL, 0, 00228 key, key_len); 00229 } 00230 00231 00232 static int hostapd_wpa_auth_get_seqnum(void *ctx, const u8 *addr, int idx, 00233 u8 *seq) 00234 { 00235 struct hostapd_data *hapd = ctx; 00236 return hostapd_get_seqnum(hapd->conf->iface, hapd, addr, idx, seq); 00237 } 00238 00239 00240 static int hostapd_wpa_auth_send_eapol(void *ctx, const u8 *addr, 00241 const u8 *data, size_t data_len, 00242 int encrypt) 00243 { 00244 struct hostapd_data *hapd = ctx; 00245 return hapd->drv.send_eapol(hapd, addr, data, data_len, encrypt); 00246 } 00247 00248 00249 static int hostapd_wpa_auth_for_each_sta( 00250 void *ctx, int (*cb)(struct wpa_state_machine *sm, void *ctx), 00251 void *cb_ctx) 00252 { 00253 struct hostapd_data *hapd = ctx; 00254 struct sta_info *sta; 00255 00256 for (sta = hapd->sta_list; sta; sta = sta->next) { 00257 if (sta->wpa_sm && cb(sta->wpa_sm, cb_ctx)) 00258 return 1; 00259 } 00260 return 0; 00261 } 00262 00263 00264 struct wpa_auth_iface_iter_data { 00265 int (*cb)(struct wpa_authenticator *sm, void *ctx); 00266 void *cb_ctx; 00267 }; 00268 00269 static int wpa_auth_iface_iter(struct hostapd_iface *iface, void *ctx) 00270 { 00271 struct wpa_auth_iface_iter_data *data = ctx; 00272 size_t i; 00273 for (i = 0; i < iface->num_bss; i++) { 00274 if (iface->bss[i]->wpa_auth && 00275 data->cb(iface->bss[i]->wpa_auth, data->cb_ctx)) 00276 return 1; 00277 } 00278 return 0; 00279 } 00280 00281 00282 static int hostapd_wpa_auth_for_each_auth( 00283 void *ctx, int (*cb)(struct wpa_authenticator *sm, void *ctx), 00284 void *cb_ctx) 00285 { 00286 struct hostapd_data *hapd = ctx; 00287 struct wpa_auth_iface_iter_data data; 00288 if (hapd->iface->for_each_interface == NULL) 00289 return -1; 00290 data.cb = cb; 00291 data.cb_ctx = cb_ctx; 00292 return hapd->iface->for_each_interface(hapd->iface->interfaces, 00293 wpa_auth_iface_iter, &data); 00294 } 00295 00296 00297 static int hostapd_wpa_auth_send_ether(void *ctx, const u8 *dst, u16 proto, 00298 const u8 *data, size_t data_len) 00299 { 00300 struct hostapd_data *hapd = ctx; 00301 00302 if (hapd->driver && hapd->driver->send_ether) 00303 return hapd->driver->send_ether(hapd->drv_priv, dst, 00304 hapd->own_addr, proto, 00305 data, data_len); 00306 if (hapd->l2 == NULL) 00307 return -1; 00308 return l2_packet_send(hapd->l2, dst, proto, data, data_len); 00309 } 00310 00311 00312 #ifdef CONFIG_IEEE80211R 00313 00314 static int hostapd_wpa_auth_send_ft_action(void *ctx, const u8 *dst, 00315 const u8 *data, size_t data_len) 00316 { 00317 struct hostapd_data *hapd = ctx; 00318 int res; 00319 struct ieee80211_mgmt *m; 00320 size_t mlen; 00321 struct sta_info *sta; 00322 00323 sta = ap_get_sta(hapd, dst); 00324 if (sta == NULL || sta->wpa_sm == NULL) 00325 return -1; 00326 00327 m = os_zalloc(sizeof(*m) + data_len); 00328 if (m == NULL) 00329 return -1; 00330 mlen = ((u8 *) &m->u - (u8 *) m) + data_len; 00331 m->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, 00332 WLAN_FC_STYPE_ACTION); 00333 os_memcpy(m->da, dst, ETH_ALEN); 00334 os_memcpy(m->sa, hapd->own_addr, ETH_ALEN); 00335 os_memcpy(m->bssid, hapd->own_addr, ETH_ALEN); 00336 os_memcpy(&m->u, data, data_len); 00337 00338 res = hapd->drv.send_mgmt_frame(hapd, (u8 *) m, mlen); 00339 os_free(m); 00340 return res; 00341 } 00342 00343 00344 static struct wpa_state_machine * 00345 hostapd_wpa_auth_add_sta(void *ctx, const u8 *sta_addr) 00346 { 00347 struct hostapd_data *hapd = ctx; 00348 struct sta_info *sta; 00349 00350 sta = ap_sta_add(hapd, sta_addr); 00351 if (sta == NULL) 00352 return NULL; 00353 if (sta->wpa_sm) { 00354 sta->auth_alg = WLAN_AUTH_FT; 00355 return sta->wpa_sm; 00356 } 00357 00358 sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->addr); 00359 if (sta->wpa_sm == NULL) { 00360 ap_free_sta(hapd, sta); 00361 return NULL; 00362 } 00363 sta->auth_alg = WLAN_AUTH_FT; 00364 00365 return sta->wpa_sm; 00366 } 00367 00368 00369 static void hostapd_rrb_receive(void *ctx, const u8 *src_addr, const u8 *buf, 00370 size_t len) 00371 { 00372 struct hostapd_data *hapd = ctx; 00373 wpa_ft_rrb_rx(hapd->wpa_auth, src_addr, buf, len); 00374 } 00375 00376 #endif /* CONFIG_IEEE80211R */ 00377 00378 00379 int hostapd_setup_wpa(struct hostapd_data *hapd) 00380 { 00381 struct wpa_auth_config _conf; 00382 struct wpa_auth_callbacks cb; 00383 const u8 *wpa_ie; 00384 size_t wpa_ie_len; 00385 00386 hostapd_wpa_auth_conf(hapd->conf, &_conf); 00387 os_memset(&cb, 0, sizeof(cb)); 00388 cb.ctx = hapd; 00389 cb.logger = hostapd_wpa_auth_logger; 00390 cb.disconnect = hostapd_wpa_auth_disconnect; 00391 cb.mic_failure_report = hostapd_wpa_auth_mic_failure_report; 00392 cb.set_eapol = hostapd_wpa_auth_set_eapol; 00393 cb.get_eapol = hostapd_wpa_auth_get_eapol; 00394 cb.get_psk = hostapd_wpa_auth_get_psk; 00395 cb.get_msk = hostapd_wpa_auth_get_msk; 00396 cb.set_key = hostapd_wpa_auth_set_key; 00397 cb.get_seqnum = hostapd_wpa_auth_get_seqnum; 00398 cb.send_eapol = hostapd_wpa_auth_send_eapol; 00399 cb.for_each_sta = hostapd_wpa_auth_for_each_sta; 00400 cb.for_each_auth = hostapd_wpa_auth_for_each_auth; 00401 cb.send_ether = hostapd_wpa_auth_send_ether; 00402 #ifdef CONFIG_IEEE80211R 00403 cb.send_ft_action = hostapd_wpa_auth_send_ft_action; 00404 cb.add_sta = hostapd_wpa_auth_add_sta; 00405 #endif /* CONFIG_IEEE80211R */ 00406 hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb); 00407 if (hapd->wpa_auth == NULL) { 00408 wpa_printf(MSG_ERROR, "WPA initialization failed."); 00409 return -1; 00410 } 00411 00412 if (hostapd_set_privacy(hapd, 1)) { 00413 wpa_printf(MSG_ERROR, "Could not set PrivacyInvoked " 00414 "for interface %s", hapd->conf->iface); 00415 return -1; 00416 } 00417 00418 wpa_ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &wpa_ie_len); 00419 if (hostapd_set_generic_elem(hapd, wpa_ie, wpa_ie_len)) { 00420 wpa_printf(MSG_ERROR, "Failed to configure WPA IE for " 00421 "the kernel driver."); 00422 return -1; 00423 } 00424 00425 if (rsn_preauth_iface_init(hapd)) { 00426 wpa_printf(MSG_ERROR, "Initialization of RSN " 00427 "pre-authentication failed."); 00428 return -1; 00429 } 00430 00431 #ifdef CONFIG_IEEE80211R 00432 if (!hostapd_drv_none(hapd)) { 00433 hapd->l2 = l2_packet_init(hapd->conf->bridge[0] ? 00434 hapd->conf->bridge : 00435 hapd->conf->iface, NULL, ETH_P_RRB, 00436 hostapd_rrb_receive, hapd, 0); 00437 if (hapd->l2 == NULL && 00438 (hapd->driver == NULL || 00439 hapd->driver->send_ether == NULL)) { 00440 wpa_printf(MSG_ERROR, "Failed to open l2_packet " 00441 "interface"); 00442 return -1; 00443 } 00444 } 00445 #endif /* CONFIG_IEEE80211R */ 00446 00447 return 0; 00448 00449 } 00450 00451 00452 void hostapd_reconfig_wpa(struct hostapd_data *hapd) 00453 { 00454 struct wpa_auth_config wpa_auth_conf; 00455 hostapd_wpa_auth_conf(hapd->conf, &wpa_auth_conf); 00456 wpa_reconfig(hapd->wpa_auth, &wpa_auth_conf); 00457 } 00458 00459 00460 void hostapd_deinit_wpa(struct hostapd_data *hapd) 00461 { 00462 rsn_preauth_iface_deinit(hapd); 00463 if (hapd->wpa_auth) { 00464 wpa_deinit(hapd->wpa_auth); 00465 hapd->wpa_auth = NULL; 00466 00467 if (hostapd_set_privacy(hapd, 0)) { 00468 wpa_printf(MSG_DEBUG, "Could not disable " 00469 "PrivacyInvoked for interface %s", 00470 hapd->conf->iface); 00471 } 00472 00473 if (hostapd_set_generic_elem(hapd, (u8 *) "", 0)) { 00474 wpa_printf(MSG_DEBUG, "Could not remove generic " 00475 "information element from interface %s", 00476 hapd->conf->iface); 00477 } 00478 } 00479 ieee802_1x_deinit(hapd); 00480 00481 #ifdef CONFIG_IEEE80211R 00482 l2_packet_deinit(hapd->l2); 00483 #endif /* CONFIG_IEEE80211R */ 00484 }