preauth_auth.c
Go to the documentation of this file.
00001 /*
00002  * hostapd - Authenticator for IEEE 802.11i RSN pre-authentication
00003  * Copyright (c) 2004-2007, 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 #ifdef CONFIG_RSN_PREAUTH
00018 
00019 #include "utils/common.h"
00020 #include "utils/eloop.h"
00021 #include "l2_packet/l2_packet.h"
00022 #include "common/wpa_common.h"
00023 #include "eapol_auth/eapol_auth_sm.h"
00024 #include "eapol_auth/eapol_auth_sm_i.h"
00025 #include "hostapd.h"
00026 #include "ap_config.h"
00027 #include "ieee802_1x.h"
00028 #include "sta_info.h"
00029 #include "wpa_auth.h"
00030 #include "preauth_auth.h"
00031 
00032 #ifndef ETH_P_PREAUTH
00033 #define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */
00034 #endif /* ETH_P_PREAUTH */
00035 
00036 static const int dot11RSNAConfigPMKLifetime = 43200;
00037 
00038 struct rsn_preauth_interface {
00039         struct rsn_preauth_interface *next;
00040         struct hostapd_data *hapd;
00041         struct l2_packet_data *l2;
00042         char *ifname;
00043         int ifindex;
00044 };
00045 
00046 
00047 static void rsn_preauth_receive(void *ctx, const u8 *src_addr,
00048                                 const u8 *buf, size_t len)
00049 {
00050         struct rsn_preauth_interface *piface = ctx;
00051         struct hostapd_data *hapd = piface->hapd;
00052         struct ieee802_1x_hdr *hdr;
00053         struct sta_info *sta;
00054         struct l2_ethhdr *ethhdr;
00055 
00056         wpa_printf(MSG_DEBUG, "RSN: receive pre-auth packet "
00057                    "from interface '%s'", piface->ifname);
00058         if (len < sizeof(*ethhdr) + sizeof(*hdr)) {
00059                 wpa_printf(MSG_DEBUG, "RSN: too short pre-auth packet "
00060                            "(len=%lu)", (unsigned long) len);
00061                 return;
00062         }
00063 
00064         ethhdr = (struct l2_ethhdr *) buf;
00065         hdr = (struct ieee802_1x_hdr *) (ethhdr + 1);
00066 
00067         if (os_memcmp(ethhdr->h_dest, hapd->own_addr, ETH_ALEN) != 0) {
00068                 wpa_printf(MSG_DEBUG, "RSN: pre-auth for foreign address "
00069                            MACSTR, MAC2STR(ethhdr->h_dest));
00070                 return;
00071         }
00072 
00073         sta = ap_get_sta(hapd, ethhdr->h_source);
00074         if (sta && (sta->flags & WLAN_STA_ASSOC)) {
00075                 wpa_printf(MSG_DEBUG, "RSN: pre-auth for already association "
00076                            "STA " MACSTR, MAC2STR(sta->addr));
00077                 return;
00078         }
00079         if (!sta && hdr->type == IEEE802_1X_TYPE_EAPOL_START) {
00080                 sta = ap_sta_add(hapd, ethhdr->h_source);
00081                 if (sta == NULL)
00082                         return;
00083                 sta->flags = WLAN_STA_PREAUTH;
00084 
00085                 ieee802_1x_new_station(hapd, sta);
00086                 if (sta->eapol_sm == NULL) {
00087                         ap_free_sta(hapd, sta);
00088                         sta = NULL;
00089                 } else {
00090                         sta->eapol_sm->radius_identifier = -1;
00091                         sta->eapol_sm->portValid = TRUE;
00092                         sta->eapol_sm->flags |= EAPOL_SM_PREAUTH;
00093                 }
00094         }
00095         if (sta == NULL)
00096                 return;
00097         sta->preauth_iface = piface;
00098         ieee802_1x_receive(hapd, ethhdr->h_source, (u8 *) (ethhdr + 1),
00099                            len - sizeof(*ethhdr));
00100 }
00101 
00102 
00103 static int rsn_preauth_iface_add(struct hostapd_data *hapd, const char *ifname)
00104 {
00105         struct rsn_preauth_interface *piface;
00106 
00107         wpa_printf(MSG_DEBUG, "RSN pre-auth interface '%s'", ifname);
00108 
00109         piface = os_zalloc(sizeof(*piface));
00110         if (piface == NULL)
00111                 return -1;
00112         piface->hapd = hapd;
00113 
00114         piface->ifname = os_strdup(ifname);
00115         if (piface->ifname == NULL) {
00116                 goto fail1;
00117         }
00118 
00119         piface->l2 = l2_packet_init(piface->ifname, NULL, ETH_P_PREAUTH,
00120                                     rsn_preauth_receive, piface, 1);
00121         if (piface->l2 == NULL) {
00122                 wpa_printf(MSG_ERROR, "Failed to open register layer 2 access "
00123                            "to ETH_P_PREAUTH");
00124                 goto fail2;
00125         }
00126 
00127         piface->next = hapd->preauth_iface;
00128         hapd->preauth_iface = piface;
00129         return 0;
00130 
00131 fail2:
00132         os_free(piface->ifname);
00133 fail1:
00134         os_free(piface);
00135         return -1;
00136 }
00137 
00138 
00139 void rsn_preauth_iface_deinit(struct hostapd_data *hapd)
00140 {
00141         struct rsn_preauth_interface *piface, *prev;
00142 
00143         piface = hapd->preauth_iface;
00144         hapd->preauth_iface = NULL;
00145         while (piface) {
00146                 prev = piface;
00147                 piface = piface->next;
00148                 l2_packet_deinit(prev->l2);
00149                 os_free(prev->ifname);
00150                 os_free(prev);
00151         }
00152 }
00153 
00154 
00155 int rsn_preauth_iface_init(struct hostapd_data *hapd)
00156 {
00157         char *tmp, *start, *end;
00158 
00159         if (hapd->conf->rsn_preauth_interfaces == NULL)
00160                 return 0;
00161 
00162         tmp = os_strdup(hapd->conf->rsn_preauth_interfaces);
00163         if (tmp == NULL)
00164                 return -1;
00165         start = tmp;
00166         for (;;) {
00167                 while (*start == ' ')
00168                         start++;
00169                 if (*start == '\0')
00170                         break;
00171                 end = os_strchr(start, ' ');
00172                 if (end)
00173                         *end = '\0';
00174 
00175                 if (rsn_preauth_iface_add(hapd, start)) {
00176                         rsn_preauth_iface_deinit(hapd);
00177                         os_free(tmp);
00178                         return -1;
00179                 }
00180 
00181                 if (end)
00182                         start = end + 1;
00183                 else
00184                         break;
00185         }
00186         os_free(tmp);
00187         return 0;
00188 }
00189 
00190 
00191 static void rsn_preauth_finished_cb(void *eloop_ctx, void *timeout_ctx)
00192 {
00193         struct hostapd_data *hapd = eloop_ctx;
00194         struct sta_info *sta = timeout_ctx;
00195         wpa_printf(MSG_DEBUG, "RSN: Removing pre-authentication STA entry for "
00196                    MACSTR, MAC2STR(sta->addr));
00197         ap_free_sta(hapd, sta);
00198 }
00199 
00200 
00201 void rsn_preauth_finished(struct hostapd_data *hapd, struct sta_info *sta,
00202                           int success)
00203 {
00204         const u8 *key;
00205         size_t len;
00206         hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
00207                        HOSTAPD_LEVEL_INFO, "pre-authentication %s",
00208                        success ? "succeeded" : "failed");
00209 
00210         key = ieee802_1x_get_key(sta->eapol_sm, &len);
00211         if (len > PMK_LEN)
00212                 len = PMK_LEN;
00213         if (success && key) {
00214                 if (wpa_auth_pmksa_add_preauth(hapd->wpa_auth, key, len,
00215                                                sta->addr,
00216                                                dot11RSNAConfigPMKLifetime,
00217                                                sta->eapol_sm) == 0) {
00218                         hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
00219                                        HOSTAPD_LEVEL_DEBUG,
00220                                        "added PMKSA cache entry (pre-auth)");
00221                 } else {
00222                         hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
00223                                        HOSTAPD_LEVEL_DEBUG,
00224                                        "failed to add PMKSA cache entry "
00225                                        "(pre-auth)");
00226                 }
00227         }
00228 
00229         /*
00230          * Finish STA entry removal from timeout in order to avoid freeing
00231          * STA data before the caller has finished processing.
00232          */
00233         eloop_register_timeout(0, 0, rsn_preauth_finished_cb, hapd, sta);
00234 }
00235 
00236 
00237 void rsn_preauth_send(struct hostapd_data *hapd, struct sta_info *sta,
00238                       u8 *buf, size_t len)
00239 {
00240         struct rsn_preauth_interface *piface;
00241         struct l2_ethhdr *ethhdr;
00242 
00243         piface = hapd->preauth_iface;
00244         while (piface) {
00245                 if (piface == sta->preauth_iface)
00246                         break;
00247                 piface = piface->next;
00248         }
00249 
00250         if (piface == NULL) {
00251                 wpa_printf(MSG_DEBUG, "RSN: Could not find pre-authentication "
00252                            "interface for " MACSTR, MAC2STR(sta->addr));
00253                 return;
00254         }
00255 
00256         ethhdr = os_malloc(sizeof(*ethhdr) + len);
00257         if (ethhdr == NULL)
00258                 return;
00259 
00260         os_memcpy(ethhdr->h_dest, sta->addr, ETH_ALEN);
00261         os_memcpy(ethhdr->h_source, hapd->own_addr, ETH_ALEN);
00262         ethhdr->h_proto = host_to_be16(ETH_P_PREAUTH);
00263         os_memcpy(ethhdr + 1, buf, len);
00264 
00265         if (l2_packet_send(piface->l2, sta->addr, ETH_P_PREAUTH, (u8 *) ethhdr,
00266                            sizeof(*ethhdr) + len) < 0) {
00267                 wpa_printf(MSG_ERROR, "Failed to send preauth packet using "
00268                            "l2_packet_send\n");
00269         }
00270         os_free(ethhdr);
00271 }
00272 
00273 
00274 void rsn_preauth_free_station(struct hostapd_data *hapd, struct sta_info *sta)
00275 {
00276         eloop_cancel_timeout(rsn_preauth_finished_cb, hapd, sta);
00277 }
00278 
00279 #endif /* CONFIG_RSN_PREAUTH */


wpa_supplicant
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Apr 24 2014 15:34:35