wpa_auth_glue.c
Go to the documentation of this file.
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 }


wpa_supplicant_node
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Apr 24 2014 15:33:21